\documentclass[dvipdfm]{book}
\setlength{\textwidth}{400pt}
\usepackage{hyperref}
\usepackage{axiom}
\usepackage{makeidx}
\setlength{\textwidth}{400pt}
\makeindex
\usepackage{graphicx}
\begin{document}
\begin{titlepage}
\center{\includegraphics{ps/axiomfront.ps}}
\vskip 0.1in
\includegraphics{ps/bluebayou.ps}\\
\vskip 0.1in
{\Huge{The 30 Year Horizon}}
\vskip 0.1in
$$
\begin{array}{lll}
Manuel\ Bronstein      & William\ Burge   & Timothy\ Daly \\
James\ Davenport       & Michael\ Dewar   & Martin\ Dunstan \\
Albrecht\ Fortenbacher & Patrizia\ Gianni & Johannes\ Grabmeier \\
Jocelyn\ Guidry        & Richard\ Jenks   & Larry\ Lambe \\
Michael\ Monagan       & Scott\ Morrison  & William\ Sit \\
Jonathan\ Steinbach    & Robert\ Sutor    & Barry\ Trager \\
Stephen\ Watt          & Jim\ Wen         & Clifton\ Williamson
\end{array}
$$
\center{\large{Volume 7.1: Axiom Hyperdoc Pages}}
\end{titlepage}
\pagenumbering{roman}
\begin{verbatim}
Portions Copyright (c) 2005 Timothy Daly

The Blue Bayou image Copyright (c) 2004 Jocelyn Guidry

Portions Copyright (c) 2004 Martin Dunstan

Portions Copyright (c) 1991-2002, 
The Numerical ALgorithms Group Ltd.
All rights reserved.

This book and the Axiom software is licensed as follows:

Redistribution and use in source and binary forms, with or 
without modification, are permitted provided that the following 
conditions are
met:

    - Redistributions of source code must retain the above 
      copyright notice, this list of conditions and the 
      following disclaimer.

    - Redistributions in binary form must reproduce the above
      copyright notice, this list of conditions and the 
      following disclaimer in the documentation and/or other 
      materials provided with the distribution.

    - Neither the name of The Numerical ALgorithms Group Ltd. 
      nor the names of its contributors may be used to endorse 
      or promote products derived from this software without 
      specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
SUCH DAMAGE.

\end{verbatim}

Inclusion of names in the list of credits is based on historical
information and is as accurate as possible. Inclusion of names
does not in any way imply an endorsement but represents historical
influence on Axiom development.
\vfill
\eject
\begin{tabular}{lll}
Cyril Alberga         & Roy Adler             & Richard Anderson\\
George Andrews        & Henry Baker           & Stephen Balzac\\
Yurij Baransky        & David R. Barton       & Gerald Baumgartner\\
Gilbert Baumslag      & Fred Blair            & Vladimir Bondarenko\\
Mark Botch            & Alexandre Bouyer      & Peter A. Broadbery\\
Martin Brock          & Manuel Bronstein      & Florian Bundschuh\\
William Burge         & Quentin Carpent       & Bob Caviness\\
Bruce Char            & Cheekai Chin          & David V. Chudnovsky\\
Gregory V. Chudnovsky & Josh Cohen            & Christophe Conil\\
Don Coppersmith       & George Corliss        & Robert Corless\\
Gary Cornell          & Meino Cramer          & Claire Di Crescenzo\\
Timothy Daly Sr.      & Timothy Daly Jr.      & James H. Davenport\\
Jean Della Dora       & Gabriel Dos Reis      & Michael Dewar\\
Claire DiCrescendo    & Sam Dooley            & Lionel Ducos\\
Martin Dunstan        & Brian Dupee           & Dominique Duval\\
Robert Edwards        & Heow Eide-Goodman     & Lars Erickson\\
Richard Fateman       & Bertfried Fauser      & Stuart Feldman\\
Brian Ford            & Albrecht Fortenbacher & George Frances\\
Constantine Frangos   & Timothy Freeman       & Korrinn Fu\\
Marc Gaetano          & Rudiger Gebauer       & Kathy Gerber\\
Patricia Gianni       & Holger Gollan         & Teresa Gomez-Diaz\\
Laureano Gonzalez-Vega& Stephen Gortler       & Johannes Grabmeier\\
Matt Grayson          & James Griesmer        & Vladimir Grinberg\\
Oswald Gschnitzer     & Jocelyn Guidry        & Steve Hague\\
Vilya Harvey          & Satoshi Hamaguchi     & Martin Hassner\\
Ralf Hemmecke         & Henderson             & Antoine Hersen\\
Pietro Iglio          & Richard Jenks         & Kai Kaminski\\
Grant Keady           & Tony Kennedy          & Paul Kosinski\\
Klaus Kusche          & Bernhard Kutzler      & Larry Lambe\\
Frederic Lehobey      & Michel Levaud         & Howard Levy\\
Rudiger Loos          & Michael Lucks         & Richard Luczak\\
Camm Maguire          & Bob McElrath          & Michael McGettrick\\
Ian Meikle            & David Mentre          & Victor S. Miller\\
Gerard Milmeister     & Mohammed Mobarak      & H. Michael Moeller\\
Michael Monagan       & Marc Moreno-Maza      & Scott Morrison\\
Mark Murray           & William Naylor        & C. Andrew Neff\\
John Nelder           & Godfrey Nolan         & Arthur Norman\\
Jinzhong Niu          & Michael O'Connor      & Kostas Oikonomou\\
Julian A. Padget      & Bill Page             & Jaap Weel\\
Susan Pelzel          & Michel Petitot        & Didier Pinchon\\
Claude Quitte         & Norman Ramsey         & Michael Richardson\\
Renaud Rioboo         & Jean Rivlin           & Nicolas Robidoux\\
Simon Robinson        & Michael Rothstein     & Martin Rubey\\
Philip Santas         & Alfred Scheerhorn     & William Schelter\\
Gerhard Schneider     & Martin Schoenert      & Marshall Schor\\
Fritz Schwarz         & Nick Simicich         & William Sit\\
Elena Smirnova        & Jonathan Steinbach    & Christine Sundaresan\\
Robert Sutor          & Moss E. Sweedler      & Eugene Surowitz\\
James Thatcher        & Baldir Thomas         & Mike Thomas\\
Dylan Thurston        & Barry Trager          & Themos T. Tsikas\\
Gregory Vanuxem       & Bernhard Wall         & Stephen Watt\\
Juergen Weiss         & M. Weller             & Mark Wegman\\
James Wen             & Thorsten Werther      & Michael Wester\\
John M. Wiley         & Berhard Will          & Clifton J. Williamson\\
Stephen Wilson        & Shmuel Winograd       & Robert Wisbauer\\
Sandra Wityak         & Waldemar Wiwianka     & Knut Wolf\\
Clifford Yapp         & David Yun             & Richard Zippel\\
Evelyn Zoernack       & Bruno Zuercher        & Dan Zwillinger 
\end{tabular}
\eject
\tableofcontents
\vfill
\eject
\setlength{\parindent}{0em}
\setlength{\parskip}{1ex}
{\Large{\bf New Foreword}}
\vskip .25in

On October 1, 2001 Axiom was withdrawn from the market and ended
life as a commercial product.
On September 3, 2002 Axiom was released under the Modified BSD
license, including this document.
On August 27, 2003 Axiom was released as free and open source
software available for download from the Free Software Foundation's
website, Savannah.

Work on Axiom has had the generous support of the Center for 
Algorithms and Interactive Scientific Computation (CAISS) at
City College of New York. Special thanks go to Dr. Gilbert 
Baumslag for his support of the long term goal.

The online version of this documentation is roughly 1000 pages.
In order to make printed versions we've broken it up into three
volumes. The first volume is tutorial in nature. The second volume
is for programmers. The third volume is reference material. We've
also added a fourth volume for developers. All of these changes
represent an experiment in print-on-demand delivery of documentation.
Time will tell whether the experiment succeeded.

Axiom has been in existence for over thirty years. It is estimated to
contain about three hundred man-years of research and has, as of
September 3, 2003, 143 people listed in the credits. All of these
people have contributed directly or indirectly to making Axiom
available.  Axiom is being passed to the next generation. I'm looking
forward to future milestones.

With that in mind I've introduced the theme of the ``30 year horizon''.
We must invent the tools that support the Computational Mathematician
working 30 years from now. How will research be done when every bit of
mathematical knowledge is online and instantly available? What happens
when we scale Axiom by a factor of 100, giving us 1.1 million domains?
How can we integrate theory with code? How will we integrate theorems
and proofs of the mathematics with space-time complexity proofs and
running code? What visualization tools are needed? How do we support
the conceptual structures and semantics of mathematics in effective
ways? How do we support results from the sciences? How do we teach
the next generation to be effective Computational Mathematicians?

The ``30 year horizon'' is much nearer than it appears.

\vskip .25in
%\noindent
Tim Daly\\
CAISS, City College of New York\\
November 10, 2003 ((iHy))
\vfill
\eject
\pagenumbering{arabic}
\setcounter{chapter}{0} % Chapter 1
\chapter{Release Notes}
\section{releasenotes.ht}
\pagetitle{releaseNotes}{releasenotes.ht}{What is new in Axiom}
\pagepic{ps/v71releasenotes.eps}{releasenotes}{0.65}
\pagefrom{Root Page}{RootPage}
\pageto{Online information}{onlineInformation}
\pageto{January 2012}{jan2012}
\pageto{November 2011}{nov2011}
\pageto{September 2011}{sept2011}
\pageto{July 2011}{july2011}
\pageto{May 2011}{may2011}
\pageto{March 2011}{mar2011}
\pageto{January 2011}{jan2011}
\pageto{November 2010}{nov2010}
\pageto{September 2010}{sept2010}
\pageto{July 2010}{july2010}
\pageto{May 2010}{may2010}
\pageto{March 2010}{mar2010}
\pageto{January 2010}{jan2010}
\pageto{November 2009}{nov2009}
\pageto{September 2009}{sept2009}
\pageto{July 2009}{july2009}
\pageto{May 2009}{may2009}
\pageto{March 2009}{mar2009}
\pageto{January 2009}{jan2009}
\pageto{November 2008}{nov2008}
\pageto{September 2008}{sept2008}
\pageto{July 2008}{july2008}
\pageto{May 2008}{may2008}
\pageto{March 2008}{march2008}
\pageto{January 2008}{january2008}
\pageto{November 2007}{november2007}
\pageto{February 2005}{feb2005}
\begin{chunk}{releasenotes.ht}
\begin{page}{releaseNotes}{0. What's New in Axiom}
\beginscroll
\beginmenu
    \menudownlink{Online information}{onlineInformation}
    \menudownlink{January 2012}{jan2012}
    \menudownlink{November 2011}{nov2011}
    \menudownlink{September 2011}{sept2011}
    \menudownlink{July 2011}{july2011}
    \menudownlink{May 2011}{may2011}
    \menudownlink{March 2011}{mar2011}
    \menudownlink{January 2011}{jan2011}
    \menudownlink{November 2010}{nov2010}
    \menudownlink{September 2010}{sept2010}
    \menudownlink{July 2010}{july2010}
    \menudownlink{May 2010}{may2010}
    \menudownlink{March 2010}{mar2010}
    \menudownlink{January 2010}{jan2010}
    \menudownlink{November 2009}{nov2009}
    \menudownlink{September 2009}{sept2009}
    \menudownlink{July 2009}{july2009}
    \menudownlink{May 2009}{may2009}
    \menudownlink{March 2009}{mar2009}
    \menudownlink{January 2009}{jan2009}
    \menudownlink{November 2008}{nov2008}
    \menudownlink{September 2008}{sept2008}
    \menudownlink{July 2008}{july2008}
    \menudownlink{May 2008}{may2008}
    \menudownlink{March 2008}{march2008}
    \menudownlink{January 2008}{january2008}
    \menudownlink{November 2007}{november2007}
    \menudownlink{February 2005}{feb2005}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{onlineInformation}{releasenotes.ht}{Online Information}
\pagepic{ps/v71onlineinformation.eps}{onlineinformation}{0.50}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{onlineInformation}{Online information}
\beginscroll
Axiom information can be found online at
{http://axiom.axiom-developer.org}
{http://savannah.nongnu.org/projects/axiom}
{http://sourceforge.net/projects/axiom}
\endscroll
\autobuttons
\end{page}

\end{chunk}

\pagetitle{jan2012}{releasenotes.ht}{January 2012 Release Notes}
\pagepic{ps/v71jan2012.eps}{jan2012}{0.60}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{jan2012}{January 2012 Release Notes}
\beginscroll
\begin{verbatim}
January 2012 Release

The Jenks book was updated by adding appendix E, and the 
graphics images from the center of the book.

These people were added to the credits list:
   Guilherme Reis, Michael Albaugh, Roger House to credits

Literate documentation was added to the book 9, the compiler
The axiomgraphs were created for the compile command and the parser.

The website was updated with several changes including a global
rewrite of the color and fixes for broken links.

Treeshaking of the compiler and interpreter code continues.

Work was done but not completed to move to GCL-2.6.8pre6

bookvol0.pamphlet 
   add Appendix E
   add graphics images from middle of book

bookvol10.4.pamphlet 
   add Guilherme Reis, Michael Albaugh, Roger House

books/bookvol5
   localize function names
   treeshake interpreter
   add Guilherme Reis, Michael Albaugh, Roger House

books/bookvol9 
   add comment graphs
   code cleanup
   localize function names
   treeshake and document compiler

books/bookvolbib 
   add additional Axiom literature references

books/ps/
   add v0hroot.eps, v0hyper.eps, v0page1.eps, v0page2.eps, v0page3.eps
   add v0page4.eps, v0page5.eps, v0page6.eps, v0page7.eps, v0page8.eps
   v9CommentRecording.eps comment recording chapter
   v9CommentSyntaxChecking.eps comment syntax chapter
   v9comdefine.eps document compiler
   v9compiler.eps document compiler

readme
   add Guilherme Reis, Michael Albaugh, Roger House

src/algebra
   Makefile fix autoload

src/axiom-website/
   global background color change to ECEA81
   axiom.png make background transparent
   books.html fix broken links
   litprog.html fix argument count
   litprog.html note HTML escape code flaw

  /axiomgraph/
     axiomgraph.tex literate form of js
     index.html add graphs

  /axiomgraph/js
     arbor.js add graphs
     axiomcode.js add graphs, parse tree, default compiler
     jquery-1.7.1.js add graphs

  /xiomgraph/maps/
     algebra.json add graphs
     comment.json update comment
     add compile.json for the compile command
     add compiler.json for the compiler
     add dstruct.json for data structures
     add funsel.json for function selection
     nine.json for global compiler
     parse.json for parser

  /axiomgraph/style/
     axiomgraph.css change background
     axiomicon.png add icon

  /hyperdoc
     change page background color

src/doc/
   axiom.sty fix comments

src/input/
   Makefile add i2e.input
   i2e.input demo InputForm to Expression(Integer)
   pasta.input graphics test cases

src/interp
   br-con.lisp localize function names, treeshake compiler
   cattable.lisp treeshake compiler
   ht-util.lisp localize function names
   i-funsel.lisp treeshake compiler
   parsing.lisp localize function names, treeshake compiler
   patches.lisp localize function names
   util.lisp treeshake compiler
   vmlisp.lisp localize function names, treeshake compiler

src/scripts/tex/
   axiom.sty fix comments


20111130 tpd src/axiom-website/patches.html 20111130.04.tpd.patch
20111130 tpd src/axiom-website/patches.html 20111130 update patch frontier
20111130 tpd src/axiom-website/releasenotes.html
20111130 tpd books/ps/v71releasenotes.eps add release notes
20111130 tpd books/ps/v71nov2011.eps added
20111130 tpd books/bookvol7.1 update What's New Page
20111130 tpd Makefile.pamphlet VERSION = November 2011
20111130 tpd Makefile VERSION = November 2011

\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}


\pagetitle{nov2011}{releasenotes.ht}{November 2011 Release Notes}
\pagepic{ps/v71nov2011.eps}{nov2011}{0.60}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{nov2011}{November 2011 Release Notes}
\beginscroll
\begin{verbatim}
November 2011 Release

Treeshaking the interpreter and compiler continues and a few more files
were merged and removed.

Several books and Makefiles were converted to use lisp tangle rather 
than noweb. This is part of the general process to remove noweb.

Global function rewrites continue, including removing GETREFV and makeprop.

Work was done to improve OpenMath support. The OpenMath semantics CDs were
added and the OpenMath parser was enhanced.

More effort was put into literate work. In particular, an example of a
literate program using HTML was created and presented at the Clojure/Conj
conference.

books/Makefile
   removed noweb, move to lisp tangle
   fix missing index files on PDfs

books/tangle.lisp 
   fix .input file algebra extraction

books/bookvol10.2
   missing/unused function cleanup
   remove makeprop
   remove noweb, move to lisp tangle

books/bookvol10.3 
   remove GETREFV
   remove makeprop
   remove noweb, move to lisp tangle

books/bookvol10.4 
   remove noweb, move to lisp tangle

books/bookvol10.5 
   remove noweb, move to lisp tangle

books/bookvol4
   missing/unused function cleanup
   remove makeprop

books/bookvol5 
   OpenMath support
   add OpenMath stubs
   missing/unused function cleanup
   remove makeprop
   remove noweb, move to lisp tangle
   treeshake interpreter

books/bookvol7.1 
   fix documentation
   update What's New Page

books/bookvol9
   missing/unused function cleanup
   remove makeprop
   treeshake and merge c-doc.lisp

books/bookvolbib
   Axiom OpenMath references
   add additional references
   add references

books/ps/
   v71releasenotes.eps add release notes
   v71sept2011.eps added

src/algebra/Makefile 
   fix .input file algebra extraction
   remove noweb, move to lisp tangle

src/axiom-website/documentation.html
   add Alexander quote
   add Knuth quote
   add litprog.html
   add quote

src/axiom-website/download.html
   update to latest release

src/axiom-website/litprog.html
   added
   add quote
   literate program example update

src/interp/Makefile 
   remove apply.lisp
   remove c-doc.lisp
   remove noweb, move to lisp tangle
   remove nruntime.lisp

src/interp
   apply.lisp removed, merged with bookvol9
   buildom.lisp remove GETREFV
   c-doc.lisp removed
   c-util.lisp missing/unused function cleanup
   category.lisp remove GETREFV
   functor.lisp missing/unused function cleanup, remove GETREFV
   g-util.lisp missing/unused function cleanup
   i-eval.lisp remove nruntime.lisp
   i-spec1.lisp treeshake interpreter
   i-spec2.lisp fix AN has sqrt: % -> %
   i-spec2.lisp remove makeprop
   nruncomp.lisp remove GETREFV, treeshake compiler
   nrungo.lisp remove nruntime.lisp, treeshake interpreter, remove GETREFV
   nruntime.lisp removed
   parsing.lisp remove makeprop
   sys-pkg.lisp missing/unused function cleanup, remove GETREFV, makeprop
   template.lisp remove GETREFV
   vmlisp.lisp missing/unused function cleanup, remove GETREFV, makeprop

zips
   add cds.tar.gz OpenMath support. add OpenMath CDs
\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}

\pagetitle{sept2011}{releasenotes.ht}{September 2011 Release Notes}
\pagepic{ps/v71sept2011.eps}{sept2011}{0.60}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{sept2011}{September 2011 Release Notes}
\beginscroll
\begin{verbatim}
September 2011 Release

This release continues the task of treeshaking the compiler and
interpreter. Nine files were merged and removed. In addition,
several passes were made for code cleanup.

The Symbolic Ito Calculus package is being added, starting with the
BasicStochasticDifferential and  StochasticDifferential domains.
More work remains to be done.

The GUESS package is being upgraded. 

James Cloos and Wilfrid Kendall were added to the credits.

books/bookvol10.3 
  add BasicStochasticDifferential and  StochasticDifferential
  remove pairp
  start upgrade of GUESS package

books/bookvol10.4 
  remove packageTran

books/bookvol10.5 
  add StochasticDifferential

books/bookvol5 
  add BasicStochasticDifferential domain
  merge nocompil.lisp, as.lisp, nci.lisp
  treeshake interpreter
  remove pairp, ncParseAndInterpretString, packageTran
  use qc(ad)r forms

books/bookvol7 
  merge nocompil.lisp

books/bookvol7.1 
  update What's New Page

books/bookvol9
  remove pairp, isPackageFunction
  treeshake compiler
  use qc(ad)r forms

books/bookvolbib
   add Kendall Ken99a, Ken99b literature references to Axiom

books/ps/
  v103basicstochasticdifferential.ps added
  v103stochasticdifferential.ps added
  v71july2011.eps 
  v71releasenotes.eps add release notes

src/algebra/Makefile 
  BasicStochasticDifferential domain
  add StochasticDifferential
  remove upper GUESS package code

src/axiom-website/download.html add Gentoo notes by James Cloos
src/axiom-website/download.html add ubuntu

src/axiom-website/releasenotes.html

src/doc/axiom.sty 
  fix defplist

src/input/Makefile 
  document finite field bug 
  respect the BUILD=fast variable value

src/input/
  fix broken tests in axiom, cmds, setcmd, unittest1, unittest2
  ffieldbug.input: added

src/interp/Makefile 
  remove as.lisp, compiler.lisp, database.lisp, define.lisp, foam_l
  remove g-opt.lisp, nci.lisp, package.lisp, ax.lisp

\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}

\pagetitle{july2011}{releasenotes.ht}{July 2011 Release Notes}
\pagepic{ps/v71july2011.eps}{july2011}{0.60}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{july2011}{July 2011 Release Notes}
\beginscroll
\begin{verbatim}
July 2011 Release

The prior release had a bug that caused it to remember the build location.
This was a change introduced by the underlying lisp. This was fixed.

This release continues treeshaking the compiler. 
The modemap.lisp file has been merged and no longer exists.

This release continues to treeshake the interpreter. 
The axext_l.lisp file has been removed.

Makefile.pamphlet
  add BUILD=full / BUILD=fast switch

Book Volume 5 (Interpreter)
  treeshake interpreter

Book Volume 9 (Compiler)
  treeshake compiler

Book Volume 10.3 (Domains)
  help and unit tests for RewriteRule

axiom.sty
  add /refsdollar and /defsdollar for better cross references

src/interp/Makefile
  add (si::reset-sys-paths) per Camm
  remove axext_l aldor support file
  remove modemap.lisp

\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}

\pagetitle{may2011}{releasenotes.ht}{May 2011 Release Notes}
\pagepic{ps/v71may2011.eps}{may2011}{0.60}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{may2011}{May 2011 Release Notes}
\beginscroll
\begin{verbatim}
May 2011 Release

This release involved more work treeshaking of the compiler and
interpreter. Argument naming conventions were normalized to improve
the documentation and clarity.

Time was spent proofreading the books and reducing or eliminating
latex warnings. Missing index files were fixed and errors in the Jenks
book were fixed.

The website has been updated to make Arthur Ralf's book available
from every page. The website is being rewritten to be IPv6 enabled.

Doug Telford was added to the credits.

Book Volume 0 (Jenks book)
  proofread to chapter 1 (pdf page 86)
  replace "operator over" by "operate over"
  set textlength 400
  port changes to Arthur Ralfs HTML version

Book Volume 1 (Tutorial)
  proofread and copyedit
  set textlength 400
  update HTML image

Book Volume 2 
  set textlength 400

Book Volume 3
  set textlength 400

Book Volume 4
  set textlength 400

Book Volume 5 (Interpreter)
  add Doug Telford to credits
  set textlength 400
  treeshake interpreter

Book Volume 6
  set textlength 400

Book Volume 7 (Hyperdoc)
  set textlength 400

Book Volume 7.1 (Hyperdoc pages)
  set textlength 400
  update What's New Page
  ps/v71mar2011.eps
  ps/v71releasenotes.eps add release notes

Book Volume 8
  set textlength 400

Book Volume 9 (Compiler)
  normalize argument names to top level functions
  treeshake compiler

Book Volume 10
  set textlength 400

Book Volume 10.1
  set textlength 400

Book Volume 10.2 (Categories)
  set textlength 400

Book Volume 10.3 (Domains)
  set textlength 400

Book Volume 10.4 (Packages)
  set textlength 400

Book Volume 10.5 (Numerics)
  set textlength 400

Book Volume 11
  set textlength 400

Book Volume 12
  set textlength 400

Biblography
  add several references
  set textlength 400

readme
  add Doug Telford to credits

website
  set up IPv6 address range
  download.html add binaries
  bugreport.html add bug reporting instructions
 
  The website now has an online version of the Jenks book which is a 
  link to Arthur Ralf's HTML version. This has been updated with the
  proofreading changes for the latex version.

     *.html add online book link to Arthur Ralfs HTML version
     hyperdoc/axbook/ps/h-root.png port changes
     hyperdoc/axbook/section-0.1.xhtml, section-0.6.xhtml, section-0.7.xhtml

Makefiles
  books/Makefile fix missing index
  books/Makefile set textlength 400

Testing
  Makefile add davis.input
  Makefile add erf.input
  Makefile bug report regression test
  davis.input
  erf.input add examples of erf integration
  telford.input bug report regression test


src/interp/
  define.lisp treeshake compiler
  parsing.lisp treeshake compiler
  vmlisp.lisp treeshake compiler

\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}

\pagetitle{mar2011}{releasenotes.ht}{March 2011 Release Notes}
\pagepic{ps/v71mar2011.eps}{mar2011}{0.60}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{mar2011}{March 2011 Release Notes}
\beginscroll
\begin{verbatim}
March 2011 Release

This release involved more work treeshaking the compiler. 

Book Volume 5 (Interpreter)
   add trapNumericErrors
   fixup seebook xrefs
   move numericFailure code for plot3d
   treeshake compiler
   treeshake compiler

Book Volume 9 (Compiler)
   add seebook changes
   fix special declaration for lines in preparse1
   fixup seebook xrefs
   treeshake compiler

Book Volume 10.3 (Domains)
   fix algebra ++ to --

Biblography
   add Davenport [Dav10], [DSTxx]
   add Fateman [Fat05]

tangle.lisp
   fix help file extraction

src/scripts/tex/axiom.sty
   add \seebook

src/interp/
 Makefile
    preload bookvol9
 g-util.lisp 
    treeshake compiler
 parsing.lisp
    treeshake compiler
 util.lisp
    treeshake compiler
 vmlisp.lisp
    move numericFailure code for plot3d
    remove extra end{chunk}
    treeshake compiler


\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}


\pagetitle{jan2011}{releasenotes.ht}{January 2011 Release Notes}
\pagepic{ps/v71jan2011.eps}{jan2011}{0.60}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{jan2011}{January 2011 Release Notes}
\beginscroll
\begin{verbatim}
January 2011 Release

This release involved more work treeshaking the compiler. 
There is a move to using lisp tangle rather than noweb notangle.
Many of the latex error messages were fixed.

books/Makefile
   move bookvol9 to lisp tangle
   move to lisp tangle
   reduce the noise during make

books/bookvol5
   cleaning vmlisp
   convert to lisp tangle
   move to lisp tangle
   sort monitor results

books/bookvol6
   move to lisp tangle

books/bookvol7
   move to lisp tangle

books/bookvol7.1
   move to lisp tangle
   update What's New page

books/bookvol9
   cleaning vmlisp
   merge and remove newaux.lisp
   merge and remove postprop.lisp
   move to lisp tangle
   treeshake compiler

books/bookvol10.3
   cleaning vmlisp

books/bookvol10.4
   fixup IntersectionDivisorPackage chunk

books/bookvol12
   add discussion of GTFL

books/bookvolbib
   [Loe09], [Mar07], [Wei03], [Wei06], [Flo63], [Pra73]

books/ps/v71nov2010.eps
   update What's New page

books/ps/v71releasenotes.eps
   update What's New page

src/Makefile
   move to lisp tangle

src/axiom-website/download.html
   add ubuntu

src/axiom-website/releasenotes.html
   add release notes

src/input/Makefile
   clean up failing tests

src/input/
   *.input add \setlength{\textwidth}{400pt}
   fix overfull boxes
   clean up failing tests
   fix long lines
   series.input -- add series to polynomial example
   unit-i-funsel.input -- removed

src/interp
   Makefile convert bookvol5 to lisp tangle
   Makefile merge and remove newaux.lisp
   Makefile move to lisp tangle
   Makefile remove postprop.lisp
   src/interp/br-con.lisp cleaning vmlisp
   src/interp/compiler.lisp treeshake compiler
   src/interp/newaux.lisp remove newaux.lisp
   src/interp/postprop.lisp merged with bookvol9, removed.
   src/interp/regress.lisp handle "ok" on --S
   src/interp/vmlisp.lisp cleaning 

\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}

\pagetitle{nov2010}{releasenotes.ht}{November 2010 Release Notes}
\pagepic{ps/v71nov2010.eps}{nov2010}{0.60}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{nov2010}{November 2010 Release Notes}
\beginscroll
\begin{verbatim}
November 2010 Release

This release concentrated on treeshaking the compiler code into book volume 9.
Due to the complexity of this task it will take several releases to complete.

Makefile 
   automate making help files

books/bookvol4
   documented debugging technique

books/bookvol5
   document compiler related routines
   cleanup latex

books/bookvol6
   added section on research ideas

books/bookvol9
   treeshake compiler code
   document compiler code
   fix |special| bug
   merge and remove fnewmeta
   move meta code into bookvol9 from parsing.lisp

books/bookvolbib
   Chee Keng Yap [Yap00], Chudnovsky and Jenks [CJ86], Eric Weisstein [Wein],
   David and Gregory Chudnovsky [Chu89], Jenks, [Jen69], Kaufmann [KMJ00],
   Linger [LMW79], Wester [Wes99]

src/algebra/Makefile automate making input files

src/doc
   axiom.sty collect all script commands in one place
   axiom.sty consolidate latex macros

src/input
   setcmd.input clean up broken tests

src/interp
   Makefile merge and remove fnewmeta

   apply, br-con, define, info, category, modemap, postprop  fix |special| bug
   vmlisp   fix |special| bug
   
   compiler, define, fnewmeta, g-boot, interp-proclaims, iterator, modemap, 
   parsing, postprop vmlisp treeshake compiler

   fnewmeta.lisp removed

   i-output.lisp remove droptrailingblanks

   parsing.lisp cleanup and reformat

   vmlisp.lisp comment out plist assignments
   vmlisp.lisp remove droptrailingblanks
   vmlisp.lisp rename some fnewmeta variables
   vmlisp.lisp rename variables to remove underscores
   
src/scripts/tex
   axiom.sty add defplist, usesstruct

src/doc
   axiom.sty add defplist, usesstruct

src/axiom-website/
   documentation.html add literate thinking quote

\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{sept2010}{releasenotes.ht}{September 2010 Release Notes}
\pagepic{ps/v71sept2010.eps}{sept2010}{0.60}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{sept2010}{September 2010 Release Notes}
\beginscroll
\begin{verbatim}
September 2010 Release

This release concentrated on treeshaking the compiler code into book volume 9.
Due to the complexity of this task it will take several releases to complete.

Additional global changes included collecting all of the Axiom-related
latex macros into axiom.sty and removing references to Aldor.

Makefile 
  always run help extractions in parallel
  build src/input quietly

books/bookvol0
   remove references to aldor

books/bookvol1
   remove references to aldor

books/bookvol5
   expose StreamTensor, U32Vector, U32VectorPolynomialOperations
   mark pure common lisp routines
   merge ptrop, varini
   move latex macros to axiom.sty
   remove POLYVEC
   remove compile, duplicated in vol9
   remove memq
   remove references to aldor
   treeshake
   remove $useNewParser

books/bookvol7.1
   move latex macros to axiom.sty
   remove references to aldor
   rewrite \pagehead to \pagetitle

books/bookvol9
   cross-reference functions and variables
   move latex macros to axiom.sty
   remove memq
   treeshake the compiler code
   remove $useNewParser

books/bookvol10
   move latex macros to axiom.sty
   move GOPT0 from bookvol10.3

books/bookvol10.1
   move latex macros to axiom.sty

books/bookvol10.2
   move latex macros to axiom.sty

books/bookvol10.3
   add U32Vector, move GOPT0 from bookvol10.4
   move latex macros to axiom.sty

books/bookvol10.4
   add StreamTensor, U32VectorPolynomialOperations
   fix ScriptTensor regression test
   move latex macros to axiom.sty
   remove POLYVEC
   update Chinese Remainder documentation

books/bookvol10.5
   move latex macros to axiom.sty

books/bookvolbib
   Parnas & Madey [PM95], Parnas & Jin [PJ10], GCL92, AS64, NIST10, RF94, 
   Hamdy [Ham04], Steele [Ste90], Tim Lahey's Sage Integration Test Suite

books/ps/
   v103guessoptionfunctions0, v103u32vector, v104streamtensor,
   v104u32vectorpolynomialoperations, v104u32vectorpolynomialoperations

src/algebra
   Makefile help and test for StreamTensor
   Makefile help and test for U32Vector
   Makefile remove references to aldor
   Makefile test and help for POLYVEC
   Makefile remove POLYVEC
   Makefile add help and test for new algebra
   Makefile handle case-insensitive MAC filesystem
   Makefile remove new algebra scaffolding code

src/doc
   axiom.sty collect all script commands in one place
   axiom.sty consolidate latex macros

src/input
   Makefile add guess.input, manuel.input, risch.input
   guess.input test examples of the GUESS package
   kamke3.input clean up broken tests
   manuel.input add Manuel's integral to test suite
   richlog300-391.input clean up broken tests
   richtrig800-899.input clean up broken tests
   risch.input illustrate the Risch algorithm
   setcmd.input clean up broken tests
   test.input clean up broken tests

src/interp
   Makefile merge varini
   Makefile remove nspadaux, mark, pspad1, pspad2, ptrop, wi1, wi2
   *.lisp remove memq
   treeshake compiler -- br-con, cattable, compiler
   remove nspadaux.lisp, mark.lisp, pspad1.lisp, pspad2.lisp, 
   remove ptrop.lisp, wi1.lisp, wi2.lisp
   add HTMLFormat code i-output.lisp, vmlisp.lisp

src/scripts/tex
   axiom.sty collect all script commands
   axiom.sty consolidate latex macros

src/axiom-website/
   documentation.html add Knuth quote per W. Sit
   download.html add debian, fedora, mandriva, opensuse, slackware, vector
   download.html update ubuntu yum advice



\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{july2010}{releasenotes.ht}{July 2010 Release Notes}
\pagepic{ps/v71july2010.eps}{july2010}{0.60}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{july2010}{July 2010 Release Notes}
\beginscroll
\begin{verbatim}
July 2010 Release

This release concentrated on the work of Albert Rich and his Rubi pattern
matching machinery. All of his integrals from his test suite were converted
to a regression test suite. This will form a baseline for the pattern work
in future releases. David Parnas has a table-based method of specifying
programs. Axiom is trying to synthesize this work with the pattern match
work to create pattern specifications using tables. Martin Baker added
HTML output to the system. Waldek Hebisch implemented the DoubleFloat
representation routines. Martin Rubey implemented Dirichlet.

The symbolic version of the fresnel integrals was added as well as a
numeric implementation of the fresnelC and fresnelS functions. The
output of these numeric functions were validated against Pearcy's tables,
with the comparison as part of the regression tests. Further work on
numeric approximation is ongoing and expected in the next release.

These people were added to the credits list:

  Albert D. Rich, David Parnas, Martin Baker

readme 
  update credits list

Makefile 
  add Mandriva
  fix environment variables
  segment test set choice from command line

books/axbook.tgz
  rewrite section 8.3.2 for current output

books/bookvol0
  rewrite section 8.3.2 for current output

books/bookvol10.2
  add fresnelS, fresnelC to LFCAT
  add test and help files for all categories

books/bookvol10.3
  add CDFMAT ComplexDoubleFloatMatrix
  add CDFVEC ComplexDoubleFloatVector
  add DIR Dirichlet
  add DFMAT DoubleFloatMatrix
  add DFVEC DoubleFloatVector
  add HTMLFORM HTMLFormat
  add fresnelS, fresnelC to EXPR

books/bookvol10.4
  add EXP3D Export3D
  add GDRAW  GnuDraw
  add fresnelC, fresnelS numeric computation to DFSFUN
  add fresnelS, fresnelC symbolics to LF, COMMONOP, LIMITPS

books/bookvol10.5
  start of numeric analysis of BLAS/LAPACK
  tighten array type declarations in BLAS
  use simple-array, not simple-vector type in BLAS

books/bookvol4
  document the Makefile build process

books/bookvol5
  change )version to include *build-version* info
  add macros to support algebra
  add Albert D. Rich, David Parnas, Martin Baker to credits

books/bookvol6
  fix deleted variable from axiom script
  remove AXIOMXLROOT reference

books/bookvol7.1
  document HTMLFormat

books/bookvol8
  add 3D graphic file format table

books/bookvolbib
  Adams [AL94], Brunelli [Bru09], Burcin [ES10], Dewar [Dew94], Golub [GL89], 
  Higham [Hig02], Householder [Hou81], Jenks [JT18], [JT18a], [JT18b], [JWS87],
  Lecerf [Le96], Losch [Los60], Luke [Luk169], [Luk269], Pearcey [Pea56], 
  Press [PTVF95], Taivalsaari [Tai96]

src/algebra/Makefile
  add help and test for new algebra
  handle case-insensitive MAC filesystem
  remove new algebra scaffolding code

src/doc/Makefile
  cleanly latex pure latex files

src/input/Makefile add TESTSET=notests
  add derivefail, exampleagcode, hyperell, paffexample, 
  rule-based algebraic integration, rule-based rational integration,
  rule-based exponential integration, rule-based hyper integration, 
  rule-based inverse hyperbolic integration, rule-based log integration,
  rule-based inverse trig integration, rule-based trig integration

zips
  remove aldor.20070901.tgz 

src/input
  derivefail, examplegcode, hyperell, monitortest, paffexample,
  richalgebraic000-099, richalgebraic100-199, richalgebraic200-299,
  richalgebraic300-399, richalgebraic400-461, richerror000-078,
  richexponential, richhyper000-099, richhyper100-199, richhyper100-199,
  richhyper1000-1098, richhyper200-299, richhyper300-399, 
  richhyper400-499, richhyper500-599, richhyper600-699, richhyper700-799, 
  richhyper800-899, richhyper900-999, richintfunc000-032, 
  richinvhyper000-099, richinvhyper100-199, richinvhyper200-296, 
  richinvtrig000-092, richlog000-099, richlog100-199, richlog200-299, 
  richlog300-391, richrational.input, richspecfunc000-022, 
  richtrig000-099, richtrig100-199, richtrig200-299, richtrig300-399,
  richtrig400-499, richtrig500-599, richtrig600-699, richtrig700-799, 
  richtrig800-899, richtrig900-920

src/interp
  i-output.lisp, vmlisp.lisp HTMLFormat support code

src/share/algebra/
  browse, category, compress, interp, operation, users daase updated
  remove libaldor.al

GCL was upgraded, thanks to Camm Maquire.
\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{may2010}{releasenotes.ht}{May 2010 Release Notes}
\pagepic{ps/v71may2010.eps}{may2010}{0.65}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{may2010}{May 2010 Release Notes}
\beginscroll
\begin{verbatim}
May 2010 Release

This release concentrated on adding new algebra.
A new package was added for factoring over finite fields.
A new volume Axiom Numerics was added, including BLAS and LAPACK in lisp.
A new volume Axiom Bibliography was added for literature citations.
GCL was upgraded, thanks to Camm Maquire.

These people were added to the credits list:

  Nelson H. F. Beebe, Gaetan Hache, Bill Hart, Kaj Laurson,
  Patrice Naudin, Claude Quitte, Steve Toleque

readme 
  update credits list

Makefile
  GCLVERSION gcl-2.6.8pre4 change
  clean books from src/algebra
  merge all fedoraN stanzas into fedora

books/Makefile
  add Axiom Bibliography book
  add bookvol10.5 add Axiom Algebra Numerics

books/bookvol4 Axiom Developers Guide
  document how to make graphs in algebra books
  document process to add new algebra
  document steps for adding algebra

books/bookvol5 Axiom Interpreter
  add Naudin, Laurson, Hache to credits
  change .spad.pamphlet to just .pamphlet
  Add new algebra to exposure list
  fix )describe to accept abbreviations

books/bookvol7.1 Axiom Hyperdoc Pages
  add mar2010 what's new page

books/bookvol10.2 Axiom Categories
  add AFSPCAT  AffineSpaceCategory
  add BLMETCT  BlowUpMethodCategory
  add DIVCAT   DivisorCategory
  add DSTRCAT  DesingTreeCategory
  add INFCLCT  InfinitlyClosePointCategory
  add LOCPOWC  LocalPowerSeriesCategory
  add PACEXTC  PseudoAlgebraicClosureOfAlgExtOfRationalNumberCategory
  add PACFFC   PseudoAlgebraicClosureOfFiniteFieldCategory
  add PACPERC  PseudoAlgebraicClosureOfPerfectFieldCategory
  add PACRATC  PseudoAlgebraicClosureOfRationalNumberCategory
  add PLACESC  PlacesCategory
  add PRSPCAT  ProjectiveSpaceCategory
  add SETCATD  SetCategoryWithDegree

books/bookvol10.3 Axiom Domains
  add AFFPL    AffinePlane
  add AFFPLPS  AffinePlaneOverPseudoAlgebraicClosureOfFiniteField
  add AFFSP    AffineSpace
  add BLHN     BlowUpWithHamburgerNoether
  add BLQT     BlowUpWithQuadTrans
  add DIV      Divisor
  add DSTREE   DesingTree
  add ICP      InfClsPt
  add INFCLSPS InfinitlyClosePointOverPseudoAlgebraicClosureOfFiniteField
  add INFCLSPT InfinitlyClosePoint
  add NSDPS    NeitherSparseOrDensePowerSeries
  add PACEXT   PseudoAlgebraicClosureOfAlgExtOfRationalNumber
  add PACOFF   PseudoAlgebraicClosureOfFiniteField
  add PACRAT   PseudoAlgebraicClosureOfRationalNumber
  add PLACES   Places
  add PLACESPS PlacesOverPseudoAlgebraicClosureOfFiniteField
  add PLCS     Plcs
  add PROJPL   ProjectivePlane
  add PROJPLPS ProjectivePlaneOverPseudoAlgebraicClosureOfFiniteField
  add PROJSP   ProjectiveSpace
  add UTSZ     UnivariateTaylorSeriesCZero
  document and test Interval

books/bookvol10.4 Axiom Packages
  add AFALGGRO AffineAlgebraicSetComputeWithGroebnerBasis
  add AFALGRES AffineAlgebraicSetComputeWithResultant
  add BLUPPACK BlowUpPackage
  add DTP      DesingTreePackage
  add FACTEXT  FactorisationOverPseudoAlgebraicClosureOfAlgExtOfRationalNumber
  add FACTRN   FactorisationOverPseudoAlgebraicClosureOfRationalNumber
  add FFFACTSE FiniteFieldFactorizationWithSizeParseBySideEffect
  add FFSQFR   FiniteFieldSquareFreeDecomposition
  add GPAFF    GeneralPackageForAlgebraicFunctionField
  add INTDIVP  IntersectionDivisorPackage
  add INTERGB  InterfaceGroebnerPackage
  add INTFRSP  InterpolateFormsPackage
  add LISYSER  LinearSystemFromPowerSeriesPackage
  add LOP      LinesOpPack
  add LPARSPT  LocalParametrizationOfSimplePointPackage
  add NPOLYGON NewtonPolygon
  add PAFF     PackageForAlgebraicFunctionField
  add PAFFFF   PackageForAlgebraicFunctionFieldOverFiniteField
  add PARAMP   ParametrizationPackage
  add PFORP    PackageForPoly
  add PLPKCRV  PolynomialPackageForCurve
  add PRJALGPK ProjectiveAlgebraicSetPackage
  add RFP      RootsFindingPackage

books/bookvol10.5 Axiom Numerics
  BLAS1 regress, help, and function documentation
  add BLAS1 dasum function
  add BLAS1 daxpy
  add BLAS1 dcopy

books/bookvolbib Axiom Bibliography
  Buh05 DLMF Mah05 Sei95 Seixx Sch92 SCC92 WJST90
  Du95, Ga95, Ha95, Ha96, HI96, HL95, LR88, St93
  add Assia Mahboubi [Mah05]
  add Soren L. Buhl [Buh05]
  add citation SDJ07
  rename and align biblio with bookvol10.1

faq 
  FAQ 52: Who was User?

lsp/Makefile.pamphlet
  GCLVERSION gcl-2.6.8pre4 

src/Makefile
  add Volume 10.5 Axiom Numerics
  change .spad.pamphlet to .pamphlet

src/algebra/Makefile 
  help and test files for all new algebra
  remove unused .as.pamphlet files
    axtimer.as, ffrac.as, herm.as, interval.as, invnode.as, 
    invrender.as, invtypes.as, invutils.as, iviews.as, 
    mlift.spad.jhd, ndftip.as, nepip.as, noptip.as, nqip.as,
    nrc.as, nsfip.as removed

src/input/Makefile 
  remove duplicate curl.input invocation
  add curry.input, davenport.input, liska.input, paff.input, zimmer.input
  fix biquat.input, chtheorem.input, chtheorem.input, cmds.input,
      complexfactor.input,dfloat.input, dftrig.input, dop.input,
      e1.input, ei.input, en.input, gamma.input, grpthry.input,
      gstbl.input, ico.input, numericgamma.input, test.input, 
      unit-i-funsel.input, unittest1.input, unittest1.input,
      unittest2.input, unittest2.input

src/interp/Makefile
  add Volume 10.5 Axiom Numerics

src/share/algebra
  update browse.daase, category.daase, compress.daase, users.daase,
         dependents.daase, interp.daase, libdb.text, operation.daase

zips
  gcl-2.6.8pre4.tgz added, fix for ubuntu 9.10
  gcl-2.6.8pre4.h.linux.defs.patch added
  gcl-2.6.8pre4.o.read.d.patch added
  gcl-2.6.8pre4.unixport.init_gcl.lsp.in.patch
  gcl-2.6.8pre4.unixport.makefile.patch

src/axiom-website/documentation.html 
  add Axiom Algebra Numerics
  literate programming quotes

src/axiom-website/download.html 
  add march 2010 ubuntu
  update available binary list

\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}

\pagetitle{mar2010}{releasenotes.ht}{March 2010 Release Notes}
\pagepic{ps/v71mar2010.eps}{mar2010}{0.75}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{mar2010}{March 2010 Release Notes}
\beginscroll
\begin{verbatim}
March 2010 Release

This release concentrated on treeshaking more code into the Interpreter
volume. Support for )set break quit was added. Additional documentation
was added for branch cuts and clifford algebras. The first draft of a
new volume (10.5) on Numerics was added. An example of unicode was tested
to fulfill the long-term goal of unicode I/O support. 

This release is an interim step in the process of merging the interpreter
source code into a single volume. Due to the size and complexity of the
task it will take several releases.

Three people were added to the credits list:
   John P. Fletcher <J.P.Fletcher@aston.ac.uk>
   Nathaniel Daly <nathaniel.daly@gmail.com
   Ted Kosan <ted.kosan@gmail.com>

The Axiom website was completely rewritten based on a new style css
provided by Nate. This change was also made to axiom-developer.com.

There is a new set option ")set break quit" per Ralf Hemmecke.
This will cause the interpreter to quit on failure. Documentation
was added to the books.

books/bookvol4 Axiom Developers Guide
   add )set break quit

books/bookvol5 Axiom Interpreter
   add )set break quit
   add support for IndexedBits
   begin documentation of macex
   merge and remove lisp files from src/interp
   remove non-common lisp macros
   rewrite to common lisp functions

books/bookvol7.1 Axiom Hyperdoc Pages
   add jan2010 what's new page
   books/ps/v71jan2010.eps added
   books/ps/v71releasenotes.eps updated for January 2010

books/bookvol8 Axiom Graphics
   redefine R1 in view3D for ARM processor

books/bookvol10 Axiom Algebra Implementation
   A new section on Elementary Functions branch cuts based on the
   Numerical Mathematics Consortium was added.

books/bookvol10.1 Axiom Algebra Theory
   A new chapter on the Clifford algebra was added.
   A quote on quaternions from Altman was added

books/bookvol10.3 Axiom Domains
   defstream function and KAFILE test bug fixed
   fix IndexedBits range error
   remove non-common lisp macros
   rewrite to common lisp functions

books/bookvol10.4 Axiom Packages
   add Ted Kosan to credits
   fix broken credit test

books/bookvol10.5 Axiom Numerics
   first draft of numerics volume

faq 
   FAQ 51: How can I do unicode in xterm?

src/algebra/Makefile 
   unit test IndexedBits

src/input/Makefile 
   add monitortest
   remove redundant kafile.input

src/input/
   cachedf.input     fix tests for )set break quit
   kafile.input      redundant with KAFILE test, removed
   monitortest.input unit test monitor code
   pmint.input       add comments
   pmint.input       update pmint with code
   setcmd.input      add )set break quit
   textfile.input    --I out failing test
   unittest2.input   add Nate Daly to credits
   wester.input      reformat into regression test file

src/interp
    remove compat.lisp, cparse.lisp, intint.lisp, macex.lisp,
           monitor.lisp, pf2sex.lisp, ptrees.lisp, serror.lisp

    remove MAKESTRING macro from all files

    remove non common lisp macros

    remove unused functions

    g-error.lisp add )set break quit
    htcheck.lisp add READLINE from compat.lisp
    nci.lisp pick up functions from intint
    patches.lisp move global variables to bookvol5
    posit.lisp move position functions to bookvol5
    util.lisp move global variables to bookvol5
    varini.lisp pick up functions from intint
    vmlisp.lisp add )set break quit
    vmlisp.lisp fix )set break resume bug
    vmlisp.lisp remove some define-functions

zips
   utf-8-demo.txt added to demo utf-8 I/O

\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}

\pagetitle{jan2010}{releasenotes.ht}{January 2010 Release Notes}
\pagepic{ps/v71jan2010.eps}{jan2010}{0.75}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{jan2010}{January 2010 Release Notes}
\beginscroll
\begin{verbatim}
January 2010 Release

This release concentrated on treeshaking more code into the Interpreter
volume. Ten files have been merged and removed. Call graphs were generated
for all C code and added to the documentation. Several new functions were
added, including flush, machineFraction, and integerDecode.

This release is an interim step in the process of merging the interpreter
source code into a single volume. Due to the size and complexity of the
task it will take several releases.

Volume 0: Jenks
  Lee Duhum fix typos

Volume 1: Tutorial
  Lee Duham fix typos

Volume 5: Interpreter
   )describe no longer needs cat, dom, pkg arg
   add Lee Duham to credits list
   add banner and cleanup globals
   add DoubleFloat trig macros
   support DFLOAT machineFraction, integerDecode
   do not set si::*system-directory* in restart
   fix )display all output bug
   merge fname.lisp, alql.lisp, i-syscmd, i-toplev, pathname.lisp
   merge daase.lisp, exposed.lsp

Volume 7: Hyperdoc
   add call graph for ex2ht, htadd, hthits, hypertex, spadbuf

Volume 8: Graphics
   add call graph for view2d, view3d, viewalone,  viewman

Volume 10.2 Categories
  latex cleanup
  FileCategory add flush 

Volume 10.3 Domains
  DoubleFloat add dfloat machineFraction, integerDecode
  DoubleFloat rewrite doublefloat to use typed macros
  File add flush

Volume 10.4 Packages
  document RepeatedSquaring
  fix API regression

lsp/Makefile add compiler::link per Camm Maguire

src/algebra
   remove exposed.lsp

src/axiom-website
   add fedora 10 nov2009 build
   add nov2009 builds
   move CVS instruction to git
   axbook add Stack and Queue
   axbook fix typos

src/input
   add ackerman to test function caching
   add dftrig to test DoubleFloat trig changes
   rewrite dfloat, dop, e1, ei, en, numericgamma using machineFraction
   r20bugs, setcmd, unittest1, unitest2 fix broken tests
   zimmbron fix typo in bibliography

src/interp
   remove alql, cformat, daase, fname, i-sysmcd, i-toplev, intfile,
          pathname, packtran

other src files
   add call graph information edible.c, asq.c
   src/doc/msgs/s2-us.msgs remove S2IZ0049D
   src/share/doc/msgs/s2-us.msgs removed 

\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{nov2009}{releasenotes.ht}{November 2009 Release Notes}
\pagepic{ps/v71nov2009.eps}{nov2009}{0.50}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{nov2009}{November 2009 Release Notes}
\beginscroll
\begin{verbatim}
Summary: November 2009 release

The major changes are:
   A new )describe command, boot language removal, and more motion
   toward a fully literate system.

The )describe command was added.

   The )describe function was added to Volume 5 (Interpreter)
   The )describe function was documented in Volume 2 (Users Guide)
   The Description field for the Categories, Domains, and Packages 
   were cleanup up and reformatted in Volumes 10.2 (Categories)
   10.3 (Domains) and 10.4 (Packages)
 

Boot Language removal

    All of the boot-converted lisp files were reformatted from their 
    compiler generated output. These files are being merged into
    Volume 5 (Interpreter) and Volume 9 (Compiler) as appropriate.
    This work will continue for the next few releases.

    All or portions of the following files were merged into 
    Volume 5 (Interpreter):
      astr, cstream.lisp, dq, incl, int-top, i-syscmd, msg, nci,
      obey, osyscmd, parini, patches, pile, scan

    The src/boot subdirectory is gone, including the files:
      Makefile, boot-proclaims, boothdr, bootload, btincl2, btpile2,
      btscan2, ccl-bootsys, ccl-depsys.lsp, exports.lisp, npextras, ptyout,
      tyextra, typars, typrops, tytree1, sys-pkg, vmlisp, ptrees, wi2

    The bootsys image is no longer part of the build process


Patch ports from Fricas and Open-Axiom

    The Tuples patch was picked up and applied.

    The SXHASH function is the hash default in SetCategory

    The function ListOfTerms was renamed to listOfTerms


Input file changes

    New input files have been added to show how to compute
    results using Axiom or to create regression tests for fixes:
      complexfactor, rubey, zimmbron, branchcut, cachedf, finitegraph,
      newtonlisp, nonlinhomodiffeq, distexpr, numericgamma, donsimple
      solveperf, tuplebug, unit-macro, testprob, unittest2

    lexp was removed and moved to the LEXP algebra file

    dop and gstbl had minor fixes

New Help files and Function examples were added

    There are new help files:
      describe, AlgebraicallyClosedField, RationalFunctionSum,
      RadicalSolvePackage, PartialFractionPackage, Product,
      OrderedFreeMonoid

Website update:

  The developer.html page was rewritten. An old Scratchpad group
  photo was added to the site.

  Work continues on re-hosting the axiom-developer.org domain.

  We now own axiom-developer.com and axiom-developer.net which will
  be retargetted to the new host as soon as it is available

Interpreter changes:

    Axiom will sit in a single package in the near future.
    The VMLISP package was partially removed from the system.
    Work continues on this path.

    The util.ht file is created earlier in the parallel build
    so there are fewer compiler messages about documentation.

Research:
 
    A Cohen algebra domain is being developed to enable symbolic
    manipulation of expressions with explanations and controlled
    simplification. 

\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{sept2009}{releasenotes.ht}{September 2009 Release Notes}
\pagepic{ps/v71sept2009.eps}{sept2009}{0.50}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{sept2009}{September 2009 Release Notes}
\beginscroll
\begin{verbatim}
September 26, 2009 Release Notes

A major project milestone has been achieved with this release.
Axiom is implemented in lisp, removing all code in Boot.

The major effort in this release has been the boot to lisp rewrite.
There are several follow-on phases which are "in-process" but only
partially complete with this release. These include:
  source cleanup - 
    generating warning-free compiles which involves cleaning up the
    boot-to-lisp artifacts
  generating unit tests
    unit tests are being developed for each of the translated files to
    ensure that the rewrite does not introduce bugs
  file merge
    the individual files are being prepared to merge into the interpreter
    and compiler volumes.
  global variable handling
    the system uses many globals which are being either explained or
    rewritten to reduce coupling
  data structure extraction
    the various data structures used by the compiler and interpreter 
    are being identified and explained
  API vs implementation 
    the functions used externally vs the functions used internally are 
    being identified
  code refactoring
    the generated lisp code is being rewritten into human form without
    changing the behavior

The target goal is to have the code cleanly merged into the interpreter
and compiler volumes in a logical way that form chapters related to function.

Additional changes in this release include:

  Add Steven Segletes to credits. He was the author of the paper that
  supplied the coefficients for computing E1. He has contributed a later,
  unpublished paper which has more accurate coefficients. This is in-plan
  to implement.

  Barry Trager contributed an example of computing Shannon Matrices.
  This has been added to the input/regression suite.

  The .dvi files for the interpreter are no longer being built. The
  individual pamphlets will shortly disappear.

  Debugsys is no longer built. I am the only user of it and I can build
  it when needed.

  Bootsys is no longer built. It is no longer needed.

  The Makefiles now use the := rather than = assignment limiting re-evals

  Parallel Make is now the default since the documentation build is now 
  independent of the interpreter build

\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{july2009}{releasenotes.ht}{July 2009 Release Notes}
\pagepic{ps/v71july2009.eps}{july2009}{0.50}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{july2009}{July 2009 Release Notes}
\beginscroll
\begin{verbatim}
July 2009 Release Notes

The syntactic conversion from the prior #1 form to the +-> form
is complete except for the GUESS package. Both forms still work
but the #1 form is discouraged.

All algebra files from src/algebra are now in books.

Work has concentrated on the hyperdoc browser. 
  * The browser files which get autoloaded into the interpreter were
    merged and removed in preparation for being rewritten into book form.
  * Glossary files were missing from the build and were added.

Work has started on a new CATS collection of verified algebraic identities,
the tpiezas set. See http://sites.google.com/site/tpiezas

Volume 5: Axiom Interpreter
  * set message autoload now defaults to off

Volume 7 Axiom Hyperdoc
  * htsearch moved to $AXIOM/bin

Volume 10.1 Axiom Algebra Theory
  * add chapter on quaternions

Volume 10.3 Domains
  * Any now has regression and help files
  * MathMLFormat domain moved from Volume 10.4
  * TexFormat has regression and help files
  * TexFormat fix for horizontal fractions
  * Quaternion was added from src/algebra

Volume 10.4 Packages
   * IntegerNumberTheoryFunctions fix divisors regression
   * Waldek's QUATCT2 algebra was added, including a help file, 
     regression tests and command examples.

Makefile 
  * make help files in parallel
  * make xhtml pages in parallel
  * make books documentation in parallel

interpreter
  * src/interp/i-output.boot fix horizontal fractions

axiom-website
  * download.html add mandriva
  * download.html add may2009 binaries

input files
  * ffdemo.input fix steps 27, 57 due to divisors change
  * numbers.input fix random zero failure
  * spline.input explain how to compute 2D splines
  * tpiezas001.input CATS tests of algebraic identities
  * tpiezas002.input CATS tests of algebraic identities

\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{may2009}{releasenotes.ht}{May 2009 Release Notes}
\pagepic{ps/v71may2009.eps}{may2009}{0.50}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{may2009}{May 2009 Release Notes}
\beginscroll
\begin{verbatim}
May 2009 Release Notes

Axiom now supports latex chunk syntax in pamphlets, thus
Axiom pamphlets can now be pure latex. 
Axiom can now read pamphlet files and extract latex chunks directly.
All input files were converted to the new format.

This change has several long term implications. Once all of the 
pamphlet files are pure latex we no longer need the NOWEAVE function.
Once Axiom can read all of its input formats, that is, )read and )compile
work directly on their pamphlet forms we will no longer need NOTANGLE.
At that point, we no longer need noweb.

This release sees the introduction of new domains and packages
as well as more documentation. The original Jenks books has been
modified to include new documentation, more help files were added,
and the )d op function documentation was expanded.

More effort has been applied to collecting interpreter and compiler
code into literate form in book volume 5.

A new effort to collect the compiler code into book volume 9 started.

The compiler was modified (by Waldek) to allow +-> in place of #1 syntax.
This conversion is nearly complete, with only a few packages remaining
to be converted. Lisp code to regression check the algebra changes was
written so the generated algebra is parsed and highlighted.

A method for running Axiom on Windows was developed and documented
on the home page of the website.

Unit testing of interpreter and compiler changes was added to the
regression testing. This will expand in future versions as changes
are made so ensure that things continue to function.

Volume 0: Axiom Jenks and Sutor
  Richard Jenks bio was added

  Section 9: Examples of Domains and Packages expanded
     ApplicationProgramInterface (API) 
     Dequeue (DEQUEUE) 
     EuclideanGroebnerBasisPackage
     GeneralDistributedMultivariatePolynomial
     GroebnerPackage
     HomogeneousDistributedMultivariatePolynomial
     NottinghamGroup
     Permutation
     RealSolvePackage
     TwoDimensionalViewport

  Cross references were fixed

  More spelling typo fixes

Volume 4: Axiom Developers Guide
  A section was added explaining how to find anonymous function signatures

Volume 5: Axiom Interpreter
  Michael Becker was added to the credit list

  )set debug is now a new top level command to collect all of
  the developer-level commands to enable/disable internal messages
  and tracing functions.

  \defunsec macro was added to handle section titles with docstrings

  More interpreter code was moved from other files into this book

  All regression test numbering was fixed to conform to the new,
  stronger regression test. Thus --S requires the "of NN" phrase
  or a FAILED message will be raised.

  The compiler root was moved to volume 9: Axiom Compiler

Volume 7: Axiom Hyperdoc
  Fixup verbatim breakage

Volume 7.1: Axiom Hyperdoc Pages
  Update What's New for March 2009

Volume 9: Axiom Compiler
  The compiler code is being collected from other parts of the
  system into this book. In particular, 
    The root functions for the compiler were added
    The top level loop code of the compiler was added
    The next layer of compiler code was added

Volume 10.2: Axiom Algebra Categories
  There was a general change to allow +-> syntax in algebra and
  this was made to all existing categories

  MatrixCategory now has regression test cases, a help page, 
  and )d op function examples

  Document binomial category

Volume 10.3: Axiom Algebra Domains
  There was a general change to allow +-> syntax in algebra and
  this was made to all existing domains

  SparseMultivariateTaylorSeries now has regression test cases, a help page, 
  and )d op function examples

  Permutation now has regression test cases, a help page, 
  and )d op function examples

  The regression tests now conform to the new, stronger 
  regression test requirements

Volume 10.4: Axiom Algebra Packages
  There was a general change to allow +-> syntax in algebra and
  this was made to some existing packages. There is more to be done.

  Bezier package was added, including regression test cases, a help page, 
  and )d op function examples

  CombiniatorialFunction now has regression test cases, a help page, 
  and )d op function examples

  ElementaryFunction now has regression test cases, a help page, 
  and )d op function examples

  IntegerCombinatoricFunctions now has regression test cases, a help page, 
  and )d op function examples

  LazardSetSolvingPackage now has regression test cases, a help page, 
  and )d op function examples

  The regression tests now conform to the new, stronger 
  regression test requirements

Volume 12: Axiom Crystal
  Add Gelernter's observations on Layout and Linking

Bug fixes
   7191: set *system-directory* dynamically     (20090413.03.tpd.patch)
   7192: )edit now works because SPADEDIT added (20090414.02.tpd.patch)
   7197: fix hyperdoc/graphics failure          (20090530.01.tpd.patch)

Makefile changes
  Top Level Makfile
    The BOOKS environment shell variable was added to ENV
    Makefile.slackware chunk exists 
    Makefile reports regression failures after builds

  lsp/Makefile 
    Build tangle into the lisp image

  src/Makefile 
    Copy bookvol9, the compiler,  to src/interp at build time

  src/algebra/Makefile 
    Add Bezier package
    Add LazardSetSolvingPackage.help
    Add MatrixCategory.input, .help
    Add help, regress for ElementaryFunction
    Add input, help, examples for SparseMultivariateTaylorSeries
    Fix LazardSetSolvingPackage typo
    Move egrep to grep -E since egrep might not be installed
    Move help to bookvol5

  src/doc/Makefile 
    Move help to bookvol5

  src/input/Makefile 
    Add FRAC regression test
    Add unittest* files for regression testing non-algebra changes
    Change input files to latex tangle
    Fix regress format to conform to the new, improved regression testing

  src/interp/Makefile 
    Build bookvol9, the compiler from book sources
    The old gclweb code was rewritten into tangle.lisp, gclweb was removed
    Move help to bookvol5
    More interpreter code was moved to bookvol5, the interpreter
    Debugsys has been updated to stop loading deleted files
    Several files were merged, rewritten, and removed:
      apply.boot, bootlex.lisp, comp.lisp, compiler.boot, cstream.boot,
      def.lisp, i-util.boot, incl.boot, int-top.boot, metalex.lisp, 
      nci.lisp, parse.boot, parsing.lisp, postpar.boot, preparse.lisp, 
      server.boot, setq.lisp, sockio.lisp, spad.lisp, spaderror.lisp, 
      util.lisp, vmlisp.lisp

faq
  faq 50: Cannot find libXpm.a

readme 
  Add Michael Becker to credit list

books/
  tangle.lisp lisp version of tangle command
  ps/v71mar2009.ps hypertex march 2009 release notes pic
  ps/v71releasenotes.ps hypertex what's new page pic


src/interp
  Rewrite apply.boot to apply.lisp
  Regression tests, regress.lisp, now checks for the "of NN" phrase

src/algebra
  Add Bezier package to exposed.lsp

src/axiom-website
  Add March 2009 column
  Add slackware column
  Axiom on Windows as html instructions
  Add March release notes
  Add binaries

src/doc/
  Add chunk environment to axiom.sty
  Old book sources were removed
  The spadhelp file was removed and added to the interpreter book

src/input/
  All of the .input files were modified to use latex tangle

src/scripts/tex/
  axiom.sty contains new latex macros

zips
  Old GCL versions were removed
    gcl-2.6.8pre.tgz removed
    gcl-2.6.7.tgz removed

\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{mar2009}{releasenotes.ht}{March 2009 Release Notes}
\pagepic{ps/v71mar2009.eps}{mar2009}{1.50}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{mar2009}{March 2009 Release Notes}
\beginscroll
\begin{verbatim}
March 2009 Release Notes

There were two major changes in this release.

First is the completion of the first phase of Book Volume 10.4: Axiom
Packages, which collects all of the packages into one document. The
side effect is to remove almost all of the remaining algebra files
leaving src/algebra nearly empty.

Second is the start of Book Volume 5: Axiom Interpreter which will
consolidate all of the interpreter functions and document them in
book form. A side effect of this consolidation will be the ultimate
removal of all boot code, with the further side effect of removing
bootsys from the build step and boot translation time.

While consolidating the interpreter code a parallel effort will be
ongoing to build Book Volume 9: Axiom Compiler. The idea is to split
the compiler code from the interpreter code so the compiler can be
documented and upgraded.

Book Volume 0: Axiom Jenks book
  Add )include documentation

    The original book did not document the )include command. This is
    now documented.

  Add UnivariateSkewPolynomial

    This domain was added to the domain examples 

Book Volume 4: Axiom Developers Guide
  Hyperdoc

    A Hyperdoc tutorial on making new pages was written

    A tutorial on spadhelp was added

Book Volume 5: Axiom Interpreter
  Command Handling
    
    The top level commands that start with open parenthesis are all
    kept in the $setOptions data structure. This structure was documented.
    Each command has a handler routine which was integrated with the
    structure in the proper place. 

  New latex macros

    The \defun and \defmacro macros were added to ensure that
    there is a uniform handling of subsections and cross references
    for all functions and macros.

    The \defdollar macro was added to handle $foo variables in
    both index and cross reference.

    The \cmdhead macro was added to provide uniform handling of
    each of the top level commands in the $setOptions data structure

  Unit testing

    To ensure that changes did not break behavior two new regression
    test routines were added, unittest1 and setcmd. These test the
    top level command behavior.

  Trace functions added

    The trace.boot code was added. 

Book Volume 7: Axiom Hyperdoc
  Documentation

    Add Scott Morrison's original hypertex plan notes

Book Volume 10.1: Axiom Algebra Theory
  Documentation

    Add tutorial chapter on Singular Value Decomposition

Book Volume 10.3 Axiom Domains
  Algebra fixes

    Johannes Grabmeier fixed the outputFixed behavior in Float.

    A regression test chunk was added to the Float domain.

    UnivariateSkewPolynomial was documented. A regression test,
    help file, and examples were added.

    Heap was documented. A regression test, help file, and 
    examples were added.

    Dequeue was documented. A regression test, help file, and 
    examples were added.

    Queue was documented. A regression test, help file, and 
    examples were added.

    ArrayStack was documented. A regression test, help file, and 
    examples were added.

    Stack was documented. A regression test, help file, and 
    examples were added.

    NottinghamGroup was added, including regression and help files.
    Originally written by Martin Rubey.

  Regression tests

    The )sys rm now uses the -f flag to force deletion on all
    regression test files

Book Volume 10.4 Axiom Packages
  New Algebra

    All packages were moved into this volume. Almost all of the
    remaining algebra files were deleted.

    ApplicationProgramInterface (API) was added. It exposes the
    Axiom internal functions at the algebra level.

    UnivariateSkewPolynomial now has help, input, and examples

  Documentation

    The nag man pages were added to the related domain documentation

    Export lists were added for all packages.

  Regression tests

    The )sys rm now uses the -f flag to force deletion on all regression
    test files.

Boot to Lisp rewrite
  Deleted boot files

    setvars.boot is gone. The code has been rewritten and added to
    book volume 5. The code was rewritten and/or reformatted. All
    compile-time warnings were eliminated.

    setvart.boot is gone. The code has been rewritten and added to
    book volume 5. The code was rewritten and/or reformatted. All
    compile-time warnings were eliminated.

    trace.boot is gone. The code has been rewritten and added to
    book volume 5. The code was rewritten and/or reformatted. All 
    compile-time warnings were eliminated.

Regression test 
  cleanup
    )set break resume

     A subtle bug in regression testing caused by early exit of a
     test left some of the regression tests reporting success when
     there should have been failure. This was fixed by adding a
     )set break resume command to allow Axiom to continue the testing
     in the presence of an internal fault.

  new

     setcmd.input was added to regression test changes to the )set
     top level command
   
     unittest1.input was added to regresstion test other top level
     commands

     dop.input was added to unit test )d op example output

     frame.input was added to unit test frame handling

  removed

     bags.input was distributed among the algebra regression test
     files and bags.input was removed.

Bug fixes

  Bug 7183. The library handling code was repaired. Functions which do
  not exist were removed (e.g. input-libraries). The element values of
  the data structure are now pathnames.

  Bug 7182. )set mes auto did not indicate the current value. 

  Bug 7180: )set compiler input add foo triggers a call to open-library
  which was a CCL function and no longer implemented. The elements of
  the data structure were changed.  

  Bug 7179. Suprious sensitivity to )abb in documentation caused
  breakage because this was assumed to be an )abbreviation command.

  Bug 7178. Missing function inspect in ArrayStack

  Bug 7177. Missing function map! in ArrayStack

  Bug 7176. Missing function parts in ArrayStack

  Bug 7175. Missing function map in ArrayStack

  Bug 7174. Missing function map! in Stack

  Bug 7173. Missing function parts in Stack

  Bug 7172. map was missing from Stack(Integer)

  Bug 7170: )d op output failure due to X in algebra comments. The X
  symbol is now a marker for )d op examples and the use of X in comments
  is ambiguous.

  Bug 7141: )cd relative does not work

Interpreter (src/interp)
  Documentation

    document mmCost calculation

Help files
  Documentation

    The help file list is now dynamically generated from the algebra
    books.

readme
  Quote

    Add Doron Zeilberger quote about builders of CA systems.

Website
  Download

    Add fedora10 as a supported platform

    Add vector as a supported platform

Lisp 
  New patch

    read-char-no-hang was changed by Camm to ignore newlines but 
    Axiom's browser needs them to be recognized. A patch was added
    to back out Camm's change.

\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{jan2009}{releasenotes.ht}{January 2009 Release Notes}
\pagepic{ps/v71jan2009.eps}{jan2009}{0.50}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{jan2009}{January 2009 Release Notes}
\beginscroll
\begin{verbatim}
January 2009 Release Notes

One major theme of this release was restructuring the system
to move all domains to literate form in book volume 10.3

A second major theme was the first Axiom youtube tutorial video.



Book Volume 0: Axiom Reference

  Remove obsolete references to SmallFloat

Book Volume 1: Axiom Tutorial

  Remove obsolete references to SmallFloat

Book Volume 4: Axiom Developers Guide

  Add section on generating graphviz graphs

Book Volume 7.1: Axiom Hyperdoc

  Give a complete path to htadd

Book Volume 10.3 Axiom Domains

  All domains have been removed from the algebra subdirectory 
  and are now in literate form in book volume 10.3. Some
  domains include a help file, a regression test suite, and
  --X function examples for the )display command. Future work
  will extend this set.

  Each domain has a fully indexed list of functions exported.
  This allows hyperlinked access to functions.

  Each domain includes a graph segment that shows the list of
  categories, domains, and packages that provide immediate
  support in the prior build layer.

  Each domain includes a dotabb chunk which contains the
  source code necessary to recreate the graph.

  Domains which were associated with other domains in the same
  original spad file have hyperlinks to connect them.
  

Book Volume 11: Axiom Browser

  Lighten Bayou theme background image

Axiom Website (src/axiom-website)
  
  The axiom website is now under git control.
  The source tree is in src/axiom-website in the distribution.

  The build order graph exists. It contains a graph of all the
  constraints for each level. A line in the graph connects each
  category, domain, and package to every category, domain, and
  package in the prior layer that is required for the build.
  Multilayer constraints are not shown (although the data is
  in src/algebra/Makefile chunks) because the graph would be 
  too complex. 
    http://axiom-developer.org/axiom-website/hp.svg

  The Computer Algebra Test Suite (CATS) has a new test suite
  for ordinary differential equations (kamke*)
    http://axiom-developer.org/axiom-website/CATS

  The Ubuntu download now advises XTerm*metaSendsEscape: true
  due to misconfiguration of the meta key in emacs.
    http://axiom-developer.org/axiom-website/documentation.html

  A new binary for vector linux was added
    http://axiom-developer.org/axiom-website/download.html

  A new binary for doyen thumbdrive was added
  (work by Jose Alfredo Portes)
    http://axiom-developer.org/axiom-website/download.html

  The screenshots were recreated so the sources would be available.
  for matrixinmatrix.jpg, heatequation.jpg, axiomfirefox.jpg
    http://axiom-developer.org/axiom-website/screenshots.html

  The Axiom Information Sources video page was added, including
  a link to the youtube video, a local copy, and the supporting PDF.
    http://axiom-developer.org/axiom-website/videos.html

  A broken link to Book Volume 0: Axiom Reference was fixed.


Algebra (src/algebra)

  All domains were removed from spad files and moved to 
  Book Volume 10.3 Axiom Domains

  The Makefile now contains the information necessary to
  construct the build order graph as literate chunks.

  The layers were restructured. Files were moved to ensure
  that each file was at its lowest possible layer.

  The Guess package was added. However, due to nonstandard
  package files the guess function does not yet work properly.
  These packages are being rewritten.

  The Guess package has circular references. A new clique
  mechanism was added to the Makefile to handle this.

  Automatic regression test files associated with the algebra
  sources were reviewed for conforming to regression standards.

  integer.spad was reverted to remove an algebra change that
  causes a regression (cherry picked from Fricas in 2007)

Interpreter (src/interp)

  Tim Lahey added to )credits
  Karl Hegbloom added to )credits

  htcheck.boot moves util.ht to the mnt/doc directory

  setq.lisp no longer had redundant release data information
 
  nrunfast.boot Float has exp : Float -> Float now works
  This change was cherry-picked from Fricas.


Testing (src/input)

  All regression test files were reviewed and cleaned to
  conform to a standard setup.

  A parallel build race condition was fixed in the Makefile

  xpbwpoly.input was removed as it is now associated with
  its source domain and automatically generated.

  hyperbolicrules.input was added

  Tim Lahey submitted a fix for bugs in schaum17.input

  A cherry-picked patch from Fricas in 2007 was removed
  because it causes an algebra regression. The regression
  test file was corrected.

  fixed.input was converted to a regression test file


Build process

  The lsp/Makefile was updated for GCL pre3 patches

  An ubuntu64 chunk was added as a system target

  src/Makefile outputs util.ht before compiles (bug 7146)

  books/Makefile uses bash SHELL to fix echo behavior.
  The standard sh echo behaves badly.

  books/Makefile now has amssymb in preamble for toc.tex


GCL (zips)

  Axiom now includes GCL pre3, the latest snapshot of GCL.
  This can be chosen as an option for building in the top
  level Makefile.pamphlet

  The lsp/Makefile was updated for GCL pre3 patches

faq

  FAQ 49: How do I get the lastest GCL?

readme

  Tim Lahey added
  Karl Hegbloom added

  The date information for releases was removed as it is
  available elsewhere

  A John Gorka quote was added:
  "What matters the most is what you do for free" -- John Gorka


Wikipedia

  http://en.wikipedia.org/wiki/Axiom_computer_algebra_system

  Add information about Documentation

  Add link to youtube video
    http://www.youtube.com/watch?v=CV8y3UrpadY

  New screenshots were added


Youtube

  Axiom Information Sources video was created and uploaded
    http://www.youtube.com/watch?v=CV8y3UrpadY
  To date there have been 498 views


Launchpad

  Gain administrative access to launchpad.net for Axiom (Page)
    https://launchpad.net/axiom
 
\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{nov2008}{releasenotes.ht}{November 23, 2008 Release Notes}
\pagepic{ps/v71nov2008.eps}{nov2008}{0.50}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{nov2008}{November 23, 2008 Release Notes}
\beginscroll
\begin{verbatim}
November 2008 Release Notes

Axiom website

New patch tracking has been added:
   * <http://axiom-developer.org/axiom-website/patches.html>

Volumes have been significantly updated:
   * <http://axiom-developer.org/axiom-website/bookvol10.2.pdf>
   * <http://axiom-developer.org/axiom-website/bookvol10.3.pdf>

Book Volume 10.2 Axiom Categories completed

   The effort here is to create fully indexed, cross-referenced,
   graphical documentation for Axiom categories in a standalone
   form. This is a "live" literate document which contains the 
   actual source code used to build the system.

   * <http://axiom-developer.org/axiom-website/bookvol10.2.pdf>

Book Volume 10.3 Axiom Domains started

   This volume will contain the Axiom domains.

   * <http://axiom-developer.org/axiom-website/bookvol10.3.pdf>

Rosetta documentation

   Fix the Magnus URL

Input Files

   There is a new effort to automatically extract the algebra
   examples in order to regression test the user API to the
   algebra. In addition there is ongoing test work.

* New input files (Jakubi, Maltey, Rubey, Page, Daly}
     dhmatrix, reclos2
* Changed input files (Hebisch, Daly)
     sae, r20bugs

Build changes

* Testing is now run in parallel
 
\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{sept2008}{releasenotes.ht}{September 23, 2008 Release Notes}
\pagepic{ps/v71sept2008.eps}{sept2008}{0.50}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{sept2008}{September 23, 2008 Release Notes}
\beginscroll
\begin{verbatim}
September 2008 Release Notes

Axiom website
   The effort here is to improve the support for offline literate
   documentation. The primary changes are the inclusion of graphs
   and additional book volumes.

* <http://axiom-developer.org/axiom-website/documentation.html>
  Contains the new algebra volumes and subvolumes.
* <http://axiom-developer.org/axiom-website/bookvol10.2abb.html>
  Contains a "clickable" graph that indexes into the algebra.




Graphviz, PDF, and HTML integration
   The effort here is to unify these three technologies in a way
   that simplifies the user interface and improves documentation

* Graphviz is used if available but not required
* Algebra graphs are automatically generated at build time
  from algebra source files
* Graphviz graphs now properly hyperlink into PDF files allowing
  any node in a graph to link to any document page




Book volume 0 (Jenks and Sutor)

* <http://axiom-developer.org/axiom-website/bookvol0.pdf>
* replace \over with \frac



Book volume 7.1 (Hyperdoc pages)
   The effort here is to create a literate document that contains
   all of the "live" pages used in hyperdoc. The PDF is being
   constructed so that a user can effectively "browse" the static
   hyperdoc pages, which are included, without a running Axiom.

* <http://axiom-developer.org/axiom-website/bookvol7.1.pdf>
* The source for all of the pages is now contained in this book.
* Hyperdoc now fetches the pages directly from the book.
* The hyper page directory and all files are gone.
* Some of the static page images are now inside the PDF
* Pages have href links allowing "in-pdf" navigation of pages




Book volume 10 (Algebra)
   The effort here is to create a way to describe and deeply
   document the algebra. This volume was split to better handle
   the structure of Axiom's information. 

* Split into 5 volumes
   - 10   Implementation
   - 10.1 Theory
   - 10.2 Categories
   - 10.3 Domains
   - 10.4 Packages




Book volume 10.2 (Algebra Categories)
   The effort here is to create fully indexed, cross-referenced,
   graphical documentation for Axiom categories in a standalone
   form. This is a "live" literate document which contains the 
   actual source code used to build the system.

* <http://axiom-developer.org/axiom-website/bookvol10.2.pdf>
* Contains 60 categories so far
* Has partial graphs for each category
* Has list of exported functions 
* Has information about source of functions
* Has index cross reference by function and category
* Has PDF href links so that URLs work:
   <http://axiom-developer.org/axiom-website/bookvol10.2.pdf#nameddest=AGG>
* Has forward/backward links between categories
* Automatically generates "clickable" graphs:
   <http://axiom-developer.org/axiom-website/bookvol10.2abb.html>
* Graph clicking automatically opens to the proper source code




New algebra examples (Daly, Tsikas)
   The effort here is to create "real time" documentation that
   gives the end user an example of how to construct the proper
   arguments and call a function. This puts examples into the
   system so users don't need to consult other documents.

* )d op someop shows examples of function usage
* about 100 new function examples were added 
* new comment syntax added to allow automatic API testing




Input Files
   There is a new effort to automatically extract the algebra
   examples in order to regression test the user API to the
   algebra. In addition there is ongoing test work.

* New input files (Hemmecke, Stumbo, Cyganski, Daly)
     bini, biquat, ifthenelse, liu, overload, sqrt3, typetower
* Changed input files (Hemmecke, Stumbo, Cyganski, Daly)
     bern, function, linalg, regset, test, tutchap2




Build changes

* graphics does not depend on compress, done at build time
* firefox html pages are now built before tests are run



Algebra changes

* FLAGG (FiniteLinearAggregate) -- removed a duplicate function



Interpreter changes (Page)

* add cost function to bottomUp output



 
\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{july2008}{releasenotes.ht}{July 23, 2008 Release Notes}
\pagepic{ps/v71july2008.eps}{july2008}{0.50}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{july2008}{July 23, 2008 Release Notes}
\beginscroll
\begin{verbatim}
The July 2008 release marks the second large-scale change toward a
literate Axiom distribution. The original change was to make every
file into a pamphlet document. This second change draws Axiom into
tighter collections, called books (for obvious reasons). 

There is a new "books" directory which contains 14 books, most of
which are new:

 bookvol0:  The reconstructed Jenks and Sutor book
 bookvol1:  The published tutorial volume
 bookvol2:  Users Guide
 bookvol3:  Programmers Guide
 bookvol4:  Developers Guide
 bookvol5:  Interpreter
 bookvol6:  Command
 bookvol7:  Hyperdoc
 bookvol7.1 Hyperdoc Pages
 bookvol8:  Graphics
 bookvol9:  Compiler
 bookvol10: Algebra
 bookvol11: Browser
 bookvol12: Crystal

All of these books now exist. Portions of the current system have
been moved completely into book form (Graphics and Hyperdoc) so
the old files have been removed from the src tree. Both Graphics
and Hyperdoc are now built directly from their book. Work will 
follow on other parts of the system.

These books are online at:
<http://axiom.axiom-developer.org/axiom-website/documentation.html>




There is an interesting side-effect of using literate technology.
Once you combine C and .h files into a single document so that each
file is a separate chunk it becomes obvious that there is no need for
local include files. The lines that read:
   #include "foo.h"
become
   begin{chunk}{foo.h}
and get expanded inline. Once you do this it also becomes obvious
that many include files get included multiple times (a clear waste
of disk I/O and preparser time). Further it becomes clear that there
is no need for creating tiny .o files since all of the source can
be combined into one C file using chunks. 

These approaches were used to reduce the compile-time overhead
for both the graphics and the hyperdoc functions.




In addition to consolidating the source files for Graphics into
bookvol8 there were several other changes.

  * the functions for graphics, that is, viewman, view2d, view3d
    and viewalone are now built as single C files. 
  * the graphics code was reorganized into chapters of related code
  * there is the beginnings of documentation
  * there is the beginnings of a test suite based on the 
    CRC Handbook of Curves and Surfaces
  * the book is hyperlinked (Bill Page, Frederic Lehobey, Anatoly Raportirenko)
  * redundant code was eliminated
  * the code is fully indexed
  * the src/graph subdirectory is gone



In addition to consolidating the source files for Hyperdoc into
bookvol7 there were several other changes.

  * the functions for hyperdoc, that is, spadbuf, ex2ht, htadd, hthits
    and hypertex are now built as single C files
  * the hyperdoc code was reorganized into chapters of related code
  * there is the beginnngs of documentation
  * redundant code was eliminated
  * scroll wheel handling was added (Gregory Vanuxem)
  * the book is hyperlinked (Bill Page, Frederic Lehobey, Anatoly Raportirenko)
  * the code is fully indexed
  * )hd now works to start or restart Hyperdoc (Jose Alfredo Portes)
  * the src/hyper subdirectory is gone



In addition to consolidating the hyperdoc pages into bookvol7.1
there were several other changes:

  * the pages are hyperlinked
  * new latex macros were written to simplify page handling
  * images of hyperdoc pages were added
  * forward and backward hyperlinks between pages images works
    making it possible to "browse" the hyperdoc pages using only
    the single PDF file (Bill Page, Frederic Lehobey, Anatoly Raportirenko)
  * the pages are fully indexed
  * the src/hyper/pages subdirectory is gone



A combined table of contents PDF is now automatically generated
which covers all of the volumes. This makes it easier to find the
topic of interest.


In addition there were several other changes.

  * Some fixes were made for different platforms
       In particular, Fedora9 breaks the build and needs work

  * The configure script was replaced by instructions
       The standard (export AXIOM) works everywhere so the configure
       script is useless for guessing.

  * the FAQ was updated about git
       Since the May 2008 release the primary Gold source code platform
       is github. The FAQ was updated to reflect this.

  * the FAQ was updated about X11
       X11 has moved yet again so more notes are needed

  * move axbook to books
       The hyperlinked version of Jenks is now built from the books dir

  * add Ralf Hemmecke's documentation to ax.boot
  * add Monoid multiply to DirectProduct (Ralf Hemmecke)
  * add Monoid multiply regression test

\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{may2008}{releasenotes.ht}{May 27, 2008 Release Notes}
\pagepic{ps/v71may2008.eps}{may2008}{0.50}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{may2008}{May 27, 2008 Release Notes}
\beginscroll
\begin{verbatim}

COMPUTER ALGEBRA TEST SUITE

A large part of the effort for these two months has involved detailed
test cases of Axiom's integration routines against Schaum's Handbook
of Mathematical Formulas. Of the 619 integrals, the detailed results are:

419 Schaums and Axiom agree
137 No closed form solution
 60 Cannot simplify

  2 Typos found in Schaums
  1 Axiom bug

The Axiom bug was in src/algebra/intef.spad.pamphlet. There was a
fix applied to this code for a previously identified bug but the
previous fix was incorrect.

In addition, there were
 src/input/danzwill2.input.pamphlet added for the MIT Integration tests
 src/inputmapleok.input.pamphlet to fix typos
 src/input/kamke1.input.pamphlet had ode97 removed due to running time
 src/input/kamke2.input.pamphlet ode104, ode105 removed for running time

DOCUMENTATION
	Max Tegmark's 'toe' diagram, src/doc/toe.gif

PORTING
        GCLOPTS-CUSTRELOC disable-locbfd for MACOSXPPC

\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{march2008}{releasenotes.ht}{March 25, 2008 Release Notes}
\pagepic{ps/v71march2008.eps}{march2008}{0.50}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{march2008}{March 25, 2008 Release Notes}
\beginscroll
\begin{verbatim}

Summary: March 2008 release

Axiom is now available at github, a git-based code repository.
This site will have the Gold version of Axiom, that is, only
code that changes at each two-month release. To get a clone type:

   git-clone git://github.com/daly/axiom.git


USER VISIBLE CHANGES

  One primary focus of this release has been extending the Firefox
  toward being a full Axiom user interface (as opposed to a simple
  hyperdoc replacement). The Firefox console page has new, AJAX
  based, dropdown menus which are planned to be dynamically updated
  to display available functions for the last computed type. This 
  should make it much easier to find the applicable functions by
  category and type. They are currently static in this release.

* Firefox Pages

 o Dropdown menus were added to the Axiom console page
 o More hyperdoc pages were translated to Firefox/html
 o Bitmaps and graphics are now properly handled in pages
 o A minor mathml fix was applied (for invisible times)

* Refcard

 o An Axiom reference card of Axiom commands was created (src/doc/refcard)

* Examples

 o It is often difficult to figure the exact arguments required to call
   any given function in Axiom. The )display operation command used to
   only show the available modemaps. This command has now been changed.
    )display operation foo
   now shows examples of function calls for foo.

* Help

 o The plot routines have new help files and documentation

PORTING

 o Axiom was ported to MAC-OSX

 o The binary download page now has binaries for 
   Ubuntu, OpenSUsE, Redhat9, Redhat72, Debian, MACOSX at 
    <http://axiom.axiom-developer.org/axiom-website/download.html>

 o Binaries for the this release will be available shortly.


INTERNALS

* Compiler changes
 o  hashtables were used to speed up compiles

* Algebra changes
 o  There are new special functions, Ei,En,Ei1,Ei2,Ei3,Ei4,Ei5,Ei6
 o  The prime and BasicSieve functions are faster
 o  The Brent/Pollard algorithm was documented
 o  Bad gcd reductions are checked (heugcd regression test file added)
 o  The plot routines have new help files and documentation

* Makefile changes
 o  Bi-capital SVN copies are no longer made

* Interpreter changes
 o  Book Volume 5 has new documentation on the display function
 o  The display function code has been translated and moved to book volume 5
 o  PI has a higher internal precision
 o  Mappings are now properly hashed for Aldor

CATS (Computer Algebra Test Suite)

 o The differential equations regression tests are being checked against
   Mathematica, Maple, and Maxima. This has happended for the kamke2.input
   regression test file and will happen for the other regression tests.

o  Complex Gamma, logGamma, and log(Gamma) have additional tests and
   documentation. 

\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{january2008}{releasenotes.ht}{January 25, 2008 Release Notes}
\pagepic{ps/v71january2008.eps}{january2008}{0.50}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{january2008}{January 25, 2008 Release Notes}
\beginscroll
\begin{verbatim}

Summary: January 2008 release

There have been two major concentrations of effort in this release.

The first concentration is on the new Firefox Hyperdoc and the
second concentration was the verification of Axiom against
published standards.




Firefox Hyperdoc

The Firefox Hyperdoc has been integrated with the rest of the
interpreter. The new )browse command causes Axiom to listen and
serve hyperdoc pages on port 8085. 

The interpreter was changed to add the )browse command. As a 
side-effect new documentation was added to the interpreter
volume (bookvol5) to explain top-level command handling. In
addition, lisp and boot code was rewritten as part of the
literate change.

New sections were added to cover the beginning of the Computer
Algebra Test Suite (CATS) subsection which brings a focus on
compliance with published standards.

Arthur Ralf's mathml-enabled version of the Jenks book is fully
integrated into the Firefox Hyperdoc. Arthur also fixed some
rendering and ambiguity issues.

  axbook.tgz              fix the user/group settings
  axserver.spad           fix lastType output re: errors
  bookvol5                browse and top-level command handling 
  bookvol11               add standards compliance for gamma
  gammacomplexinverse.png added
  gammacomplex.png        added
  gammareal3.png          added
  loggamma.png            added
  mathml.spad             fix ambiguity bug in mathml output
  mathml.spad             fix hex(10) mathml rendering 
  mathml.spad             fix F,3 mathml rendering 
  mathml.spad             remove code to eat %% 
  psi.png                 added 




Standards Verification

The Computer Algebra Test Suite (CATS) effort checks the results
that Axiom generates against published results. Axiom has an
extensive set of regression tests (the KAMKE suite) for ordinary
differential equations, for integration (the SCHAUM suite), and
for numeric special functions (the ABRAMOWITZ suite). In addition,
results have been checked against Mathematica, Maple, and Maxima.

  asinatan.input   regression for the functions asin and atan
  asinhatanh.input regression for the functions asinh and atanh
  besselk.input    regression for the function besselK
  e1.input         regression for the function E1
  en.input         regression for the function En
  exp.input        regression for the function exp
  gamma.input      regression for the function gamma
  log.input        regression for the functions log
  pfaffian.input   regression for the function pfaffian
  seccsc.input     regression for the functions sec and csc
  sincos.input     regression for the functions sin and cos
  sinhcosh.input   regression for the functions sinh and cosh
  tancot.input     regression for the functions tan and cot
  tanhcoth.input   regression for the functions tanh and coth




New Functions Added

Axiom is missing various special functions found in other computer
algebra systems. This release adds two new ones, the Exponential
Integral E1 and the higher order Exponential Integral En.  These have
been tested against the published results.

  special.spad E1 added
  special.spad En added




Bugs Fixed

There are 15 bug fixes in this release:

  bug 7015: fix hex(10) mathml rendering
  bug 7016: remove code to eat %% 
  bug 7019: fix F,3 mathml rendering 
  bug 7023: discardGraph free corrected 
  bug 7042: ignore regression test gensym
  bug 7045: wrong Makefile for Xpm fix 
  bug 7052: spurious remake of axbook
  bug 7054: /home/silver path in bookvol11
  bug 7057: ambiguity in mathml
  bug 7089/343: FreeAbelianGroup order 
  bug 7090/355 handle besselK
  bug 7093: Function name fix
  bug 7100/149: numlock in hyperdoc
  bug 7101/204: MoreSystemCommand unnecessary loading 
  bug 7102/412: Equality testing in TableAggregate 




Regression test fixes

As changes happen in the system the regression tests are updated
to reflect the new conditions. Changing the category of PositiveInteger
caused (a + -bi) to print as (a - bi). New builds raised gensym faults
which were fixed. And new builds change random numbers so the tests
that depend on them are marked "ok" despite failures due to randomness.
The FreeAbelianGroup bug is tested.

  acplot.spad     fix output form of negative numbers
  calculus2.input fix function names 
  classtalk.input ignore gensyms
  collect.input   fix function names 
  dfloat.input    handle negative number output
  easter.input    fix function names 
  elemnum.input   handle negative number output
  exlap.input     fix function names 
  exsum.input     fix function names 
  free.input      added to test bug
  grpthry.input   mark random generation failures ok
  grpthry.input   fix function names 
  ico.input       mark random generation failures ok
  intg0.input     ignore gensyms
  is.input        type declare function
  kamke3.input    mark random generation failures ok
  knot2.input     fix function names 
  lodo.spad       ignore regression test gensym 
  mapleok.input   ignore gensyms
  mathml.input    handle new mathml sub/sup change
  ndftip.input    fix missing blank lines
  pmint.input     rewritten
  repa6.input     fix function names 
  r20bugs.input   change spacing
  sf.spad         fix output form of negative numbers
  tbagg.input     regression for equality testing in TableAggregate




Algebra file changes

The fundamental change was a supposedly transparent move of
the category for PositiveInteger. This had the effect of changing
the output form and broke several regression tests. Some mathml
issues were fixed. The new functions E1 and En were added. The
FreeAbelianGroup bug was fixed.

  axserver.spad  fix lastType output re: errors
  acplot.spad    fix output form of negative numbers
  combfunc.spad  fix bold font handling
  integer.spad   category change for PositiveInteger
  sf.spad fix    output form of negative numbers
  sf.spad        handle besselK
  op.spad        handle besselK 
  combfunc.spad  handle besselK 
  free.spad      fix FreeAbelianGroup bug 
  special.spad   add E1
  special.spad   add En
  mathml.spad    fix ambiguity bug in mathml output
  mathml.spad    fix hex(10) mathml rendering 
  mathml.spad    fix F,3 mathml rendering 
  mathml.spad    remove code to eat %% 



Interpreter changes

The primary changes are the addition of bookvol11 for the Firefox
Hyperdoc and the literate documentation of the top level command
handling in bookvol5 (the interpreter) along with rewrites of the
lisp/boot code.

  bootfuns.lisp move $systemCommands to bookvol5
  bookvol5      browse and top-level command handling
  bookvol11     added
  http.lisp     mathObject2String for hex(10) 
  incl.boot     move incBiteOff to bookvol5
  intint.lisp   move setCurrentLine to bookvol5
  int-top.boot  move ncloopCommand, etc. to bookvol5
  i-syscmd.boot move $SYSCOMMANDS to bookvol5
  Makefile      wrong Makefile for Xpm fix 
  makegraph.c   discardGraph free corrected 
  nci.lisp      move ncloopInclude to bookvol5
  setq.lisp     move command initialization to bookvol5



Documentation changes

  bookvol5      explain top level input handling (lisp/boot rewrite)
  combfunc.spad fix bold font handling
  axiom.sty     add binom 



Patches released

  20071129.01.tpd.patch
  20071129.02.tpd.patch
  20071205.01.tpd.patch
  20071206.01.tpd.patch
  20071208.01.tpd.patch
  20071215.01.tpd.patch
  20071215.02.tpd.patch
  20071215.03.gxv.patch
  20071216.01.tpd.patch
  20071216.02.tpd.patch
  20071216.03.acr.patch
  20071217.01.acr.patch
  20071217.02.tpd.patch
  20071218.01.acr.patch
  20071225.01.sxw.patch
  20071228.01.tpd.patch
  20071229.01.jap.patch
  20071230.01.acr.patch
  20071230.02.tpd.patch
  20071230.03.tpd.patch
  20080102.01.tpd.patch
  20080103.01.tpd.patch
  20080104.01.tpd.patch
  20080104.02.tpd.patch
  20080106.01.tpd.patch
  20080107.01.tpd.patch
  20080107.02.tpd.patch
  20080107.03.tpd.patch
  20080116.01.tpd.patch
  20080119.01.tpd.patch
  20080119.02.tpd.patch
  20080119.03.tpd.patch
  20080120.01.gxv.patch
  20080120.02.tpd.patch
  20080120.03.tpd.patch

\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{november2007}{releasenotes.ht}{November 23, 2007 Release Notes}
\pagepic{ps/v71november2007.eps}{november2007}{0.50}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{november2007}{November 23, 2007 Release Notes}
\beginscroll
\begin{verbatim}

Summary: November 2007 release

All of the golden sources are up to date.
  savannah.nongnu.org/projects/axiom CVS
  sourceforge.net/projects/axiom CVS
  arch@axiom-developer.org ARCH (axiom--main--1--patch-54)
  git@axiom-developer.org GIT
  

ADD NEW CREDITS
  New patches were posted by Arthur and Alfredo so their tlas were
  added to the changelog

20071001 acr Arthur C. Ralfs <arthur@mathbrane.ca>
20070914 jap Jose Alfredo Portes <doyenatccny@gmail.com>


PORT TO DIFFERENT SYSTEMS
  As part of the new axiom website there is a binary release page.
  The stanzas for these supported systems were added.

20071119 tpd Makefile.pamphlet add fedora6,7,8 stanzas


NEW Axiom WEBSITE: http://axiom-developer.org STARTED.
  The new Axiom website (currently at axiom.axiom-developer.org)
  has been started. It will include the binary release page.


REMOVE OLD REGRESSION SYSTEM
  The previous regression test system was removed. A new combined
  regression test and help documentation system was built to replace
  this mechanism.

20070901 tpd src/input/Makefile remove ALGEBRA variable
20070901 tpd src/algebra/perm.spad remove TEST mechanism
20070901 tpd src/algebra/view2d.spad remove TEST mechanism
20070901 tpd src/algebra/fr.spad remove TEST mechanism


FIX BOOK DOCUMENTATION
  Minor typos have been discovered in the book during documentation.

20070905 tpd src/doc/book remove duplicate upperCase, lowerCase typo
20070903 tpd src/doc/bookvol4 fix typos
20070902 tpd src/doc/book MultiSet -> Multiset
20080829 tpd src/doc/book.pamphlet correct typo


FIX BUGS
  Various bugs have been found and fixed.

20071101 tpd src/interp/i-output.boot fix bugs 7010 (209), 7011
20070920 tpd src/input/Makefile add bug101.input regression test
20070920 tpd src/input/bug101.input test laplace(log(z),z,w) bug 101
20070920 wxh src/algebra/laplace.spad fix laplace(log(z),z,w) bug 101
20070916 tpd src/input/Makefile add bug103.input regression test
20070916 tpd src/input/bug103.input test solve(z=z,z) bug fix
20070916 tpd src/algebra/polycat.spad solve(z=z,z) bug fix
20070916 tpd src/algebra/catdef.spad add zero? to exquo
20070915 tpd merge bug100 branch
20070915 tpd src/input/Makefile add bug100.input regression test
20070915 tpd src/input/bug100.input test integrate((z^a+1)^b,z) infinite loop
20070915 wxh src/algebra/intef.spad fix integrate((z^a+1)^b,z) infinite loop
20070915 tpd src/algebra/carten minor edit for regression cleanup
20070914 wxh src/hyper/hyper fix bad bracing of )hd change
20070914 tpd src/algebra/fraction.spad remove double )spool command
20070914 tpd src/algebra/kl.spad remove double )spool command
20070914 tpd src/algebra/lindep.spad remove double )spool command
20070914 tpd src/algebra/radix.spad remove double )spool command


ENABLE DYNAMIC RESTART OF HYPERDOC
  Hyperdoc can now be started dynamically or restarted if killed.

20070914 jap adapt changes for )hd restart to Axiom sources
20070914 wxh src/sman/bookvol6 enable restart of hyperdoc with )hd
20070914 wxh src/include/sman.h1 enable restart of hyperdoc with )hd
20070914 wxh src/hyper/hyper enable restart of hyperdoc with )hd


SET UP THE NEW FIREFOX BASED HYPERDOC
  Hyperdoc is going away. A new version of hyperdoc is being built
  which uses html/javascript/mathml. These files change the interpreter
  and algebra to support the new hyperdoc machinery.

20071019 acr src/interp/http.lisp use new return values
20071019 acr src/algebra/axserver.spad use new return values
20071014 acr src/algebra/axserver.spad use getContentType(pathvar)
20071013 acr license/license.ralfs license rewrite
20071013 acr src/interp/http.lisp faster page service
20071013 acr src/algebra/axserver.spad faster page service
20071001 tpd src/algebra/exposed.lisp add (|AxiomServer| . AXSERV) to basic
20071001 tpd src/algebra/Makefile add axserver.spad
20071001 acr src/algebra/axserver.spad axserver socket connection code
20071001 tpd src/interp/Makefile add http.lisp
20071001 acr src/interp/http.lisp axserver socket connection code
20071001 acr license/license.ralfs added


REGRESSION TEST CALCULUS
  A new regression test suite for calculus is being built. The first
  of these files has been added to the system.

20070913 tpd src/input/Makefile schaum1.input added
20070913 tpd src/input/schaum1.input added


REGRESSION TEST ORDINARY DIFFERENTIAL EQUATIONS
  A regression test suite for ordinary differential equations was built. 

20071005 tpd src/input/Makefile kamke7.input regression test added
20071005 tpd src/input/kamke7.input ODE regression test added
20071005 tpd src/input/Makefile kamke6.input regression test added
20071005 tpd src/input/kamke6.input ODE regression test added
20071005 tpd src/input/Makefile kamke5.input regression test added
20071005 tpd src/input/kamke5.input ODE regression test added
20071005 tpd src/input/Makefile kamke4.input regression test added
20071005 tpd src/input/kamke4.input ODE regression test added
20071005 tpd src/input/Makefile kamke3.input regression test added
20071005 tpd src/input/kamke3.input ODE regression test added
20071004 tpd src/input/Makefile kamke2.input regression test added
20071004 tpd src/input/kamke2.input ODE regression test added
20071004 tpd src/input/Makefile kamke1.input regression test added
20071004 tpd src/input/kamke1.input ODE regression test added
20071004 tpd src/input/Makefile kamke0.input regression test added
20071004 tpd src/input/kamke0.input ODE regression test added


REGRESSION TEST PFAFFIAN
  Martin added the pfaffian regression test. It was added and removed
  due to documentation license issues. New documentation is being written.

20070929 tpd src/input/Makefile pfaffian regression test removed
20070929 tpd src/input/pfaffian.input regression test removed
20070927 tpd src/input/Makefile pfaffian regression test added 
20070927 mxr src/input/pfaffian.input regression test added 


ADD PORTIONS OF THE GUESS PACKAGE
  The newton.spad file is actually part of the fffg.spad file so it
  was removed. The very top level spad functions in GUESS still do
  not work properly.

20070909 tpd src/algebra/newton.spad included in fffg.spad
20070909 tpd src/algebra/Makefile remove newton.spad (duplicate)


FIX BUILD PROCESS
  The build process was not properly suppressing output by default.

20070907 tpd src/algebra/acplot.spad fix PlaneAlgebraicCurvePlot.help NOISE
20070907 tpd src/algebra/Makefile make regression respect NOISE variable
20070907 tpd src/input/Makefile make regression respect NOISE variable


FIX INSTALL PROCESS
  The install process had a bug.

20070906 tpd Makefile int/sman/axiom command to target command for install
20070906 tpd src/sman/Makefile copy axiom command to int


ADD ALDOR RELEASE
  The aldor release has been added to zips. It will soon be part of
  the build mechanism but separately maintained like GCL.

20070901 tpd zips/aldor.20070901.tgz add pdf documentation
20070901 tpd zips/aldor.20070901.tgz added


ADD )HELP FACILITY
  The )help facility was recovered. The documentation is now integrated
  into the spad files and used both for help documentation and algebra
  regression testing. 

\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{feb2005}{releasenotes.ht}{Feature Complete Release Feb 2005}
\pagepic{ps/v71feb2005.eps}{feb2005}{0.50}
\pagefrom{What's New in Axiom}{releaseNotes}
\begin{chunk}{releasenotes.ht}
\begin{page}{feb2005}{Feature Complete Release Feb 2005}
\beginscroll
The February 2005 release is the first complete release of the 
Axiom system since it was first made available as open source.

This release includes the full complement of algebra, the graphics
subsystem, and the hyperdoc system. 

This full release runs on Linux and Solaris 9. 
The algebra runs on Windows.
\endscroll
\autobuttons
\end{page}

\end{chunk}
\chapter{Special hyperdoc pages}
\section{util.ht}
This file contains macros for the Axiom HyperDoc hypertext facility.
Most of the macros for the system are here though there may be some in
individual .ht files that are of a local nature.
\index{files!util.ht}
\index{util.ht files}
\subsection{Names of software and facilities}
\begin{chunk}{util.ht}
\newcommand{\Browse}{Browse}
\newcommand{\Language}{Axiom}
\newcommand{\SpadName}{\Language}
\newcommand{\LangName}{\Language}
\newcommand{\HyperName}{HyperDoc}
\newcommand{\Clef}{Clef}
\newcommand{\Lisp}{Common LISP}
\newcommand{\naglib}{NAG Foundation Library}
\newcommand{\GoBackToWork}
{\vspace{2}\newline
{Click on \  \UpButton{} \  to go back to what you were doing.}}

\end{chunk}
\subsection{Special hooks to Unix}
All unix commands should be done as macros defined here so we don't
have to go hunting when moving between Unix versions.
\begin{chunk}{util.ht}
\newcommand{\newspadclient}[1]
{xterm -n "#1" -e \$SPAD/bin/clef \$SPAD/bin/server/spadclient}
\newcommand{\searchwindow}[2]{\unixwindow{#1}{\$SPAD/lib/htsearch "#2"}}
\newcommand{\unixwindow}[2]{\unixlink{#1}{#2}}
\newcommand{\menuunixlink}[2]{\item\unixlink{\menuitemstyle{#1}}{#2}}
\newcommand{\menuunixcommand}[2]{\item\unixcommand{\menuitemstyle{#1}}{#2}}
\newcommand{\menuunixwindow}[2]{\item\unixwindow{\menuitemstyle{#1}}{#2}}

\end{chunk}
\subsection{HyperDoc menu macros}
\begin{chunk}{util.ht}
% Example:
%
% \beginmenu
% \menulink{Thing One}{PageOne} la da di da da ...
% \menulink{Thin Two}{PageTwo}  do da day ...
% \item \ACmdMacro{\menuitemstyle{Thing Three}} la di da ...
% \endmenu

% The menu environment

\newcommand{\beginmenu}          {\beginitems[\MenuDotBitmap]}
\newcommand{\endmenu}            {\enditems}

% This is the usual format for a menu item.

\newcommand{\menuitemstyle}[1]   {{\MenuDotBitmap}#1}

% Often-used menu item forms

%   These two simply do links
\newcommand{\menudownlink}[2]    {\item\downlink{\menuitemstyle{#1}}{#2}}
\newcommand{\menulink}[2]        {\menudownlink{#1}{#2}}

%   This will cause lower level links to have a HOME button
\newcommand{\menumemolink}[2]    {\item\memolink{\menuitemstyle{#1}}{#2}}

%   This opens a new window for the linked page.
\newcommand{\menuwindowlink}[2]    {\item\windowlink{\menuitemstyle{#1}}{#2}}

%   These execute lisp commands in various flavors
\newcommand{\menulispcommand}[2]
{\item\lispcommand{\menuitemstyle{#1}}{#2}}
\newcommand{\menulispdownlink}[2]
{\item\lispdownlink{\menuitemstyle{#1}}{#2}}
\newcommand{\menulispmemolink}[2]
{\item\lispmemolink{\menuitemstyle{#1}}{#2}}
\newcommand{\menulispwindowlink}[2]
{\item\lispwindowlink{\menuitemstyle{#1}}{#2}}

%   This executes a unix command
\newcommand{\menuunixcmd}[2]{\item\unixcommand{\menuitemstyle{#1}}{#2}}
\newcommand{\searchresultentry}[3]
{\tab{3}\item#3\tab{8}\downlink{\menuitemstyle{#1}}{#2}\newline}
\newcommand{\newsearchresultentry}[3]
{\tab{3}\item#1\tab{8}\downlink{\menuitemstyle{#2}}{#3}\newline}

\end{chunk}
\subsection{Bitmaps and bitmap manipulation macros}
\begin{chunk}{util.ht}
\newcommand{\htbmdir}{\env{AXIOM}/doc/bitmaps}
\newcommand{\htbmfile}[1]{\htbmdir /#1.bitmap}
\newcommand{\htbitmap}[1]{\inputbitmap{\htbmfile{#1}}}
\newcommand{\ControlBitmap}[1]{\controlbitmap{\htbmfile{#1}}}

% next group of bitmaps frequently appear in the titlebar
\newcommand{\ContinueBitmap} {\ControlBitmap{continue}}
\newcommand{\DoItBitmap}     {\ControlBitmap{doit}}
\newcommand{\ExitBitmap}     {\ControlBitmap{exit3d}}
\newcommand{\HelpBitmap}     {\ControlBitmap{help3d}}
\newcommand{\ReturnBitmap}   {\ControlBitmap{home3d}}
\newcommand{\NoopBitmap}       {\ControlBitmap{noop3d}}
\newcommand{\UpBitmap}       {\ControlBitmap{up3d}}

\newcommand{\MenuDotBitmap}{\htbitmap{menudot}}

% Including control panel pixmaps for help pages:

\newcommand{\helpbit}[1]
{\centerline{\inputpixmap{\env{AXIOM}/doc/pixmaps/{#1}}}}

\end{chunk}
\subsection{HyperDoc button objects}
\begin{chunk}{util.ht}
\newcommand{\ContinueButton}[1]{\downlink{Click here}{#1} to continue.}
\newcommand{\ExitButton}[1]{\memolink{\ExitBitmap}{#1}}
\newcommand{\HelpButton}[1]{\memolink{\HelpBitmap}{#1}}
\newcommand{\StdHelpButton}{\HelpButton{ugHyperPage}}
\newcommand{\StdExitButton}{\ExitButton{ProtectedQuitPage}}
\newcommand{\UpButton}{\upbutton{\UpBitmap}{UpPage}}
\newcommand{\ReturnButton}{\returnbutton{\ReturnBitmap}{ReturnPage}}
\newcommand{\on}[1]{{\inputbox[1]{#1}{\htbmfile{pick}}
             {\htbmfile{unpick}}}}
\newcommand{\off}[1]{{\inputbox[0]{#1}{\htbmfile{pick}}
             {\htbmfile{unpick}}}}

\end{chunk}
\subsection{Standard HyperDoc button configurations}
\begin{chunk}{util.ht}
\newcommand{\autobutt}[1]{\helppage{#1}}
\newcommand{\autobuttons}{}
\newcommand{\exitbuttons}{}

\newcommand{\autobuttLayout}[1]{\centerline{#1}}}
\newcommand{\autobuttMaker}[1]{\autobuttLayout{\HelpButton{#1}}}
\newcommand{\riddlebuttons}[1]{\autobuttLayout{\link{\HelpBitmap}{#1}}}

% Macro for downward compatibility (?).

\newcommand{\simplebox}[2]
{\inputbox[#1]{#2}{\htbitmap{xbox}}{\htbitmap{xopenbox}}}

\end{chunk}
\subsection{HyperDoc graphics macros}
\begin{chunk}{util.ht}
% Including viewport bitmaps within \HyperName pages:

\newcommand{\viewport}[1]{\inputimage{{#1}.view/image}}
\newcommand{\axiomViewport}[1]
{\inputimage{\env{AXIOM}/doc/viewports/{#1}.view/image}}
\newcommand{\spadviewport}[1]{\axiomViewport{#1}}

% Creating a real live viewport:

\newcommand{\viewportbutton}[2]{\unixcommand{#1}{viewalone #2}}
\newcommand{\axiomViewportbutton}[2]
{\unixcommand{#1}{viewalone \$AXIOM/doc/viewports/{#2}}}
\newcommand{\spadviewportbutton}[2]{\axiomViewportbutton{#1}{#2}}

% Making active viewport buttons:

\newcommand{\viewportasbutton}[1]
{\unixcommand{\inputimage{{#1}.view/image}}{viewalone {#1}}}
\newcommand{\axiomViewportasbutton}[1]
{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/{#1}.view/image}}
{viewalone \$AXIOM/doc/viewports/{#1}}}
\newcommand{\spadviewportasbutton}[1]{\axiomViewportasbutton{#1}}

\end{chunk}
\subsection{TeX and LaTeX compatibility macros}
\begin{chunk}{util.ht}
%% Begin macros that are needed because HD uses the wrong names

\newcommand{\center}[1]{\centerline{#1}}
\newcommand{\box}[1]{\fbox{#1}}

%% End   macros that are needed because HD uses the wrong names

\newcommand{\LARGE}{}
\newcommand{\LaTeX}{LaTeX}
\newcommand{\Large}{}
\newcommand{\TeX}{TeX}
\newcommand{\allowbreak}{}
\newcommand{\aleph}{\inputbitmap{\htbmdir{}/aleph.bitmap}}
\newcommand{\alpha}{\inputbitmap{\htbmdir{}/alpha.bitmap}}
\newcommand{\angle}{\inputbitmap{\htbmdir{}/angle.bitmap}}
\newcommand{\backslash}{\inputbitmap{\htbmdir{}/backslash.bitmap}}
\newcommand{\beta}{\inputbitmap{\htbmdir{}/beta.bitmap}}
\newcommand{\bigbreak}{\newline\newline}
\newcommand{\bot}{\inputbitmap{\htbmdir{}/bot.bitmap}}
\newcommand{\bullet}{\inputbitmap{\htbmdir{}/bullet.bitmap}}
\newcommand{\caption}[1]{\newline\centerline{#1}\newline}
\newcommand{\chi}{\inputbitmap{\htbmdir{}/chi.bitmap}}
\newcommand{\cite}[1]{bibliography entry for {\it #1}}
\newcommand{\cleardoublepage}{}
\newcommand{\coprod}{\inputbitmap{\htbmdir{}/coprod.bitmap}}
\newcommand{\del}{\inputbitmap{\htbmdir{}/del.bitmap}}
\newcommand{\delta}{\inputbitmap{\htbmdir{}/delta.bitmap}}
\newcommand{\Delta}{\inputbitmap{\htbmdir{}/delta-cap.bitmap}}
\newcommand{\div}{\inputbitmap{\htbmdir{}/div.bitmap}}
\newcommand{\dot}{\inputbitmap{\htbmdir{}/dot.bitmap}}
\newcommand{\ell}{\inputbitmap{\htbmdir{}/ell.bitmap}}
\newcommand{\emptyset}{\inputbitmap{\htbmdir{}/emptyset.bitmap}}
\newcommand{\epsilon}{\inputbitmap{\htbmdir{}/epsilon.bitmap}}
\newcommand{\epsffile}{}
\newcommand{\eta}{\inputbitmap{\htbmdir{}/eta.bitmap}}
\newcommand{\exists}{\inputbitmap{\htbmdir{}/exists.bitmap}}
\newcommand{\forall}{\inputbitmap{\htbmdir{}/forall.bitmap}}
\newcommand{\footnote}[1]{ {(#1)}}
\newcommand{\frenchspacing}{}
\newcommand{\gamma}{\inputbitmap{\htbmdir{}/gamma.bitmap}}
\newcommand{\Gamma}{\inputbitmap{\htbmdir{}/gamma-cap.bitmap}}
\newcommand{\hbar}{\inputbitmap{\htbmdir{}/hbar.bitmap}}
\newcommand{\hbox}[1]{{#1}}
\newcommand{\hfill}{}
\newcommand{\hfil}{}
\newcommand{\huge}{}
\newcommand{\Im}{\inputbitmap{\htbmdir{}/im-cap.bitmap}}
\newcommand{\imath}{\inputbitmap{\htbmdir{}/imath.bitmap}}
\newcommand{\infty}{\inputbitmap{\htbmdir{}/infty.bitmap}}
\newcommand{\int}{\inputbitmap{\htbmdir{}/int.bitmap}}
\newcommand{\iota}{\inputbitmap{\htbmdir{}/iota.bitmap}}
\newcommand{\index}[1]{}
\newcommand{\jmath}{\inputbitmap{\htbmdir{}/jmath.bitmap}}
\newcommand{\kappa}{\inputbitmap{\htbmdir{}/kappa.bitmap}}
\newcommand{\label}[1]{}
\newcommand{\lambda}{\inputbitmap{\htbmdir{}/lambda.bitmap}}
\newcommand{\Lambda}{\inputbitmap{\htbmdir{}/lambda-cap.bitmap}}
\newcommand{\large}{}
\newcommand{\ldots}{...}
\newcommand{\le}{<=}
\newcommand{\marginpar}[1]{}
\newcommand{\mu}{\inputbitmap{\htbmdir{}/mu.bitmap}}
\newcommand{\neg}{\inputbitmap{\htbmdir{}/neg.bitmap}}
\newcommand{\newpage}{}
\newcommand{\noindent}{\indent{0}}
\newcommand{\nonfrenchspacing}{}
\newcommand{\nabla}{\inputbitmap{\htbmdir{}/nabla.bitmap}}
\newcommand{\nu}{\inputbitmap{\htbmdir{}/nu.bitmap}}
\newcommand{\omega}{\inputbitmap{\htbmdir{}/omega.bitmap}}
\newcommand{\Omega}{\inputbitmap{\htbmdir{}/omega-cap.bitmap}}
\newcommand{\pageref}[1]{???}
\newcommand{\parallel}{\inputbitmap{\htbmdir{}/parallel.bitmap}}
\newcommand{\partial}{\inputbitmap{\htbmdir{}/partial.bitmap}}
\newcommand{\phi}{\inputbitmap{\htbmdir{}/phi.bitmap}}
\newcommand{\Phi}{\inputbitmap{\htbmdir{}/phi-cap.bitmap}}
\newcommand{\pi}{\inputbitmap{\htbmdir{}/pi.bitmap}}
\newcommand{\Pi}{\inputbitmap{\htbmdir{}/pi-cap.bitmap}}
\newcommand{\prime}{\inputbitmap{\htbmdir{}/prime.bitmap}}
\newcommand{\prod}{\inputbitmap{\htbmdir{}/prod.bitmap}}
\newcommand{\protect}{}
\newcommand{\psi}{\inputbitmap{\htbmdir{}/psi.bitmap}}
\newcommand{\Psi}{\inputbitmap{\htbmdir{}/psi-cap.bitmap}}
\newcommand{\quad}{\inputbitmap{\htbmdir{}/quad.bitmap}}
\newcommand{\Re}{\inputbitmap{\htbmdir{}/re-cap.bitmap}}
\newcommand{\rho}{\inputbitmap{\htbmdir{}/rho.bitmap}}
\newcommand{\sc}{\rm}
\newcommand{\sf}{\bf}
\newcommand{\sigma}{\inputbitmap{\htbmdir{}/sigma.bitmap}}
\newcommand{\Sigma}{\inputbitmap{\htbmdir{}/sigma-cap.bitmap}}
\newcommand{\small}{}
\newcommand{\sum}{\inputbitmap{\htbmdir{}/sum.bitmap}}
\newcommand{\surd}{\inputbitmap{\htbmdir{}/surd.bitmap}}
\newcommand{\tau}{\inputbitmap{\htbmdir{}/tau.bitmap}}
\newcommand{\theta}{\inputbitmap{\htbmdir{}/theta.bitmap}}
\newcommand{\Theta}{\inputbitmap{\htbmdir{}/theta-cap.bitmap}}
\newcommand{\times}{\inputbitmap{\htbmdir{}/times.bitmap}}
\newcommand{\top}{\inputbitmap{\htbmdir{}/top.bitmap}}
\newcommand{\triangle}{\inputbitmap{\htbmdir{}/triangle.bitmap}}
\newcommand{\upsilon}{\inputbitmap{\htbmdir{}/upsilon.bitmap}}
\newcommand{\Upsilon}{\inputbitmap{\htbmdir{}/upsilon-cap.bitmap}}
\newcommand{\vbox}[1]{{#1}}
\newcommand{\wp}{\inputbitmap{\htbmdir{}/wp.bitmap}}
\newcommand{\xi}{\inputbitmap{\htbmdir{}/xi.bitmap}}
\newcommand{\Xi}{\inputbitmap{\htbmdir{}/xi-cap.bitmap}}
\newcommand{\zeta}{\inputbitmap{\htbmdir{}/zeta.bitmap}}
\newcommand{\bs}{\\}

\end{chunk}
\subsection{Book and .ht page macros}
\begin{chunk}{util.ht}
\newcommand{\beginImportant}{\horizontalline}
\newcommand{\endImportant}{\horizontalline}
%
% following handles things like "i-th" but uses "-th"
\newcommand{\eth}[1]{{#1}-th}}
%
\newcommand{\texnewline}{}
\newcommand{\texbreak}{}
\newcommand{\Gallery}{{Axiom Images}}
\newcommand{\exptypeindex}[1]{}
\newcommand{\gotoevenpage}{}
\newcommand{\ignore}[1]{}
\newcommand{\ind}{\newline\tab{3}}
\newcommand{\labelSpace}[1]{}
\newcommand{\mathOrSpad}[1]{{\spad{#1}}}
\newcommand{\menuspadref}[2]{\menudownlink{#1}{#2Page}}
\newcommand{\menuxmpref}[1]{\menudownlink{`#1'}{#1XmpPage}}
% comment and then \spadcommand or spadsrc
\newcommand{\noOutputXtc}[2]{\xtc{#1}{#2}}  
\newcommand{\not=}{\inputbitmap{\htbmdir{}/not=.bitmap}}
\newcommand{\notequal}{\inputbitmap{\htbmdir{}/notequal.bitmap}}
% comment and then \spadcommand or spadsrc
\newcommand{\nullXtc}[2]{\xtc{#1}{#2}}      
\newcommand{\nullspadcommand}[1]{\spadcommand}
% Use this instead of \par for now.
\newcommand{\pp}{\newline}
% comment and then \spadcommand or spadsrc
\newcommand{\psXtc}[3]{\xtc{#1}{#2}}        
\newcommand{\ref}[1]{(see the graph)}
\newcommand{\showBlurb}[1]
{Issue the system command \spadcmd{)show #1} to display the full list 
of operations defined by \spadtype{#1}.}
\newcommand{\smath}[1]{\mathOrSpad{#1}}
\newcommand{\spadFileExt}{.spad}
\newcommand{\spadkey}[1]{}
\newcommand{\spadref} [1]{{\it #1}}
\newcommand{\spadsig}[2]{\spadtype{#1} {\tt ->} \spadtype{#2}}
\newcommand{\axiomSig}[2]{\axiomType{#1} {\tt ->} \axiomType{#2}}
\newcommand{\subscriptIt}[2]{{\it {#1}\_{#2}}}
\newcommand{\subscriptText}[2]{{\it {#1}\_{\it #2}}}
\newcommand{\subsubsection}[1]{\newline\indent{0}{\bf #1}\newline\newline}
\newcommand{\syscmdindex}[1]{}              % system command index macro
\newcommand{\threedim}{three-dimensional}
\newcommand{\twodim}{two-dimensional}
\newcommand{\unind}{\newline}
\newcommand{\void}{the unique value of \spadtype{Void}}
\newcommand{\xdefault}[1]{The default value is {\tt "#1"}.}
\newcommand{\xmpLine}[2]{{\tt #1}\newline}   % have to improve someday
\newcommand{\xmpref}[1]{\downlink{`#1'}{#1XmpPage}}
% comment and then \spadcommand or spadsrc
\newcommand{\xtc}[2]{#1 #2} 

% glossary terms
\newcommand{\spadgloss}[1]{\lispdownlink{#1}{(|htGloss| '|#1|)}}
\newcommand{\spadglossSee}[2]{\lispdownlink{#1}{(|htGloss| '|#2|)}}

% use this for syntax punctuation: \axiomSyntax{::}
\newcommand{\axiomSyntax}[1]{``{\tt #1}''}
\newcommand{\spadSyntax}[1]{\axiomSyntax{#1}}

% constructors
\newcommand{\axiomType}[1]{\lispdownlink{#1}{(|spadType| '|#1|)}}
\newcommand{\spadtype}[1]{\axiomType{#1}}
% things that browse can't handle
\newcommand{\nonLibAxiomType}[1]{{\it #1}}
\newcommand{\pspadtype}[1]{\nonLibAxiomType{#1}}

\newcommand{\axiom}   [1]{{\tt #1}} % note font
\newcommand{\spad}    [1]{\axiom{#1}}
% exists in ++ comments; to be removed
\newcommand{\spadvar} [1]{\axiom{#1}}
\newcommand{\s}       [1]{\axiom{#1}}

\newcommand{\httex}[2]{#1}
\newcommand{\texht}[2]{#2}

% Function names:
%
% The X versions below are used because Axiom function names that end
% in ``!'' cause problems for makeindex for had-copy.
%
% Example: \spadfunFromX{reverse}{List} prints as   reverse!
%
% In the "From" versions, the first arg is function name,
% second is constructor where exported.
%
% Use the "op" flavors of "-", "+", "*" etc, otherwise the "fun" flavors

\newcommand{\userfun} [1]{{\bf #1}} % example, non-library function names

\newcommand{\fakeAxiomFun}[1]{{\bf #1}} % not really a library function
\newcommand{\pspadfun} [1]{\fakeAxiomFun{#1}}

\newcommand{\axiomFun} [1]{\lispdownlink{#1}{(|oPage| '|#1|)}}
\newcommand{\spadfun} [1]{\axiomFun{#1}}
\newcommand{\axiomFunX}[1]{\axiomFun{#1!}}
\newcommand{\spadfunX}[1]{\axiomFun{#1!}}

\newcommand{\axiomFunFrom}[2]{\lispdownlink{#1}{(|oPageFrom| '|#1| '|#2|)}}
\newcommand{\spadfunFrom}[2]{\axiomFunFrom{#1}{#2}}
\newcommand{\axiomFunFromX}[2]{\axiomFunFrom{#1!}{#2}}
\newcommand{\spadfunFromX}[2]{\axiomFunFrom{#1!}{#2}}

\newcommand{\axiomOp} [1]{\lispdownlink{#1}{(|oPage| '|#1|)}}
\newcommand{\spadop}  [1]{\axiomOp{#1}}
\newcommand{\axiomOpX}[1]{\axiomOp{#1!}}

\newcommand{\axiomOpFrom}[2]{\lispdownlink{#1}{(|oPageFrom| '|#1| '|#2|)}}
\newcommand{\spadopFrom} [2]{\axiomOpFrom{#1}{#2}}
\newcommand{\axiomOpFromX}[2] {\axiomOpFrom{#1!}{#2}}
\newcommand{\spadopFromX}[2] {\axiomOpFrom{#1!}{#2}}

\newcommand{\spadsyscom}[1]{{\tt #1}}
\newcommand{\spadcmd}[1]{\spadsyscom{#1}}
\newcommand{\spadsys}[1]{\spadsyscom{#1}}


% Following macros should be phased out in favor of ones above:

\newcommand{\gloss}[1]{\lispdownlink{#1}{(|htGloss| '|#1|)}}
\newcommand{\spadglos}[1]{\lispdownlink{#1}{(|htGloss| '|#1|)}}
\newcommand{\glossSee}[2]{\lispdownlink{#1}{(|htGloss| '|#2|)}}

\end{chunk}
\subsection{Browse macros}
\begin{chunk}{util.ht}
\newcommand{\undocumented}[0]{is not documented yet}
\newcommand{\aliascon}[2]{\lispdownlink{#1}{(|conPage| '|#2|)}}
\newcommand{\aliasdom}[2]{\lispdownlink{#1}{(|conPage| '|#2|)}}
\newcommand{\andexample}[1]{\indent{5}\spadcommand{#1}\indent{0}\newline}
\newcommand{\blankline}{\vspace{1}\newline }
\newcommand{\con}[1]{\lispdownlink{#1}{(|conPage| '|#1|)}}

\newcommand{\conf}[2]{\lispdownlink{#1}{(|conPage| '{#2})}}
% generalizes "con" to allow arbitrary title and form

\newcommand{\ops}[3]{\lisplink{#1}{(|conOpPage| #2 '{#3})}}
% does lisplink to operation page of a constructor or form
% #1 is constructor name or form, without fences, e.g. "Matrix(Integer)"
% #2 is page number, extracted from $curPage (see fromHeading/dbOpsForm)
% #3 is constructor name or form, with fences, e.g. "(|Matrix| (|Integer|))"

\newcommand{\dlink}[2]{\downlink{#2}{#1}}
\newcommand{\dom}[1]{\lispdownlink{#1}{(|conPage| '|#1|)}}
\newcommand{\example}[1]
{\newline\indent{5}\spadcommand{#1}\indent{0}\newline}
\newcommand{\lisp}[2]{\lispdownlink{#2}{#1}}
\newcommand{\spadatt} [1]{{\it #1}}
\newcommand{\indented}[2]
{\indentrel{#1}\newline #2\indentrel{-#1}\newline}
\newcommand{\keyword}[1]{\lispdownlink{#1}{(|htsn| '|#1|)}}
\newcommand{\op}[1]{\lispdownlink{#1}{(|htsn| '|#1|)}}
\newcommand{\spadignore}[1]{#1}

\end{chunk}
\subsection{Support for output and graph paste-ins}
\begin{chunk}{util.ht}
\newcommand{\axiomcommand}[1]{\spadcommand{#1}}
\newcommand{\axiomgraph}[1]{\spadgraph{#1}}

\newcommand{\pastecommand}[1]{\spadpaste{#1}}
\newcommand{\pastegraph}[1]{\graphpaste{#1}}

\newcommand{\showpaste}{\htbitmap{sdown3d}}
\newcommand{\hidepaste}{\htbitmap{sup3d}}
\newcommand{\spadpaste}[1]{
  \newline
  \begin{paste}{\pagename Empty \examplenumber}
{\pagename Patch \examplenumber}
  \pastebutton{\pagename Empty \examplenumber}{\showpaste}
  \tab{5}\spadcommand{#1}
  \end{paste}
}

\newcommand{\graphpaste}[1]{
  \newline
  \begin{paste}{\pagename Empty \examplenumber}
{\pagename Patch \examplenumber}
  \pastebutton{\pagename Empty \examplenumber}{\showpaste}
  \tab{5}\spadgraph{#1}
  \end{paste}
}

\end{chunk}
\subsection{Hook for including a local menu item on the rootpage}
\begin{chunk}{util.ht}
\newcommand{\localinfo}{}

\end{chunk}
\pagetitle{SpadNotConnectedPage}{util.ht}{Not Connected to Axiom}
\pagefrom{Standard Pages}{HTXLinkPage2}
\begin{chunk}{util.ht}
\begin{page}{SpadNotConnectedPage}{Not Connected to Axiom}
\beginscroll
Hyperdoc isn't connected to Axiom, therefore cannot execute
the button you pressed.
%
\GoBackToWork{}
\endscroll
\end{page}

\end{chunk}
\pagetitle{ProtectedQuitPage}{util.ht}{Do You Really Want to Exit?}
\begin{chunk}{util.ht}
\begin{page}{ProtectedQuitPage}{Do You Really Want to Exit?}
\beginscroll
{Click again on \  \ExitButton{QuitPage} \  to terminate Hyperdoc.}
\vspace{1}\newline
\centerline{OR}
\GoBackToWork{}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{UnknownPage}{util.ht}{Missing Page}
\begin{chunk}{util.ht}
\begin{page}{UnknownPage}{Missing Page}
\beginscroll
\pp
The page you requested was not found in the Hyperdoc database.
\GoBackToWork{}
\endscroll
\end{page}

\end{chunk}
\pagetitle{ErrorPage}{util.ht}{Something is Wrong}
\begin{chunk}{util.ht}
\begin{page}{ErrorPage}{Something is Wrong}
\beginscroll
{For some reason the page you tried to link to cannot be formatted.}
\GoBackToWork{}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{Unlinked}{util.ht}{Sorry!}
\begin{chunk}{util.ht}
\begin{page}{Unlinked}{Sorry!}
\beginscroll
{This link is not implemented yet.}
\GoBackToWork{}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\chapter{Hyperdoc pages}
The hyperdoc pages can be viewed as a forest of rooted pages.
The main routine in hypertex will look for a page called ``RootPage''.
\pagefrom{Root Page}{RootPage}
\section{rootpage.ht}
\pagetitle{RootPage}{rootpage.ht}{Axiom HyperDoc Top Level}
\pagepic{ps/v71rootpage.eps}{rootpage}{0.50}
\pageto{Basic Commands}{BasicCommand}
\pageto{Reference}{TopReferencePage}
\pageto{Topics}{TopicPage}
\pageto{Browse}{Man0Page}
\pageto{Examples}{TopExamplePage}
\pageto{Settings}{TopSettingsPage}
\pageto{About Axiom}{RootPageLogo}
\pageto{What's New}{releaseNotes}
\begin{chunk}{rootpage.ht}
\begin{page}{RootPage}{Axiom HyperDoc Top Level}
\beginscroll
\centerline{\inputbitmap{\htbmdir{}/axiom1.bitmap}}
\horizontalline
\newline\tab{0}
What would you like to do?

\beginmenu

\menuwindowlink{Basic Commands}{BasicCommand}
\tab{16}Solve problems by filling in templates.

\menuwindowlink{Reference}{TopReferencePage}
\tab{16}Scan on-line documentation for Axiom.

\menuwindowlink{Topics}{TopicPage}
\tab{16}Learn how to use Axiom, by topic.

\menuwindowlink{Browse}{Man0Page}
\tab{16}Browse through the Axiom library.

\menuwindowlink{Examples}{TopExamplePage}
\tab{16}See examples of use of the library.

\menuwindowlink{Settings}{TopSettingsPage}
\tab{16}Display and change the system environment.

%\menuwindowlink{NAG Link}{htxl}
%\tab{16} Link to NAG Numerical Library.

%\menuwindowlink{\inputbitmap{\htbmdir{}/anna.xbm.tiny}}{UXANNA}
%\tab{16} The Axiom/NAG Numerical Analyst Expert System

\menuwindowlink{About Axiom}{RootPageLogo}
\tab{16}See some basic information about Axiom.

%\menuwindowlink{What's New}{ugWhatsNewTwoTwoPage}
\menuwindowlink{What's New}{releaseNotes}
\tab{16}Enhancements in this version of Axiom.

%menulispwindowlink is unsafe:TTT
%\menulispwindowlink{Settings}{(|htSystemVariables|)}
%\tab{16}Change an Axiom system variable.
%\menulispwindowlink{User Variables}{(|htUserVariables|)}
%\tab{16}Review user variables and \lispwindowlink{history}{(|htHistory|)}


%\localinfo
\endmenu
\endscroll
\autobutt{ugHyperPage}
\end{page}

\end{chunk}
\pagetitle{RootPageLogo}{rootpage.ht}
{Axiom -- The Scientific Computation System}
\pagepic{ps/v71rootpagelogo.eps}{rootpagelogo}{0.50}
\pagefrom{Root Page}{RootPage}
\begin{chunk}{rootpage.ht}
\begin{page}{RootPageLogo}{Axiom -- The Scientific Computation System}
\beginscroll
\centerline{\inputbitmap{\htbmdir{}/axiom1.bitmap}}
Axiom is now free and open source software released under the Modified
BSD license. For further information visit
\newline
http://axiom.axiom-developer.org
\newline
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997 by
the Numerical Algorithms Group Limited, which is also the 
proprietor of the trademarks Axiom and the Axiom logo and 
of the registered trademarks NAG and the NAG logo.
\newline
Axiom was originally developed by the Research Division of 
the International Business Machines Corporation, Yorktown 
Heights, New York, USA.
\endscroll
\end{page}

\end{chunk}
\pagetitle{TopSettingsPage}{rootpage.ht}{System Commands}
\pagepic{ps/v71topsettingspage.eps}{topsettingspage}{0.50}
\pagefrom{Root Page}{RootPage}
\pageto{Commands}{ugSysCmdPage}
\newline{}The ``Settings'' link is implemented in lisp.
\begin{chunk}{rootpage.ht}
\begin{page}{TopSettingsPage}{System Commands}
\beginscroll
System commands are used to perform Axiom environment
management and change Axiom system variables.
\beginmenu
\menumemolink{Commands}{ugSysCmdPage}
\tab{12}System commands that control your environment.

\menulispmemolink{Settings}{(|htSystemVariables|)}
\tab{12}Change an Axiom variable.

\endmenu
\endscroll
\end{page}

\end{chunk}
\pagetitle{TopExamplePage}{rootpage.ht}{Axiom Examples}
\pagepic{ps/v71topexamplepage.eps}{topexamplepage}{0.50}
\pagefrom{Root Page}{RootPage}
\pageto{Graphics}{GraphicsExamplePage}
\pageto{Domains}{ExamplesExposedPage}
\pageto{Operations}{ExampleCoverPage}
\begin{chunk}{rootpage.ht}
\begin{page}{TopExamplePage}{Axiom Examples}
\beginscroll
What would you like to see?
\beginmenu
\item\menudownlink{Graphics}{GraphicsExamplePage}
\tab{12}Examples of Axiom Graphics
\item\menudownlink{Domains}{ExamplesExposedPage}
\tab{12}Examples of use of Axiom domains and packages
\item\menudownlink{Operations}{ExampleCoverPage}
\tab{12}Examples of Axiom Operations, by topic
\endmenu
\endscroll
\autobuttons
\end{page}

\beginmenu
\item\menudownlink{Graphics}{GraphicsExamplePage}
\tab{12}Examples of Axiom Graphics
\item\menudownlink{Domains}{ExamplesExposedPage}
\tab{12}Examples of use of Axiom domains and packages
\item\menudownlink{Operations}{ExampleCoverPage}
\tab{12}Examples of Axiom Operations, by topic
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{TopReferencePage}{rootpage.ht}{Axiom Reference}
\pagepic{ps/v71topreferencepage.eps}{topreferencepage}{0.50}
\pagefrom{Root Page}{RootPage}
\pageto{this font}{YouTriedIt}
\pageto{What's New}{ugWhatsNewTwoTwoPage}
\pageto{Axiom Book}{UsersGuidePage}
\pageto{NAG Library}{FoundationLibraryDocPage}
\pageto{Topics}{TopicPage}
\pageto{Language}{ugLangPage}
\pageto{Examples}{ExamplesExposedPage}
\pageto{Commands}{ugSysCmdPage}
\pageto{Glossary}{GlossaryPage}
\pageto{HyperDoc}{HTXTopPage}
\pageto{Search}{RefSearchPage}
\begin{chunk}{rootpage.ht}
\begin{page}{TopReferencePage}{Axiom Reference}
\newline
\pp
To select an item, move the cursor with the mouse to
any word in \downlink{this font}{YouTriedIt} and click the left mouse button.
\beginscroll
\beginmenu
\menumemolink{What's New}{ugWhatsNewTwoTwoPage}
\tab{12}A synopsis of what's new in this release.

\menumemolink{Axiom Book}{UsersGuidePage}
\tab{12}The on-line version of the Jenks/Sutor book.

%\menumemolink{\asharp{} Guide}{AsUsersGuidePage}
%\tab{12}The on-line \asharp{} Users Guide.

\menumemolink{NAG Library}{FoundationLibraryDocPage}
\tab{12}The on-line \naglib{} documentation.

\menumemolink{Topics}{TopicPage}
\tab{12}Learn how to use Axiom, by topic.

\menumemolink{Language}{ugLangPage}
\tab{12}Introduction to the Axiom language.

\menumemolink{Examples}{ExamplesExposedPage}
\tab{12}Examples for exposed domains and packages

\menumemolink{Commands}{ugSysCmdPage}
\tab{12}System commands that control your workspace.

%\menumemolink{Operations}{NoPageYet} \tab{12}
%A guide to useful operations

%\menulispcommand{System Variables}{(|htsv|)}\tab{12}
%\tab{16}View and change a system-defined variable

\menumemolink{Glossary}{GlossaryPage}\tab{12}
A glossary of Axiom terms.

\menumemolink{Hyperdoc}{HTXTopPage}
\tab{12} How to write your own Hyperdoc pages.

\menumemolink{Search}{RefSearchPage}
\tab{12} Reference pages for occurrences of a string.
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{FoundationLibraryDocPage}{rootpage.ht}{NAG Documentation}
\pagepic{ps/v71foundationlibrarydocpage.eps}{foundationlibrarydocpage}{0.50}
\pagefrom{Reference}{TopReferencePage}
\begin{chunk}{rootpage.ht}
\begin{page}{FoundationLibraryDocPage}{NAG Documentation}
\begin{scroll}

\beginitems
\item\downlink{\menuitemstyle
{Essential Introduction to the NAG Foundation Library}}{manpageXXintro}
\item Foundation Library Chapter Manual Pages
\beginitems
\item\downlink{\menuitemstyle{C02}}
{manpageXXc02}\tab{8} Zeros of Polynomials
\indentrel{8}\newline
\table{
{\downlink{c02aff}{manpageXXc02aff}}
{\downlink{c02agf}{manpageXXc02agf}}
}\indentrel{-8}
\item\downlink{\menuitemstyle{C05}}
{manpageXXc05}\tab{8} Roots of One or More Transcendental Equations
\indentrel{8}\newline
\table{
{\downlink{c05adf}{manpageXXc05adf}}
{\downlink{c05nbf}{manpageXXc05nbf}}
{\downlink{c05pbf}{manpageXXc05pbf}}
{\downlink{c05zaf}{manpageXXc05zaf}}
}\indentrel{-8}
\item\downlink{\menuitemstyle{C06}}
{manpageXXc06}\tab{8} Summation of Series
\indentrel{8}\newline
\table{
{\downlink{c06eaf}{manpageXXc06eaf}}
{\downlink{c06ebf}{manpageXXc06ebf}}
{\downlink{c06ecf}{manpageXXc06ecf}}
{\downlink{c06ekf}{manpageXXc06ekf}}
{\downlink{c06fpf}{manpageXXc06fpf}}
{\downlink{c06fqf}{manpageXXc06fqf}}
{\downlink{c06frf}{manpageXXc06frf}}
{\downlink{c06fuf}{manpageXXc06fuf}}
{\downlink{c06gbf}{manpageXXc06gbf}}
{\downlink{c06gcf}{manpageXXc06gcf}}
{\downlink{c06gqf}{manpageXXc06gqf}}
{\downlink{c06gsf}{manpageXXc06gsf}}
}\indentrel{-8}
\item\downlink{\menuitemstyle{D01}}{manpageXXd01}\tab{8} Quadrature
\indentrel{8}\newline
\table{
{\downlink{d01ajf}{manpageXXd01ajf}}
{\downlink{d01akf}{manpageXXd01akf}}
{\downlink{d01alf}{manpageXXd01alf}}
{\downlink{d01amf}{manpageXXd01amf}}
{\downlink{d01anf}{manpageXXd01anf}}
{\downlink{d01apf}{manpageXXd01apf}}
{\downlink{d01aqf}{manpageXXd01aqf}}
{\downlink{d01asf}{manpageXXd01asf}}
{\downlink{d01bbf}{manpageXXd01bbf}}
{\downlink{d01fcf}{manpageXXd01fcf}}
{\downlink{d01gaf}{manpageXXd01gaf}}
{\downlink{d01gbf}{manpageXXd01gbf}}
}\indentrel{-8}
\item\downlink{\menuitemstyle{D02}}
{manpageXXd02}\tab{8} Ordinary Differential Equations
\indentrel{8}\newline
\table{
{\downlink{d02bbf}{manpageXXd02bbf}}
{\downlink{d02bhf}{manpageXXd02bhf}}
{\downlink{d02cjf}{manpageXXd02cjf}}
{\downlink{d02ejf}{manpageXXd02ejf}}
{\downlink{d02gaf}{manpageXXd02gaf}}
{\downlink{d02gbf}{manpageXXd02gbf}}
{\downlink{d02kef}{manpageXXd02kef}}
{\downlink{d02raf}{manpageXXd02raf}}
}\indentrel{-8}
\item\downlink{\menuitemstyle{D03}}
{manpageXXd03}\tab{8} Partial Differential Equations
\indentrel{8}\newline
\table{
{\downlink{d03edf}{manpageXXd03edf}}
{\downlink{d03eef}{manpageXXd03eef}}
{\downlink{d03faf}{manpageXXd03faf}}
}\indentrel{-8}
\item\downlink{\menuitemstyle{E01}}{manpageXXe01}\tab{8} Interpolation
\indentrel{8}\newline
\table{
{\downlink{e01baf}{manpageXXe01baf}}
{\downlink{e01bef}{manpageXXe01bef}}
{\downlink{e01bff}{manpageXXe01bff}}
{\downlink{e01bgf}{manpageXXe01bgf}}
{\downlink{e01bhf}{manpageXXe01bhf}}
{\downlink{e01daf}{manpageXXe01daf}}
{\downlink{e01saf}{manpageXXe01saf}}
{\downlink{e01sbf}{manpageXXe01sbf}}
{\downlink{e01sef}{manpageXXe01sef}}
{\downlink{e01sff}{manpageXXe01sff}}
}\indentrel{-8}
\item\downlink{\menuitemstyle{E02}}
{manpageXXe02}\tab{8} Curve and Surface Fitting
\indentrel{8}\newline
\table{
{\downlink{e02adf}{manpageXXe02adf}}
{\downlink{e02aef}{manpageXXe02aef}}
{\downlink{e02agf}{manpageXXe02agf}}
{\downlink{e02ahf}{manpageXXe02ahf}}
{\downlink{e02ajf}{manpageXXe02ajf}}
{\downlink{e02akf}{manpageXXe02akf}}
{\downlink{e02baf}{manpageXXe02baf}}
{\downlink{e02bbf}{manpageXXe02bbf}}
{\downlink{e02bcf}{manpageXXe02bcf}}
{\downlink{e02bdf}{manpageXXe02bdf}}
{\downlink{e02bef}{manpageXXe02bef}}
{\downlink{e02daf}{manpageXXe02daf}}
{\downlink{e02dcf}{manpageXXe02dcf}}
{\downlink{e02ddf}{manpageXXe02ddf}}
{\downlink{e02def}{manpageXXe02def}}
{\downlink{e02dff}{manpageXXe02dff}}
{\downlink{e02gaf}{manpageXXe02gaf}}
{\downlink{e02zaf}{manpageXXe02zaf}}
}\indentrel{-8}
\item\downlink{\menuitemstyle{E04}}
{manpageXXe04}\tab{8} Minimizing or Maximizing a Function
\indentrel{8}\newline
\table{
{\downlink{e04dgf}{manpageXXe04dgf}}
{\downlink{e04djf}{manpageXXe04djf}}
{\downlink{e04dkf}{manpageXXe04dkf}}
{\downlink{e04fdf}{manpageXXe04fdf}}
{\downlink{e04gcf}{manpageXXe04gcf}}
{\downlink{e04jaf}{manpageXXe04jaf}}
{\downlink{e04mbf}{manpageXXe04mbf}}
{\downlink{e04naf}{manpageXXe04naf}}
{\downlink{e04ucf}{manpageXXe04ucf}}
{\downlink{e04udf}{manpageXXe04udf}}
{\downlink{e04uef}{manpageXXe04uef}}
{\downlink{e04ycf}{manpageXXe04ycf}}
}\indentrel{-8}
\item\downlink{\menuitemstyle{F}}{manpageXXf}\tab{8} Linear Algebra
\item\downlink{\menuitemstyle{F01}}
{manpageXXf01}\tab{8} Matrix Operations, Including Inversion
\indentrel{8}\newline
\table{
{\downlink{f01brf}{manpageXXf01brf}}
{\downlink{f01bsf}{manpageXXf01bsf}}
{\downlink{f01maf}{manpageXXf01maf}}
{\downlink{f01mcf}{manpageXXf01mcf}}
{\downlink{f01qcf}{manpageXXf01qcf}}
{\downlink{f01qdf}{manpageXXf01qdf}}
{\downlink{f01qef}{manpageXXf01qef}}
{\downlink{f01rcf}{manpageXXf01rcf}}
{\downlink{f01rdf}{manpageXXf01rdf}}
{\downlink{f01ref}{manpageXXf01ref}}
}\indentrel{-8}
\item\downlink{\menuitemstyle{F02}}
{manpageXXf02}\tab{8} Eigenvalues and Eigenvectors
\indentrel{8}\newline
\table{
{\downlink{f02aaf}{manpageXXf02aaf}}
{\downlink{f02abf}{manpageXXf02abf}}
{\downlink{f02adf}{manpageXXf02adf}}
{\downlink{f02aef}{manpageXXf02aef}}
{\downlink{f02aff}{manpageXXf02aff}}
{\downlink{f02agf}{manpageXXf02agf}}
{\downlink{f02ajf}{manpageXXf02ajf}}
{\downlink{f02akf}{manpageXXf02akf}}
{\downlink{f02awf}{manpageXXf02awf}}
{\downlink{f02axf}{manpageXXf02axf}}
{\downlink{f02bbf}{manpageXXf02bbf}}
{\downlink{f02bjf}{manpageXXf02bjf}}
{\downlink{f02fjf}{manpageXXf02fjf}}
{\downlink{f02wef}{manpageXXf02wef}}
{\downlink{f02xef}{manpageXXf02xef}}
}\indentrel{-8}
\item\downlink{\menuitemstyle{F04}}
{manpageXXf04}\tab{8} Simultaneous Linear Equations
\indentrel{8}\newline
\table{
{\downlink{f04adf}{manpageXXf04adf}}
{\downlink{f04arf}{manpageXXf04arf}}
{\downlink{f04asf}{manpageXXf04asf}}
{\downlink{f04atf}{manpageXXf04atf}}
{\downlink{f04axf}{manpageXXf04axf}}
{\downlink{f04faf}{manpageXXf04faf}}
{\downlink{f04jgf}{manpageXXf04jgf}}
{\downlink{f04maf}{manpageXXf04maf}}
{\downlink{f04mbf}{manpageXXf04mbf}}
{\downlink{f04mcf}{manpageXXf04mcf}}
{\downlink{f04qaf}{manpageXXf04qaf}}
}\indentrel{-8}
\item\downlink{\menuitemstyle{F07}}
{manpageXXf07}\tab{8} Linear Equations (LAPACK)
\indentrel{8}\newline
\table{
{\downlink{f07adf}{manpageXXf07adf}}
{\downlink{f07aef}{manpageXXf07aef}}
{\downlink{f07fdf}{manpageXXf07fdf}}
{\downlink{f07fef}{manpageXXf07fef}}
}\indentrel{-8}
\item\downlink{\menuitemstyle{S}}
{manpageXXs}\tab{8} Approximations of Special Functions
\indentrel{8}\newline
\table{
{\downlink{s01eaf}{manpageXXs01eaf}}
{\downlink{s13aaf}{manpageXXs13aaf}}
{\downlink{s13acf}{manpageXXs13acf}}
{\downlink{s13adf}{manpageXXs13adf}}
{\downlink{s14aaf}{manpageXXs14aaf}}
{\downlink{s14abf}{manpageXXs14abf}}
{\downlink{s14baf}{manpageXXs14baf}}
{\downlink{s15adf}{manpageXXs15adf}}
{\downlink{s15aef}{manpageXXs15aef}}
{\downlink{s17acf}{manpageXXs17acf}}
{\downlink{s17adf}{manpageXXs17adf}}
{\downlink{s17aef}{manpageXXs17aef}}
{\downlink{s17aff}{manpageXXs17aff}}
{\downlink{s17agf}{manpageXXs17agf}}
{\downlink{s17ahf}{manpageXXs17ahf}}
{\downlink{s17ajf}{manpageXXs17ajf}}
{\downlink{s17akf}{manpageXXs17akf}}
{\downlink{s17dcf}{manpageXXs17dcf}}
{\downlink{s17def}{manpageXXs17def}}
{\downlink{s17dgf}{manpageXXs17dgf}}
{\downlink{s17dhf}{manpageXXs17dhf}}
{\downlink{s17dlf}{manpageXXs17dlf}}
{\downlink{s18acf}{manpageXXs18acf}}
{\downlink{s18adf}{manpageXXs18adf}}
{\downlink{s18aef}{manpageXXs18aef}}
{\downlink{s18aff}{manpageXXs18aff}}
{\downlink{s18dcf}{manpageXXs18dcf}}
{\downlink{s18def}{manpageXXs18def}}
{\downlink{s19aaf}{manpageXXs19aaf}}
{\downlink{s19abf}{manpageXXs19abf}}
{\downlink{s19acf}{manpageXXs19acf}}
{\downlink{s19adf}{manpageXXs19adf}}
{\downlink{s20acf}{manpageXXs20acf}}
{\downlink{s20adf}{manpageXXs20adf}}
{\downlink{s21baf}{manpageXXs21baf}}
{\downlink{s21bbf}{manpageXXs21bbf}}
{\downlink{s21bcf}{manpageXXs21bcf}}
{\downlink{s21bdf}{manpageXXs21bdf}}
}\indentrel{-8}
\enditems
\item\downlink{\menuitemstyle
{Introduction to NAG On-Line Documentation}}{manpageXXonline}
\item\downlink{\menuitemstyle{Keywords in Context}}{manpageXXkwic}
\item\downlink{\menuitemstyle{List of all \naglib{} Routines}}
{manpageXXsummary}
\item\downlink{\menuitemstyle
{Converting from the Workstation Library}}{manpageXXconvert}
\enditems
\end{scroll}
\end{page}

\end{chunk}
\section{algebra.ht}
\pagetitle{AlgebraPage}{algebra.ht}{Abstract Algebra}
\pagepic{ps/v71algebrapage.eps}{algebrapage}{0.50}
\pagefrom{Topics}{TopicPage}
\pageto{Number Theory}{NumberTheoryPage}
\pageto{Group Theory}{GroupTheoryPage}
\begin{chunk}{algebra.ht}
\begin{page}{AlgebraPage}{Abstract Algebra}
\beginscroll
Axiom provides various facilities for treating topics in abstract
algebra.
\beginmenu
\menulink{Number Theory}{NumberTheoryPage} \newline
Topics in algebraic number theory.
%\menulink{Algebraic Geometry}{AlgebraicGeometryPage} \newline
%Computational algebraic geometry: Groebner bases, integral bases,
%divisors on curves.
\menulink{Group Theory}{GroupTheoryPage} \newline
Permutation groups; representation theory.
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{NumberTheoryPage}{algebra.ht}{Number Theory}
\pageto{Galois Groups}{ugProblemGaloisPage}
\pageto{Number Theory Functions}{IntNumberTheoryFnsXmpPage}
\begin{chunk}{algebra.ht}
\begin{page}{NumberTheoryPage}{Number Theory}
\beginscroll
Here are some sample computations using Axiom's algebraic number
facilities.
\beginmenu
\menulink{Galois Groups}{ugProblemGaloisPage} \newline
Computation of Galois groups using factorizations over number fields.
\menulink{Number Theory Functions}
{IntNumberTheoryFnsXmpPage}\newline
Some functions of interest to number theorists.
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\section{alist.ht}
\pagetitle{AssociationListXmpPage}{alist.ht}{AssociationList}
\pageto{Table}{TableXmpPage}
\pageto{List}{ListXmpPage}
\begin{chunk}{alist.ht}
\begin{page}{AssociationListXmpPage}{AssociationList}
\beginscroll

The \spadtype{AssociationList} constructor provides a general
structure for associative storage.  This type provides association
lists in which data objects can be saved according to keys of any
type.  For a given association list, specific types must be chosen for
the keys and entries.  You can think of the representation of an
association list as a list of records with key and entry fields.

Association lists are a form of table and so most of the operations
available for \spadtype{Table} are also available for
\spadtype{AssociationList}.  They can also be viewed as lists and can
be manipulated accordingly.

\xtc{
This is a \pspadtype{Record} type with age and gender fields.
}{
\spadpaste{Data := Record(monthsOld : Integer, gender : String) \bound{Data}}
}
\xtc{
In this expression, \spad{al} is declared to be an association
list whose keys are strings and whose entries are the above records.
}{
\spadpaste{al : AssociationList(String,Data) \free{Data}\bound{al}}
}
\xtc{
The \spadfunFrom{table}{AssociationList} operation is used to create
an empty association list.
}{
\spadpaste{al := table() \free{al}\bound{al1}}
}
\xtc{
You can use assignment syntax to add things to the association list.
}{
\spadpaste{al."bob" := [407,"male"]\$Data \free{al1}\bound{al2}}
}
\xtc{
}{
\spadpaste{al."judith" := [366,"female"]\$Data \free{al2}\bound{al3}}
}
\xtc{
}{
\spadpaste{al."katie" := [24,"female"]\$Data \free{al3}\bound{al4}}
}
\xtc{
Perhaps we should have included a species field.
}{
\spadpaste{al."smokie" := [200,"female"]\$Data \free{al4}\bound{al5}}
}
\xtc{
Now look at what is in the association list.
Note that the last-added (key, entry) pair is at the beginning of the list.
}{
\spadpaste{al \free{al5}}
}
\xtc{
You can reset the entry for an existing key.
}{
\spadpaste{al."katie" := [23,"female"]\$Data \free{al5}\bound{al6}}
}
\xtc{
Use \spadfunFromX{delete}{AssociationList} to destructively remove
an element of the association list.
Use \spadfunFrom{delete}{AssociationList} to return a copy of the
association list with the element deleted.
The second argument is the index of the element to delete.
}{
\spadpaste{delete!(al,1) \free{al6}\bound{al7}}
}

For more information about tables, 
see \downlink{`Table'}{TableXmpPage}\ignore{Table}.
For more information about lists, 
see \downlink{`List'}{ListXmpPage}\ignore{List}.
\showBlurb{AssociationList}
\endscroll
\autobuttons
\end{page}

\begin{patch}{AssociationListXmpPagePatch1}
\begin{paste}{AssociationListXmpPageFull1}{AssociationListXmpPageEmpty1}
\pastebutton{AssociationListXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{
Data := Record(monthsOld : Integer, gender : String)\bound{Data }}
\indentrel{3}\begin{verbatim}
   (1)  Record(monthsOld: Integer,gender: String)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{AssociationListXmpPageEmpty1}
\begin{paste}{AssociationListXmpPageEmpty1}{AssociationListXmpPagePatch1}
\pastebutton{AssociationListXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{
Data := Record(monthsOld : Integer, gender : String)\bound{Data }}
\end{paste}\end{patch}

\begin{patch}{AssociationListXmpPagePatch2}
\begin{paste}{AssociationListXmpPageFull2}{AssociationListXmpPageEmpty2}
\pastebutton{AssociationListXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{
al : AssociationList(String,Data)\free{Data }\bound{al }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{AssociationListXmpPageEmpty2}
\begin{paste}{AssociationListXmpPageEmpty2}{AssociationListXmpPagePatch2}
\pastebutton{AssociationListXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{
al : AssociationList(String,Data)\free{Data }\bound{al }}
\end{paste}\end{patch}

\begin{patch}{AssociationListXmpPagePatch3}
\begin{paste}{AssociationListXmpPageFull3}{AssociationListXmpPageEmpty3}
\pastebutton{AssociationListXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{al := table()\free{al }\bound{al1 }}
\indentrel{3}\begin{verbatim}
   (3)  table()
Type: AssociationList(String,Record(monthsOld: Integer,gender: String))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{AssociationListXmpPageEmpty3}
\begin{paste}{AssociationListXmpPageEmpty3}{AssociationListXmpPagePatch3}
\pastebutton{AssociationListXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{al := table()\free{al }\bound{al1 }}
\end{paste}\end{patch}

\begin{patch}{AssociationListXmpPagePatch4}
\begin{paste}{AssociationListXmpPageFull4}{AssociationListXmpPageEmpty4}
\pastebutton{AssociationListXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{al."bob" := [407,"male"]$Data\free{al1 }\bound{al2 }}
\indentrel{3}\begin{verbatim}
   (4)  [monthsOld= 407,gender= "male"]
        Type: Record(monthsOld: Integer,gender: String)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{AssociationListXmpPageEmpty4}
\begin{paste}{AssociationListXmpPageEmpty4}{AssociationListXmpPagePatch4}
\pastebutton{AssociationListXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{al."bob" := [407,"male"]$Data\free{al1 }\bound{al2 }}
\end{paste}\end{patch}

\begin{patch}{AssociationListXmpPagePatch5}
\begin{paste}{AssociationListXmpPageFull5}{AssociationListXmpPageEmpty5}
\pastebutton{AssociationListXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{
al."judith" := [366,"female"]$Data\free{al2 }\bound{al3 }}
\indentrel{3}\begin{verbatim}
   (5)  [monthsOld= 366,gender= "female"]
        Type: Record(monthsOld: Integer,gender: String)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{AssociationListXmpPageEmpty5}
\begin{paste}{AssociationListXmpPageEmpty5}{AssociationListXmpPagePatch5}
\pastebutton{AssociationListXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{
al."judith" := [366,"female"]$Data\free{al2 }\bound{al3 }}
\end{paste}\end{patch}

\begin{patch}{AssociationListXmpPagePatch6}
\begin{paste}{AssociationListXmpPageFull6}{AssociationListXmpPageEmpty6}
\pastebutton{AssociationListXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{
al."katie" := [24,"female"]$Data\free{al3 }\bound{al4 }}
\indentrel{3}\begin{verbatim}
   (6)  [monthsOld= 24,gender= "female"]
        Type: Record(monthsOld: Integer,gender: String)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{AssociationListXmpPageEmpty6}
\begin{paste}{AssociationListXmpPageEmpty6}{AssociationListXmpPagePatch6}
\pastebutton{AssociationListXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{
al."katie" := [24,"female"]$Data\free{al3 }\bound{al4 }}
\end{paste}\end{patch}

\begin{patch}{AssociationListXmpPagePatch7}
\begin{paste}{AssociationListXmpPageFull7}{AssociationListXmpPageEmpty7}
\pastebutton{AssociationListXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{
al."smokie" := [200,"female"]$Data\free{al4 }\bound{al5 }}
\indentrel{3}\begin{verbatim}
   (7)  [monthsOld= 200,gender= "female"]
        Type: Record(monthsOld: Integer,gender: String)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{AssociationListXmpPageEmpty7}
\begin{paste}{AssociationListXmpPageEmpty7}{AssociationListXmpPagePatch7}
\pastebutton{AssociationListXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{
al."smokie" := [200,"female"]$Data\free{al4 }\bound{al5 }}
\end{paste}\end{patch}

\begin{patch}{AssociationListXmpPagePatch8}
\begin{paste}{AssociationListXmpPageFull8}{AssociationListXmpPageEmpty8}
\pastebutton{AssociationListXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{al\free{al5 }}
\indentrel{3}\begin{verbatim}
   (8)
   table
      "smokie"= [monthsOld= 200,gender= "female"]
  ,
      "katie"= [monthsOld= 24,gender= "female"]
  ,
      "judith"= [monthsOld= 366,gender= "female"]
  ,
      "bob"= [monthsOld= 407,gender= "male"]
Type: AssociationList(String,Record(monthsOld: Integer,gender: String))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{AssociationListXmpPageEmpty8}
\begin{paste}{AssociationListXmpPageEmpty8}{AssociationListXmpPagePatch8}
\pastebutton{AssociationListXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{al\free{al5 }}
\end{paste}\end{patch}

\begin{patch}{AssociationListXmpPagePatch9}
\begin{paste}{AssociationListXmpPageFull9}{AssociationListXmpPageEmpty9}
\pastebutton{AssociationListXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{
al."katie" := [23,"female"]$Data\free{al5 }\bound{al6 }}
\indentrel{3}\begin{verbatim}
   (9)  [monthsOld= 23,gender= "female"]
        Type: Record(monthsOld: Integer,gender: String)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{AssociationListXmpPageEmpty9}
\begin{paste}{AssociationListXmpPageEmpty9}{AssociationListXmpPagePatch9}
\pastebutton{AssociationListXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{
al."katie" := [23,"female"]$Data\free{al5 }\bound{al6 }}
\end{paste}\end{patch}

\begin{patch}{AssociationListXmpPagePatch10}
\begin{paste}{AssociationListXmpPageFull10}{AssociationListXmpPageEmpty10}
\pastebutton{AssociationListXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{delete!(al,1)\free{al6 }\bound{al7 }}
\indentrel{3}\begin{verbatim}
   (10)
   table
      "katie"= [monthsOld= 23,gender= "female"]
  ,
      "judith"= [monthsOld= 366,gender= "female"]
  ,
      "bob"= [monthsOld= 407,gender= "male"]
Type: AssociationList(String,Record(monthsOld: Integer,gender: String))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{AssociationListXmpPageEmpty10}
\begin{paste}
{AssociationListXmpPageEmpty10}{AssociationListXmpPagePatch10}
\pastebutton{AssociationListXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{delete!(al,1)\free{al6 }\bound{al7 }}
\end{paste}\end{patch}


\end{chunk}
\section{array1.ht}
\pagetitle{OneDimensionalArrayXmpPage}{array1.ht}{OneDimensionalArray}
\pageto{Vector}{VectorXmpPage}
\pageto{FlexibleArray}{FlexibleArrayXmpPage}
\begin{chunk}{array1.ht}
\begin{page}{OneDimensionalArrayXmpPage}{OneDimensionalArray}
\beginscroll
The \spadtype{OneDimensionalArray} domain is used for storing data in
a one-dimensional indexed data structure.  Such an array is a
homogeneous data structure in that all the entries of the array must
belong to the same Axiom domain.  Each array has a fixed length
specified by the user and arrays are not extensible.  The indexing of
one-dimensional arrays is one-based.  This means that the ``first''
element of an array is given the index \spad{1}.
See also \downlink{`Vector'}{VectorXmpPage}\ignore{Vector} and 
\downlink{`FlexibleArray'}{FlexibleArrayXmpPage}\ignore{FlexibleArray}.
\xtc{
To create a one-dimensional array, apply the
operation \spadfun{oneDimensionalArray} to a list.
}{
\spadpaste{oneDimensionalArray [i**2 for i in 1..10]}
}
\xtc{
Another approach is to first create \spad{a}, a one-dimensional 
array of 10 \spad{0}'s.
\spadtype{OneDimensionalArray} has the convenient 
abbreviation \spadtype{ARRAY1}.
}{
\spadpaste{a : ARRAY1 INT := new(10,0)\bound{a}}
}
\xtc{
Set each \spad{i}th element to i, then display the result.
}{
\spadpaste{for i in 1..10 repeat a.i := i; a\bound{a1}\free{a}}
}
\xtc{
Square each element by mapping the function
\texht{$i \mapsto i^2$}{i +-> i**2} onto each element.
}{
\spadpaste{map!(i +-> i ** 2,a); a\bound{a3}\free{a2}}
}
\xtc{
Reverse the elements in place.
}{
\spadpaste{reverse! a\bound{a4}\free{a3}}
}
\xtc{
Swap the \spad{4}th and \spad{5}th element.
}{
\spadpaste{swap!(a,4,5); a\bound{a5}\free{a4}}
}
\xtc{
Sort the elements in place.
}{
\spadpaste{sort! a \bound{a6}\free{a5}}
}
\xtc{
Create a new one-dimensional array \spad{b} containing the 
last 5 elements of \spad{a}.
}{
\spadpaste{b := a(6..10)\bound{b}\free{a6}}
}
\xtc{
Replace the first 5 elements of \spad{a} with those of \spad{b}.
}{
\spadpaste{copyInto!(a,b,1)\free{b}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{OneDimensionalArrayXmpPagePatch1}
\begin{paste}{OneDimensionalArrayXmpPageFull1}
{OneDimensionalArrayXmpPageEmpty1}
\pastebutton{OneDimensionalArrayXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{oneDimensionalArray [i**2 for i in 1..10]}
\indentrel{3}\begin{verbatim}
   (1)  [1,4,9,16,25,36,49,64,81,100]
              Type: OneDimensionalArray PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OneDimensionalArrayXmpPageEmpty1}
\begin{paste}{OneDimensionalArrayXmpPageEmpty1}
{OneDimensionalArrayXmpPagePatch1}
\pastebutton{OneDimensionalArrayXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{oneDimensionalArray [i**2 for i in 1..10]}
\end{paste}\end{patch}

\begin{patch}{OneDimensionalArrayXmpPagePatch2}
\begin{paste}{OneDimensionalArrayXmpPageFull2}
{OneDimensionalArrayXmpPageEmpty2}
\pastebutton{OneDimensionalArrayXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{a : ARRAY1 INT := new(10,0)\bound{a }}
\indentrel{3}\begin{verbatim}
   (2)  [0,0,0,0,0,0,0,0,0,0]
                      Type: OneDimensionalArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OneDimensionalArrayXmpPageEmpty2}
\begin{paste}{OneDimensionalArrayXmpPageEmpty2}
{OneDimensionalArrayXmpPagePatch2}
\pastebutton{OneDimensionalArrayXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{a : ARRAY1 INT := new(10,0)\bound{a }}
\end{paste}\end{patch}

\begin{patch}{OneDimensionalArrayXmpPagePatch3}
\begin{paste}{OneDimensionalArrayXmpPageFull3}
{OneDimensionalArrayXmpPageEmpty3}
\pastebutton{OneDimensionalArrayXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{
for i in 1..10 repeat a.i := i; a\bound{a1 }\free{a }}
\indentrel{3}\begin{verbatim}
   (3)  [1,2,3,4,5,6,7,8,9,10]
                      Type: OneDimensionalArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OneDimensionalArrayXmpPageEmpty3}
\begin{paste}{OneDimensionalArrayXmpPageEmpty3}
{OneDimensionalArrayXmpPagePatch3}
\pastebutton{OneDimensionalArrayXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{
for i in 1..10 repeat a.i := i; a\bound{a1 }\free{a }}
\end{paste}\end{patch}

\begin{patch}{OneDimensionalArrayXmpPagePatch4}
\begin{paste}{OneDimensionalArrayXmpPageFull4}
{OneDimensionalArrayXmpPageEmpty4}
\pastebutton{OneDimensionalArrayXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{map!(i +-> i ** 2,a); a\bound{a3 }\free{a2 }}
\indentrel{3}\begin{verbatim}
   (4)  [1,4,9,16,25,36,49,64,81,100]
                      Type: OneDimensionalArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OneDimensionalArrayXmpPageEmpty4}
\begin{paste}{OneDimensionalArrayXmpPageEmpty4}
{OneDimensionalArrayXmpPagePatch4}
\pastebutton{OneDimensionalArrayXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{map!(i +-> i ** 2,a); a\bound{a3 }\free{a2 }}
\end{paste}\end{patch}

\begin{patch}{OneDimensionalArrayXmpPagePatch5}
\begin{paste}{OneDimensionalArrayXmpPageFull5}
{OneDimensionalArrayXmpPageEmpty5}
\pastebutton{OneDimensionalArrayXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{reverse! a\bound{a4 }\free{a3 }}
\indentrel{3}\begin{verbatim}
   (5)  [100,81,64,49,36,25,16,9,4,1]
                      Type: OneDimensionalArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OneDimensionalArrayXmpPageEmpty5}
\begin{paste}{OneDimensionalArrayXmpPageEmpty5}
{OneDimensionalArrayXmpPagePatch5}
\pastebutton{OneDimensionalArrayXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{reverse! a\bound{a4 }\free{a3 }}
\end{paste}\end{patch}

\begin{patch}{OneDimensionalArrayXmpPagePatch6}
\begin{paste}{OneDimensionalArrayXmpPageFull6}
{OneDimensionalArrayXmpPageEmpty6}
\pastebutton{OneDimensionalArrayXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{swap!(a,4,5); a\bound{a5 }\free{a4 }}
\indentrel{3}\begin{verbatim}
   (6)  [100,81,64,36,49,25,16,9,4,1]
                      Type: OneDimensionalArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OneDimensionalArrayXmpPageEmpty6}
\begin{paste}{OneDimensionalArrayXmpPageEmpty6}
{OneDimensionalArrayXmpPagePatch6}
\pastebutton{OneDimensionalArrayXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{swap!(a,4,5); a\bound{a5 }\free{a4 }}
\end{paste}\end{patch}

\begin{patch}{OneDimensionalArrayXmpPagePatch7}
\begin{paste}{OneDimensionalArrayXmpPageFull7}
{OneDimensionalArrayXmpPageEmpty7}
\pastebutton{OneDimensionalArrayXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{sort! a\bound{a6 }\free{a5 }}
\indentrel{3}\begin{verbatim}
   (7)  [1,4,9,16,25,36,49,64,81,100]
                      Type: OneDimensionalArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OneDimensionalArrayXmpPageEmpty7}
\begin{paste}{OneDimensionalArrayXmpPageEmpty7}
{OneDimensionalArrayXmpPagePatch7}
\pastebutton{OneDimensionalArrayXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{sort! a\bound{a6 }\free{a5 }}
\end{paste}\end{patch}

\begin{patch}{OneDimensionalArrayXmpPagePatch8}
\begin{paste}{OneDimensionalArrayXmpPageFull8}
{OneDimensionalArrayXmpPageEmpty8}
\pastebutton{OneDimensionalArrayXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{b := a(6..10)\bound{b }\free{a6 }}
\indentrel{3}\begin{verbatim}
   (8)  [36,49,64,81,100]
                      Type: OneDimensionalArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OneDimensionalArrayXmpPageEmpty8}
\begin{paste}{OneDimensionalArrayXmpPageEmpty8}
{OneDimensionalArrayXmpPagePatch8}
\pastebutton{OneDimensionalArrayXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{b := a(6..10)\bound{b }\free{a6 }}
\end{paste}\end{patch}

\begin{patch}{OneDimensionalArrayXmpPagePatch9}
\begin{paste}{OneDimensionalArrayXmpPageFull9}
{OneDimensionalArrayXmpPageEmpty9}
\pastebutton{OneDimensionalArrayXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{copyInto!(a,b,1)\free{b }}
\indentrel{3}\begin{verbatim}
   (9)  [36,49,64,81,100,36,49,64,81,100]
                      Type: OneDimensionalArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OneDimensionalArrayXmpPageEmpty9}
\begin{paste}{OneDimensionalArrayXmpPageEmpty9}
{OneDimensionalArrayXmpPagePatch9}
\pastebutton{OneDimensionalArrayXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{copyInto!(a,b,1)\free{b }}
\end{paste}\end{patch}

\end{chunk}
\section{array2.ht}
\pagetitle{TwoDimensionalArrayXmpPage}{array2.ht}{TwoDimensionalArray}
\pageto{The Any Domain}{ugTypesAnyNonePage}
\pageto{Matrix}{MatrixXmpPage}
\pageto{OneDimensionalArray}{OneDimensionalArrayXmpPage}
\begin{chunk}{array2.ht}
\begin{page}{TwoDimensionalArrayXmpPage}{TwoDimensionalArray}
\beginscroll

The \spadtype{TwoDimensionalArray} domain is used for storing data in
a \twodim{} data structure indexed by row and by column.  Such an
array is a homogeneous data structure in that all the entries of the
array must belong to the same Axiom domain (although see
\downlink{``The Any Domain''}{ugTypesAnyNonePage} in Section 2.6
\ignore{ugTypesAnyNone}).  Each array has a fixed
number of rows and columns specified by the user and arrays are not
extensible.  In Axiom, the indexing of two-dimensional arrays is
one-based.  This means that both the ``first'' row of an array and the
``first'' column of an array are given the index \spad{1}.  Thus, the
entry in the upper left corner of an array is in position
\spad{(1,1)}.


The operation \spadfunFrom{new}{TwoDimensionalArray} creates an array
with a specified number of rows and columns and fills the components
of that array with a specified entry.  The arguments of this operation
specify the number of rows, the number of columns, and the entry.
\xtc{
This creates a five-by-four array of integers, all of whose entries are
zero.
}{
\spadpaste{arr : ARRAY2 INT := new(5,4,0) \bound{arr}}
}
The entries of this array can be set to other integers using
the operation \spadfunFrom{setelt}{TwoDimensionalArray}.

\xtc{
Issue this to set the element in the upper left corner of this array to
\spad{17}.
}{
\spadpaste{setelt(arr,1,1,17) \free{arr}\bound{arr1}}
}
\xtc{
Now the first element of the array is \spad{17.}
}{
\spadpaste{arr \free{arr1}}
}
\xtc{
Likewise, elements of an array are extracted using the operation
\spadfunFrom{elt}{TwoDimensionalArray}.
}{
\spadpaste{elt(arr,1,1) \free{arr1}}
}
\xtc{
Another way to use these two operations is as follows.
This sets the element in position \spad{(3,2)} of the array to \spad{15}.
}{
\spadpaste{arr(3,2) := 15 \free{arr1}\bound{arr2}}
}
\xtc{
This extracts the element in position \spad{(3,2)} of the array.
}{
\spadpaste{arr(3,2) \free{arr2}}
}
The operations \spadfunFrom{elt}{TwoDimensionalArray} and
\spadfunFrom{setelt}{TwoDimensionalArray} come equipped with an error
check which verifies that the indices are in the proper ranges.
For example, the above array has five rows and four columns, so if you ask
for the entry in position \spad{(6,2)} with \spad{arr(6,2)} Axiom
displays an error message.
If there is no need for an error check, you can call the operations
\spadfunFrom{qelt}{TwoDimensionalArray} and
\spadfunFromX{qsetelt}{TwoDimensionalArray} which provide the same
functionality but without the error check.
Typically, these operations are called in well-tested programs.

\xtc{
The operations \spadfunFrom{row}{TwoDimensionalArray} and
\spadfunFrom{column}{TwoDimensionalArray} extract rows and columns,
respectively, and return objects of \spadtype{OneDimensionalArray} with
the same underlying element type.
}{
\spadpaste{row(arr,1) \free{arr2}}
}
\xtc{
}{
\spadpaste{column(arr,1) \free{arr2}}
}

\xtc{
You can determine the dimensions of an array by calling the
operations \spadfunFrom{nrows}{TwoDimensionalArray} and
\spadfunFrom{ncols}{TwoDimensionalArray},
which return the number of rows and columns, respectively.
}{
\spadpaste{nrows(arr) \free{arr2}}
}
\xtc{
}{
\spadpaste{ncols(arr) \free{arr2}}
}
\xtc{
To apply an operation to every element of an array, use
\spadfunFrom{map}{TwoDimensionalArray}.
This creates a new array.
This expression negates every element.
}{
\spadpaste{map(-,arr) \free{arr2}}
}
\xtc{
This creates an array where all the elements are doubled.
}{
\spadpaste{map((x +-> x + x),arr) \free{arr2}}
}
\xtc{
To change the array destructively, use
\spadfunFromX{map}{TwoDimensionalArray} instead of
\spadfunFrom{map}{TwoDimensionalArray}.
If you need to make a copy of any array, use
\spadfunFrom{copy}{TwoDimensionalArray}.
}{
\spadpaste{arrc := copy(arr) \bound{arrc}\free{arr2}}
}
\xtc{
}{
\spadpaste{map!(-,arrc) \free{arrc}}
}
\xtc{
}{
\spadpaste{arrc \free{arrc}}
}
\xtc{
}{
\spadpaste{arr  \free{arr2}}
}

\xtc{
Use \spadfunFrom{member?}{TwoDimensionalArray} to see if a given element
is in an array.
}{
\spadpaste{member?(17,arr) \free{arr2}}
}
\xtc{
}{
\spadpaste{member?(10317,arr) \free{arr2}}
}
\xtc{
To see how many times an element appears in an array, use
\spadfunFrom{count}{TwoDimensionalArray}.
}{
\spadpaste{count(17,arr) \free{arr2}}
}
\xtc{
}{
\spadpaste{count(0,arr) \free{arr2}}
}

For more information about the operations available for
\spadtype{TwoDimensionalArray}, issue \spadcmd{)show
TwoDimensionalArray}.
For information on related topics, see 
\downlink{`Matrix'}{MatrixXmpPage}\ignore{Matrix} and
\downlink{`OneDimensionalArray'}{OneDimensionalArrayXmpPage}
\ignore{OneDimensionalArray}.
\endscroll
\autobuttons
\end{page}

\begin{patch}{TwoDimensionalArrayXmpPagePatch1}
\begin{paste}{TwoDimensionalArrayXmpPageFull1}
{TwoDimensionalArrayXmpPageEmpty1}
\pastebutton{TwoDimensionalArrayXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{arr : ARRAY2 INT := new(5,4,0)\bound{arr }}
\indentrel{3}\begin{verbatim}
        Ú0  0  0  0¿
        ³          ³
        ³0  0  0  0³
        ³          ³
   (1)  ³0  0  0  0³
        ³          ³
        ³0  0  0  0³
        ³          ³
        À0  0  0  0Ù
                      Type: TwoDimensionalArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPageEmpty1}
\begin{paste}{TwoDimensionalArrayXmpPageEmpty1}
{TwoDimensionalArrayXmpPagePatch1}
\pastebutton{TwoDimensionalArrayXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{arr : ARRAY2 INT := new(5,4,0)\bound{arr }}
\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPagePatch2}
\begin{paste}{TwoDimensionalArrayXmpPageFull2}
{TwoDimensionalArrayXmpPageEmpty2}
\pastebutton{TwoDimensionalArrayXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{setelt(arr,1,1,17)\free{arr }\bound{arr1 }}
\indentrel{3}\begin{verbatim}
   (2)  17
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPageEmpty2}
\begin{paste}{TwoDimensionalArrayXmpPageEmpty2}
{TwoDimensionalArrayXmpPagePatch2}
\pastebutton{TwoDimensionalArrayXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{setelt(arr,1,1,17)\free{arr }\bound{arr1 }}
\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPagePatch3}
\begin{paste}{TwoDimensionalArrayXmpPageFull3}
{TwoDimensionalArrayXmpPageEmpty3}
\pastebutton{TwoDimensionalArrayXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{arr\free{arr1 }}
\indentrel{3}\begin{verbatim}
        Ú17  0  0  0¿
        ³           ³
        ³0   0  0  0³
        ³           ³
   (3)  ³0   0  0  0³
        ³           ³
        ³0   0  0  0³
        ³           ³
        À0   0  0  0Ù
                      Type: TwoDimensionalArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPageEmpty3}
\begin{paste}{TwoDimensionalArrayXmpPageEmpty3}
{TwoDimensionalArrayXmpPagePatch3}
\pastebutton{TwoDimensionalArrayXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{arr\free{arr1 }}
\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPagePatch4}
\begin{paste}{TwoDimensionalArrayXmpPageFull4}
{TwoDimensionalArrayXmpPageEmpty4}
\pastebutton{TwoDimensionalArrayXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{elt(arr,1,1)\free{arr1 }}
\indentrel{3}\begin{verbatim}
   (4)  17
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPageEmpty4}
\begin{paste}{TwoDimensionalArrayXmpPageEmpty4}
{TwoDimensionalArrayXmpPagePatch4}
\pastebutton{TwoDimensionalArrayXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{elt(arr,1,1)\free{arr1 }}
\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPagePatch5}
\begin{paste}{TwoDimensionalArrayXmpPageFull5}
{TwoDimensionalArrayXmpPageEmpty5}
\pastebutton{TwoDimensionalArrayXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{arr(3,2) := 15\free{arr1 }\bound{arr2 }}
\indentrel{3}\begin{verbatim}
   (5)  15
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPageEmpty5}
\begin{paste}{TwoDimensionalArrayXmpPageEmpty5}
{TwoDimensionalArrayXmpPagePatch5}
\pastebutton{TwoDimensionalArrayXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{arr(3,2) := 15\free{arr1 }\bound{arr2 }}
\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPagePatch6}
\begin{paste}{TwoDimensionalArrayXmpPageFull6}
{TwoDimensionalArrayXmpPageEmpty6}
\pastebutton{TwoDimensionalArrayXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{arr(3,2)\free{arr2 }}
\indentrel{3}\begin{verbatim}
   (6)  15
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPageEmpty6}
\begin{paste}{TwoDimensionalArrayXmpPageEmpty6}
{TwoDimensionalArrayXmpPagePatch6}
\pastebutton{TwoDimensionalArrayXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{arr(3,2)\free{arr2 }}
\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPagePatch7}
\begin{paste}{TwoDimensionalArrayXmpPageFull7}
{TwoDimensionalArrayXmpPageEmpty7}
\pastebutton{TwoDimensionalArrayXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{row(arr,1)\free{arr2 }}
\indentrel{3}\begin{verbatim}
   (7)  [17,0,0,0]
                      Type: OneDimensionalArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPageEmpty7}
\begin{paste}{TwoDimensionalArrayXmpPageEmpty7}
{TwoDimensionalArrayXmpPagePatch7}
\pastebutton{TwoDimensionalArrayXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{row(arr,1)\free{arr2 }}
\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPagePatch8}
\begin{paste}{TwoDimensionalArrayXmpPageFull8}
{TwoDimensionalArrayXmpPageEmpty8}
\pastebutton{TwoDimensionalArrayXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{column(arr,1)\free{arr2 }}
\indentrel{3}\begin{verbatim}
   (8)  [17,0,0,0,0]
                      Type: OneDimensionalArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPageEmpty8}
\begin{paste}{TwoDimensionalArrayXmpPageEmpty8}
{TwoDimensionalArrayXmpPagePatch8}
\pastebutton{TwoDimensionalArrayXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{column(arr,1)\free{arr2 }}
\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPagePatch9}
\begin{paste}{TwoDimensionalArrayXmpPageFull9}
{TwoDimensionalArrayXmpPageEmpty9}
\pastebutton{TwoDimensionalArrayXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{nrows(arr)\free{arr2 }}
\indentrel{3}\begin{verbatim}
   (9)  5
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPageEmpty9}
\begin{paste}{TwoDimensionalArrayXmpPageEmpty9}
{TwoDimensionalArrayXmpPagePatch9}
\pastebutton{TwoDimensionalArrayXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{nrows(arr)\free{arr2 }}
\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPagePatch10}
\begin{paste}{TwoDimensionalArrayXmpPageFull10}
{TwoDimensionalArrayXmpPageEmpty10}
\pastebutton{TwoDimensionalArrayXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{ncols(arr)\free{arr2 }}
\indentrel{3}\begin{verbatim}
   (10)  4
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPageEmpty10}
\begin{paste}{TwoDimensionalArrayXmpPageEmpty10}
{TwoDimensionalArrayXmpPagePatch10}
\pastebutton{TwoDimensionalArrayXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{ncols(arr)\free{arr2 }}
\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPagePatch11}
\begin{paste}{TwoDimensionalArrayXmpPageFull11}
{TwoDimensionalArrayXmpPageEmpty11}
\pastebutton{TwoDimensionalArrayXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{map(-,arr)\free{arr2 }}
\indentrel{3}\begin{verbatim}
         Ú- 17   0    0  0¿
         ³                ³
         ³ 0     0    0  0³
         ³                ³
   (11)  ³ 0    - 15  0  0³
         ³                ³
         ³ 0     0    0  0³
         ³                ³
         À 0     0    0  0Ù
                      Type: TwoDimensionalArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPageEmpty11}
\begin{paste}{TwoDimensionalArrayXmpPageEmpty11}
{TwoDimensionalArrayXmpPagePatch11}
\pastebutton{TwoDimensionalArrayXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{map(-,arr)\free{arr2 }}
\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPagePatch12}
\begin{paste}{TwoDimensionalArrayXmpPageFull12}
{TwoDimensionalArrayXmpPageEmpty12}
\pastebutton{TwoDimensionalArrayXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{map((x +-> x + x),arr)\free{arr2 }}
\indentrel{3}\begin{verbatim}
         Ú34  0   0  0¿
         ³            ³
         ³0   0   0  0³
         ³            ³
   (12)  ³0   30  0  0³
         ³            ³
         ³0   0   0  0³
         ³            ³
         À0   0   0  0Ù
                      Type: TwoDimensionalArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPageEmpty12}
\begin{paste}{TwoDimensionalArrayXmpPageEmpty12}
{TwoDimensionalArrayXmpPagePatch12}
\pastebutton{TwoDimensionalArrayXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{map((x +-> x + x),arr)\free{arr2 }}
\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPagePatch13}
\begin{paste}{TwoDimensionalArrayXmpPageFull13}
{TwoDimensionalArrayXmpPageEmpty13}
\pastebutton{TwoDimensionalArrayXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{arrc := copy(arr)\bound{arrc }\free{arr2 }}
\indentrel{3}\begin{verbatim}
         Ú17  0   0  0¿
         ³            ³
         ³0   0   0  0³
         ³            ³
   (13)  ³0   15  0  0³
         ³            ³
         ³0   0   0  0³
         ³            ³
         À0   0   0  0Ù
                      Type: TwoDimensionalArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPageEmpty13}
\begin{paste}{TwoDimensionalArrayXmpPageEmpty13}
{TwoDimensionalArrayXmpPagePatch13}
\pastebutton{TwoDimensionalArrayXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{arrc := copy(arr)\bound{arrc }\free{arr2 }}
\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPagePatch14}
\begin{paste}{TwoDimensionalArrayXmpPageFull14}
{TwoDimensionalArrayXmpPageEmpty14}
\pastebutton{TwoDimensionalArrayXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{map!(-,arrc)\free{arrc }}
\indentrel{3}\begin{verbatim}
         Ú- 17   0    0  0¿
         ³                ³
         ³ 0     0    0  0³
         ³                ³
   (14)  ³ 0    - 15  0  0³
         ³                ³
         ³ 0     0    0  0³
         ³                ³
         À 0     0    0  0Ù
                      Type: TwoDimensionalArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPageEmpty14}
\begin{paste}{TwoDimensionalArrayXmpPageEmpty14}
{TwoDimensionalArrayXmpPagePatch14}
\pastebutton{TwoDimensionalArrayXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{map!(-,arrc)\free{arrc }}
\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPagePatch15}
\begin{paste}{TwoDimensionalArrayXmpPageFull15}
{TwoDimensionalArrayXmpPageEmpty15}
\pastebutton{TwoDimensionalArrayXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{arrc\free{arrc }}
\indentrel{3}\begin{verbatim}
         Ú- 17   0    0  0¿
         ³                ³
         ³ 0     0    0  0³
         ³                ³
   (15)  ³ 0    - 15  0  0³
         ³                ³
         ³ 0     0    0  0³
         ³                ³
         À 0     0    0  0Ù
                      Type: TwoDimensionalArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPageEmpty15}
\begin{paste}{TwoDimensionalArrayXmpPageEmpty15}
{TwoDimensionalArrayXmpPagePatch15}
\pastebutton{TwoDimensionalArrayXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{arrc\free{arrc }}
\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPagePatch16}
\begin{paste}{TwoDimensionalArrayXmpPageFull16}
{TwoDimensionalArrayXmpPageEmpty16}
\pastebutton{TwoDimensionalArrayXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{arr\free{arr2 }}
\indentrel{3}\begin{verbatim}
         Ú17  0   0  0¿
         ³            ³
         ³0   0   0  0³
         ³            ³
   (16)  ³0   15  0  0³
         ³            ³
         ³0   0   0  0³
         ³            ³
         À0   0   0  0Ù
                      Type: TwoDimensionalArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPageEmpty16}
\begin{paste}{TwoDimensionalArrayXmpPageEmpty16}
{TwoDimensionalArrayXmpPagePatch16}
\pastebutton{TwoDimensionalArrayXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{arr\free{arr2 }}
\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPagePatch17}
\begin{paste}{TwoDimensionalArrayXmpPageFull17}
{TwoDimensionalArrayXmpPageEmpty17}
\pastebutton{TwoDimensionalArrayXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{member?(17,arr)\free{arr2 }}
\indentrel{3}\begin{verbatim}
   (17)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPageEmpty17}
\begin{paste}{TwoDimensionalArrayXmpPageEmpty17}
{TwoDimensionalArrayXmpPagePatch17}
\pastebutton{TwoDimensionalArrayXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{member?(17,arr)\free{arr2 }}
\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPagePatch18}
\begin{paste}{TwoDimensionalArrayXmpPageFull18}
{TwoDimensionalArrayXmpPageEmpty18}
\pastebutton{TwoDimensionalArrayXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{member?(10317,arr)\free{arr2 }}
\indentrel{3}\begin{verbatim}
   (18)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPageEmpty18}
\begin{paste}{TwoDimensionalArrayXmpPageEmpty18}
{TwoDimensionalArrayXmpPagePatch18}
\pastebutton{TwoDimensionalArrayXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{member?(10317,arr)\free{arr2 }}
\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPagePatch19}
\begin{paste}{TwoDimensionalArrayXmpPageFull19}
{TwoDimensionalArrayXmpPageEmpty19}
\pastebutton{TwoDimensionalArrayXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{count(17,arr)\free{arr2 }}
\indentrel{3}\begin{verbatim}
   (19)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPageEmpty19}
\begin{paste}{TwoDimensionalArrayXmpPageEmpty19}
{TwoDimensionalArrayXmpPagePatch19}
\pastebutton{TwoDimensionalArrayXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{count(17,arr)\free{arr2 }}
\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPagePatch20}
\begin{paste}{TwoDimensionalArrayXmpPageFull20}
{TwoDimensionalArrayXmpPageEmpty20}
\pastebutton{TwoDimensionalArrayXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{count(0,arr)\free{arr2 }}
\indentrel{3}\begin{verbatim}
   (20)  18
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TwoDimensionalArrayXmpPageEmpty20}
\begin{paste}{TwoDimensionalArrayXmpPageEmpty20}
{TwoDimensionalArrayXmpPagePatch20}
\pastebutton{TwoDimensionalArrayXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{count(0,arr)\free{arr2 }}
\end{paste}\end{patch}


\end{chunk}
\section{basic.ht}
\pagetitle{BasicCommand}{basic.ht}{Basic Commands}
\pagepic{ps/v71basiccommand.eps}{basiccommand}{0.50}
\pagefrom{Root Page}{RootPage}
\pageto{Calculus}{Calculus}
\pageto{Matrix}{LispFunctions}
\pageto{Draw}{LispFunctions}
\pageto{Series}{LispFunctions}
\pageto{Solve}{LispFunctions}
\index{Function!bcMatrix}
\index{bcMatrix Function}
\index{Function!bcExpand}
\index{bcExpand Function}
\index{Function!bcDraw}
\index{bcDraw Function}
\index{Function!bcSeries}
\index{bcSeries Function}
\index{Function!bcSolve}
\index{bcSolve Function}
\begin{chunk}{basic.ht}
\begin{page}{BasicCommand}{Basic Commands}
\beginscroll
\beginmenu
\menumemolink{Calculus}{Calculus}\tab{10}
  Compute integrals, derivatives, or limits
\menulispmemolink{Matrix}{(|bcMatrix|)}\tab{10}
  Create a matrix
%\menulispmemolink{Operations}{(|bcExpand|)}
%  Expand, factor, simplify, substitute, etc.
\menulispmemolink{Draw}{(|bcDraw|)}\tab{10}
  Create 2D or 3D plots.
\menulispmemolink{Series}{(|bcSeries|)}\tab{10}
  Create a power series
\menulispmemolink{Solve}{(|bcSolve|)}\tab{10}
  Solve an equation or system of equations.
\endmenu
\endscroll
\autobuttons 
\end{page}
 
\end{chunk}
\pagetitle{Calculus}{basic.ht}{Calculus}
\pagepic{ps/v71calculus.eps}{calculus}{0.50}
\pagefrom{Basic Commands}{BasicCommand}
\pageto{Differentiate}{LispFunctions}
\pageto{Do an Indefinite Integral}{LispFunctions}
\pageto{Do a Definite Integral}{LispFunctions}
\pageto{Find a Limit}{LispFunctions}
\pageto{Do a summation}{LispFunctions}
\index{Function!bcDifferentiate}
\index{bcDifferentiate Function}
\index{Function!bcIndefiniteIntegral}
\index{bcIndefiniteIntegral Function}
\index{Function!bcDefiniteIntegral}
\index{bcDefiniteIntegral Function}
\index{Function!bcLimit}
\index{bcLimit Function}
\index{Function!bcSum}
\index{bcSum Function}
\index{Function!bcProduct}
\index{bcProduct Function}
\begin{chunk}{basic.ht}
\begin{page}{Calculus}{Calculus}
\beginscroll
What would you like to do?
\beginmenu
\menulispdownlink{Differentiate}{(|bcDifferentiate|)}\space{}
\menulispdownlink{Do an Indefinite Integral}
{(|bcIndefiniteIntegrate|)}\space{}
\menulispdownlink{Do a Definite Integral}{(|bcDefiniteIntegrate|)}\space{}
\menulispdownlink{Find a limit}{(|bcLimit|)}\space{}
\menulispdownlink{Do a summation}{(|bcSum|)}\space{}
%\menulispdownlink{Compute a product}{(|bcProduct|)}\space{}
\endmenu
\endscroll
\autobuttons 
\end{page}
 
\end{chunk}
\section{bbtree.ht}
\pagetitle{BalancedBinaryTreeXmpPage}{bbtree.ht}{BalancedBinaryTree}
\begin{chunk}{bbtree.ht}
\begin{page}{BalancedBinaryTreeXmpPage}{BalancedBinaryTree}
\beginscroll
\spadtype{BalancedBinaryTrees(S)} is the domain
of balanced binary trees with elements of type \spad{S} at the nodes.
A binary tree is either \spadfun{empty} or else
consists of a \spadfun{node} having a \spadfun{value}
and two branches, each branch a binary tree.
A balanced binary tree is one that is balanced with respect its leaves.
One with \texht{$2^k$}{2**k} leaves is
perfectly ``balanced'': the tree has minimum depth, and
the \spadfun{left} and \spadfun{right}
branch of every interior node is identical in shape.

Balanced binary trees are useful in algebraic computation for
so-called ``divide-and-conquer'' algorithms.  Conceptually, the data
for a problem is initially placed at the root of the tree.  The
original data is then split into two subproblems, one for each
subtree.  And so on.  Eventually, the problem is solved at the leaves
of the tree.  A solution to the original problem is obtained by some
mechanism that can reassemble the pieces.  In fact, an implementation
of the Chinese Remainder Algorithm using balanced binary trees was
first proposed by David Y. Y.  Yun at the IBM T. J.  Watson Research
Center in Yorktown Heights, New York, in 1978.  It served as the
prototype for polymorphic algorithms in Axiom.

In what follows, rather than perform a series of computations with
a single expression, the expression is reduced modulo a number of
integer primes, a computation is done with modular arithmetic for
each prime, and the Chinese Remainder Algorithm is used to obtain
the answer to the original problem.
We illustrate this principle with the computation of 
\texht{$12^2 = 144$}{12 ** 2 = 144}.

\xtc{
A list of moduli.
}{
\spadpaste{lm := [3,5,7,11]\bound{lm}}
}
\xtc{
The expression \spad{modTree(n, lm)}
creates a balanced binary tree with leaf values
\spad{n mod m} for each modulus \spad{m} in \spad{lm}.
}{
\spadpaste{modTree(12,lm)\free{lm}}
}
\xtc{
Operation \spad{modTree} does this using
operations on balanced binary trees.
We trace its steps.
Create a balanced binary tree \spad{t} of zeros with four leaves.
}{
\spadpaste{t := balancedBinaryTree(\#lm, 0)\bound{t}\free{lm}}
}
\xtc{
The leaves of the tree are set to the individual moduli.
}{
\spadpaste{setleaves!(t,lm)\bound{t1}\free{t}}
}
\xtc{
Use \spadfunX{mapUp} to do
a bottom-up traversal of \spad{t}, setting each interior node
to the product of the values at the nodes of its children.
}{
\spadpaste{mapUp!(t,_*)\bound{t2}\free{t1}}
}
\xtc{
The value at the node of every subtree is the product of the moduli
of the leaves of the subtree.
}{
\spadpaste{t \bound{t3}\free{t2}}
}
\xtc{
Operation \spadfunX{mapDown}\spad{(t,a,fn)} replaces the value
\spad{v} at each node of \spad{t} by \spad{fn(a,v)}.
}{
\spadpaste{mapDown!(t,12,_rem)\bound{t4}\free{t3}}
}
\xtc{
The operation \spadfun{leaves} returns the leaves of the resulting
tree.
In this case, it returns the list of \spad{12 mod m} for each
modulus \spad{m}.
}{
\spadpaste{leaves \%\bound{t5}\free{t4}}
}
\xtc{
Compute the square of the images of \spad{12} modulo each \spad{m}.
}{
\spadpaste{squares := [x**2 rem m for x in \% for m in lm]\bound{t6}\free{t5}}
}
\xtc{
Call the Chinese Remainder Algorithm to get the
answer for \texht{$12^2$}{12**2}.
}{
\spadpaste{chineseRemainder(\%,lm)\free{t6}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{BalancedBinaryTreeXmpPagePatch1}
\begin{paste}{BalancedBinaryTreeXmpPageFull1}
{BalancedBinaryTreeXmpPageEmpty1}
\pastebutton{BalancedBinaryTreeXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{lm := [3,5,7,11]\bound{lm }}
\indentrel{3}\begin{verbatim}
   (1)  [3,5,7,11]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BalancedBinaryTreeXmpPageEmpty1}
\begin{paste}{BalancedBinaryTreeXmpPageEmpty1}
{BalancedBinaryTreeXmpPagePatch1}
\pastebutton{BalancedBinaryTreeXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{lm := [3,5,7,11]\bound{lm }}
\end{paste}\end{patch}

\begin{patch}{BalancedBinaryTreeXmpPagePatch2}
\begin{paste}{BalancedBinaryTreeXmpPageFull2}
{BalancedBinaryTreeXmpPageEmpty2}
\pastebutton{BalancedBinaryTreeXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{modTree(12,lm)\free{lm }}
\indentrel{3}\begin{verbatim}
   (2)  [0,2,5,1]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BalancedBinaryTreeXmpPageEmpty2}
\begin{paste}{BalancedBinaryTreeXmpPageEmpty2}
{BalancedBinaryTreeXmpPagePatch2}
\pastebutton{BalancedBinaryTreeXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{modTree(12,lm)\free{lm }}
\end{paste}\end{patch}

\begin{patch}{BalancedBinaryTreeXmpPagePatch3}
\begin{paste}{BalancedBinaryTreeXmpPageFull3}
{BalancedBinaryTreeXmpPageEmpty3}
\pastebutton{BalancedBinaryTreeXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{
t := balancedBinaryTree(\#lm, 0)\bound{t }\free{lm }}
\indentrel{3}\begin{verbatim}
   (3)  [[0,0,0],0,[0,0,0]]
            Type: BalancedBinaryTree NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BalancedBinaryTreeXmpPageEmpty3}
\begin{paste}{BalancedBinaryTreeXmpPageEmpty3}
{BalancedBinaryTreeXmpPagePatch3}
\pastebutton{BalancedBinaryTreeXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{t := balancedBinaryTree(\#lm, 0)\bound{t }\free{lm }}
\end{paste}\end{patch}

\begin{patch}{BalancedBinaryTreeXmpPagePatch4}
\begin{paste}{BalancedBinaryTreeXmpPageFull4}
{BalancedBinaryTreeXmpPageEmpty4}
\pastebutton{BalancedBinaryTreeXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{setleaves!(t,lm)\bound{t1 }\free{t }}
\indentrel{3}\begin{verbatim}
   (4)  [[3,0,5],0,[7,0,11]]
            Type: BalancedBinaryTree NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BalancedBinaryTreeXmpPageEmpty4}
\begin{paste}{BalancedBinaryTreeXmpPageEmpty4}
{BalancedBinaryTreeXmpPagePatch4}
\pastebutton{BalancedBinaryTreeXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{setleaves!(t,lm)\bound{t1 }\free{t }}
\end{paste}\end{patch}

\begin{patch}{BalancedBinaryTreeXmpPagePatch5}
\begin{paste}{BalancedBinaryTreeXmpPageFull5}
{BalancedBinaryTreeXmpPageEmpty5}
\pastebutton{BalancedBinaryTreeXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{mapUp!(t,_*)\bound{t2 }\free{t1 }}
\indentrel{3}\begin{verbatim}
   (5)  1155
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BalancedBinaryTreeXmpPageEmpty5}
\begin{paste}{BalancedBinaryTreeXmpPageEmpty5}
{BalancedBinaryTreeXmpPagePatch5}
\pastebutton{BalancedBinaryTreeXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{mapUp!(t,_*)\bound{t2 }\free{t1 }}
\end{paste}\end{patch}

\begin{patch}{BalancedBinaryTreeXmpPagePatch6}
\begin{paste}{BalancedBinaryTreeXmpPageFull6}
{BalancedBinaryTreeXmpPageEmpty6}
\pastebutton{BalancedBinaryTreeXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{t\bound{t3 }\free{t2 }}
\indentrel{3}\begin{verbatim}
   (6)  [[3,15,5],1155,[7,77,11]]
            Type: BalancedBinaryTree NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BalancedBinaryTreeXmpPageEmpty6}
\begin{paste}{BalancedBinaryTreeXmpPageEmpty6}
{BalancedBinaryTreeXmpPagePatch6}
\pastebutton{BalancedBinaryTreeXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{t\bound{t3 }\free{t2 }}
\end{paste}\end{patch}

\begin{patch}{BalancedBinaryTreeXmpPagePatch7}
\begin{paste}{BalancedBinaryTreeXmpPageFull7}
{BalancedBinaryTreeXmpPageEmpty7}
\pastebutton{BalancedBinaryTreeXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{mapDown!(t,12,_rem)\bound{t4 }\free{t3 }}
\indentrel{3}\begin{verbatim}
   (7)  [[0,12,2],12,[5,12,1]]
            Type: BalancedBinaryTree NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BalancedBinaryTreeXmpPageEmpty7}
\begin{paste}{BalancedBinaryTreeXmpPageEmpty7}
{BalancedBinaryTreeXmpPagePatch7}
\pastebutton{BalancedBinaryTreeXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{mapDown!(t,12,_rem)\bound{t4 }\free{t3 }}
\end{paste}\end{patch}

\begin{patch}{BalancedBinaryTreeXmpPagePatch8}
\begin{paste}{BalancedBinaryTreeXmpPageFull8}
{BalancedBinaryTreeXmpPageEmpty8}
\pastebutton{BalancedBinaryTreeXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{leaves \%\bound{t5 }\free{t4 }}
\indentrel{3}\begin{verbatim}
   (8)  [0,2,5,1]
                          Type: List NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BalancedBinaryTreeXmpPageEmpty8}
\begin{paste}{BalancedBinaryTreeXmpPageEmpty8}
{BalancedBinaryTreeXmpPagePatch8}
\pastebutton{BalancedBinaryTreeXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{leaves \%\bound{t5 }\free{t4 }}
\end{paste}\end{patch}

\begin{patch}{BalancedBinaryTreeXmpPagePatch9}
\begin{paste}{BalancedBinaryTreeXmpPageFull9}
{BalancedBinaryTreeXmpPageEmpty9}
\pastebutton{BalancedBinaryTreeXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{
squares := [x**2 rem m for x in \% for m in lm]\bound{t6 }\free{t5 }}
\indentrel{3}\begin{verbatim}
   (9)  [0,4,4,1]
                          Type: List NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BalancedBinaryTreeXmpPageEmpty9}
\begin{paste}{BalancedBinaryTreeXmpPageEmpty9}
{BalancedBinaryTreeXmpPagePatch9}
\pastebutton{BalancedBinaryTreeXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{
squares := [x**2 rem m for x in \% for m in lm]\bound{t6 }\free{t5 }}
\end{paste}\end{patch}

\begin{patch}{BalancedBinaryTreeXmpPagePatch10}
\begin{paste}{BalancedBinaryTreeXmpPageFull10}
{BalancedBinaryTreeXmpPageEmpty10}
\pastebutton{BalancedBinaryTreeXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{chineseRemainder(\%,lm)\free{t6 }}
\indentrel{3}\begin{verbatim}
   (10)  144
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BalancedBinaryTreeXmpPageEmpty10}
\begin{paste}{BalancedBinaryTreeXmpPageEmpty10}
{BalancedBinaryTreeXmpPagePatch10}
\pastebutton{BalancedBinaryTreeXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{chineseRemainder(\%,lm)\free{t6 }}
\end{paste}\end{patch}

\end{chunk}
\section{binary.ht}
\pagetitle{BinaryExpansionXmpPage}{binary.ht}{BinaryExpansion}
\pagepic{ps/v71binaryexpansionxmppage.eps}{BinaryExpansionXmpPage}{0.50}
\pagefrom{Axiom Number Types}{NumberPage}
\pagefrom{Integer}{IntegerXmpPage}
\pageto{DecimalExpansion}{DecimalExpansionXmpPage}
\pageto{RadixExpansion}{RadixExpansionXmpPage}
\pageto{HexadecimalExpansion}{HexExpansionXmpPage}
\begin{chunk}{binary.ht}
\begin{page}{BinaryExpansionXmpPage}{BinaryExpansion}
\beginscroll
All rational numbers have repeating binary expansions.
Operations to access the individual bits of a binary expansion can
be obtained by converting the value to \spadtype{RadixExpansion(2)}.
More examples of expansions are available in
\downlink{`DecimalExpansion'}{DecimalExpansionXmpPage}
\ignore{DecimalExpansion},
\downlink{`HexadecimalExpansion'}{HexExpansionXmpPage}
\ignore{HexadecimalExpansion}, and
\downlink{`RadixExpansion'}{RadixExpansionXmpPage}\ignore{RadixExpansion}.
 
\xtc{
The expansion (of type \spadtype{BinaryExpansion}) of a rational number
is returned by the \spadfunFrom{binary}{BinaryExpansion} operation.
}{
\spadpaste{r := binary(22/7) \bound{r}}
}
\xtc{
Arithmetic is exact.
}{
\spadpaste{r + binary(6/7) \free{r}}
}
\xtc{
The period of the expansion can be short or long \ldots
}{
\spadpaste{[binary(1/i) for i in 102..106] }
}
\xtc{
or very long.
}{
\spadpaste{binary(1/1007) }
}
\xtc{
These numbers are bona fide algebraic objects.
}{
\spadpaste{p := binary(1/4)*x**2 + binary(2/3)*x + binary(4/9)  \bound{p}}
}
\xtc{
}{
\spadpaste{q := D(p, x) \free{p}\bound{q}}
}
\xtc{
}{
\spadpaste{g := gcd(p, q)            \free{p q}\bound{g}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{BinaryExpansionXmpPagePatch1}
\begin{paste}{BinaryExpansionXmpPageFull1}{BinaryExpansionXmpPageEmpty1}
\pastebutton{BinaryExpansionXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{r := binary(22/7)\bound{r }}
\indentrel{3}\begin{verbatim}
           ___
   (1)  11.001
                                  Type: BinaryExpansion
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BinaryExpansionXmpPageEmpty1}
\begin{paste}{BinaryExpansionXmpPageEmpty1}{BinaryExpansionXmpPagePatch1}
\pastebutton{BinaryExpansionXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{r := binary(22/7)\bound{r }}
\end{paste}\end{patch}

\begin{patch}{BinaryExpansionXmpPagePatch2}
\begin{paste}{BinaryExpansionXmpPageFull2}{BinaryExpansionXmpPageEmpty2}
\pastebutton{BinaryExpansionXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{r + binary(6/7)\free{r }}
\indentrel{3}\begin{verbatim}
   (2)  100
                                  Type: BinaryExpansion
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BinaryExpansionXmpPageEmpty2}
\begin{paste}{BinaryExpansionXmpPageEmpty2}{BinaryExpansionXmpPagePatch2}
\pastebutton{BinaryExpansionXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{r + binary(6/7)\free{r }}
\end{paste}\end{patch}

\begin{patch}{BinaryExpansionXmpPagePatch3}
\begin{paste}{BinaryExpansionXmpPageFull3}{BinaryExpansionXmpPageEmpty3}
\pastebutton{BinaryExpansionXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{[binary(1/i) for i in 102..106]}
\indentrel{3}\begin{verbatim}
   (3)
       ________
   [0.000000101,
      ___________________________________________________
    0.000000100111110001000101100101111001110010010101001,
         ____________    ____________
    0.000000100111011, 0.000000100111,

     0.0
       OVERBAR
          00000100110101001000011100111110110010101101111
            00011
     ]
                             Type: List BinaryExpansion
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BinaryExpansionXmpPageEmpty3}
\begin{paste}{BinaryExpansionXmpPageEmpty3}{BinaryExpansionXmpPagePatch3}
\pastebutton{BinaryExpansionXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{[binary(1/i) for i in 102..106]}
\end{paste}\end{patch}

\begin{patch}{BinaryExpansionXmpPagePatch4}
\begin{paste}{BinaryExpansionXmpPageFull4}{BinaryExpansionXmpPageEmpty4}
\pastebutton{BinaryExpansionXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{binary(1/1007)}
\indentrel{3}\begin{verbatim}
   (4)
   0.
     OVERBAR
        0000000001000001000101001001011110000011111100001
          01111110010110001111101000100111001001100110001
          10010010101011110110100110000000011000011001111
          01110001101000101111010010001111011000010101110
          11100111010101110011001010010111000000011100011
          11001000000100100100110111001010100111010001101
          11011010111000100100000110010110110000001011001
          01111100010100000101010101101011000001101101110
          10010101111111010111010100110010000101001101100
          0100110001000100001000011000111010011110001
                                  Type: BinaryExpansion
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BinaryExpansionXmpPageEmpty4}
\begin{paste}{BinaryExpansionXmpPageEmpty4}{BinaryExpansionXmpPagePatch4}
\pastebutton{BinaryExpansionXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{binary(1/1007)}
\end{paste}\end{patch}

\begin{patch}{BinaryExpansionXmpPagePatch5}
\begin{paste}{BinaryExpansionXmpPageFull5}{BinaryExpansionXmpPageEmpty5}
\pastebutton{BinaryExpansionXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{
p := binary(1/4)*x**2 + binary(2/3)*x + binary(4/9)\bound{p }}
\indentrel{3}\begin{verbatim}
             2     __      ______
   (5)  0.01x  + 0.10x + 0.011100
                       Type: Polynomial BinaryExpansion
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BinaryExpansionXmpPageEmpty5}
\begin{paste}{BinaryExpansionXmpPageEmpty5}{BinaryExpansionXmpPagePatch5}
\pastebutton{BinaryExpansionXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{
p := binary(1/4)*x**2 + binary(2/3)*x + binary(4/9)\bound{p }}
\end{paste}\end{patch}

\begin{patch}{BinaryExpansionXmpPagePatch6}
\begin{paste}{BinaryExpansionXmpPageFull6}{BinaryExpansionXmpPageEmpty6}
\pastebutton{BinaryExpansionXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{q := D(p, x)\free{p }\bound{q }}
\indentrel{3}\begin{verbatim}
                 __
   (6)  0.1x + 0.10
                       Type: Polynomial BinaryExpansion
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BinaryExpansionXmpPageEmpty6}
\begin{paste}{BinaryExpansionXmpPageEmpty6}{BinaryExpansionXmpPagePatch6}
\pastebutton{BinaryExpansionXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{q := D(p, x)\free{p }\bound{q }}
\end{paste}\end{patch}

\begin{patch}{BinaryExpansionXmpPagePatch7}
\begin{paste}{BinaryExpansionXmpPageFull7}{BinaryExpansionXmpPageEmpty7}
\pastebutton{BinaryExpansionXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{g := gcd(p, q)\free{p q }\bound{g }}
\indentrel{3}\begin{verbatim}
              __
   (7)  x + 1.01
                       Type: Polynomial BinaryExpansion
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BinaryExpansionXmpPageEmpty7}
\begin{paste}{BinaryExpansionXmpPageEmpty7}{BinaryExpansionXmpPagePatch7}
\pastebutton{BinaryExpansionXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{g := gcd(p, q)\free{p q }\bound{g }}
\end{paste}\end{patch}

\end{chunk}
\section{bmcat.ht}
\pagetitle{BitMaps}{bmcat.ht}{Bit Map Catalog}
\begin{chunk}{bmcat.ht}
\begin{page}{BitMaps}{Bit Map Catalog}
\beginscroll
\space{} {\inputbitmap{\htbmdir{}/xfbox.bitmap}}      xfbox    \space{4}
\space{} {\inputbitmap{\htbmdir{}/xfcirc.bitmap}}     xfcirc   \space{4}
\space{} {\inputbitmap{\htbmdir{}/xnobox.bitmap}}     Xnobox   \space{2}
\space{} {\inputbitmap{\htbmdir{}/xnocirc.bitmap}}    xnocirc  \space{2}
\newline
\space{} {\inputbitmap{\htbmdir{}/xfullfbox.bitmap}}  xfullfbox 
\space{} {\inputbitmap{\htbmdir{}/xfullfcirc.bitmap}} xfullfcirc
\space{} {\inputbitmap{\htbmdir{}/xfullbox.bitmap}}   xfullbox  
\space{} {\inputbitmap{\htbmdir{}/xfullcirc.bitmap}}  xfullcirc
\newline
\space{} {\inputbitmap{\htbmdir{}/xgreyfbox.bitmap}}  xgreyfbox 
\space{} {\inputbitmap{\htbmdir{}/xgreyfcirc.bitmap}} xgreyfcirc
\space{} {\inputbitmap{\htbmdir{}/xgreybox.bitmap}}   xgreybox  
\space{} {\inputbitmap{\htbmdir{}/xgreycirc.bitmap}}  xgreycirc
\newline
\space{} {\inputbitmap{\htbmdir{}/xopenfbox.bitmap}}  xopenfbox
\space{} {\inputbitmap{\htbmdir{}/xopenfcirc.bitmap}} xopenfcirc
\space{} {\inputbitmap{\htbmdir{}/xopenbox.bitmap}}   xopenbox  
\space{} {\inputbitmap{\htbmdir{}/xopencirc.bitmap}}  xopencirc
\newline
\space{} {\inputbitmap{\htbmdir{}/xtickfbox.bitmap}}  xtickfbox 
\space{} {\inputbitmap{\htbmdir{}/xtickfcirc.bitmap}} xtickfcirc
\space{} {\inputbitmap{\htbmdir{}/xtickbox.bitmap}}   xtickbox  
\space{} {\inputbitmap{\htbmdir{}/xtickcirc.bitmap}}  xtickcirc
\newline
\space{} {\inputbitmap{\htbmdir{}/xxfbox.bitmap}}     xxfbox    \space{3}
\space{} {\inputbitmap{\htbmdir{}/xxfcirc.bitmap}}    xxfcirc   \space{3}
\space{} {\inputbitmap{\htbmdir{}/xxbox.bitmap}}      xxbox     \space{3}
\space{} {\inputbitmap{\htbmdir{}/xxcirc.bitmap}}     xxcirc    \space{3}
\horizontalline
\space{} {\inputbitmap{\htbmdir{}/xnoface.bitmap}}    xnoface
\space{} {\inputbitmap{\htbmdir{}/xhappy.bitmap}}     xhappy
\space{} {\inputbitmap{\htbmdir{}/xsad.bitmap}}       xsad
\space{} {\inputbitmap{\htbmdir{}/xdesp.bitmap}}      xdesp
\space{} {\inputbitmap{\htbmdir{}/xperv.bitmap}}      xperv
\horizontalline
\space{} {\inputbitmap{\htbmdir{}/exit.bitmap}} exit
\space{} {\inputbitmap{\htbmdir{}/help3.bitmap}} help3
\newline
\space{} {\inputbitmap{\htbmdir{}/down3.bitmap}} down3
\space{} {\inputbitmap{\htbmdir{}/up3.bitmap}} up3
\space{} {\inputbitmap{\htbmdir{}/return3.bitmap}} return3
\newline
\space{} {\inputbitmap{\htbmdir{}/tear.bitmap}} tear
\space{} {\inputbitmap{\htbmdir{}/eqpage.bitmap}} eqpage
\horizontalline
\space{} {\inputbitmap{\htbmdir{}/sup.bm}} sup.bm
\space{} {\inputbitmap{\htbmdir{}/sup.bitmap}} sup
\space{} {\inputbitmap{\htbmdir{}/sdown.bm}} sdown.bm
\newline
\space{} {\inputbitmap{\htbmdir{}/ht_icon}} ht_icon
\space{} {\inputbitmap{\htbmdir{}/smile.bitmap}} smile
\newline
\space{} {\inputbitmap{\htbmdir{}/drown.bm}} drown.bm
\space{} {\inputbitmap{\htbmdir{}/help2.bitmap}} help2
\space{} {\inputbitmap{\htbmdir{}/return.bitmap}} return
\space{} {\inputbitmap{\htbmdir{}/back.bitmap}} back
\endscroll
\autobuttons
\end{page}

\end{chunk}
\section{bop.ht}
\pagetitle{BasicOperatorXmpPage}{bop.ht}{BasicOperator}
\begin{chunk}{bop.ht}
\begin{page}{BasicOperatorXmpPage}{BasicOperator}
\beginscroll

A basic operator is an object that can be symbolically
applied to a list of arguments from a set, the result being
a kernel over that set or an expression.
In addition to this section, please see 
\downlink{`Expression'}{ExpressionXmpPage}\ignore{Expression}
and \downlink{`Kernel'}{KernelXmpPage}\ignore{Kernel} 
for additional information and examples.

You create an object of type \axiomType{BasicOperator} by using the
\axiomFunFrom{operator}{BasicOperator} operation.
This first form of this operation has one argument and it
must be a symbol.
The symbol should be quoted in case the
name has been used as an identifier to which a value
has been assigned.

A frequent application of \axiomType{BasicOperator} is the
creation of an operator to represent the unknown function when
solving a differential equation.
\xtc{
Let \axiom{y} be the unknown function in terms of \axiom{x}.
}{
\spadpaste{y := operator 'y \bound{y}}
}
%
\xtc{
This is how you enter
the equation \axiom{y'' + y' + y = 0}.
}{
\spadpaste{deq := D(y x, x, 2) + D(y x, x) + y x = 0\bound{e1}\free{y}}
}
%
\xtc{
To solve the above equation, enter this.
}{
\spadpaste{solve(deq, y, x) \free{e1}\free{y}}
}
See \downlink{``Solution of Differential Equations''}{ugProblemDEQPage} 
in Section 8.10\ignore{ugProblemDEQ}
for this kind of use of \axiomType{BasicOperator}.

Use the single argument form of
\axiomFunFrom{operator}{BasicOperator} (as above) when you intend
to use the operator to create functional expressions with an
arbitrary number of arguments
\xtc{
{\it Nary} means an arbitrary number of arguments can be used
in the functional expressions.
}{
\spadpaste{nary? y \free{y}}
}
\xtc{
}{
\spadpaste{unary? y \free{y}}
}
Use the two-argument form when you want to restrict the number of
arguments in the functional expressions created with the operator.
\xtc{
This operator can only be used to create functional expressions
with one argument.
}{
\spadpaste{opOne := operator('opOne, 1) \bound{opOne}}
}
\xtc{
}{
\spadpaste{nary? opOne \free{opOne}}
}
\xtc{
}{
\spadpaste{unary? opOne \free{opOne}}
}
\xtc{
Use \axiomFunFrom{arity}{BasicOperator} to learn the number of
arguments that can be used.
It returns {\tt "false"} if the operator is nary.
}{
\spadpaste{arity opOne \free{opOne}}
}
\xtc{
Use \axiomFunFrom{name}{BasicOperator} to learn the name of an
operator.
}{
\spadpaste{name opOne \free{opOne}}
}
\xtc{
Use \axiomFunFrom{is?}{BasicOperator} to learn if an operator has a
particular name.
}{
\spadpaste{is?(opOne, 'z2) \free{opOne}}
}
\xtc{
You can also use a string as the name to be tested against.
}{
\spadpaste{is?(opOne, "opOne") \free{opOne}}
}

You can attached named properties to an operator.
These are rarely used at the top-level of the Axiom
interactive environment but are used with Axiom
library source code.
\xtc{
By default, an operator has no properties.
}{
\spadpaste{properties y \free{y}}
}
The interface for setting and getting properties is somewhat awkward
because the property values are stored as values of type
\axiomType{None}.
\xtc{
Attach a property by using \axiomFunFrom{setProperty}{BasicOperator}.
}{
\spadpaste{setProperty(y, "use", "unknown function" :: None ) 
\free{y}\bound{spy}}
}
\xtc{
}{
\spadpaste{properties y \free{y spy}}
}
\xtc{
We {\it know} the property value has type \axiomType{String}.
}{
\spadpaste{property(y, "use") :: None pretend String \free{y spy}}
}
\xtc{
Use \axiomFunFrom{deleteProperty!}{BasicOperator} to destructively
remove a property.
}{
\spadpaste{deleteProperty!(y, "use") \free{y spy}\bound{dpy}}
}
\xtc{
}{
\spadpaste{properties y \free{dpy}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{BasicOperatorXmpPagePatch1}
\begin{paste}{BasicOperatorXmpPageFull1}{BasicOperatorXmpPageEmpty1}
\pastebutton{BasicOperatorXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{y := operator 'y\bound{y }}
\indentrel{3}\begin{verbatim}
   (1)  y
                                    Type: BasicOperator
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPageEmpty1}
\begin{paste}{BasicOperatorXmpPageEmpty1}{BasicOperatorXmpPagePatch1}
\pastebutton{BasicOperatorXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{y := operator 'y\bound{y }}
\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPagePatch2}
\begin{paste}{BasicOperatorXmpPageFull2}{BasicOperatorXmpPageEmpty2}
\pastebutton{BasicOperatorXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{
deq := D(y x, x, 2) + D(y x, x) + y x = 0\bound{e1 }\free{y }}
\indentrel{3}\begin{verbatim}
         ,,       ,
   (2)  y  (x) + y (x) + y(x)= 0

                      Type: Equation Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPageEmpty2}
\begin{paste}{BasicOperatorXmpPageEmpty2}{BasicOperatorXmpPagePatch2}
\pastebutton{BasicOperatorXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{
deq := D(y x, x, 2) + D(y x, x) + y x = 0\bound{e1 }\free{y }}
\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPagePatch3}
\begin{paste}{BasicOperatorXmpPageFull3}{BasicOperatorXmpPageEmpty3}
\pastebutton{BasicOperatorXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{solve(deq, y, x)\free{e1 }\free{y }}
\indentrel{3}\begin{verbatim}
   (3)
   [particular= 0,
                          x     x
                  ÚÄ¿   - Ä   - Ä      ÚÄ¿
                x\³3      2     2    x\³3
    basis= [cos(ÄÄÄÄÄ)%e   ,%e   sin(ÄÄÄÄÄ)]]
                  2                    2
Type: Union(Record(particular: Expression Integer,
                   basis: List Expression Integer),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPageEmpty3}
\begin{paste}{BasicOperatorXmpPageEmpty3}{BasicOperatorXmpPagePatch3}
\pastebutton{BasicOperatorXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{solve(deq, y, x)\free{e1 }\free{y }}
\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPagePatch4}
\begin{paste}{BasicOperatorXmpPageFull4}{BasicOperatorXmpPageEmpty4}
\pastebutton{BasicOperatorXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{nary? y\free{y }}
\indentrel{3}\begin{verbatim}
   (4)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPageEmpty4}
\begin{paste}{BasicOperatorXmpPageEmpty4}{BasicOperatorXmpPagePatch4}
\pastebutton{BasicOperatorXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{nary? y\free{y }}
\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPagePatch5}
\begin{paste}{BasicOperatorXmpPageFull5}{BasicOperatorXmpPageEmpty5}
\pastebutton{BasicOperatorXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{unary? y\free{y }}
\indentrel{3}\begin{verbatim}
   (5)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPageEmpty5}
\begin{paste}{BasicOperatorXmpPageEmpty5}{BasicOperatorXmpPagePatch5}
\pastebutton{BasicOperatorXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{unary? y\free{y }}
\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPagePatch6}
\begin{paste}{BasicOperatorXmpPageFull6}{BasicOperatorXmpPageEmpty6}
\pastebutton{BasicOperatorXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{opOne := operator('opOne, 1)\bound{opOne }}
\indentrel{3}\begin{verbatim}
   (6)  opOne
                                    Type: BasicOperator
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPageEmpty6}
\begin{paste}{BasicOperatorXmpPageEmpty6}{BasicOperatorXmpPagePatch6}
\pastebutton{BasicOperatorXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{opOne := operator('opOne, 1)\bound{opOne }}
\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPagePatch7}
\begin{paste}{BasicOperatorXmpPageFull7}{BasicOperatorXmpPageEmpty7}
\pastebutton{BasicOperatorXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{nary? opOne\free{opOne }}
\indentrel{3}\begin{verbatim}
   (7)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPageEmpty7}
\begin{paste}{BasicOperatorXmpPageEmpty7}{BasicOperatorXmpPagePatch7}
\pastebutton{BasicOperatorXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{nary? opOne\free{opOne }}
\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPagePatch8}
\begin{paste}{BasicOperatorXmpPageFull8}{BasicOperatorXmpPageEmpty8}
\pastebutton{BasicOperatorXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{unary? opOne\free{opOne }}
\indentrel{3}\begin{verbatim}
   (8)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPageEmpty8}
\begin{paste}{BasicOperatorXmpPageEmpty8}{BasicOperatorXmpPagePatch8}
\pastebutton{BasicOperatorXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{unary? opOne\free{opOne }}
\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPagePatch9}
\begin{paste}{BasicOperatorXmpPageFull9}{BasicOperatorXmpPageEmpty9}
\pastebutton{BasicOperatorXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{arity opOne\free{opOne }}
\indentrel{3}\begin{verbatim}
   (9)  1
                    Type: Union(NonNegativeInteger,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPageEmpty9}
\begin{paste}{BasicOperatorXmpPageEmpty9}{BasicOperatorXmpPagePatch9}
\pastebutton{BasicOperatorXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{arity opOne\free{opOne }}
\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPagePatch10}
\begin{paste}{BasicOperatorXmpPageFull10}{BasicOperatorXmpPageEmpty10}
\pastebutton{BasicOperatorXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{name opOne\free{opOne }}
\indentrel{3}\begin{verbatim}
   (10)  opOne
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPageEmpty10}
\begin{paste}{BasicOperatorXmpPageEmpty10}{BasicOperatorXmpPagePatch10}
\pastebutton{BasicOperatorXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{name opOne\free{opOne }}
\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPagePatch11}
\begin{paste}{BasicOperatorXmpPageFull11}{BasicOperatorXmpPageEmpty11}
\pastebutton{BasicOperatorXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{is?(opOne, 'z2)\free{opOne }}
\indentrel{3}\begin{verbatim}
   (11)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPageEmpty11}
\begin{paste}{BasicOperatorXmpPageEmpty11}{BasicOperatorXmpPagePatch11}
\pastebutton{BasicOperatorXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{is?(opOne, 'z2)\free{opOne }}
\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPagePatch12}
\begin{paste}{BasicOperatorXmpPageFull12}{BasicOperatorXmpPageEmpty12}
\pastebutton{BasicOperatorXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{is?(opOne, "opOne")\free{opOne }}
\indentrel{3}\begin{verbatim}
   (12)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPageEmpty12}
\begin{paste}{BasicOperatorXmpPageEmpty12}{BasicOperatorXmpPagePatch12}
\pastebutton{BasicOperatorXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{is?(opOne, "opOne")\free{opOne }}
\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPagePatch13}
\begin{paste}{BasicOperatorXmpPageFull13}{BasicOperatorXmpPageEmpty13}
\pastebutton{BasicOperatorXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{properties y\free{y }}
\indentrel{3}\begin{verbatim}
   (13)  table()
                     Type: AssociationList(String,None)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPageEmpty13}
\begin{paste}{BasicOperatorXmpPageEmpty13}{BasicOperatorXmpPagePatch13}
\pastebutton{BasicOperatorXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{properties y\free{y }}
\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPagePatch14}
\begin{paste}{BasicOperatorXmpPageFull14}{BasicOperatorXmpPageEmpty14}
\pastebutton{BasicOperatorXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{
setProperty(y, "use", "unknown function" :: None )\free{y }\bound{spy }}
\indentrel{3}\begin{verbatim}
   (14)  y
                                    Type: BasicOperator
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPageEmpty14}
\begin{paste}{BasicOperatorXmpPageEmpty14}{BasicOperatorXmpPagePatch14}
\pastebutton{BasicOperatorXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{
setProperty(y, "use", "unknown function" :: None )\free{y }\bound{spy }}
\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPagePatch15}
\begin{paste}{BasicOperatorXmpPageFull15}{BasicOperatorXmpPageEmpty15}
\pastebutton{BasicOperatorXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{properties y\free{y spy }}
\indentrel{3}\begin{verbatim}
   (15)  table("use"= NONE)
                     Type: AssociationList(String,None)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPageEmpty15}
\begin{paste}{BasicOperatorXmpPageEmpty15}{BasicOperatorXmpPagePatch15}
\pastebutton{BasicOperatorXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{properties y\free{y spy }}
\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPagePatch16}
\begin{paste}{BasicOperatorXmpPageFull16}{BasicOperatorXmpPageEmpty16}
\pastebutton{BasicOperatorXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{property(y, "use") :: None pretend String\free{y spy }}
\indentrel{3}\begin{verbatim}
   (16)  "unknown function"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPageEmpty16}
\begin{paste}{BasicOperatorXmpPageEmpty16}{BasicOperatorXmpPagePatch16}
\pastebutton{BasicOperatorXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{property(y, "use") :: None pretend String\free{y spy }}
\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPagePatch17}
\begin{paste}{BasicOperatorXmpPageFull17}{BasicOperatorXmpPageEmpty17}
\pastebutton{BasicOperatorXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{deleteProperty!(y, "use")\free{y spy }\bound{dpy }}
\indentrel{3}\begin{verbatim}
   (17)  y
                                    Type: BasicOperator
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPageEmpty17}
\begin{paste}{BasicOperatorXmpPageEmpty17}{BasicOperatorXmpPagePatch17}
\pastebutton{BasicOperatorXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{deleteProperty!(y, "use")\free{y spy }\bound{dpy }}
\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPagePatch18}
\begin{paste}{BasicOperatorXmpPageFull18}{BasicOperatorXmpPageEmpty18}
\pastebutton{BasicOperatorXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{properties y\free{dpy }}
\indentrel{3}\begin{verbatim}
   (18)  table()
                     Type: AssociationList(String,None)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BasicOperatorXmpPageEmpty18}
\begin{paste}{BasicOperatorXmpPageEmpty18}{BasicOperatorXmpPagePatch18}
\pastebutton{BasicOperatorXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{properties y\free{dpy }}
\end{paste}\end{patch}


\end{chunk}
\section{bstree.ht}
\pagetitle{BinarySearchTreeXmpPage}{bstree.ht}{BinarySearchTree}
\begin{chunk}{bstree.ht}
\begin{page}{BinarySearchTreeXmpPage}{BinarySearchTree}
\beginscroll

\spadtype{BinarySearchTree(R)} is the domain of binary trees with
elements of type \spad{R}, ordered across the nodes of the tree.  A
non-empty binary search tree has a value of type \spad{R}, and
\spadfun{right} and \spadfun{left} binary search subtrees.  If a
subtree is empty, it is displayed as a period (``.'').

\xtc{
Define a list of values to be placed across the tree.
The resulting tree has \spad{8} at the root;
all other elements are in the left subtree.
}{
\spadpaste{lv := [8,3,5,4,6,2,1,5,7]\bound{lv}}
}
\xtc{
A convenient way to create a binary search tree is to
apply the operation \spadfun{binarySearchTree} to a list of elements.
}{
\spadpaste{t := binarySearchTree lv\free{lv}\bound{t}}
}
\xtc{
Another approach is to first create an empty binary search tree of integers.
}{
\spadpaste{emptybst := empty()\$BSTREE(INT)\bound{e}}
}
\xtc{
Insert the value \spad{8}.
This establishes \spad{8} as the root of the binary search tree.
Values inserted later that are less than \spad{8} get stored in
the \spadfun{left} subtree, others in the \spadfun{right} subtree.
}{
\spadpaste{t1 := insert!(8,emptybst)\free{e}\bound{t1}}
}
\xtc{
Insert the value \spad{3}. This number becomes the root of the
\spadfun{left} subtree of \spad{t1}.
For optimal retrieval, it is thus important to insert the
middle elements first.
}{
\spadpaste{insert!(3,t1)\free{t1}}
}
\xtc{
We go back to the original tree \spad{t}.
The leaves of the binary search tree are those which have empty
\spadfun{left} and \spadfun{right} subtrees.
}{
\spadpaste{leaves t\free{t}}
}
\xtc{
The operation
\spadfun{split}\spad{(k,t)} returns a \spadgloss{record} containing
the two subtrees: one with all elements ``less'' than \spad{k},
another with elements ``greater'' than \spad{k}.
}{
\spadpaste{split(3,t)\free{t}}
}
\xtc{
Define \userfun{insertRoot} to insert new elements by
creating a new node.
}{
\spadpaste{insertRoot: (INT,BSTREE INT) -> BSTREE INT\bound{x}}
}
\xtc{
The new node puts the inserted value between its
``less'' tree and ``greater'' tree.
}{
\begin{spadsrc}[\bound{x1}\free{x}]
insertRoot(x, t) ==
    a := split(x, t)
    node(a.less, x, a.greater)
\end{spadsrc}
}
\xtc{
Function \userfun{buildFromRoot} builds
a binary search tree from a list of elements \spad{ls}
and the empty tree \spad{emptybst}.
}{
\spadpaste{buildFromRoot ls == reduce(insertRoot,ls,emptybst)
\bound{x2}\free{x1 e}}
}
\xtc{
Apply this to the reverse of the list \spad{lv}.
}{
\spadpaste{rt := buildFromRoot reverse lv\bound{rt}\free{lv x2}}
}
\xtc{
Have Axiom check that these are equal.
}{
\spadpaste{(t = rt)@Boolean\free{rt t}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{BinarySearchTreeXmpPagePatch1}
\begin{paste}{BinarySearchTreeXmpPageFull1}{BinarySearchTreeXmpPageEmpty1}
\pastebutton{BinarySearchTreeXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{lv := [8,3,5,4,6,2,1,5,7]\bound{lv }}
\indentrel{3}\begin{verbatim}
   (1)  [8,3,5,4,6,2,1,5,7]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPageEmpty1}
\begin{paste}{BinarySearchTreeXmpPageEmpty1}{BinarySearchTreeXmpPagePatch1}
\pastebutton{BinarySearchTreeXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{lv := [8,3,5,4,6,2,1,5,7]\bound{lv }}
\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPagePatch2}
\begin{paste}{BinarySearchTreeXmpPageFull2}{BinarySearchTreeXmpPageEmpty2}
\pastebutton{BinarySearchTreeXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{t := binarySearchTree lv\free{lv }\bound{t }}
\indentrel{3}\begin{verbatim}
   (2)  [[[1,2,.],3,[4,5,[5,6,7]]],8,.]
                 Type: BinarySearchTree PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPageEmpty2}
\begin{paste}{BinarySearchTreeXmpPageEmpty2}{BinarySearchTreeXmpPagePatch2}
\pastebutton{BinarySearchTreeXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{t := binarySearchTree lv\free{lv }\bound{t }}
\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPagePatch3}
\begin{paste}{BinarySearchTreeXmpPageFull3}{BinarySearchTreeXmpPageEmpty3}
\pastebutton{BinarySearchTreeXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{emptybst := empty()$BSTREE(INT)\bound{e }}
\indentrel{3}\begin{verbatim}
   (3)  []
                         Type: BinarySearchTree Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPageEmpty3}
\begin{paste}{BinarySearchTreeXmpPageEmpty3}{BinarySearchTreeXmpPagePatch3}
\pastebutton{BinarySearchTreeXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{emptybst := empty()$BSTREE(INT)\bound{e }}
\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPagePatch4}
\begin{paste}{BinarySearchTreeXmpPageFull4}{BinarySearchTreeXmpPageEmpty4}
\pastebutton{BinarySearchTreeXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{t1 := insert!(8,emptybst)\free{e }\bound{t1 }}
\indentrel{3}\begin{verbatim}
   (4)  8
                         Type: BinarySearchTree Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPageEmpty4}
\begin{paste}{BinarySearchTreeXmpPageEmpty4}{BinarySearchTreeXmpPagePatch4}
\pastebutton{BinarySearchTreeXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{t1 := insert!(8,emptybst)\free{e }\bound{t1 }}
\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPagePatch5}
\begin{paste}{BinarySearchTreeXmpPageFull5}{BinarySearchTreeXmpPageEmpty5}
\pastebutton{BinarySearchTreeXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{insert!(3,t1)\free{t1 }}
\indentrel{3}\begin{verbatim}
   (5)  [3,8,.]
                         Type: BinarySearchTree Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPageEmpty5}
\begin{paste}{BinarySearchTreeXmpPageEmpty5}{BinarySearchTreeXmpPagePatch5}
\pastebutton{BinarySearchTreeXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{insert!(3,t1)\free{t1 }}
\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPagePatch6}
\begin{paste}{BinarySearchTreeXmpPageFull6}{BinarySearchTreeXmpPageEmpty6}
\pastebutton{BinarySearchTreeXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{leaves t\free{t }}
\indentrel{3}\begin{verbatim}
   (6)  [1,4,5,7]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPageEmpty6}
\begin{paste}{BinarySearchTreeXmpPageEmpty6}{BinarySearchTreeXmpPagePatch6}
\pastebutton{BinarySearchTreeXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{leaves t\free{t }}
\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPagePatch7}
\begin{paste}{BinarySearchTreeXmpPageFull7}{BinarySearchTreeXmpPageEmpty7}
\pastebutton{BinarySearchTreeXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{split(3,t)\free{t }}
\indentrel{3}\begin{verbatim}
   (7)
   [less= [1,2,.],greater= [[.,3,[4,5,[5,6,7]]],8,.]]
Type: Record(less: BinarySearchTree PositiveInteger,
             greater: BinarySearchTree PositiveInteger)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPageEmpty7}
\begin{paste}{BinarySearchTreeXmpPageEmpty7}{BinarySearchTreeXmpPagePatch7}
\pastebutton{BinarySearchTreeXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{split(3,t)\free{t }}
\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPagePatch8}
\begin{paste}{BinarySearchTreeXmpPageFull8}{BinarySearchTreeXmpPageEmpty8}
\pastebutton{BinarySearchTreeXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{insertRoot: (INT,BSTREE INT) -> BSTREE INT\bound{x }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPageEmpty8}
\begin{paste}{BinarySearchTreeXmpPageEmpty8}{BinarySearchTreeXmpPagePatch8}
\pastebutton{BinarySearchTreeXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{insertRoot: (INT,BSTREE INT) -> BSTREE INT\bound{x }}
\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPagePatch9}
\begin{paste}{BinarySearchTreeXmpPageFull9}{BinarySearchTreeXmpPageEmpty9}
\pastebutton{BinarySearchTreeXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{insertRoot(x, t) ==
    a := split(x, t)
    node(a.less, x, a.greater)
\bound{x1 }\free{x }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPageEmpty9}
\begin{paste}{BinarySearchTreeXmpPageEmpty9}{BinarySearchTreeXmpPagePatch9}
\pastebutton{BinarySearchTreeXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{insertRoot(x, t) ==
    a := split(x, t)
    node(a.less, x, a.greater)
\bound{x1 }\free{x }}
\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPagePatch10}
\begin{paste}{BinarySearchTreeXmpPageFull10}{BinarySearchTreeXmpPageEmpty10}
\pastebutton{BinarySearchTreeXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{
buildFromRoot ls == reduce(insertRoot,ls,emptybst)\bound{x2 }\free{x1 e }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPageEmpty10}
\begin{paste}{BinarySearchTreeXmpPageEmpty10}
{BinarySearchTreeXmpPagePatch10}
\pastebutton{BinarySearchTreeXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{
buildFromRoot ls == reduce(insertRoot,ls,emptybst)\bound{x2 }\free{x1 e }}
\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPagePatch11}
\begin{paste}{BinarySearchTreeXmpPageFull11}
{BinarySearchTreeXmpPageEmpty11}
\pastebutton{BinarySearchTreeXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{rt := buildFromRoot reverse lv\bound{rt }\free{lv x2 }}
\indentrel{3}\begin{verbatim}
   (11)  [[[1,2,.],3,[4,5,[5,6,7]]],8,.]
                         Type: BinarySearchTree Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPageEmpty11}
\begin{paste}{BinarySearchTreeXmpPageEmpty11}
{BinarySearchTreeXmpPagePatch11}
\pastebutton{BinarySearchTreeXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{rt := buildFromRoot reverse lv\bound{rt }\free{lv x2 }}
\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPagePatch12}
\begin{paste}{BinarySearchTreeXmpPageFull12}
{BinarySearchTreeXmpPageEmpty12}
\pastebutton{BinarySearchTreeXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{(t = rt)@Boolean\free{rt t }}
\indentrel{3}\begin{verbatim}
   (12)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{BinarySearchTreeXmpPageEmpty12}
\begin{paste}{BinarySearchTreeXmpPageEmpty12}
{BinarySearchTreeXmpPagePatch12}
\pastebutton{BinarySearchTreeXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{(t = rt)@Boolean\free{rt t }}
\end{paste}\end{patch}

\end{chunk}
\section{card.ht}
\pagetitle{CardinalNumberXmpPage}{card.ht}{CardinalNumber}
\pagepic{ps/v71cardinalnumberxmppage.eps}{CardinalNumberXmpPage}{0.50}
\pagefrom{Axiom Number Types}{NumberPage}
\begin{chunk}{card.ht}
\begin{page}{CardinalNumberXmpPage}{CardinalNumber}
\beginscroll
The \spadtype{CardinalNumber} domain can be used for values indicating
the cardinality of sets, both finite and infinite.
For example, the \spadfunFrom{dimension}{VectorSpace} operation in the
category \spadtype{VectorSpace} returns a cardinal number.

The non-negative integers have a natural construction as cardinals
\begin{verbatim}
0 = #{ }, 1 = {0}, 2 = {0, 1}, ..., n = {i | 0 <= i < n}.
\end{verbatim}
The fact that \spad{0} acts as a zero for the multiplication of 
cardinals is equivalent to the axiom of choice.

\xtc{
Cardinal numbers can be created by conversion from non-negative integers.
}{
\spadpaste{c0 := 0 :: CardinalNumber \bound{c0}}
}
\xtc{
}{
\spadpaste{c1 := 1 :: CardinalNumber \bound{c1}}
}
\xtc{
}{
\spadpaste{c2 := 2 :: CardinalNumber \bound{c2}}
}
\xtc{
}{
\spadpaste{c3 := 3 :: CardinalNumber \bound{c3}}
}
\xtc{
They can also be obtained as the named cardinal \spad{Aleph(n)}.
}{
\spadpaste{A0 := Aleph 0 \bound{A0}}
}
\xtc{
}{
\spadpaste{A1 := Aleph 1 \bound{A1}}
}
\xtc{
The \spadfunFrom{finite?}{CardinalNumber} operation tests whether a 
value is a finite cardinal, that is, a non-negative integer.
}{
\spadpaste{finite? c2 \free{c2}}
}
\xtc{
}{
\spadpaste{finite? A0 \free{A0}}
}
\xtc{
Similarly, the \spadfunFrom{countable?}{CardinalNumber}
operation determines whether a value is
a countable cardinal, that is, finite or \spad{Aleph(0)}.
}{
\spadpaste{countable? c2 \free{c2}}
}
\xtc{
}{
\spadpaste{countable? A0 \free{A0}}
}
\xtc{
}{
\spadpaste{countable? A1 \free{A1}}
}
Arithmetic operations are defined on cardinal numbers as follows:
If \spad{x = \#X}  and  \spad{y = \#Y} then

\indent{0}
\spad{x+y  = \#(X+Y)} 
\tab{20} cardinality of the disjoint union \newline
\spad{x-y  = \#(X-Y)} 
\tab{20} cardinality of the relative complement \newline
\spad{x*y  = \#(X*Y)} 
\tab{20} cardinality of the Cartesian product \newline
\spad{x**y = \#(X**Y)}
\tab{20} cardinality of the set of maps from \spad{Y} to \spad{X} \newline

\xtc{
Here are some arithmetic examples.
}{
\spadpaste{[c2 + c2, c2 + A1] \free{c2 A1}}
}
\xtc{
}{
\spadpaste{[c0*c2, c1*c2, c2*c2, c0*A1, c1*A1, c2*A1, A0*A1] 
\free{c0,c1,c2,A0,A1}}
}
\xtc{
}{
\spadpaste{[c2**c0, c2**c1, c2**c2, A1**c0, A1**c1, A1**c2] 
\free{c0,c1,c2,A1}}
}
\xtc{
Subtraction is a partial operation: it is not defined
when subtracting a larger cardinal from a smaller one, nor
when subtracting two equal infinite cardinals.
}{
\spadpaste{[c2-c1, c2-c2, c2-c3, A1-c2, A1-A0, A1-A1] 
\free{c1,c2,c3,A0,A1}}
}
The generalized continuum hypothesis asserts that
\begin{verbatim}
2**Aleph i = Aleph(i+1)
\end{verbatim}
and is independent of the axioms of set theory.\footnote{Goedel,
{\it The consistency of the continuum hypothesis,}
Ann. Math. Studies, Princeton Univ. Press, 1940.}
\xtc{
The \spadtype{CardinalNumber} domain provides an operation to assert
whether the hypothesis is to be assumed.
}{
\spadpaste{generalizedContinuumHypothesisAssumed true \bound{GCH}}
}
\xtc{
When the generalized continuum hypothesis
is assumed, exponentiation to a transfinite power is allowed.
}{
\spadpaste{[c0**A0, c1**A0, c2**A0, A0**A0, A0**A1, A1**A0, A1**A1] 
\free{c0,c1,c2,A0,A1,GCH}}
}

Three commonly encountered cardinal numbers are

\indent{0}
\spad{a = \#}{\bf Z} \tab{20}       countable infinity \newline
\spad{c = \#}{\bf R} \tab{20}      the continuum       \newline
\spad{f = \#\{g| g: [0,1] -> {\bf R}\}}                \newline

\xtc{
In this domain, these values are obtained under the
generalized continuum hypothesis in this way.
}{
\spadpaste{a := Aleph 0 \free{GCH}\bound{a}}
}
\xtc{
}{
\spadpaste{c := 2**a    \free{a}  \bound{c}}
}
\xtc{
}{
\spadpaste{f := 2**c    \free{c}  \bound{f}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{CardinalNumberXmpPagePatch1}
\begin{paste}{CardinalNumberXmpPageFull1}{CardinalNumberXmpPageEmpty1}
\pastebutton{CardinalNumberXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{c0 := 0 :: CardinalNumber\bound{c0 }}
\indentrel{3}\begin{verbatim}
   (1)  0
                                   Type: CardinalNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPageEmpty1}
\begin{paste}{CardinalNumberXmpPageEmpty1}{CardinalNumberXmpPagePatch1}
\pastebutton{CardinalNumberXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{c0 := 0 :: CardinalNumber\bound{c0 }}
\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPagePatch2}
\begin{paste}{CardinalNumberXmpPageFull2}{CardinalNumberXmpPageEmpty2}
\pastebutton{CardinalNumberXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{c1 := 1 :: CardinalNumber\bound{c1 }}
\indentrel{3}\begin{verbatim}
   (2)  1
                                   Type: CardinalNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPageEmpty2}
\begin{paste}{CardinalNumberXmpPageEmpty2}{CardinalNumberXmpPagePatch2}
\pastebutton{CardinalNumberXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{c1 := 1 :: CardinalNumber\bound{c1 }}
\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPagePatch3}
\begin{paste}{CardinalNumberXmpPageFull3}{CardinalNumberXmpPageEmpty3}
\pastebutton{CardinalNumberXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{c2 := 2 :: CardinalNumber\bound{c2 }}
\indentrel{3}\begin{verbatim}
   (3)  2
                                   Type: CardinalNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPageEmpty3}
\begin{paste}{CardinalNumberXmpPageEmpty3}{CardinalNumberXmpPagePatch3}
\pastebutton{CardinalNumberXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{c2 := 2 :: CardinalNumber\bound{c2 }}
\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPagePatch4}
\begin{paste}{CardinalNumberXmpPageFull4}{CardinalNumberXmpPageEmpty4}
\pastebutton{CardinalNumberXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{c3 := 3 :: CardinalNumber\bound{c3 }}
\indentrel{3}\begin{verbatim}
   (4)  3
                                   Type: CardinalNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPageEmpty4}
\begin{paste}{CardinalNumberXmpPageEmpty4}{CardinalNumberXmpPagePatch4}
\pastebutton{CardinalNumberXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{c3 := 3 :: CardinalNumber\bound{c3 }}
\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPagePatch5}
\begin{paste}{CardinalNumberXmpPageFull5}{CardinalNumberXmpPageEmpty5}
\pastebutton{CardinalNumberXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{A0 := Aleph 0\bound{A0 }}
\indentrel{3}\begin{verbatim}
   (5)  Aleph(0)
                                   Type: CardinalNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPageEmpty5}
\begin{paste}{CardinalNumberXmpPageEmpty5}{CardinalNumberXmpPagePatch5}
\pastebutton{CardinalNumberXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{A0 := Aleph 0\bound{A0 }}
\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPagePatch6}
\begin{paste}{CardinalNumberXmpPageFull6}{CardinalNumberXmpPageEmpty6}
\pastebutton{CardinalNumberXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{A1 := Aleph 1\bound{A1 }}
\indentrel{3}\begin{verbatim}
   (6)  Aleph(1)
                                   Type: CardinalNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPageEmpty6}
\begin{paste}{CardinalNumberXmpPageEmpty6}{CardinalNumberXmpPagePatch6}
\pastebutton{CardinalNumberXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{A1 := Aleph 1\bound{A1 }}
\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPagePatch7}
\begin{paste}{CardinalNumberXmpPageFull7}{CardinalNumberXmpPageEmpty7}
\pastebutton{CardinalNumberXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{finite? c2\free{c2 }}
\indentrel{3}\begin{verbatim}
   (7)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPageEmpty7}
\begin{paste}{CardinalNumberXmpPageEmpty7}{CardinalNumberXmpPagePatch7}
\pastebutton{CardinalNumberXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{finite? c2\free{c2 }}
\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPagePatch8}
\begin{paste}{CardinalNumberXmpPageFull8}{CardinalNumberXmpPageEmpty8}
\pastebutton{CardinalNumberXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{finite? A0\free{A0 }}
\indentrel{3}\begin{verbatim}
   (8)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPageEmpty8}
\begin{paste}{CardinalNumberXmpPageEmpty8}{CardinalNumberXmpPagePatch8}
\pastebutton{CardinalNumberXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{finite? A0\free{A0 }}
\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPagePatch9}
\begin{paste}{CardinalNumberXmpPageFull9}{CardinalNumberXmpPageEmpty9}
\pastebutton{CardinalNumberXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{countable? c2\free{c2 }}
\indentrel{3}\begin{verbatim}
   (9)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPageEmpty9}
\begin{paste}{CardinalNumberXmpPageEmpty9}{CardinalNumberXmpPagePatch9}
\pastebutton{CardinalNumberXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{countable? c2\free{c2 }}
\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPagePatch10}
\begin{paste}{CardinalNumberXmpPageFull10}{CardinalNumberXmpPageEmpty10}
\pastebutton{CardinalNumberXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{countable? A0\free{A0 }}
\indentrel{3}\begin{verbatim}
   (10)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPageEmpty10}
\begin{paste}{CardinalNumberXmpPageEmpty10}{CardinalNumberXmpPagePatch10}
\pastebutton{CardinalNumberXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{countable? A0\free{A0 }}
\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPagePatch11}
\begin{paste}{CardinalNumberXmpPageFull11}{CardinalNumberXmpPageEmpty11}
\pastebutton{CardinalNumberXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{countable? A1\free{A1 }}
\indentrel{3}\begin{verbatim}
   (11)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPageEmpty11}
\begin{paste}{CardinalNumberXmpPageEmpty11}{CardinalNumberXmpPagePatch11}
\pastebutton{CardinalNumberXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{countable? A1\free{A1 }}
\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPagePatch12}
\begin{paste}{CardinalNumberXmpPageFull12}{CardinalNumberXmpPageEmpty12}
\pastebutton{CardinalNumberXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{[c2 + c2, c2 + A1]\free{c2 A1 }}
\indentrel{3}\begin{verbatim}
   (12)  [4,Aleph(1)]
                              Type: List CardinalNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPageEmpty12}
\begin{paste}{CardinalNumberXmpPageEmpty12}{CardinalNumberXmpPagePatch12}
\pastebutton{CardinalNumberXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{[c2 + c2, c2 + A1]\free{c2 A1 }}
\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPagePatch13}
\begin{paste}{CardinalNumberXmpPageFull13}{CardinalNumberXmpPageEmpty13}
\pastebutton{CardinalNumberXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{
[c0*c2, c1*c2, c2*c2, c0*A1, c1*A1, c2*A1, A0*A1]\free{c0 c1 c2 A0 A1 }}
\indentrel{3}\begin{verbatim}
   (13)  [0,2,4,0,Aleph(1),Aleph(1),Aleph(1)]
                              Type: List CardinalNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPageEmpty13}
\begin{paste}{CardinalNumberXmpPageEmpty13}{CardinalNumberXmpPagePatch13}
\pastebutton{CardinalNumberXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{
[c0*c2, c1*c2, c2*c2, c0*A1, c1*A1, c2*A1, A0*A1]\free{c0 c1 c2 A0 A1 }}
\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPagePatch14}
\begin{paste}{CardinalNumberXmpPageFull14}{CardinalNumberXmpPageEmpty14}
\pastebutton{CardinalNumberXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{
[c2**c0, c2**c1, c2**c2, A1**c0, A1**c1, A1**c2]\free{c0 c1 c2 A1 }}
\indentrel{3}\begin{verbatim}
   (14)  [1,2,4,1,Aleph(1),Aleph(1)]
                              Type: List CardinalNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPageEmpty14}
\begin{paste}{CardinalNumberXmpPageEmpty14}{CardinalNumberXmpPagePatch14}
\pastebutton{CardinalNumberXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{
[c2**c0, c2**c1, c2**c2, A1**c0, A1**c1, A1**c2]\free{c0 c1 c2 A1 }}
\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPagePatch15}
\begin{paste}{CardinalNumberXmpPageFull15}{CardinalNumberXmpPageEmpty15}
\pastebutton{CardinalNumberXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{
[c2-c1, c2-c2, c2-c3, A1-c2, A1-A0, A1-A1]\free{c1 c2 c3 A0 A1 }}
\indentrel{3}\begin{verbatim}
   (15)  [1,0,"failed",Aleph(1),Aleph(1),"failed"]
              Type: List Union(CardinalNumber,"failed")
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPageEmpty15}
\begin{paste}{CardinalNumberXmpPageEmpty15}{CardinalNumberXmpPagePatch15}
\pastebutton{CardinalNumberXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{
[c2-c1, c2-c2, c2-c3, A1-c2, A1-A0, A1-A1]\free{c1 c2 c3 A0 A1 }}
\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPagePatch16}
\begin{paste}{CardinalNumberXmpPageFull16}{CardinalNumberXmpPageEmpty16}
\pastebutton{CardinalNumberXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{generalizedContinuumHypothesisAssumed true\bound{GCH }}
\indentrel{3}\begin{verbatim}
   (16)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPageEmpty16}
\begin{paste}{CardinalNumberXmpPageEmpty16}{CardinalNumberXmpPagePatch16}
\pastebutton{CardinalNumberXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{generalizedContinuumHypothesisAssumed true\bound{GCH }}
\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPagePatch17}
\begin{paste}{CardinalNumberXmpPageFull17}{CardinalNumberXmpPageEmpty17}
\pastebutton{CardinalNumberXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{
[c0**A0, c1**A0, c2**A0, A0**A0, A0**A1, A1**A0, A1**A1]
\free{c0 c1 c2 A0 A1 GCH }}
\indentrel{3}\begin{verbatim}
   (17)
   [0,1,Aleph(1),Aleph(1),Aleph(2),Aleph(1),Aleph(2)]
                              Type: List CardinalNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPageEmpty17}
\begin{paste}{CardinalNumberXmpPageEmpty17}{CardinalNumberXmpPagePatch17}
\pastebutton{CardinalNumberXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{
[c0**A0, c1**A0, c2**A0, A0**A0, A0**A1, A1**A0, A1**A1]
\free{c0 c1 c2 A0 A1 GCH }}
\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPagePatch18}
\begin{paste}{CardinalNumberXmpPageFull18}{CardinalNumberXmpPageEmpty18}
\pastebutton{CardinalNumberXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{a := Aleph 0\free{GCH }\bound{a }}
\indentrel{3}\begin{verbatim}
   (18)  Aleph(0)
                                   Type: CardinalNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPageEmpty18}
\begin{paste}{CardinalNumberXmpPageEmpty18}{CardinalNumberXmpPagePatch18}
\pastebutton{CardinalNumberXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{a := Aleph 0\free{GCH }\bound{a }}
\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPagePatch19}
\begin{paste}{CardinalNumberXmpPageFull19}{CardinalNumberXmpPageEmpty19}
\pastebutton{CardinalNumberXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{c := 2**a\free{a }\bound{c }}
\indentrel{3}\begin{verbatim}
   (19)  Aleph(1)
                                   Type: CardinalNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPageEmpty19}
\begin{paste}{CardinalNumberXmpPageEmpty19}{CardinalNumberXmpPagePatch19}
\pastebutton{CardinalNumberXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{c := 2**a\free{a }\bound{c }}
\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPagePatch20}
\begin{paste}{CardinalNumberXmpPageFull20}{CardinalNumberXmpPageEmpty20}
\pastebutton{CardinalNumberXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{f := 2**c\free{c }\bound{f }}
\indentrel{3}\begin{verbatim}
   (20)  Aleph(2)
                                   Type: CardinalNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CardinalNumberXmpPageEmpty20}
\begin{paste}{CardinalNumberXmpPageEmpty20}{CardinalNumberXmpPagePatch20}
\pastebutton{CardinalNumberXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{f := 2**c\free{c }\bound{f }}
\end{paste}\end{patch}

\end{chunk}
\section{carten.ht}
\pagetitle{CartesianTensorXmpPage}{carten.ht}{CartesianTensor}
\begin{chunk}{carten.ht}
\begin{page}{CartesianTensorXmpPage}{CartesianTensor}
\beginscroll

\spadtype{CartesianTensor(i0,dim,R)}
provides Cartesian tensors with
components belonging to a commutative ring \spad{R}.
Tensors can be described as a generalization of vectors and matrices.
This gives a concise {\it tensor algebra} for multilinear objects
supported by the \spadtype{CartesianTensor} domain.
You can form the inner or outer product of any two tensors and you can add
or subtract tensors with the same number of components.
Additionally, various forms of traces and transpositions are useful.

The \spadtype{CartesianTensor} constructor allows you to specify the
minimum index for subscripting.
In what follows we discuss in detail how to manipulate tensors.

\xtc{
Here we construct the domain of Cartesian tensors of dimension 2 over the
integers, with indices starting at 1.
}{
\spadpaste{CT := CARTEN(i0 := 1, 2, Integer) \bound{CT i0}}
}

\subsubsection{Forming tensors}
\labelSpace{2pc}
\xtc{
Scalars can be converted to tensors of rank zero.
}{
\spadpaste{t0: CT := 8 \free{CT}\bound{t0}}
}
\xtc{
}{
\spadpaste{rank t0 \free{t0}}
}
\xtc{
Vectors (mathematical direct products, rather than one dimensional array
structures) can be converted to tensors of rank one.
}{
\spadpaste{v: DirectProduct(2, Integer) := directProduct [3,4] \bound{v}}
}
\xtc{
}{
\spadpaste{Tv: CT := v \free{v CT}\bound{Tv}}
}
\xtc{
Matrices can be converted to tensors of rank two.
}{
\spadpaste{m: SquareMatrix(2, Integer) := matrix [[1,2],[4,5]] \bound{m}}
}
\xtc{
}{
\spadpaste{Tm: CT := m \bound{Tm}\free{CT m}}
}
\xtc{
}{
\spadpaste{n: SquareMatrix(2, Integer) := matrix [[2,3],[0,1]] \bound{n}}
}
\xtc{
}{
\spadpaste{Tn: CT := n \bound{Tn}\free{CT n}}
}
\xtc{
In general, a tensor of rank \spad{k} can be formed by making a
list of rank \spad{k-1} tensors or, alternatively, a \spad{k}-deep nested
list of lists.
}{
\spadpaste{t1: CT := [2, 3] \free{CT}\bound{t1}}
}
\xtc{
}{
\spadpaste{rank t1 \free{t1}}
}
\xtc{
}{
\spadpaste{t2: CT := [t1, t1] \free{CT t1}\bound{t2}}
}
\xtc{
}{
\spadpaste{t3: CT := [t2, t2] \free{CT t2}\bound{t3}}
}
\xtc{
}{
\spadpaste{tt: CT := [t3, t3]; tt := [tt, tt] \free{CT t3}\bound{tt}}
}
\xtc{
}{
\spadpaste{rank tt \free{tt}}
}

\subsubsection{Multiplication}
%\head{subsection}{Multiplication}{ugxCartenMult}

Given two tensors of rank \spad{k1} and \spad{k2}, the outer
{CartesianTensor}
\spadfunFrom{product}{CartesianTensor} forms a new tensor of rank
\spad{k1+k2}.
\xtc{
Here
\texht{$T_{mn}(i,j,k,l) = T_m(i,j) \  T_n(k,l).$}{%
\spad{Tmn(i,j,k,l) = Tm(i,j)*Tn(k,l).}}
}{
\spadpaste{Tmn := product(Tm, Tn)\free{Tm Tn}\bound{Tmn}}
}

The inner product (\spadfunFrom{contract}{CartesianTensor}) forms a tensor
{CartesianTensor}
of rank \spad{k1+k2-2}.
This product generalizes the vector dot product and matrix-vector product
by summing component products along two indices.
\xtc{
Here we sum along the second index of \texht{$T_m$}{\spad{Tm}} and the
first index of \texht{$T_v$}{\spad{Tv}}.
Here
\texht{$T_{mv} = \sum_{j=1}^{\hbox{\tiny\rm dim}} T_m(i,j) \  T_v(j)$}{%
\spad{Tmv(i) = sum Tm(i,j) * Tv(j) for j in 1..dim.}}
}{
\spadpaste{Tmv := contract(Tm,2,Tv,1)\free{Tm Tv}\bound{Tmv}}
}

The multiplication operator \spadopFrom{*}{CartesianTensor} is scalar
multiplication or an inner product depending on the ranks of the
arguments.
\xtc{
If either argument is rank zero it is treated as scalar multiplication.
Otherwise, \spad{a*b} is the inner product summing the last index of
\spad{a} with the first index of \spad{b}.
}{
\spadpaste{Tm*Tv \free{Tm Tv}}
}
\xtc{
This definition is consistent with the inner product on matrices
and vectors.
}{
\spadpaste{Tmv = m * v \free{Tmv m v}}
}

\subsubsection{Selecting Components}
%\head{subsection}{Selecting Components}{ugxCartenSelect}

\labelSpace{2pc}
\xtc{
For tensors of low rank (that is, four or less), components can be selected
by applying the tensor to its indices.
}{
\spadpaste{t0()      \free{t0}}
}
\xtc{
}{
\spadpaste{t1(1+1)   \free{t1}}
}
\xtc{
}{
\spadpaste{t2(2,1)   \free{t2}}
}
\xtc{
}{
\spadpaste{t3(2,1,2) \free{t3}}
}
\xtc{
}{
\spadpaste{Tmn(2,1,2,1) \free{Tmn}}
}
\xtc{
A general indexing mechanism is provided for a list of indices.
}{
\spadpaste{t0[]        \free{t0}}
}
\xtc{
}{
\spadpaste{t1[2]        \free{t1}}
}
\xtc{
}{
\spadpaste{t2[2,1]      \free{t2}}
}
\xtc{
The general mechanism works for tensors of arbitrary rank, but is
somewhat less efficient since the intermediate index list must be created.
}{
\spadpaste{t3[2,1,2]    \free{t3}}
}
\xtc{
}{
\spadpaste{Tmn[2,1,2,1] \free{Tmn}}
}

\subsubsection{Contraction}
%\head{subsection}{Contraction}{ugxCartenContract}

A ``contraction'' between two tensors is an inner product, as we have
seen above.
You can also contract a pair of indices of a single tensor.
This corresponds to a ``trace'' in linear algebra.
The expression \spad{contract(t,k1,k2)} forms a new tensor by summing the
diagonal given by indices in position \spad{k1} and \spad{k2}.
\xtc{
This is the tensor given by
\texht{$xT_{mn} = \sum_{k=1}^{\hbox{\tiny\rm dim}} T_{mn}(k,k,i,j).$}{%
\spad{cTmn(i,j) = sum Tmn(k,k,i,j) for k in 1..dim.}}
}{
\spadpaste{cTmn := contract(Tmn,1,2) \free{Tmn}\bound{cTmn}}
}
\xtc{
Since \spad{Tmn} is the outer product of matrix \spad{m} and matrix \spad{n},
the above is equivalent to this.
}{
\spadpaste{trace(m) * n \free{m n}}
}
\xtc{
In this and the next few examples,
we show all possible contractions of \spad{Tmn} and their matrix
algebra equivalents.
}{
\spadpaste{contract(Tmn,1,2) = trace(m) * n      \free{Tmn m n}}
}
\xtc{
}{
\spadpaste{contract(Tmn,1,3) = transpose(m) * n  \free{Tmn m n}}
}
\xtc{
}{
\spadpaste{contract(Tmn,1,4) = transpose(m) * transpose(n) \free{Tmn m n}}
}
\xtc{
}{
\spadpaste{contract(Tmn,2,3) = m * n             \free{Tmn m n}}
}
\xtc{
}{
\spadpaste{contract(Tmn,2,4) = m * transpose(n)  \free{Tmn m n}}
}
\xtc{
}{
\spadpaste{contract(Tmn,3,4) = trace(n) * m      \free{Tmn m n}}
}

\subsubsection{Transpositions}
%\head{subsection}{Transpositions}{ugxCartenTranspos}

You can exchange any desired pair of indices using the
\spadfunFrom{transpose}{CartesianTensor} operation.

\labelSpace{1pc}
\xtc{
Here the indices in positions one and three are exchanged, that is,
\texht{$tT_{mn}(i,j,k,l) = T_{mn}(k,j,i,l).$}{%
\spad{tTmn(i,j,k,l) = Tmn(k,j,i,l).}}
}{
\spadpaste{tTmn := transpose(Tmn,1,3) \free{tTmn}}
}
\xtc{
If no indices are specified, the first and last index are exchanged.
}{
\spadpaste{transpose Tmn \free{Tmn}}
}
\xtc{
This is consistent with the matrix transpose.
}{
\spadpaste{transpose Tm = transpose m \free{Tm m}}
}

If a more complicated reordering of the indices is required, then the
\spadfunFrom{reindex}{CartesianTensor} operation can be used.
This operation allows the indices to be arbitrarily permuted.
\xtc{
This defines
\texht{$rT_{mn}(i,j,k,l) = \allowbreak T_{mn}(i,l,j,k).$}{%
\spad{rTmn(i,j,k,l) = Tmn(i,l,j,k).}}
}{
\spadpaste{rTmn := reindex(Tmn, [1,4,2,3]) \free{Tmn}\bound{rTmn}}
}

\subsubsection{Arithmetic}
%\head{subsection}{Arithmetic}{ugxCartenArith}

\labelSpace{2pc}
\xtc{
Tensors of equal rank can be added or subtracted so arithmetic
expressions can be used to produce new tensors.
}{
\spadpaste{tt := transpose(Tm)*Tn - Tn*transpose(Tm) \free{Tm Tn}\bound{tt2}}
}
\xtc{
}{
\spadpaste{Tv*(tt+Tn) \free{tt2 Tv Tn}}
}
\xtc{
}{
\spadpaste{reindex(product(Tn,Tn),[4,3,2,1])+3*Tn*product(Tm,Tm) \free{Tm Tn}}
}

\subsubsection{Specific Tensors}
%\head{subsection}{Specific Tensors}{ugxCartenSpecific}

Two specific tensors have properties which depend only on the
dimension.

\labelSpace{1pc}
\xtc{
The Kronecker delta satisfies
\texht{}{%
\begin{verbatim}
             +-
             |   1  if i  = j
delta(i,j) = |
             |   0  if i ^= j
             +-
\end{verbatim}
}%
}{
\spadpaste{delta:  CT := kroneckerDelta()   \free{CT}\bound{delta}}
}
\xtc{
This can be used to reindex via contraction.
}{
\spadpaste{contract(Tmn, 2, delta, 1) = reindex(Tmn, [1,3,4,2]) 
\free{Tmn delta}}
}

\xtc{
The Levi Civita symbol determines the sign of a permutation of indices.
}{
\spadpaste{epsilon:CT := leviCivitaSymbol() \free{CT}\bound{epsilon}}
}
Here we have:
\texht{}{%
\begin{verbatim}
epsilon(i1,...,idim)
     = +1  if i1,...,idim is an even permutation of i0,...,i0+dim-1
     = -1  if i1,...,idim is an  odd permutation of i0,...,i0+dim-1
     =  0  if i1,...,idim is not   a permutation of i0,...,i0+dim-1
\end{verbatim}
}
\xtc{
This property can be used to form determinants.
}{
\spadpaste{contract(epsilon*Tm*epsilon, 1,2) = 2 * determinant m \free{epsilon Tm m}}
}

\subsubsection{Properties of the CartesianTensor domain}
%\head{subsection}{Properties of the CartesianTensor domain}{ugxCartenProp}

\spadtype{GradedModule(R,E)} denotes ``\spad{E}-graded \spad{R}-module'',
that is, a collection of \spad{R}-modules indexed by an abelian monoid
\spad{E.}
An element \spad{g} of \spad{G[s]} for some specific \spad{s}
in \spad{E} is said to be an element of \spad{G} with
\spadfunFrom{degree}{GradedModule} \spad{s}.
Sums are defined in each module \spad{G[s]} so two elements of
\spad{G} can be added if they have the same degree.
Morphisms can be defined and composed by degree to give the
mathematical category of graded modules.

\spadtype{GradedAlgebra(R,E)} denotes ``\spad{E}-graded \spad{R}-algebra.''
{CartesianTensor}
A graded algebra is a graded module together with a degree preserving
\spad{R}-bilinear map, called the \spadfunFrom{product}{GradedAlgebra}.

\begin{verbatim}
degree(product(a,b))= degree(a) + degree(b)

product(r*a,b) = product(a,r*b) = r*product(a,b)
product(a1+a2,b) = product(a1,b) + product(a2,b)
product(a,b1+b2) = product(a,b1) + product(a,b2)
product(a,product(b,c)) = product(product(a,b),c)
\end{verbatim}

The domain \spadtype{CartesianTensor(i0, dim, R)} belongs
to the category \spadtype{GradedAlgebra(R, NonNegativeInteger)}.
The non-negative integer \spadfunFrom{degree}{GradedAlgebra}
is the tensor rank
and the graded algebra \spadfunFrom{product}{GradedAlgebra}
is the tensor outer product.
The graded module addition captures the notion that
only tensors of equal rank can be added.

If \spad{V} is a vector space of dimension \spad{dim} over \spad{R},
then the tensor module \spad{T[k](V)} is defined as
\begin{verbatim}
T[0](V) = R
T[k](V) = T[k-1](V) * V
\end{verbatim}
where \spadop{*} denotes the \spad{R}-module tensor
\spadfunFrom{product}{GradedAlgebra}.
\spadtype{CartesianTensor(i0,dim,R)} is the graded algebra in which
the degree \spad{k} module is \spad{T[k](V)}.

\subsubsection{Tensor Calculus}
%\head{subsection}{Tensor Calculus}{ugxCartenCalculus}

It should be noted here that often tensors are used in the context of
tensor-valued manifold maps.  This leads to the notion of covariant
and contravariant bases with tensor component functions transforming
in specific ways under a change of coordinates on the manifold.  This
is no more directly supported by the \spadtype{CartesianTensor} domain
than it is by the \spadtype{Vector} domain.  However, it is possible
to have the components implicitly represent component maps by choosing
a polynomial or expression type for the components.  In this case, it
is up to the user to satisfy any constraints which arise on the basis
of this interpretation.
\endscroll
\autobuttons
\end{page}

\begin{patch}{CartesianTensorXmpPagePatch1}
\begin{paste}{CartesianTensorXmpPageFull1}{CartesianTensorXmpPageEmpty1}
\pastebutton{CartesianTensorXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{CT := CARTEN(i0 := 1, 2, Integer)\bound{CT i0 }}
\indentrel{3}\begin{verbatim}
   (1)  CartesianTensor(1,2,Integer)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty1}
\begin{paste}{CartesianTensorXmpPageEmpty1}{CartesianTensorXmpPagePatch1}
\pastebutton{CartesianTensorXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{CT := CARTEN(i0 := 1, 2, Integer)\bound{CT i0 }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch2}
\begin{paste}{CartesianTensorXmpPageFull2}{CartesianTensorXmpPageEmpty2}
\pastebutton{CartesianTensorXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{t0: CT := 8\free{CT }\bound{t0 }}
\indentrel{3}\begin{verbatim}
   (2)  8
                     Type: CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty2}
\begin{paste}{CartesianTensorXmpPageEmpty2}{CartesianTensorXmpPagePatch2}
\pastebutton{CartesianTensorXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{t0: CT := 8\free{CT }\bound{t0 }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch3}
\begin{paste}{CartesianTensorXmpPageFull3}{CartesianTensorXmpPageEmpty3}
\pastebutton{CartesianTensorXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{rank t0\free{t0 }}
\indentrel{3}\begin{verbatim}
   (3)  0
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty3}
\begin{paste}{CartesianTensorXmpPageEmpty3}{CartesianTensorXmpPagePatch3}
\pastebutton{CartesianTensorXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{rank t0\free{t0 }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch4}
\begin{paste}{CartesianTensorXmpPageFull4}{CartesianTensorXmpPageEmpty4}
\pastebutton{CartesianTensorXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{
v: DirectProduct(2, Integer) := directProduct [3,4]\bound{v }}
\indentrel{3}\begin{verbatim}
   (4)  [3,4]
                         Type: DirectProduct(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty4}
\begin{paste}{CartesianTensorXmpPageEmpty4}{CartesianTensorXmpPagePatch4}
\pastebutton{CartesianTensorXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{
v: DirectProduct(2, Integer) := directProduct [3,4]\bound{v }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch5}
\begin{paste}{CartesianTensorXmpPageFull5}{CartesianTensorXmpPageEmpty5}
\pastebutton{CartesianTensorXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{Tv: CT := v\free{v CT }\bound{Tv }}
\indentrel{3}\begin{verbatim}
   (5)  [3,4]
                     Type: CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty5}
\begin{paste}{CartesianTensorXmpPageEmpty5}{CartesianTensorXmpPagePatch5}
\pastebutton{CartesianTensorXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{Tv: CT := v\free{v CT }\bound{Tv }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch6}
\begin{paste}{CartesianTensorXmpPageFull6}{CartesianTensorXmpPageEmpty6}
\pastebutton{CartesianTensorXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{
m: SquareMatrix(2, Integer) := matrix [[1,2],[4,5]]\bound{m }}
\indentrel{3}\begin{verbatim}
        Ú1  2¿
   (6)  ³    ³
        À4  5Ù
                          Type: SquareMatrix(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty6}
\begin{paste}{CartesianTensorXmpPageEmpty6}{CartesianTensorXmpPagePatch6}
\pastebutton{CartesianTensorXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{
m: SquareMatrix(2, Integer) := matrix [[1,2],[4,5]]\bound{m }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch7}
\begin{paste}{CartesianTensorXmpPageFull7}{CartesianTensorXmpPageEmpty7}
\pastebutton{CartesianTensorXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{Tm: CT := m\bound{Tm }\free{CT m }}
\indentrel{3}\begin{verbatim}
        Ú1  2¿
   (7)  ³    ³
        À4  5Ù
                     Type: CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty7}
\begin{paste}{CartesianTensorXmpPageEmpty7}{CartesianTensorXmpPagePatch7}
\pastebutton{CartesianTensorXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{Tm: CT := m\bound{Tm }\free{CT m }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch8}
\begin{paste}{CartesianTensorXmpPageFull8}{CartesianTensorXmpPageEmpty8}
\pastebutton{CartesianTensorXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{
n: SquareMatrix(2, Integer) := matrix [[2,3],[0,1]]\bound{n }}
\indentrel{3}\begin{verbatim}
        Ú2  3¿
   (8)  ³    ³
        À0  1Ù
                          Type: SquareMatrix(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty8}
\begin{paste}{CartesianTensorXmpPageEmpty8}{CartesianTensorXmpPagePatch8}
\pastebutton{CartesianTensorXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{
n: SquareMatrix(2, Integer) := matrix [[2,3],[0,1]]\bound{n }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch9}
\begin{paste}{CartesianTensorXmpPageFull9}{CartesianTensorXmpPageEmpty9}
\pastebutton{CartesianTensorXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{Tn: CT := n\bound{Tn }\free{CT n }}
\indentrel{3}\begin{verbatim}
        Ú2  3¿
   (9)  ³    ³
        À0  1Ù
                     Type: CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty9}
\begin{paste}{CartesianTensorXmpPageEmpty9}{CartesianTensorXmpPagePatch9}
\pastebutton{CartesianTensorXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{Tn: CT := n\bound{Tn }\free{CT n }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch10}
\begin{paste}{CartesianTensorXmpPageFull10}{CartesianTensorXmpPageEmpty10}
\pastebutton{CartesianTensorXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{t1: CT := [2, 3]\free{CT }\bound{t1 }}
\indentrel{3}\begin{verbatim}
   (10)  [2,3]
                     Type: CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty10}
\begin{paste}{CartesianTensorXmpPageEmpty10}{CartesianTensorXmpPagePatch10}
\pastebutton{CartesianTensorXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{t1: CT := [2, 3]\free{CT }\bound{t1 }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch11}
\begin{paste}{CartesianTensorXmpPageFull11}{CartesianTensorXmpPageEmpty11}
\pastebutton{CartesianTensorXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{rank t1\free{t1 }}
\indentrel{3}\begin{verbatim}
   (11)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty11}
\begin{paste}{CartesianTensorXmpPageEmpty11}{CartesianTensorXmpPagePatch11}
\pastebutton{CartesianTensorXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{rank t1\free{t1 }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch12}
\begin{paste}{CartesianTensorXmpPageFull12}{CartesianTensorXmpPageEmpty12}
\pastebutton{CartesianTensorXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{t2: CT := [t1, t1]\free{CT t1 }\bound{t2 }}
\indentrel{3}\begin{verbatim}
         Ú2  3¿
   (12)  ³    ³
         À2  3Ù
                     Type: CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty12}
\begin{paste}{CartesianTensorXmpPageEmpty12}{CartesianTensorXmpPagePatch12}
\pastebutton{CartesianTensorXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{t2: CT := [t1, t1]\free{CT t1 }\bound{t2 }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch13}
\begin{paste}{CartesianTensorXmpPageFull13}{CartesianTensorXmpPageEmpty13}
\pastebutton{CartesianTensorXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{t3: CT := [t2, t2]\free{CT t2 }\bound{t3 }}
\indentrel{3}\begin{verbatim}
          Ú2  3¿ Ú2  3¿
   (13)  [³    ³,³    ³]
          À2  3Ù À2  3Ù
                     Type: CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty13}
\begin{paste}{CartesianTensorXmpPageEmpty13}{CartesianTensorXmpPagePatch13}
\pastebutton{CartesianTensorXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{t3: CT := [t2, t2]\free{CT t2 }\bound{t3 }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch14}
\begin{paste}{CartesianTensorXmpPageFull14}{CartesianTensorXmpPageEmpty14}
\pastebutton{CartesianTensorXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{
tt: CT := [t3, t3]; tt := [tt, tt]\free{CT t3 }\bound{tt }}
\indentrel{3}\begin{verbatim}
          ÚÚ2  3¿  Ú2  3¿¿ ÚÚ2  3¿  Ú2  3¿¿
          ³³    ³  ³    ³³ ³³    ³  ³    ³³
          ³À2  3Ù  À2  3Ù³ ³À2  3Ù  À2  3Ù³
   (14)  [³              ³,³              ³]
          ³Ú2  3¿  Ú2  3¿³ ³Ú2  3¿  Ú2  3¿³
          ³³    ³  ³    ³³ ³³    ³  ³    ³³
          ÀÀ2  3Ù  À2  3ÙÙ ÀÀ2  3Ù  À2  3ÙÙ
                     Type: CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty14}
\begin{paste}{CartesianTensorXmpPageEmpty14}{CartesianTensorXmpPagePatch14}
\pastebutton{CartesianTensorXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{
tt: CT := [t3, t3]; tt := [tt, tt]\free{CT t3 }\bound{tt }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch15}
\begin{paste}{CartesianTensorXmpPageFull15}{CartesianTensorXmpPageEmpty15}
\pastebutton{CartesianTensorXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{rank tt\free{tt }}
\indentrel{3}\begin{verbatim}
   (15)  5
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty15}
\begin{paste}{CartesianTensorXmpPageEmpty15}{CartesianTensorXmpPagePatch15}
\pastebutton{CartesianTensorXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{rank tt\free{tt }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch16}
\begin{paste}{CartesianTensorXmpPageFull16}{CartesianTensorXmpPageEmpty16}
\pastebutton{CartesianTensorXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{Tmn := product(Tm, Tn)\free{Tm Tn }\bound{Tmn }}
\indentrel{3}\begin{verbatim}
         ÚÚ2  3¿    Ú4  6¿ ¿
         ³³    ³    ³    ³ ³
         ³À0  1Ù    À0  2Ù ³
   (16)  ³                 ³
         ³Ú8  12¿  Ú10  15¿³
         ³³     ³  ³      ³³
         ÀÀ0  4 Ù  À0   5 ÙÙ
                     Type: CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty16}
\begin{paste}{CartesianTensorXmpPageEmpty16}{CartesianTensorXmpPagePatch16}
\pastebutton{CartesianTensorXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{Tmn := product(Tm, Tn)\free{Tm Tn }\bound{Tmn }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch17}
\begin{paste}{CartesianTensorXmpPageFull17}{CartesianTensorXmpPageEmpty17}
\pastebutton{CartesianTensorXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{Tmv := contract(Tm,2,Tv,1)\free{Tm Tv }\bound{Tmv }}
\indentrel{3}\begin{verbatim}
   (17)  [11,32]
                     Type: CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty17}
\begin{paste}{CartesianTensorXmpPageEmpty17}{CartesianTensorXmpPagePatch17}
\pastebutton{CartesianTensorXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{Tmv := contract(Tm,2,Tv,1)\free{Tm Tv }\bound{Tmv }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch18}
\begin{paste}{CartesianTensorXmpPageFull18}{CartesianTensorXmpPageEmpty18}
\pastebutton{CartesianTensorXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{Tm*Tv\free{Tm Tv }}
\indentrel{3}\begin{verbatim}
   (18)  [11,32]
                     Type: CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty18}
\begin{paste}{CartesianTensorXmpPageEmpty18}{CartesianTensorXmpPagePatch18}
\pastebutton{CartesianTensorXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{Tm*Tv\free{Tm Tv }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch19}
\begin{paste}{CartesianTensorXmpPageFull19}{CartesianTensorXmpPageEmpty19}
\pastebutton{CartesianTensorXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{Tmv = m * v\free{Tmv m v }}
\indentrel{3}\begin{verbatim}
   (19)  [11,32]= [11,32]
            Type: Equation CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty19}
\begin{paste}{CartesianTensorXmpPageEmpty19}{CartesianTensorXmpPagePatch19}
\pastebutton{CartesianTensorXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{Tmv = m * v\free{Tmv m v }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch20}
\begin{paste}{CartesianTensorXmpPageFull20}{CartesianTensorXmpPageEmpty20}
\pastebutton{CartesianTensorXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{t0()\free{t0 }}
\indentrel{3}\begin{verbatim}
   (20)  8
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty20}
\begin{paste}{CartesianTensorXmpPageEmpty20}{CartesianTensorXmpPagePatch20}
\pastebutton{CartesianTensorXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{t0()\free{t0 }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch21}
\begin{paste}{CartesianTensorXmpPageFull21}{CartesianTensorXmpPageEmpty21}
\pastebutton{CartesianTensorXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{t1(1+1)\free{t1 }}
\indentrel{3}\begin{verbatim}
   (21)  3
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty21}
\begin{paste}{CartesianTensorXmpPageEmpty21}{CartesianTensorXmpPagePatch21}
\pastebutton{CartesianTensorXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{t1(1+1)\free{t1 }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch22}
\begin{paste}{CartesianTensorXmpPageFull22}{CartesianTensorXmpPageEmpty22}
\pastebutton{CartesianTensorXmpPageFull22}{\hidepaste}
\tab{5}\spadcommand{t2(2,1)\free{t2 }}
\indentrel{3}\begin{verbatim}
   (22)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty22}
\begin{paste}{CartesianTensorXmpPageEmpty22}{CartesianTensorXmpPagePatch22}
\pastebutton{CartesianTensorXmpPageEmpty22}{\showpaste}
\tab{5}\spadcommand{t2(2,1)\free{t2 }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch23}
\begin{paste}{CartesianTensorXmpPageFull23}{CartesianTensorXmpPageEmpty23}
\pastebutton{CartesianTensorXmpPageFull23}{\hidepaste}
\tab{5}\spadcommand{t3(2,1,2)\free{t3 }}
\indentrel{3}\begin{verbatim}
   (23)  3
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty23}
\begin{paste}{CartesianTensorXmpPageEmpty23}{CartesianTensorXmpPagePatch23}
\pastebutton{CartesianTensorXmpPageEmpty23}{\showpaste}
\tab{5}\spadcommand{t3(2,1,2)\free{t3 }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch24}
\begin{paste}{CartesianTensorXmpPageFull24}{CartesianTensorXmpPageEmpty24}
\pastebutton{CartesianTensorXmpPageFull24}{\hidepaste}
\tab{5}\spadcommand{Tmn(2,1,2,1)\free{Tmn }}
\indentrel{3}\begin{verbatim}
   (24)  0
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty24}
\begin{paste}{CartesianTensorXmpPageEmpty24}{CartesianTensorXmpPagePatch24}
\pastebutton{CartesianTensorXmpPageEmpty24}{\showpaste}
\tab{5}\spadcommand{Tmn(2,1,2,1)\free{Tmn }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch25}
\begin{paste}{CartesianTensorXmpPageFull25}{CartesianTensorXmpPageEmpty25}
\pastebutton{CartesianTensorXmpPageFull25}{\hidepaste}
\tab{5}\spadcommand{t0[]\free{t0 }}
\indentrel{3}\begin{verbatim}
   (25)  8
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty25}
\begin{paste}{CartesianTensorXmpPageEmpty25}{CartesianTensorXmpPagePatch25}
\pastebutton{CartesianTensorXmpPageEmpty25}{\showpaste}
\tab{5}\spadcommand{t0[]\free{t0 }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch26}
\begin{paste}{CartesianTensorXmpPageFull26}{CartesianTensorXmpPageEmpty26}
\pastebutton{CartesianTensorXmpPageFull26}{\hidepaste}
\tab{5}\spadcommand{t1[2]\free{t1 }}
\indentrel{3}\begin{verbatim}
   (26)  3
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty26}
\begin{paste}{CartesianTensorXmpPageEmpty26}{CartesianTensorXmpPagePatch26}
\pastebutton{CartesianTensorXmpPageEmpty26}{\showpaste}
\tab{5}\spadcommand{t1[2]\free{t1 }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch27}
\begin{paste}{CartesianTensorXmpPageFull27}{CartesianTensorXmpPageEmpty27}
\pastebutton{CartesianTensorXmpPageFull27}{\hidepaste}
\tab{5}\spadcommand{t2[2,1]\free{t2 }}
\indentrel{3}\begin{verbatim}
   (27)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty27}
\begin{paste}{CartesianTensorXmpPageEmpty27}{CartesianTensorXmpPagePatch27}
\pastebutton{CartesianTensorXmpPageEmpty27}{\showpaste}
\tab{5}\spadcommand{t2[2,1]\free{t2 }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch28}
\begin{paste}{CartesianTensorXmpPageFull28}{CartesianTensorXmpPageEmpty28}
\pastebutton{CartesianTensorXmpPageFull28}{\hidepaste}
\tab{5}\spadcommand{t3[2,1,2]\free{t3 }}
\indentrel{3}\begin{verbatim}
   (28)  3
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty28}
\begin{paste}{CartesianTensorXmpPageEmpty28}{CartesianTensorXmpPagePatch28}
\pastebutton{CartesianTensorXmpPageEmpty28}{\showpaste}
\tab{5}\spadcommand{t3[2,1,2]\free{t3 }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch29}
\begin{paste}{CartesianTensorXmpPageFull29}{CartesianTensorXmpPageEmpty29}
\pastebutton{CartesianTensorXmpPageFull29}{\hidepaste}
\tab{5}\spadcommand{Tmn[2,1,2,1]\free{Tmn }}
\indentrel{3}\begin{verbatim}
   (29)  0
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty29}
\begin{paste}{CartesianTensorXmpPageEmpty29}{CartesianTensorXmpPagePatch29}
\pastebutton{CartesianTensorXmpPageEmpty29}{\showpaste}
\tab{5}\spadcommand{Tmn[2,1,2,1]\free{Tmn }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch30}
\begin{paste}{CartesianTensorXmpPageFull30}{CartesianTensorXmpPageEmpty30}
\pastebutton{CartesianTensorXmpPageFull30}{\hidepaste}
\tab{5}\spadcommand{cTmn := contract(Tmn,1,2)\free{Tmn }\bound{cTmn }}
\indentrel{3}\begin{verbatim}
         Ú12  18¿
   (30)  ³      ³
         À0   6 Ù
                     Type: CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty30}
\begin{paste}{CartesianTensorXmpPageEmpty30}{CartesianTensorXmpPagePatch30}
\pastebutton{CartesianTensorXmpPageEmpty30}{\showpaste}
\tab{5}\spadcommand{cTmn := contract(Tmn,1,2)\free{Tmn }\bound{cTmn }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch31}
\begin{paste}{CartesianTensorXmpPageFull31}{CartesianTensorXmpPageEmpty31}
\pastebutton{CartesianTensorXmpPageFull31}{\hidepaste}
\tab{5}\spadcommand{trace(m) * n\free{m n }}
\indentrel{3}\begin{verbatim}
         Ú12  18¿
   (31)  ³      ³
         À0   6 Ù
                          Type: SquareMatrix(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty31}
\begin{paste}{CartesianTensorXmpPageEmpty31}{CartesianTensorXmpPagePatch31}
\pastebutton{CartesianTensorXmpPageEmpty31}{\showpaste}
\tab{5}\spadcommand{trace(m) * n\free{m n }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch32}
\begin{paste}{CartesianTensorXmpPageFull32}{CartesianTensorXmpPageEmpty32}
\pastebutton{CartesianTensorXmpPageFull32}{\hidepaste}
\tab{5}\spadcommand{contract(Tmn,1,2) = trace(m) * n\free{Tmn m n }}
\indentrel{3}\begin{verbatim}
         Ú12  18¿  Ú12  18¿
   (32)  ³      ³= ³      ³
         À0   6 Ù  À0   6 Ù
            Type: Equation CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty32}
\begin{paste}{CartesianTensorXmpPageEmpty32}{CartesianTensorXmpPagePatch32}
\pastebutton{CartesianTensorXmpPageEmpty32}{\showpaste}
\tab{5}\spadcommand{contract(Tmn,1,2) = trace(m) * n\free{Tmn m n }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch33}
\begin{paste}{CartesianTensorXmpPageFull33}{CartesianTensorXmpPageEmpty33}
\pastebutton{CartesianTensorXmpPageFull33}{\hidepaste}
\tab{5}\spadcommand{contract(Tmn,1,3) = transpose(m) * n\free{Tmn m n }}
\indentrel{3}\begin{verbatim}
         Ú2  7 ¿  Ú2  7 ¿
   (33)  ³     ³= ³     ³
         À4  11Ù  À4  11Ù
            Type: Equation CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty33}
\begin{paste}{CartesianTensorXmpPageEmpty33}{CartesianTensorXmpPagePatch33}
\pastebutton{CartesianTensorXmpPageEmpty33}{\showpaste}
\tab{5}\spadcommand{contract(Tmn,1,3) = transpose(m) * n\free{Tmn m n }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch34}
\begin{paste}{CartesianTensorXmpPageFull34}{CartesianTensorXmpPageEmpty34}
\pastebutton{CartesianTensorXmpPageFull34}{\hidepaste}
\tab{5}\spadcommand{
contract(Tmn,1,4) = transpose(m) * transpose(n)\free{Tmn m n }}
\indentrel{3}\begin{verbatim}
         Ú14  4¿  Ú14  4¿
   (34)  ³     ³= ³     ³
         À19  5Ù  À19  5Ù
            Type: Equation CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty34}
\begin{paste}{CartesianTensorXmpPageEmpty34}{CartesianTensorXmpPagePatch34}
\pastebutton{CartesianTensorXmpPageEmpty34}{\showpaste}
\tab{5}\spadcommand{
contract(Tmn,1,4) = transpose(m) * transpose(n)\free{Tmn m n }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch35}
\begin{paste}{CartesianTensorXmpPageFull35}{CartesianTensorXmpPageEmpty35}
\pastebutton{CartesianTensorXmpPageFull35}{\hidepaste}
\tab{5}\spadcommand{contract(Tmn,2,3) = m * n\free{Tmn m n }}
\indentrel{3}\begin{verbatim}
         Ú2  5 ¿  Ú2  5 ¿
   (35)  ³     ³= ³     ³
         À8  17Ù  À8  17Ù
            Type: Equation CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty35}
\begin{paste}{CartesianTensorXmpPageEmpty35}{CartesianTensorXmpPagePatch35}
\pastebutton{CartesianTensorXmpPageEmpty35}{\showpaste}
\tab{5}\spadcommand{contract(Tmn,2,3) = m * n\free{Tmn m n }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch36}
\begin{paste}{CartesianTensorXmpPageFull36}{CartesianTensorXmpPageEmpty36}
\pastebutton{CartesianTensorXmpPageFull36}{\hidepaste}
\tab{5}\spadcommand{contract(Tmn,2,4) = m * transpose(n)\free{Tmn m n }}
\indentrel{3}\begin{verbatim}
         Ú8   2¿  Ú8   2¿
   (36)  ³     ³= ³     ³
         À23  5Ù  À23  5Ù
            Type: Equation CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty36}
\begin{paste}{CartesianTensorXmpPageEmpty36}{CartesianTensorXmpPagePatch36}
\pastebutton{CartesianTensorXmpPageEmpty36}{\showpaste}
\tab{5}\spadcommand{contract(Tmn,2,4) = m * transpose(n)\free{Tmn m n }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch37}
\begin{paste}{CartesianTensorXmpPageFull37}{CartesianTensorXmpPageEmpty37}
\pastebutton{CartesianTensorXmpPageFull37}{\hidepaste}
\tab{5}\spadcommand{contract(Tmn,3,4) = trace(n) * m\free{Tmn m n }}
\indentrel{3}\begin{verbatim}
         Ú3   6 ¿  Ú3   6 ¿
   (37)  ³      ³= ³      ³
         À12  15Ù  À12  15Ù
            Type: Equation CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty37}
\begin{paste}{CartesianTensorXmpPageEmpty37}{CartesianTensorXmpPagePatch37}
\pastebutton{CartesianTensorXmpPageEmpty37}{\showpaste}
\tab{5}\spadcommand{contract(Tmn,3,4) = trace(n) * m\free{Tmn m n }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch38}
\begin{paste}{CartesianTensorXmpPageFull38}{CartesianTensorXmpPageEmpty38}
\pastebutton{CartesianTensorXmpPageFull38}{\hidepaste}
\tab{5}\spadcommand{tTmn := transpose(Tmn,1,3)\free{tTmn }}
\indentrel{3}\begin{verbatim}
         ÚÚ2  3 ¿  Ú4   6 ¿¿
         ³³     ³  ³      ³³
         ³À8  12Ù  À10  15Ù³
   (38)  ³                 ³
         ³Ú0  1¿    Ú0  2¿ ³
         ³³    ³    ³    ³ ³
         ÀÀ0  4Ù    À0  5Ù Ù
                     Type: CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty38}
\begin{paste}{CartesianTensorXmpPageEmpty38}{CartesianTensorXmpPagePatch38}
\pastebutton{CartesianTensorXmpPageEmpty38}{\showpaste}
\tab{5}\spadcommand{tTmn := transpose(Tmn,1,3)\free{tTmn }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch39}
\begin{paste}{CartesianTensorXmpPageFull39}{CartesianTensorXmpPageEmpty39}
\pastebutton{CartesianTensorXmpPageFull39}{\hidepaste}
\tab{5}\spadcommand{transpose Tmn\free{Tmn }}
\indentrel{3}\begin{verbatim}
         ÚÚ2  8¿   Ú4  10¿¿
         ³³    ³   ³     ³³
         ³À0  0Ù   À0  0 Ù³
   (39)  ³                ³
         ³Ú3  12¿  Ú6  15¿³
         ³³     ³  ³     ³³
         ÀÀ1  4 Ù  À2  5 ÙÙ
                     Type: CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty39}
\begin{paste}{CartesianTensorXmpPageEmpty39}{CartesianTensorXmpPagePatch39}
\pastebutton{CartesianTensorXmpPageEmpty39}{\showpaste}
\tab{5}\spadcommand{transpose Tmn\free{Tmn }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch40}
\begin{paste}{CartesianTensorXmpPageFull40}{CartesianTensorXmpPageEmpty40}
\pastebutton{CartesianTensorXmpPageFull40}{\hidepaste}
\tab{5}\spadcommand{transpose Tm = transpose m\free{Tm m }}
\indentrel{3}\begin{verbatim}
         Ú1  4¿  Ú1  4¿
   (40)  ³    ³= ³    ³
         À2  5Ù  À2  5Ù
            Type: Equation CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty40}
\begin{paste}{CartesianTensorXmpPageEmpty40}{CartesianTensorXmpPagePatch40}
\pastebutton{CartesianTensorXmpPageEmpty40}{\showpaste}
\tab{5}\spadcommand{transpose Tm = transpose m\free{Tm m }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch41}
\begin{paste}{CartesianTensorXmpPageFull41}{CartesianTensorXmpPageEmpty41}
\pastebutton{CartesianTensorXmpPageFull41}{\hidepaste}
\tab{5}\spadcommand{rTmn := reindex(Tmn, [1,4,2,3])\free{Tmn }\bound{rTmn }}
\indentrel{3}\begin{verbatim}
         ÚÚ2  0¿   Ú3  1¿ ¿
         ³³    ³   ³    ³ ³
         ³À4  0Ù   À6  2Ù ³
   (41)  ³                ³
         ³Ú8   0¿  Ú12  4¿³
         ³³     ³  ³     ³³
         ÀÀ10  0Ù  À15  5ÙÙ
                     Type: CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty41}
\begin{paste}{CartesianTensorXmpPageEmpty41}{CartesianTensorXmpPagePatch41}
\pastebutton{CartesianTensorXmpPageEmpty41}{\showpaste}
\tab{5}\spadcommand{rTmn := reindex(Tmn, [1,4,2,3])\free{Tmn }\bound{rTmn }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch42}
\begin{paste}{CartesianTensorXmpPageFull42}{CartesianTensorXmpPageEmpty42}
\pastebutton{CartesianTensorXmpPageFull42}{\hidepaste}
\tab{5}\spadcommand{
tt := transpose(Tm)*Tn - Tn*transpose(Tm)\free{Tm Tn }\bound{tt2 }}
\indentrel{3}\begin{verbatim}
         Ú- 6  - 16¿
   (42)  ³         ³
         À 2    6  Ù
                     Type: CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty42}
\begin{paste}{CartesianTensorXmpPageEmpty42}{CartesianTensorXmpPagePatch42}
\pastebutton{CartesianTensorXmpPageEmpty42}{\showpaste}
\tab{5}\spadcommand{
tt := transpose(Tm)*Tn - Tn*transpose(Tm)\free{Tm Tn }\bound{tt2 }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch43}
\begin{paste}{CartesianTensorXmpPageFull43}{CartesianTensorXmpPageEmpty43}
\pastebutton{CartesianTensorXmpPageFull43}{\hidepaste}
\tab{5}\spadcommand{Tv*(tt+Tn)\free{tt2 Tv Tn }}
\indentrel{3}\begin{verbatim}
   (43)  [- 4,- 11]
                     Type: CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty43}
\begin{paste}{CartesianTensorXmpPageEmpty43}{CartesianTensorXmpPagePatch43}
\pastebutton{CartesianTensorXmpPageEmpty43}{\showpaste}
\tab{5}\spadcommand{Tv*(tt+Tn)\free{tt2 Tv Tn }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch44}
\begin{paste}{CartesianTensorXmpPageFull44}{CartesianTensorXmpPageEmpty44}
\pastebutton{CartesianTensorXmpPageFull44}{\hidepaste}
\tab{5}\spadcommand{
reindex(product(Tn,Tn),[4,3,2,1])+3*Tn*product(Tm,Tm)\free{Tm Tn }}
\indentrel{3}\begin{verbatim}
         ÚÚ46   84 ¿  Ú57   114¿¿
         ³³        ³  ³        ³³
         ³À174  212Ù  À228  285Ù³
   (44)  ³                      ³
         ³ Ú18  24¿    Ú17  30¿ ³
         ³ ³      ³    ³      ³ ³
         À À57  63Ù    À63  76Ù Ù
                     Type: CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty44}
\begin{paste}{CartesianTensorXmpPageEmpty44}{CartesianTensorXmpPagePatch44}
\pastebutton{CartesianTensorXmpPageEmpty44}{\showpaste}
\tab{5}\spadcommand{
reindex(product(Tn,Tn),[4,3,2,1])+3*Tn*product(Tm,Tm)\free{Tm Tn }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch45}
\begin{paste}{CartesianTensorXmpPageFull45}{CartesianTensorXmpPageEmpty45}
\pastebutton{CartesianTensorXmpPageFull45}{\hidepaste}
\tab{5}\spadcommand{delta: CT := kroneckerDelta()\free{CT }\bound{delta }}
\indentrel{3}\begin{verbatim}
         Ú1  0¿
   (45)  ³    ³
         À0  1Ù
                     Type: CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty45}
\begin{paste}{CartesianTensorXmpPageEmpty45}{CartesianTensorXmpPagePatch45}
\pastebutton{CartesianTensorXmpPageEmpty45}{\showpaste}
\tab{5}\spadcommand{delta: CT := kroneckerDelta()\free{CT }\bound{delta }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch46}
\begin{paste}{CartesianTensorXmpPageFull46}{CartesianTensorXmpPageEmpty46}
\pastebutton{CartesianTensorXmpPageFull46}{\hidepaste}
\tab{5}\spadcommand{
contract(Tmn, 2, delta, 1) = reindex(Tmn, [1,3,4,2])\free{Tmn delta }}
\indentrel{3}\begin{verbatim}
         Ú Ú2  4¿   Ú0  0¿¿  Ú Ú2  4¿   Ú0  0¿¿
         ³ ³    ³   ³    ³³  ³ ³    ³   ³    ³³
         ³ À3  6Ù   À1  2Ù³  ³ À3  6Ù   À1  2Ù³
   (46)  ³                ³= ³                ³
         ³Ú8   10¿  Ú0  0¿³  ³Ú8   10¿  Ú0  0¿³
         ³³      ³  ³    ³³  ³³      ³  ³    ³³
         ÀÀ12  15Ù  À4  5ÙÙ  ÀÀ12  15Ù  À4  5ÙÙ
            Type: Equation CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty46}
\begin{paste}{CartesianTensorXmpPageEmpty46}{CartesianTensorXmpPagePatch46}
\pastebutton{CartesianTensorXmpPageEmpty46}{\showpaste}
\tab{5}\spadcommand{
contract(Tmn, 2, delta, 1) = reindex(Tmn, [1,3,4,2])\free{Tmn delta }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch47}
\begin{paste}{CartesianTensorXmpPageFull47}{CartesianTensorXmpPageEmpty47}
\pastebutton{CartesianTensorXmpPageFull47}{\hidepaste}
\tab{5}\spadcommand{
epsilon:CT := leviCivitaSymbol()\free{CT }\bound{epsilon }}
\indentrel{3}\begin{verbatim}
         Ú 0   1¿
   (47)  ³      ³
         À- 1  0Ù
                     Type: CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty47}
\begin{paste}{CartesianTensorXmpPageEmpty47}
{CartesianTensorXmpPagePatch47}
\pastebutton{CartesianTensorXmpPageEmpty47}{\showpaste}
\tab{5}\spadcommand{
epsilon:CT := leviCivitaSymbol()\free{CT }\bound{epsilon }}
\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPagePatch48}
\begin{paste}{CartesianTensorXmpPageFull48}{CartesianTensorXmpPageEmpty48}
\pastebutton{CartesianTensorXmpPageFull48}{\hidepaste}
\tab{5}\spadcommand{
contract(epsilon*Tm*epsilon, 1,2) = 2 * determinant m\free{epsilon Tm m }}
\indentrel{3}\begin{verbatim}
   (48)  - 6= - 6
            Type: Equation CartesianTensor(1,2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CartesianTensorXmpPageEmpty48}
\begin{paste}{CartesianTensorXmpPageEmpty48}{CartesianTensorXmpPagePatch48}
\pastebutton{CartesianTensorXmpPageEmpty48}{\showpaste}
\tab{5}\spadcommand{
contract(epsilon*Tm*epsilon, 1,2) = 2 * determinant m\free{epsilon Tm m }}
\end{paste}\end{patch}

\end{chunk}
\section{cclass.ht}
\pagetitle{CharacterClassXmpPage}{cclass.ht}{CharacterClass}
\begin{chunk}{cclass.ht}
\begin{page}{CharacterClassXmpPage}{CharacterClass}
\beginscroll
 
The \spadtype{CharacterClass} domain allows classes of characters to be
defined and manipulated efficiently.
 
\xtc{
Character classes can be created by giving either a string or a list
of characters.
}{
\spadpaste{cl1 := 
charClass [char "a", char "e", char "i", char "o", char "u", char "y"] 
\bound{cl1}}
}
\xtc{
}{
\spadpaste{cl2 := charClass "bcdfghjklmnpqrstvwxyz" \bound{cl2}}
}
\xtc{
A number of character classes are predefined for convenience.
}{
\spadpaste{digit()}
}
\xtc{
}{
\spadpaste{hexDigit()}
}
\xtc{
}{
\spadpaste{upperCase()}
}
\xtc{
}{
\spadpaste{lowerCase()}
}
\xtc{
}{
\spadpaste{alphabetic()}
}
\xtc{
}{
\spadpaste{alphanumeric()}
}
\xtc{
You can quickly test whether a character belongs to a class.
}{
\spadpaste{member?(char "a", cl1) \free{cl1}}
}
\xtc{
}{
\spadpaste{member?(char "a", cl2) \free{cl2}}
}
\xtc{
Classes have the usual set operations because
the \spadtype{CharacterClass} domain belongs to the category
\spadtype{FiniteSetAggregate(Character)}.
}{
\spadpaste{intersect(cl1, cl2)  \free{cl1 cl2}}
}
\xtc{
}{
\spadpaste{union(cl1,cl2)       \free{cl1 cl2}}
}
\xtc{
}{
\spadpaste{difference(cl1,cl2)  \free{cl1 cl2}}
}
\xtc{
}{
\spadpaste{intersect(complement(cl1),cl2)  \free{cl1 cl2}}
}
\xtc{
You can modify character classes by adding or removing characters.
}{
\spadpaste{insert!(char "a", cl2) \free{cl2}\bound{cl22}}
}
\xtc{
}{
\spadpaste{remove!(char "b", cl2) \free{cl22}\bound{cl23}}
}
 
For more information on related topics, see
\downlink{`Character'}{CharacterXmpPage}\ignore{Character} and
\downlink{`String'}{StringXmpPage}\ignore{String}.
%
\showBlurb{CharacterClass}
\endscroll
\autobuttons
\end{page}

\begin{patch}{CharacterClassXmpPagePatch1}
\begin{paste}{CharacterClassXmpPageFull1}{CharacterClassXmpPageEmpty1}
\pastebutton{CharacterClassXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{
cl1:=charClass[char "a", char "e", char "i", char "o", char "u", char "y"]
\bound{cl1 }}
\indentrel{3}\begin{verbatim}
   (1)  "aeiouy"
                                   Type: CharacterClass
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPageEmpty1}
\begin{paste}{CharacterClassXmpPageEmpty1}{CharacterClassXmpPagePatch1}
\pastebutton{CharacterClassXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{
cl1:=charClass [char "a", char "e", char "i", char "o", char "u", char "y"]
\bound{cl1 }}
\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPagePatch2}
\begin{paste}{CharacterClassXmpPageFull2}{CharacterClassXmpPageEmpty2}
\pastebutton{CharacterClassXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{cl2 := charClass "bcdfghjklmnpqrstvwxyz"\bound{cl2 }}
\indentrel{3}\begin{verbatim}
   (2)  "bcdfghjklmnpqrstvwxyz"
                                   Type: CharacterClass
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPageEmpty2}
\begin{paste}{CharacterClassXmpPageEmpty2}{CharacterClassXmpPagePatch2}
\pastebutton{CharacterClassXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{cl2 := charClass "bcdfghjklmnpqrstvwxyz"\bound{cl2 }}
\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPagePatch3}
\begin{paste}{CharacterClassXmpPageFull3}{CharacterClassXmpPageEmpty3}
\pastebutton{CharacterClassXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{digit()}
\indentrel{3}\begin{verbatim}
   (3)  "0123456789"
                                   Type: CharacterClass
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPageEmpty3}
\begin{paste}{CharacterClassXmpPageEmpty3}{CharacterClassXmpPagePatch3}
\pastebutton{CharacterClassXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{digit()}
\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPagePatch4}
\begin{paste}{CharacterClassXmpPageFull4}{CharacterClassXmpPageEmpty4}
\pastebutton{CharacterClassXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{hexDigit()}
\indentrel{3}\begin{verbatim}
   (4)  "0123456789ABCDEFabcdef"
                                   Type: CharacterClass
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPageEmpty4}
\begin{paste}{CharacterClassXmpPageEmpty4}{CharacterClassXmpPagePatch4}
\pastebutton{CharacterClassXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{hexDigit()}
\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPagePatch5}
\begin{paste}{CharacterClassXmpPageFull5}{CharacterClassXmpPageEmpty5}
\pastebutton{CharacterClassXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{upperCase()}
\indentrel{3}\begin{verbatim}
   (5)  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                                   Type: CharacterClass
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPageEmpty5}
\begin{paste}{CharacterClassXmpPageEmpty5}{CharacterClassXmpPagePatch5}
\pastebutton{CharacterClassXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{upperCase()}
\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPagePatch6}
\begin{paste}{CharacterClassXmpPageFull6}{CharacterClassXmpPageEmpty6}
\pastebutton{CharacterClassXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{lowerCase()}
\indentrel{3}\begin{verbatim}
   (6)  "abcdefghijklmnopqrstuvwxyz"
                                   Type: CharacterClass
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPageEmpty6}
\begin{paste}{CharacterClassXmpPageEmpty6}{CharacterClassXmpPagePatch6}
\pastebutton{CharacterClassXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{lowerCase()}
\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPagePatch7}
\begin{paste}{CharacterClassXmpPageFull7}{CharacterClassXmpPageEmpty7}
\pastebutton{CharacterClassXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{alphabetic()}
\indentrel{3}\begin{verbatim}
   (7)
   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
                                   Type: CharacterClass
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPageEmpty7}
\begin{paste}{CharacterClassXmpPageEmpty7}{CharacterClassXmpPagePatch7}
\pastebutton{CharacterClassXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{alphabetic()}
\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPagePatch8}
\begin{paste}{CharacterClassXmpPageFull8}{CharacterClassXmpPageEmpty8}
\pastebutton{CharacterClassXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{alphanumeric()}
\indentrel{3}\begin{verbatim}
   (8)
  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr
  stuvwxyz"
                                   Type: CharacterClass
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPageEmpty8}
\begin{paste}{CharacterClassXmpPageEmpty8}{CharacterClassXmpPagePatch8}
\pastebutton{CharacterClassXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{alphanumeric()}
\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPagePatch9}
\begin{paste}{CharacterClassXmpPageFull9}{CharacterClassXmpPageEmpty9}
\pastebutton{CharacterClassXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{member?(char "a", cl1)\free{cl1 }}
\indentrel{3}\begin{verbatim}
   (9)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPageEmpty9}
\begin{paste}{CharacterClassXmpPageEmpty9}{CharacterClassXmpPagePatch9}
\pastebutton{CharacterClassXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{member?(char "a", cl1)\free{cl1 }}
\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPagePatch10}
\begin{paste}{CharacterClassXmpPageFull10}{CharacterClassXmpPageEmpty10}
\pastebutton{CharacterClassXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{member?(char "a", cl2)\free{cl2 }}
\indentrel{3}\begin{verbatim}
   (10)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPageEmpty10}
\begin{paste}{CharacterClassXmpPageEmpty10}{CharacterClassXmpPagePatch10}
\pastebutton{CharacterClassXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{member?(char "a", cl2)\free{cl2 }}
\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPagePatch11}
\begin{paste}{CharacterClassXmpPageFull11}{CharacterClassXmpPageEmpty11}
\pastebutton{CharacterClassXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{intersect(cl1, cl2)\free{cl1 cl2 }}
\indentrel{3}\begin{verbatim}
   (11)  "y"
                                   Type: CharacterClass
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPageEmpty11}
\begin{paste}{CharacterClassXmpPageEmpty11}{CharacterClassXmpPagePatch11}
\pastebutton{CharacterClassXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{intersect(cl1, cl2)\free{cl1 cl2 }}
\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPagePatch12}
\begin{paste}{CharacterClassXmpPageFull12}{CharacterClassXmpPageEmpty12}
\pastebutton{CharacterClassXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{union(cl1,cl2)\free{cl1 cl2 }}
\indentrel{3}\begin{verbatim}
   (12)  "abcdefghijklmnopqrstuvwxyz"
                                   Type: CharacterClass
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPageEmpty12}
\begin{paste}{CharacterClassXmpPageEmpty12}{CharacterClassXmpPagePatch12}
\pastebutton{CharacterClassXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{union(cl1,cl2)\free{cl1 cl2 }}
\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPagePatch13}
\begin{paste}{CharacterClassXmpPageFull13}{CharacterClassXmpPageEmpty13}
\pastebutton{CharacterClassXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{difference(cl1,cl2)\free{cl1 cl2 }}
\indentrel{3}\begin{verbatim}
   (13)  "aeiou"
                                   Type: CharacterClass
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPageEmpty13}
\begin{paste}{CharacterClassXmpPageEmpty13}{CharacterClassXmpPagePatch13}
\pastebutton{CharacterClassXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{difference(cl1,cl2)\free{cl1 cl2 }}
\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPagePatch14}
\begin{paste}{CharacterClassXmpPageFull14}{CharacterClassXmpPageEmpty14}
\pastebutton{CharacterClassXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{intersect(complement(cl1),cl2)\free{cl1 cl2 }}
\indentrel{3}\begin{verbatim}
   (14)  "bcdfghjklmnpqrstvwxz"
                                   Type: CharacterClass
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPageEmpty14}
\begin{paste}{CharacterClassXmpPageEmpty14}{CharacterClassXmpPagePatch14}
\pastebutton{CharacterClassXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{intersect(complement(cl1),cl2)\free{cl1 cl2 }}
\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPagePatch15}
\begin{paste}{CharacterClassXmpPageFull15}{CharacterClassXmpPageEmpty15}
\pastebutton{CharacterClassXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{insert!(char "a", cl2)\free{cl2 }\bound{cl22 }}
\indentrel{3}\begin{verbatim}
   (15)  "abcdfghjklmnpqrstvwxyz"
                                   Type: CharacterClass
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPageEmpty15}
\begin{paste}{CharacterClassXmpPageEmpty15}{CharacterClassXmpPagePatch15}
\pastebutton{CharacterClassXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{insert!(char "a", cl2)\free{cl2 }\bound{cl22 }}
\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPagePatch16}
\begin{paste}{CharacterClassXmpPageFull16}{CharacterClassXmpPageEmpty16}
\pastebutton{CharacterClassXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{remove!(char "b", cl2)\free{cl22 }\bound{cl23 }}
\indentrel{3}\begin{verbatim}
   (16)  "acdfghjklmnpqrstvwxyz"
                                   Type: CharacterClass
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterClassXmpPageEmpty16}
\begin{paste}{CharacterClassXmpPageEmpty16}{CharacterClassXmpPagePatch16}
\pastebutton{CharacterClassXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{remove!(char "b", cl2)\free{cl22 }\bound{cl23 }}
\end{paste}\end{patch}

\end{chunk}
\section{char.ht}
\pagetitle{CharacterXmpPage}{char.ht}{Character}
\pageto{CharacterClass}{CharacterClassXmpPage}
\pageto{String}{StringXmpPage}
\begin{chunk}{char.ht}
\begin{page}{CharacterXmpPage}{Character}
\beginscroll
 
The members of the domain \spadtype{Character} are values
representing letters, numerals and other text elements.
For more information on related topics, see
\downlink{`CharacterClass'}{CharacterClassXmpPage}\ignore{CharacterClass} 
and \downlink{`String'}{StringXmpPage}\ignore{String}.
 
\xtc{
Characters can be obtained using \spadtype{String} notation.
}{
\spadpaste{chars := [char "a", char "A", char "X", char "8", char "+"] 
\bound{chars}}
}
\xtc{
Certain characters are available by name.
This is the blank character.
}{
\spadpaste{space()}
}
\xtc{
This is the quote that is used in strings.
}{
\spadpaste{quote()}
}
\xtc{
This is the escape character that allows quotes and other characters
within strings.
}{
\spadpaste{escape()}
}
\xtc{
Characters are represented as integers in a machine-dependent way.
The integer value can be obtained using the \spadfunFrom{ord}{Character}
operation.
It is always true that \spad{char(ord c) = c} and \spad{ord(char i) = i},
provided that \spad{i} is in the range \spad{0..size()\$Character-1}.
}{
\spadpaste{[ord c for c in chars] \free{chars}}
}
 
\xtc{
The \spadfunFrom{lowerCase}{Character} operation converts an upper case
letter to the corresponding lower case letter.
If the argument is not an upper case letter, then it is returned
unchanged.
}{
\spadpaste{[upperCase c for c in chars] \free{chars}}
}
\xtc{
Likewise, the \spadfunFrom{upperCase}{Character} operation converts lower
case letters to upper case.
}{
\spadpaste{[lowerCase c for c in chars] \free{chars}}
}
 
\xtc{
A number of tests are available to determine whether characters
belong to certain families.
}{
\spadpaste{[alphabetic? c for c in chars] \free{chars}}
}
\xtc{
}{
\spadpaste{[upperCase? c for c in chars] \free{chars}}
}
\xtc{
}{
\spadpaste{[lowerCase? c for c in chars] \free{chars}}
}
\xtc{
}{
\spadpaste{[digit? c for c in chars] \free{chars}}
}
\xtc{
}{
\spadpaste{[hexDigit? c for c in chars] \free{chars}}
}
\xtc{
}{
\spadpaste{[alphanumeric? c for c in chars] \free{chars}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{CharacterXmpPagePatch1}
\begin{paste}{CharacterXmpPageFull1}{CharacterXmpPageEmpty1}
\pastebutton{CharacterXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{
chars := [char "a", char "A", char "X", char "8", char "+"]\bound{chars }}
\indentrel{3}\begin{verbatim}
   (1)  [a,A,X,8,+]
                                   Type: List Character
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterXmpPageEmpty1}
\begin{paste}{CharacterXmpPageEmpty1}{CharacterXmpPagePatch1}
\pastebutton{CharacterXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{
chars := [char "a", char "A", char "X", char "8", char "+"]\bound{chars }}
\end{paste}\end{patch}

\begin{patch}{CharacterXmpPagePatch2}
\begin{paste}{CharacterXmpPageFull2}{CharacterXmpPageEmpty2}
\pastebutton{CharacterXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{space()}
\indentrel{3}\begin{verbatim}
   (2)
                                        Type: Character
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterXmpPageEmpty2}
\begin{paste}{CharacterXmpPageEmpty2}{CharacterXmpPagePatch2}
\pastebutton{CharacterXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{space()}
\end{paste}\end{patch}

\begin{patch}{CharacterXmpPagePatch3}
\begin{paste}{CharacterXmpPageFull3}{CharacterXmpPageEmpty3}
\pastebutton{CharacterXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{quote()}
\indentrel{3}\begin{verbatim}
   (3)  "
                                        Type: Character
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterXmpPageEmpty3}
\begin{paste}{CharacterXmpPageEmpty3}{CharacterXmpPagePatch3}
\pastebutton{CharacterXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{quote()}
\end{paste}\end{patch}

\begin{patch}{CharacterXmpPagePatch4}
\begin{paste}{CharacterXmpPageFull4}{CharacterXmpPageEmpty4}
\pastebutton{CharacterXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{escape()}
\indentrel{3}\begin{verbatim}
   (4)  _
                                        Type: Character
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterXmpPageEmpty4}
\begin{paste}{CharacterXmpPageEmpty4}{CharacterXmpPagePatch4}
\pastebutton{CharacterXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{escape()}
\end{paste}\end{patch}

\begin{patch}{CharacterXmpPagePatch5}
\begin{paste}{CharacterXmpPageFull5}{CharacterXmpPageEmpty5}
\pastebutton{CharacterXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{[ord c for c in chars]\free{chars }}
\indentrel{3}\begin{verbatim}
   (5)  [97,65,88,56,43]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterXmpPageEmpty5}
\begin{paste}{CharacterXmpPageEmpty5}{CharacterXmpPagePatch5}
\pastebutton{CharacterXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{[ord c for c in chars]\free{chars }}
\end{paste}\end{patch}

\begin{patch}{CharacterXmpPagePatch6}
\begin{paste}{CharacterXmpPageFull6}{CharacterXmpPageEmpty6}
\pastebutton{CharacterXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{[upperCase c for c in chars]\free{chars }}
\indentrel{3}\begin{verbatim}
   (6)  [A,A,X,8,+]
                                   Type: List Character
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterXmpPageEmpty6}
\begin{paste}{CharacterXmpPageEmpty6}{CharacterXmpPagePatch6}
\pastebutton{CharacterXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{[upperCase c for c in chars]\free{chars }}
\end{paste}\end{patch}

\begin{patch}{CharacterXmpPagePatch7}
\begin{paste}{CharacterXmpPageFull7}{CharacterXmpPageEmpty7}
\pastebutton{CharacterXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{[lowerCase c for c in chars]\free{chars }}
\indentrel{3}\begin{verbatim}
   (7)  [a,a,x,8,+]
                                   Type: List Character
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterXmpPageEmpty7}
\begin{paste}{CharacterXmpPageEmpty7}{CharacterXmpPagePatch7}
\pastebutton{CharacterXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{[lowerCase c for c in chars]\free{chars }}
\end{paste}\end{patch}

\begin{patch}{CharacterXmpPagePatch8}
\begin{paste}{CharacterXmpPageFull8}{CharacterXmpPageEmpty8}
\pastebutton{CharacterXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{[alphabetic? c for c in chars]\free{chars }}
\indentrel{3}\begin{verbatim}
   (8)  [true,true,true,false,false]
                                     Type: List Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterXmpPageEmpty8}
\begin{paste}{CharacterXmpPageEmpty8}{CharacterXmpPagePatch8}
\pastebutton{CharacterXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{[alphabetic? c for c in chars]\free{chars }}
\end{paste}\end{patch}

\begin{patch}{CharacterXmpPagePatch9}
\begin{paste}{CharacterXmpPageFull9}{CharacterXmpPageEmpty9}
\pastebutton{CharacterXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{[upperCase? c for c in chars]\free{chars }}
\indentrel{3}\begin{verbatim}
   (9)  [false,true,true,false,false]
                                     Type: List Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterXmpPageEmpty9}
\begin{paste}{CharacterXmpPageEmpty9}{CharacterXmpPagePatch9}
\pastebutton{CharacterXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{[upperCase? c for c in chars]\free{chars }}
\end{paste}\end{patch}

\begin{patch}{CharacterXmpPagePatch10}
\begin{paste}{CharacterXmpPageFull10}{CharacterXmpPageEmpty10}
\pastebutton{CharacterXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{[lowerCase? c for c in chars]\free{chars }}
\indentrel{3}\begin{verbatim}
   (10)  [true,false,false,false,false]
                                     Type: List Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterXmpPageEmpty10}
\begin{paste}{CharacterXmpPageEmpty10}{CharacterXmpPagePatch10}
\pastebutton{CharacterXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{[lowerCase? c for c in chars]\free{chars }}
\end{paste}\end{patch}

\begin{patch}{CharacterXmpPagePatch11}
\begin{paste}{CharacterXmpPageFull11}{CharacterXmpPageEmpty11}
\pastebutton{CharacterXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{[digit? c for c in chars]\free{chars }}
\indentrel{3}\begin{verbatim}
   (11)  [false,false,false,true,false]
                                     Type: List Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterXmpPageEmpty11}
\begin{paste}{CharacterXmpPageEmpty11}{CharacterXmpPagePatch11}
\pastebutton{CharacterXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{[digit? c for c in chars]\free{chars }}
\end{paste}\end{patch}

\begin{patch}{CharacterXmpPagePatch12}
\begin{paste}{CharacterXmpPageFull12}{CharacterXmpPageEmpty12}
\pastebutton{CharacterXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{[hexDigit? c for c in chars]\free{chars }}
\indentrel{3}\begin{verbatim}
   (12)  [true,true,false,true,false]
                                     Type: List Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterXmpPageEmpty12}
\begin{paste}{CharacterXmpPageEmpty12}{CharacterXmpPagePatch12}
\pastebutton{CharacterXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{[hexDigit? c for c in chars]\free{chars }}
\end{paste}\end{patch}

\begin{patch}{CharacterXmpPagePatch13}
\begin{paste}{CharacterXmpPageFull13}{CharacterXmpPageEmpty13}
\pastebutton{CharacterXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{[alphanumeric? c for c in chars]\free{chars }}
\indentrel{3}\begin{verbatim}
   (13)  [true,true,true,true,false]
                                     Type: List Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CharacterXmpPageEmpty13}
\begin{paste}{CharacterXmpPageEmpty13}{CharacterXmpPagePatch13}
\pastebutton{CharacterXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{[alphanumeric? c for c in chars]\free{chars }}
\end{paste}\end{patch}


\end{chunk}
\pagetitle{CliffordAlgebraXmpPage}{clif.ht}{CliffordAlgebra}
\pageto{The Complex Numbers as a Clifford Algebra}
{ugxCliffordComplexPage}
\pageto{The Quaternion Numbers as a Clifford AlgebraNo}
{ugxCliffordQuaternPage}
\pageto{The Exterior Algebra on a Three Space}{ugxCliffordExteriorPage}
\pageto{The Dirac Spin Algebra}{ugxCliffordDiracPage}
\begin{chunk}{clif.ht}
\begin{page}{CliffordAlgebraXmpPage}{CliffordAlgebra}
\beginscroll

\noindent
\spadtype{CliffordAlgebra(n,K,Q)} defines a vector space of dimension
\texht{$2^n$}{\spad{2**n}} over the field \texht{$K$}{\spad{K}} with a
given quadratic form \spad{Q}.
If \texht{$\{e_1, \ldots, e_n\}$}{\spad{\{e(i), 1<=i<=n\}}}
is a basis for  \texht{$K^n$}{\spad{K**n}} then
\begin{verbatim}
{ 1,
  e(i) 1 <= i <= n,
  e(i1)*e(i2) 1 <= i1 < i2 <=n,
  ...,
  e(1)*e(2)*...*e(n) }
\end{verbatim}
is a basis for the Clifford algebra.
The algebra is defined by the relations
\begin{verbatim}
e(i)*e(i) = Q(e(i))
e(i)*e(j) = -e(j)*e(i),  i ^= j
\end{verbatim}
Examples of Clifford Algebras are
gaussians (complex numbers), quaternions,
exterior algebras and spin algebras.
%

\beginmenu
    \menudownlink{{9.10.1. The Complex Numbers as a Clifford Algebra}}
{ugxCliffordComplexPage}
    \menudownlink{{9.10.2. The Quaternion Numbers as a Clifford Algebra}}
{ugxCliffordQuaternPage}
    \menudownlink{{9.10.3. The Exterior Algebra on a Three Space}}
{ugxCliffordExteriorPage}
    \menudownlink{{9.10.4. The Dirac Spin Algebra}}
{ugxCliffordDiracPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugxCliffordComplexPage}{clif.ht}
{The Complex Numbers as a Clifford Algebra}
\pageto{Complex}{ComplexXmpPage}
\begin{chunk}{clif.ht}
\begin{page}{ugxCliffordComplexPage}
{The Complex Numbers as a Clifford Algebra}
\beginscroll

\labelSpace{5pc}
\xtc{
This is the field over which we will work, rational functions with
integer coefficients.
}{
\spadpaste{K := Fraction Polynomial Integer \bound{K}}
}
\xtc{
We use this matrix for the quadratic form.
}{
\spadpaste{m := matrix [[-1]] \bound{m}}
}
\xtc{
We get complex arithmetic by using this domain.
}{
\spadpaste{C := CliffordAlgebra(1, K, quadraticForm m) \free{K m}
\bound{C}}
}
\xtc{
Here is \spad{i}, the usual square root of \spad{-1.}
}{
\spadpaste{i: C := e(1)   \bound{i}\free{C}}
}
\xtc{
Here are some examples of the arithmetic.
}{
\spadpaste{x := a + b * i \bound{x}\free{i}}
}
\xtc{
}{
\spadpaste{y := c + d * i \bound{y}\free{i}}
}
\xtc{
See \downlink{`Complex'}{ComplexXmpPage}\ignore{Complex} 
for examples of Axiom's constructor
implementing complex numbers.
}{
\spadpaste{x * y \free{x y}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxCliffordComplexPagePatch1}
\begin{paste}{ugxCliffordComplexPageFull1}{ugxCliffordComplexPageEmpty1}
\pastebutton{ugxCliffordComplexPageFull1}{\hidepaste}
\tab{5}\spadcommand{K := Fraction Polynomial Integer\bound{K }}
\indentrel{3}\begin{verbatim}
   (1)  Fraction Polynomial Integer
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordComplexPageEmpty1}
\begin{paste}{ugxCliffordComplexPageEmpty1}{ugxCliffordComplexPagePatch1}
\pastebutton{ugxCliffordComplexPageEmpty1}{\showpaste}
\tab{5}\spadcommand{K := Fraction Polynomial Integer\bound{K }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordComplexPagePatch2}
\begin{paste}{ugxCliffordComplexPageFull2}{ugxCliffordComplexPageEmpty2}
\pastebutton{ugxCliffordComplexPageFull2}{\hidepaste}
\tab{5}\spadcommand{m := matrix [[-1]]\bound{m }}
\indentrel{3}\begin{verbatim}
   (2)  [- 1]
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordComplexPageEmpty2}
\begin{paste}{ugxCliffordComplexPageEmpty2}{ugxCliffordComplexPagePatch2}
\pastebutton{ugxCliffordComplexPageEmpty2}{\showpaste}
\tab{5}\spadcommand{m := matrix [[-1]]\bound{m }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordComplexPagePatch3}
\begin{paste}{ugxCliffordComplexPageFull3}{ugxCliffordComplexPageEmpty3}
\pastebutton{ugxCliffordComplexPageFull3}{\hidepaste}
\tab{5}\spadcommand{
C := CliffordAlgebra(1, K, quadraticForm m)\free{K m }\bound{C }}
\indentrel{3}\begin{verbatim}
   (3)
   CliffordAlgebra(1,Fraction Polynomial Integer,MATRIX)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordComplexPageEmpty3}
\begin{paste}{ugxCliffordComplexPageEmpty3}{ugxCliffordComplexPagePatch3}
\pastebutton{ugxCliffordComplexPageEmpty3}{\showpaste}
\tab{5}\spadcommand{
C := CliffordAlgebra(1, K, quadraticForm m)\free{K m }\bound{C }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordComplexPagePatch4}
\begin{paste}{ugxCliffordComplexPageFull4}{ugxCliffordComplexPageEmpty4}
\pastebutton{ugxCliffordComplexPageFull4}{\hidepaste}
\tab{5}\spadcommand{i: C := e(1)\bound{i }\free{C }}
\indentrel{3}\begin{verbatim}
   (4)  e
         1
Type: CliffordAlgebra(1,Fraction Polynomial Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordComplexPageEmpty4}
\begin{paste}{ugxCliffordComplexPageEmpty4}{ugxCliffordComplexPagePatch4}
\pastebutton{ugxCliffordComplexPageEmpty4}{\showpaste}
\tab{5}\spadcommand{i: C := e(1)\bound{i }\free{C }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordComplexPagePatch5}
\begin{paste}{ugxCliffordComplexPageFull5}{ugxCliffordComplexPageEmpty5}
\pastebutton{ugxCliffordComplexPageFull5}{\hidepaste}
\tab{5}\spadcommand{x := a + b * i\bound{x }\free{i }}
\indentrel{3}\begin{verbatim}
   (5)  a + b e
               1
Type: CliffordAlgebra(1,Fraction Polynomial Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordComplexPageEmpty5}
\begin{paste}{ugxCliffordComplexPageEmpty5}{ugxCliffordComplexPagePatch5}
\pastebutton{ugxCliffordComplexPageEmpty5}{\showpaste}
\tab{5}\spadcommand{x := a + b * i\bound{x }\free{i }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordComplexPagePatch6}
\begin{paste}{ugxCliffordComplexPageFull6}{ugxCliffordComplexPageEmpty6}
\pastebutton{ugxCliffordComplexPageFull6}{\hidepaste}
\tab{5}\spadcommand{y := c + d * i\bound{y }\free{i }}
\indentrel{3}\begin{verbatim}
   (6)  c + d e
               1
Type: CliffordAlgebra(1,Fraction Polynomial Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordComplexPageEmpty6}
\begin{paste}{ugxCliffordComplexPageEmpty6}{ugxCliffordComplexPagePatch6}
\pastebutton{ugxCliffordComplexPageEmpty6}{\showpaste}
\tab{5}\spadcommand{y := c + d * i\bound{y }\free{i }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordComplexPagePatch7}
\begin{paste}{ugxCliffordComplexPageFull7}{ugxCliffordComplexPageEmpty7}
\pastebutton{ugxCliffordComplexPageFull7}{\hidepaste}
\tab{5}\spadcommand{x * y\free{x y }}
\indentrel{3}\begin{verbatim}
   (7)  - b d + a c + (a d + b c)e
                                  1
Type: CliffordAlgebra(1,Fraction Polynomial Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordComplexPageEmpty7}
\begin{paste}{ugxCliffordComplexPageEmpty7}{ugxCliffordComplexPagePatch7}
\pastebutton{ugxCliffordComplexPageEmpty7}{\showpaste}
\tab{5}\spadcommand{x * y\free{x y }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxCliffordQuaternPage}{clif.ht}
{The Quaternion Numbers as a Clifford Algebra}
\pageto{Quaternion}{QuaternionXmpPage}
\begin{chunk}{clif.ht}
\begin{page}{ugxCliffordQuaternPage}
{The Quaternion Numbers as a Clifford Algebra}
\beginscroll

\labelSpace{3pc}
\xtc{
This is the field over which we will work, rational functions with
integer coefficients.
}{
\spadpaste{K := Fraction Polynomial Integer \bound{K}}
}
\xtc{
We use this matrix for the quadratic form.
}{
\spadpaste{m := matrix [[-1,0],[0,-1]] \bound{m}}
}
\xtc{
The resulting domain is the quaternions.
}{
\spadpaste{H  := CliffordAlgebra(2, K, quadraticForm m) \free{K m}\bound{H}}
}
\xtc{
We use Hamilton's notation for \spad{i},\spad{j},\spad{k}.
}{
\spadpaste{i: H  := e(1) \free{H}\bound{i}}
}
\xtc{
}{
\spadpaste{j: H  := e(2) \free{H}\bound{j}}
}
\xtc{
}{
\spadpaste{k: H  := i * j \free{H,i,j}\bound{k}}
}
\xtc{
}{
\spadpaste{x := a + b * i + c * j + d * k \free{i j k}\bound{x}}
}
\xtc{
}{
\spadpaste{y := e + f * i + g * j + h * k \free{i j k}\bound{y}}
}
\xtc{
}{
\spadpaste{x + y \free{x y}}
}
\xtc{
}{
\spadpaste{x * y \free{x y}}
}
\xtc{
See \downlink{`Quaternion'}{QuaternionXmpPage}
\ignore{Quaternion} for examples of Axiom's constructor
implementing quaternions.
}{
\spadpaste{y * x \free{x y}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxCliffordQuaternPagePatch1}
\begin{paste}{ugxCliffordQuaternPageFull1}{ugxCliffordQuaternPageEmpty1}
\pastebutton{ugxCliffordQuaternPageFull1}{\hidepaste}
\tab{5}\spadcommand{K := Fraction Polynomial Integer\bound{K }}
\indentrel{3}\begin{verbatim}
   (1)  Fraction Polynomial Integer
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordQuaternPageEmpty1}
\begin{paste}{ugxCliffordQuaternPageEmpty1}{ugxCliffordQuaternPagePatch1}
\pastebutton{ugxCliffordQuaternPageEmpty1}{\showpaste}
\tab{5}\spadcommand{K := Fraction Polynomial Integer\bound{K }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordQuaternPagePatch2}
\begin{paste}{ugxCliffordQuaternPageFull2}{ugxCliffordQuaternPageEmpty2}
\pastebutton{ugxCliffordQuaternPageFull2}{\hidepaste}
\tab{5}\spadcommand{m := matrix [[-1,0],[0,-1]]\bound{m }}
\indentrel{3}\begin{verbatim}
        Ú- 1   0 ¿
   (2)  ³        ³
        À 0   - 1Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordQuaternPageEmpty2}
\begin{paste}{ugxCliffordQuaternPageEmpty2}{ugxCliffordQuaternPagePatch2}
\pastebutton{ugxCliffordQuaternPageEmpty2}{\showpaste}
\tab{5}\spadcommand{m := matrix [[-1,0],[0,-1]]\bound{m }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordQuaternPagePatch3}
\begin{paste}{ugxCliffordQuaternPageFull3}{ugxCliffordQuaternPageEmpty3}
\pastebutton{ugxCliffordQuaternPageFull3}{\hidepaste}
\tab{5}\spadcommand{
H := CliffordAlgebra(2, K, quadraticForm m)\free{K m }\bound{H }}
\indentrel{3}\begin{verbatim}
   (3)
   CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordQuaternPageEmpty3}
\begin{paste}{ugxCliffordQuaternPageEmpty3}{ugxCliffordQuaternPagePatch3}
\pastebutton{ugxCliffordQuaternPageEmpty3}{\showpaste}
\tab{5}\spadcommand{
H := CliffordAlgebra(2, K, quadraticForm m)\free{K m }\bound{H }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordQuaternPagePatch4}
\begin{paste}{ugxCliffordQuaternPageFull4}{ugxCliffordQuaternPageEmpty4}
\pastebutton{ugxCliffordQuaternPageFull4}{\hidepaste}
\tab{5}\spadcommand{i: H := e(1)\free{H }\bound{i }}
\indentrel{3}\begin{verbatim}
   (4)  e
         1
Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordQuaternPageEmpty4}
\begin{paste}{ugxCliffordQuaternPageEmpty4}{ugxCliffordQuaternPagePatch4}
\pastebutton{ugxCliffordQuaternPageEmpty4}{\showpaste}
\tab{5}\spadcommand{i: H := e(1)\free{H }\bound{i }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordQuaternPagePatch5}
\begin{paste}{ugxCliffordQuaternPageFull5}{ugxCliffordQuaternPageEmpty5}
\pastebutton{ugxCliffordQuaternPageFull5}{\hidepaste}
\tab{5}\spadcommand{j: H := e(2)\free{H }\bound{j }}
\indentrel{3}\begin{verbatim}
   (5)  e
         2
Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordQuaternPageEmpty5}
\begin{paste}{ugxCliffordQuaternPageEmpty5}{ugxCliffordQuaternPagePatch5}
\pastebutton{ugxCliffordQuaternPageEmpty5}{\showpaste}
\tab{5}\spadcommand{j: H := e(2)\free{H }\bound{j }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordQuaternPagePatch6}
\begin{paste}{ugxCliffordQuaternPageFull6}{ugxCliffordQuaternPageEmpty6}
\pastebutton{ugxCliffordQuaternPageFull6}{\hidepaste}
\tab{5}\spadcommand{k: H := i * j\free{H i j }\bound{k }}
\indentrel{3}\begin{verbatim}
   (6)  e e
         1 2
Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordQuaternPageEmpty6}
\begin{paste}{ugxCliffordQuaternPageEmpty6}{ugxCliffordQuaternPagePatch6}
\pastebutton{ugxCliffordQuaternPageEmpty6}{\showpaste}
\tab{5}\spadcommand{k: H := i * j\free{H i j }\bound{k }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordQuaternPagePatch7}
\begin{paste}{ugxCliffordQuaternPageFull7}{ugxCliffordQuaternPageEmpty7}
\pastebutton{ugxCliffordQuaternPageFull7}{\hidepaste}
\tab{5}\spadcommand{x := a + b * i + c * j + d * k\free{i j k }\bound{x }}
\indentrel{3}\begin{verbatim}
   (7)  a + b e  + c e  + d e e
               1      2      1 2
Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordQuaternPageEmpty7}
\begin{paste}{ugxCliffordQuaternPageEmpty7}{ugxCliffordQuaternPagePatch7}
\pastebutton{ugxCliffordQuaternPageEmpty7}{\showpaste}
\tab{5}\spadcommand{x := a + b * i + c * j + d * k\free{i j k }\bound{x }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordQuaternPagePatch8}
\begin{paste}{ugxCliffordQuaternPageFull8}{ugxCliffordQuaternPageEmpty8}
\pastebutton{ugxCliffordQuaternPageFull8}{\hidepaste}
\tab{5}\spadcommand{y := e + f * i + g * j + h * k\free{i j k }\bound{y }}
\indentrel{3}\begin{verbatim}
   (8)  e + f e  + g e  + h e e
               1      2      1 2
Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordQuaternPageEmpty8}
\begin{paste}{ugxCliffordQuaternPageEmpty8}{ugxCliffordQuaternPagePatch8}
\pastebutton{ugxCliffordQuaternPageEmpty8}{\showpaste}
\tab{5}\spadcommand{y := e + f * i + g * j + h * k\free{i j k }\bound{y }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordQuaternPagePatch9}
\begin{paste}{ugxCliffordQuaternPageFull9}{ugxCliffordQuaternPageEmpty9}
\pastebutton{ugxCliffordQuaternPageFull9}{\hidepaste}
\tab{5}\spadcommand{x + y\free{x y }}
\indentrel{3}\begin{verbatim}
   (9)  e + a + (f + b)e  + (g + c)e  + (h + d)e e
                        1           2           1 2
Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordQuaternPageEmpty9}
\begin{paste}{ugxCliffordQuaternPageEmpty9}{ugxCliffordQuaternPagePatch9}
\pastebutton{ugxCliffordQuaternPageEmpty9}{\showpaste}
\tab{5}\spadcommand{x + y\free{x y }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordQuaternPagePatch10}
\begin{paste}{ugxCliffordQuaternPageFull10}{ugxCliffordQuaternPageEmpty10}
\pastebutton{ugxCliffordQuaternPageFull10}{\hidepaste}
\tab{5}\spadcommand{x * y\free{x y }}
\indentrel{3}\begin{verbatim}
   (10)
     - d h - c g - b f + a e + (c h - d g + a f + b e)e
                                                       1
   + 
     (- b h + a g + d f + c e)e
                               2
   + 
     (a h + b g - c f + d e)e e
                             1 2
Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordQuaternPageEmpty10}
\begin{paste}{ugxCliffordQuaternPageEmpty10}{ugxCliffordQuaternPagePatch10}
\pastebutton{ugxCliffordQuaternPageEmpty10}{\showpaste}
\tab{5}\spadcommand{x * y\free{x y }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordQuaternPagePatch11}
\begin{paste}{ugxCliffordQuaternPageFull11}{ugxCliffordQuaternPageEmpty11}
\pastebutton{ugxCliffordQuaternPageFull11}{\hidepaste}
\tab{5}\spadcommand{y * x\free{x y }}
\indentrel{3}\begin{verbatim}
   (11)
     - d h - c g - b f + a e + (- c h + d g + a f + b e)e
                                                         1
   + 
   (b h + a g - d f + c e)e  + (a h - b g + c f + d e)e e
                           2                           1 2
Type: CliffordAlgebra(2,Fraction Polynomial Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordQuaternPageEmpty11}
\begin{paste}{ugxCliffordQuaternPageEmpty11}{ugxCliffordQuaternPagePatch11}
\pastebutton{ugxCliffordQuaternPageEmpty11}{\showpaste}
\tab{5}\spadcommand{y * x\free{x y }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxCliffordExteriorPage}{clif.ht}
{The Exterior Algebra on a Three Space}
\begin{chunk}{clif.ht}
\begin{page}{ugxCliffordExteriorPage}{The Exterior Algebra on a Three Space}
\beginscroll

\labelSpace{4pc}
\xtc{
This is the field over which we will work, rational functions with
integer coefficients.
}{
\spadpaste{K := Fraction Polynomial Integer \bound{K}}
}
\xtc{
If we chose the three by three zero quadratic form, we obtain
the exterior algebra on \spad{e(1),e(2),e(3)}.
}{
\spadpaste{Ext := CliffordAlgebra(3, K, quadraticForm 0) \bound{Ext}
\free{K}}
}
\xtc{
This is a three dimensional vector algebra.
We define \spad{i}, \spad{j}, \spad{k} as the unit vectors.
}{
\spadpaste{i: Ext := e(1) \free{Ext}\bound{i}}
}
\xtc{
}{
\spadpaste{j: Ext := e(2) \free{Ext}\bound{j}}
}
\xtc{
}{
\spadpaste{k: Ext := e(3) \free{Ext}\bound{k}}
}
\xtc{
Now it is possible to do arithmetic.
}{
\spadpaste{x := x1*i + x2*j + x3*k \free{i j k}\bound{x}}
}
\xtc{
}{
\spadpaste{y := y1*i + y2*j + y3*k \free{i j k}\bound{y}}
}
\xtc{
}{
\spadpaste{x + y         \free{x y}}
}
\xtc{
}{
\spadpaste{x * y + y * x \free{x y}}
}
\xtc{
On an \spad{n} space, a grade \spad{p} form has a dual \spad{n-p} form.
In particular, in three space the dual of a grade two element identifies
\spad{e1*e2->e3, e2*e3->e1, e3*e1->e2}.
}{
\spadpaste{dual2 a == coefficient(a,[2,3]) * i + coefficient(a,[3,1]) * 
j + coefficient(a,[1,2]) * k \free{i j k}\bound{dual2}}
}
\xtc{
The vector cross product is then given by this.
}{
\spadpaste{dual2(x*y) \free{x y dual2}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxCliffordExteriorPagePatch1}
\begin{paste}{ugxCliffordExteriorPageFull1}{ugxCliffordExteriorPageEmpty1}
\pastebutton{ugxCliffordExteriorPageFull1}{\hidepaste}
\tab{5}\spadcommand{K := Fraction Polynomial Integer\bound{K }}
\indentrel{3}\begin{verbatim}
   (1)  Fraction Polynomial Integer
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordExteriorPageEmpty1}
\begin{paste}{ugxCliffordExteriorPageEmpty1}{ugxCliffordExteriorPagePatch1}
\pastebutton{ugxCliffordExteriorPageEmpty1}{\showpaste}
\tab{5}\spadcommand{K := Fraction Polynomial Integer\bound{K }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordExteriorPagePatch2}
\begin{paste}{ugxCliffordExteriorPageFull2}{ugxCliffordExteriorPageEmpty2}
\pastebutton{ugxCliffordExteriorPageFull2}{\hidepaste}
\tab{5}\spadcommand{
Ext := CliffordAlgebra(3, K, quadraticForm 0)\bound{Ext }\free{K }}
\indentrel{3}\begin{verbatim}
   (2)
   CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordExteriorPageEmpty2}
\begin{paste}{ugxCliffordExteriorPageEmpty2}{ugxCliffordExteriorPagePatch2}
\pastebutton{ugxCliffordExteriorPageEmpty2}{\showpaste}
\tab{5}\spadcommand{
Ext := CliffordAlgebra(3, K, quadraticForm 0)\bound{Ext }\free{K }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordExteriorPagePatch3}
\begin{paste}{ugxCliffordExteriorPageFull3}{ugxCliffordExteriorPageEmpty3}
\pastebutton{ugxCliffordExteriorPageFull3}{\hidepaste}
\tab{5}\spadcommand{i: Ext := e(1)\free{Ext }\bound{i }}
\indentrel{3}\begin{verbatim}
   (3)  e
         1
Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordExteriorPageEmpty3}
\begin{paste}{ugxCliffordExteriorPageEmpty3}{ugxCliffordExteriorPagePatch3}
\pastebutton{ugxCliffordExteriorPageEmpty3}{\showpaste}
\tab{5}\spadcommand{i: Ext := e(1)\free{Ext }\bound{i }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordExteriorPagePatch4}
\begin{paste}{ugxCliffordExteriorPageFull4}{ugxCliffordExteriorPageEmpty4}
\pastebutton{ugxCliffordExteriorPageFull4}{\hidepaste}
\tab{5}\spadcommand{j: Ext := e(2)\free{Ext }\bound{j }}
\indentrel{3}\begin{verbatim}
   (4)  e
         2
Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordExteriorPageEmpty4}
\begin{paste}{ugxCliffordExteriorPageEmpty4}{ugxCliffordExteriorPagePatch4}
\pastebutton{ugxCliffordExteriorPageEmpty4}{\showpaste}
\tab{5}\spadcommand{j: Ext := e(2)\free{Ext }\bound{j }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordExteriorPagePatch5}
\begin{paste}{ugxCliffordExteriorPageFull5}{ugxCliffordExteriorPageEmpty5}
\pastebutton{ugxCliffordExteriorPageFull5}{\hidepaste}
\tab{5}\spadcommand{k: Ext := e(3)\free{Ext }\bound{k }}
\indentrel{3}\begin{verbatim}
   (5)  e
         3
Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordExteriorPageEmpty5}
\begin{paste}{ugxCliffordExteriorPageEmpty5}{ugxCliffordExteriorPagePatch5}
\pastebutton{ugxCliffordExteriorPageEmpty5}{\showpaste}
\tab{5}\spadcommand{k: Ext := e(3)\free{Ext }\bound{k }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordExteriorPagePatch6}
\begin{paste}{ugxCliffordExteriorPageFull6}{ugxCliffordExteriorPageEmpty6}
\pastebutton{ugxCliffordExteriorPageFull6}{\hidepaste}
\tab{5}\spadcommand{x := x1*i + x2*j + x3*k\free{i j k }\bound{x }}
\indentrel{3}\begin{verbatim}
   (6)  x1 e  + x2 e  + x3 e
            1       2       3
Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordExteriorPageEmpty6}
\begin{paste}{ugxCliffordExteriorPageEmpty6}{ugxCliffordExteriorPagePatch6}
\pastebutton{ugxCliffordExteriorPageEmpty6}{\showpaste}
\tab{5}\spadcommand{x := x1*i + x2*j + x3*k\free{i j k }\bound{x }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordExteriorPagePatch7}
\begin{paste}{ugxCliffordExteriorPageFull7}{ugxCliffordExteriorPageEmpty7}
\pastebutton{ugxCliffordExteriorPageFull7}{\hidepaste}
\tab{5}\spadcommand{y := y1*i + y2*j + y3*k\free{i j k }\bound{y }}
\indentrel{3}\begin{verbatim}
   (7)  y1 e  + y2 e  + y3 e
            1       2       3
Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordExteriorPageEmpty7}
\begin{paste}{ugxCliffordExteriorPageEmpty7}{ugxCliffordExteriorPagePatch7}
\pastebutton{ugxCliffordExteriorPageEmpty7}{\showpaste}
\tab{5}\spadcommand{y := y1*i + y2*j + y3*k\free{i j k }\bound{y }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordExteriorPagePatch8}
\begin{paste}{ugxCliffordExteriorPageFull8}{ugxCliffordExteriorPageEmpty8}
\pastebutton{ugxCliffordExteriorPageFull8}{\hidepaste}
\tab{5}\spadcommand{x + y\free{x y }}
\indentrel{3}\begin{verbatim}
   (8)  (y1 + x1)e  + (y2 + x2)e  + (y3 + x3)e
                  1             2             3
Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordExteriorPageEmpty8}
\begin{paste}{ugxCliffordExteriorPageEmpty8}{ugxCliffordExteriorPagePatch8}
\pastebutton{ugxCliffordExteriorPageEmpty8}{\showpaste}
\tab{5}\spadcommand{x + y\free{x y }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordExteriorPagePatch9}
\begin{paste}{ugxCliffordExteriorPageFull9}{ugxCliffordExteriorPageEmpty9}
\pastebutton{ugxCliffordExteriorPageFull9}{\hidepaste}
\tab{5}\spadcommand{x * y + y * x\free{x y }}
\indentrel{3}\begin{verbatim}
   (9)  0
Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordExteriorPageEmpty9}
\begin{paste}{ugxCliffordExteriorPageEmpty9}{ugxCliffordExteriorPagePatch9}
\pastebutton{ugxCliffordExteriorPageEmpty9}{\showpaste}
\tab{5}\spadcommand{x * y + y * x\free{x y }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordExteriorPagePatch10}
\begin{paste}{ugxCliffordExteriorPageFull10}{ugxCliffordExteriorPageEmpty10}
\pastebutton{ugxCliffordExteriorPageFull10}{\hidepaste}
\tab{5}\spadcommand{
dual2 a == coefficient(a,[2,3]) * i + coefficient(a,[3,1]) * _
           j + coefficient(a,[1,2]) * k\free{i j k }\bound{dual2 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordExteriorPageEmpty10}
\begin{paste}{ugxCliffordExteriorPageEmpty10}{ugxCliffordExteriorPagePatch10}
\pastebutton{ugxCliffordExteriorPageEmpty10}{\showpaste}
\tab{5}\spadcommand{
dual2 a == coefficient(a,[2,3]) * i + coefficient(a,[3,1]) * _
      j + coefficient(a,[1,2]) * k\free{i j k }\bound{dual2 }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordExteriorPagePatch11}
\begin{paste}{ugxCliffordExteriorPageFull11}{ugxCliffordExteriorPageEmpty11}
\pastebutton{ugxCliffordExteriorPageFull11}{\hidepaste}
\tab{5}\spadcommand{dual2(x*y)\free{x y dual2 }}
\indentrel{3}\begin{verbatim}
   (11)
     (x2 y3 - x3 y2)e  + (- x1 y3 + x3 y1)e
                     1                     2
   + 
     (x1 y2 - x2 y1)e
                     3
Type: CliffordAlgebra(3,Fraction Polynomial Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordExteriorPageEmpty11}
\begin{paste}{ugxCliffordExteriorPageEmpty11}{ugxCliffordExteriorPagePatch11}
\pastebutton{ugxCliffordExteriorPageEmpty11}{\showpaste}
\tab{5}\spadcommand{dual2(x*y)\free{x y dual2 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxCliffordDiracPage}{clif.ht}{The Dirac Spin Algebra}
\begin{chunk}{clif.ht}
\begin{page}{ugxCliffordDiracPage}{The Dirac Spin Algebra}
\beginscroll

\labelSpace{4pc}
{The Dirac Spin Algebra}
%
\xtc{
In this section we will work over the field of rational numbers.
}{
\spadpaste{K := Fraction Integer \bound{K}}
}
\xtc{
We define the quadratic form to be the Minkowski space-time metric.
}{
\spadpaste{g := matrix [[1,0,0,0], [0,-1,0,0], [0,0,-1,0], [0,0,0,-1]] 
\bound{g}}
}
\xtc{
We obtain the Dirac spin algebra
used in Relativistic Quantum Field Theory.
{9.10.4.}{The Dirac Spin Algebra}
}{
\spadpaste{D := CliffordAlgebra(4,K, quadraticForm g) \free{K g}\bound{D}}
}
\xtc{
The usual notation for the basis is \texht{$\gamma$}{\spad{gamma}}
with a superscript.
For Axiom input we will use \spad{gam(i)}:
}{
\spadpaste{gam := [e(i)\$D for i in 1..4] \free{D}\bound{gam}}
}
\noindent
There are various contraction identities of the form
\begin{verbatim}
g(l,t)*gam(l)*gam(m)*gam(n)*gam(r)*gam(s)*gam(t) =
      2*(gam(s)gam(m)gam(n)gam(r) + gam(r)*gam(n)*gam(m)*gam(s))
\end{verbatim}
where a sum over \spad{l} and \spad{t} is implied.
\xtc{
Verify this identity for particular values of \spad{m,n,r,s}.
}{
\spadpaste{m := 1; n:= 2; r := 3; s := 4; \bound{m,n,r,s}}
}
\xtc{
}{
\spadpaste{lhs := 
reduce(+, [reduce(+, 
[ g(l,t)*gam(l)*gam(m)*gam(n)*gam(r)*gam(s)*gam(t) for l in 1..4]) 
for t in 1..4]) \bound{lhs}\free{g gam m n r s}}
}
\xtc{
}{
\spadpaste{rhs := 2*(gam s * gam m*gam n*gam r + gam r*gam n*gam m*gam s)
\bound{rhs}\free{lhs g gam m n r s}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxCliffordDiracPagePatch1}
\begin{paste}{ugxCliffordDiracPageFull1}{ugxCliffordDiracPageEmpty1}
\pastebutton{ugxCliffordDiracPageFull1}{\hidepaste}
\tab{5}\spadcommand{K := Fraction Integer\bound{K }}
\indentrel{3}\begin{verbatim}
   (1)  Fraction Integer
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordDiracPageEmpty1}
\begin{paste}{ugxCliffordDiracPageEmpty1}{ugxCliffordDiracPagePatch1}
\pastebutton{ugxCliffordDiracPageEmpty1}{\showpaste}
\tab{5}\spadcommand{K := Fraction Integer\bound{K }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordDiracPagePatch2}
\begin{paste}{ugxCliffordDiracPageFull2}{ugxCliffordDiracPageEmpty2}
\pastebutton{ugxCliffordDiracPageFull2}{\hidepaste}
\tab{5}\spadcommand{g := matrix [[1,0,0,0], [0,-1,0,0], [0,0,-1,0], [0,0,0,-1]]\bound{g }}
\indentrel{3}\begin{verbatim}
        Ú1   0    0    0 ¿
        ³                ³
        ³0  - 1   0    0 ³
   (2)  ³                ³
        ³0   0   - 1   0 ³
        ³                ³
        À0   0    0   - 1Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordDiracPageEmpty2}
\begin{paste}{ugxCliffordDiracPageEmpty2}{ugxCliffordDiracPagePatch2}
\pastebutton{ugxCliffordDiracPageEmpty2}{\showpaste}
\tab{5}\spadcommand{
g := matrix [[1,0,0,0], [0,-1,0,0], [0,0,-1,0], [0,0,0,-1]]\bound{g }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordDiracPagePatch3}
\begin{paste}{ugxCliffordDiracPageFull3}{ugxCliffordDiracPageEmpty3}
\pastebutton{ugxCliffordDiracPageFull3}{\hidepaste}
\tab{5}\spadcommand{
D := CliffordAlgebra(4,K, quadraticForm g)\free{K g }\bound{D }}
\indentrel{3}\begin{verbatim}
   (3)  CliffordAlgebra(4,Fraction Integer,MATRIX)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordDiracPageEmpty3}
\begin{paste}{ugxCliffordDiracPageEmpty3}{ugxCliffordDiracPagePatch3}
\pastebutton{ugxCliffordDiracPageEmpty3}{\showpaste}
\tab{5}\spadcommand{
D := CliffordAlgebra(4,K, quadraticForm g)\free{K g }\bound{D }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordDiracPagePatch4}
\begin{paste}{ugxCliffordDiracPageFull4}{ugxCliffordDiracPageEmpty4}
\pastebutton{ugxCliffordDiracPageFull4}{\hidepaste}
\tab{5}\spadcommand{gam := [e(i)$D for i in 1..4]\free{D }\bound{gam }}
\indentrel{3}\begin{verbatim}
   (4)  [e ,e ,e ,e ]
          1  2  3  4
  Type: List CliffordAlgebra(4,Fraction Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordDiracPageEmpty4}
\begin{paste}{ugxCliffordDiracPageEmpty4}{ugxCliffordDiracPagePatch4}
\pastebutton{ugxCliffordDiracPageEmpty4}{\showpaste}
\tab{5}\spadcommand{gam := [e(i)$D for i in 1..4]\free{D }\bound{gam }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordDiracPagePatch5}
\begin{paste}{ugxCliffordDiracPageFull5}{ugxCliffordDiracPageEmpty5}
\pastebutton{ugxCliffordDiracPageFull5}{\hidepaste}
\tab{5}\spadcommand{m := 1; n:= 2; r := 3; s := 4;\bound{m n r s }}
\indentrel{3}\begin{verbatim}
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordDiracPageEmpty5}
\begin{paste}{ugxCliffordDiracPageEmpty5}{ugxCliffordDiracPagePatch5}
\pastebutton{ugxCliffordDiracPageEmpty5}{\showpaste}
\tab{5}\spadcommand{m := 1; n:= 2; r := 3; s := 4;\bound{m n r s }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordDiracPagePatch6}
\begin{paste}{ugxCliffordDiracPageFull6}{ugxCliffordDiracPageEmpty6}
\pastebutton{ugxCliffordDiracPageFull6}{\hidepaste}
\tab{5}\spadcommand{
lhs := reduce(+, [reduce(+, _
  [ g(l,t)*gam(l)*gam(m)*gam(n)*gam(r)*gam(s)*gam(t) for l in 1..4]) _
  for t in 1..4])\bound{lhs }\free{g gam m n r s }}
\indentrel{3}\begin{verbatim}
   (6)  - 4e e e e
            1 2 3 4
       Type: CliffordAlgebra(4,Fraction Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordDiracPageEmpty6}
\begin{paste}{ugxCliffordDiracPageEmpty6}{ugxCliffordDiracPagePatch6}
\pastebutton{ugxCliffordDiracPageEmpty6}{\showpaste}
\tab{5}\spadcommand{
lhs := reduce(+, [reduce(+, _
  [ g(l,t)*gam(l)*gam(m)*gam(n)*gam(r)*gam(s)*gam(t) for l in 1..4]) _
  for t in 1..4])\bound{lhs }\free{g gam m n r s }}
\end{paste}\end{patch}

\begin{patch}{ugxCliffordDiracPagePatch7}
\begin{paste}{ugxCliffordDiracPageFull7}{ugxCliffordDiracPageEmpty7}
\pastebutton{ugxCliffordDiracPageFull7}{\hidepaste}
\tab{5}\spadcommand{
rhs := 2*(gam s * gam m*gam n*gam r + gam r*gam n*gam m*gam s)
\bound{rhs }\free{lhs g gam m n r s }}
\indentrel{3}\begin{verbatim}
   (7)  - 4e e e e
            1 2 3 4
       Type: CliffordAlgebra(4,Fraction Integer,MATRIX)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxCliffordDiracPageEmpty7}
\begin{paste}{ugxCliffordDiracPageEmpty7}{ugxCliffordDiracPagePatch7}
\pastebutton{ugxCliffordDiracPageEmpty7}{\showpaste}
\tab{5}\spadcommand{
rhs := 2*(gam s * gam m*gam n*gam r + gam r*gam n*gam m*gam s)
\bound{rhs }\free{lhs g gam m n r s }}
\end{paste}\end{patch}

\end{chunk}
\section{complex.ht}
\pagetitle{ComplexXmpPage}{complex.ht}{Complex}
\pagepic{ps/v71complexxmppage.eps}{ComplexXmpPage}{0.50}
\pagefrom{Axiom Number Types}{NumberPage}
\pagefrom{Primes and Factorization}{ugxIntegerPrimesPage}
\pageto{Numeric Functions}{ugProblemNumericPage}
\pageto{Conversion}{ugTypesConvertPage}
\begin{chunk}{complex.ht}
\begin{page}{ComplexXmpPage}{Complex}
\beginscroll
The \spadtype{Complex} constructor implements complex objects over a
commutative ring \spad{R}.
Typically, the ring \spad{R} is \spadtype{Integer}, \spadtype{Fraction
Integer}, \spadtype{Float} or \spadtype{DoubleFloat}.
\spad{R} can also be a symbolic type, like \spadtype{Polynomial Integer}.
For more information about the numerical and graphical aspects of complex
numbers, 
see \downlink{``Numeric Functions''}{ugProblemNumericPage} in Section 8.1
\ignore{ugProblemNumeric}.

\xtc{
Complex objects are created by the \spadfunFrom{complex}{Complex} operation.
}{
\spadpaste{a := complex(4/3,5/2) \bound{a}}
}
\xtc{
}{
\spadpaste{b := complex(4/3,-5/2) \bound{b}}
}
\xtc{
The standard arithmetic operations are available.
}{
\spadpaste{a + b \free{a b}}
}
\xtc{
}{
\spadpaste{a - b \free{a b}}
}
\xtc{
}{
\spadpaste{a * b \free{a b}}
}
\xtc{
If \spad{R} is a field, you can also divide the complex objects.
}{
\spadpaste{a / b \free{a b}\bound{adb}}
}
\xtc{
Use a conversion (\downlink{``Conversion''}{ugTypesConvertPage} 
in Section 2.7\ignore{ugTypesConvert}) to view the last
object as a fraction of complex integers.
}{
\spadpaste{\% :: Fraction Complex Integer \free{adb}}
}
\xtc{
The predefined macro \spad{\%i} is defined to be \spad{complex(0,1)}.
}{
\spadpaste{3.4 + 6.7 * \%i}
}
\xtc{
You can also compute the \spadfunFrom{conjugate}{Complex} and
\spadfunFrom{norm}{Complex} of a complex number.
}{
\spadpaste{conjugate a \free{a}}
}
\xtc{
}{
\spadpaste{norm a \free{a}}
}
\xtc{
The \spadfunFrom{real}{Complex} and \spadfunFrom{imag}{Complex} operations
are provided to extract the real and imaginary parts, respectively.
}{
\spadpaste{real a \free{a}}
}
\xtc{
}{
\spadpaste{imag a \free{a}}
}

\xtc{
The domain \spadtype{Complex Integer} is also called the Gaussian
integers.
If \spad{R} is the integers (or, more generally,
a \spadtype{EuclideanDomain}), you can compute greatest common divisors.
}{
\spadpaste{gcd(13 - 13*\%i,31 + 27*\%i)}
}
\xtc{
You can also compute least common multiples.
}{
\spadpaste{lcm(13 - 13*\%i,31 + 27*\%i)}
}
\xtc{
You can \spadfunFrom{factor}{Complex} Gaussian integers.
}{
\spadpaste{factor(13 - 13*\%i)}
}
\xtc{
}{
\spadpaste{factor complex(2,0)}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ComplexXmpPagePatch1}
\begin{paste}{ComplexXmpPageFull1}{ComplexXmpPageEmpty1}
\pastebutton{ComplexXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{a := complex(4/3,5/2)\bound{a }}
\indentrel{3}\begin{verbatim}
        4   5
   (1)  Ä + Ä %i
        3   2
                         Type: Complex Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ComplexXmpPageEmpty1}
\begin{paste}{ComplexXmpPageEmpty1}{ComplexXmpPagePatch1}
\pastebutton{ComplexXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{a := complex(4/3,5/2)\bound{a }}
\end{paste}\end{patch}

\begin{patch}{ComplexXmpPagePatch2}
\begin{paste}{ComplexXmpPageFull2}{ComplexXmpPageEmpty2}
\pastebutton{ComplexXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{b := complex(4/3,-5/2)\bound{b }}
\indentrel{3}\begin{verbatim}
        4   5
   (2)  Ä - Ä %i
        3   2
                         Type: Complex Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ComplexXmpPageEmpty2}
\begin{paste}{ComplexXmpPageEmpty2}{ComplexXmpPagePatch2}
\pastebutton{ComplexXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{b := complex(4/3,-5/2)\bound{b }}
\end{paste}\end{patch}

\begin{patch}{ComplexXmpPagePatch3}
\begin{paste}{ComplexXmpPageFull3}{ComplexXmpPageEmpty3}
\pastebutton{ComplexXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{a + b\free{a b }}
\indentrel{3}\begin{verbatim}
        8
   (3)  Ä
        3
                         Type: Complex Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ComplexXmpPageEmpty3}
\begin{paste}{ComplexXmpPageEmpty3}{ComplexXmpPagePatch3}
\pastebutton{ComplexXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{a + b\free{a b }}
\end{paste}\end{patch}

\begin{patch}{ComplexXmpPagePatch4}
\begin{paste}{ComplexXmpPageFull4}{ComplexXmpPageEmpty4}
\pastebutton{ComplexXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{a - b\free{a b }}
\indentrel{3}\begin{verbatim}
   (4)  5%i
                         Type: Complex Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ComplexXmpPageEmpty4}
\begin{paste}{ComplexXmpPageEmpty4}{ComplexXmpPagePatch4}
\pastebutton{ComplexXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{a - b\free{a b }}
\end{paste}\end{patch}

\begin{patch}{ComplexXmpPagePatch5}
\begin{paste}{ComplexXmpPageFull5}{ComplexXmpPageEmpty5}
\pastebutton{ComplexXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{a * b\free{a b }}
\indentrel{3}\begin{verbatim}
        289
   (5)  ÄÄÄ
         36
                         Type: Complex Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ComplexXmpPageEmpty5}
\begin{paste}{ComplexXmpPageEmpty5}{ComplexXmpPagePatch5}
\pastebutton{ComplexXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{a * b\free{a b }}
\end{paste}\end{patch}

\begin{patch}{ComplexXmpPagePatch6}
\begin{paste}{ComplexXmpPageFull6}{ComplexXmpPageEmpty6}
\pastebutton{ComplexXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{a / b\free{a b }\bound{adb }}
\indentrel{3}\begin{verbatim}
          161   240
   (6)  - ÄÄÄ + ÄÄÄ %i
          289   289
                         Type: Complex Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ComplexXmpPageEmpty6}
\begin{paste}{ComplexXmpPageEmpty6}{ComplexXmpPagePatch6}
\pastebutton{ComplexXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{a / b\free{a b }\bound{adb }}
\end{paste}\end{patch}

\begin{patch}{ComplexXmpPagePatch7}
\begin{paste}{ComplexXmpPageFull7}{ComplexXmpPageEmpty7}
\pastebutton{ComplexXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{\% :: Fraction Complex Integer\free{adb }}
\indentrel{3}\begin{verbatim}
        - 15 + 8%i
   (7)  ÄÄÄÄÄÄÄÄÄÄ
         15 + 8%i
                         Type: Fraction Complex Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ComplexXmpPageEmpty7}
\begin{paste}{ComplexXmpPageEmpty7}{ComplexXmpPagePatch7}
\pastebutton{ComplexXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{\% :: Fraction Complex Integer\free{adb }}
\end{paste}\end{patch}

\begin{patch}{ComplexXmpPagePatch8}
\begin{paste}{ComplexXmpPageFull8}{ComplexXmpPageEmpty8}
\pastebutton{ComplexXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{3.4 + 6.7 * \%i}
\indentrel{3}\begin{verbatim}
   (8)  3.4 + 6.7 %i
                                    Type: Complex Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ComplexXmpPageEmpty8}
\begin{paste}{ComplexXmpPageEmpty8}{ComplexXmpPagePatch8}
\pastebutton{ComplexXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{3.4 + 6.7 * \%i}
\end{paste}\end{patch}

\begin{patch}{ComplexXmpPagePatch9}
\begin{paste}{ComplexXmpPageFull9}{ComplexXmpPageEmpty9}
\pastebutton{ComplexXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{conjugate a\free{a }}
\indentrel{3}\begin{verbatim}
        4   5
   (9)  Ä - Ä %i
        3   2
                         Type: Complex Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ComplexXmpPageEmpty9}
\begin{paste}{ComplexXmpPageEmpty9}{ComplexXmpPagePatch9}
\pastebutton{ComplexXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{conjugate a\free{a }}
\end{paste}\end{patch}

\begin{patch}{ComplexXmpPagePatch10}
\begin{paste}{ComplexXmpPageFull10}{ComplexXmpPageEmpty10}
\pastebutton{ComplexXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{norm a\free{a }}
\indentrel{3}\begin{verbatim}
         289
   (10)  ÄÄÄ
          36
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ComplexXmpPageEmpty10}
\begin{paste}{ComplexXmpPageEmpty10}{ComplexXmpPagePatch10}
\pastebutton{ComplexXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{norm a\free{a }}
\end{paste}\end{patch}

\begin{patch}{ComplexXmpPagePatch11}
\begin{paste}{ComplexXmpPageFull11}{ComplexXmpPageEmpty11}
\pastebutton{ComplexXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{real a\free{a }}
\indentrel{3}\begin{verbatim}
         4
   (11)  Ä
         3
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ComplexXmpPageEmpty11}
\begin{paste}{ComplexXmpPageEmpty11}{ComplexXmpPagePatch11}
\pastebutton{ComplexXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{real a\free{a }}
\end{paste}\end{patch}

\begin{patch}{ComplexXmpPagePatch12}
\begin{paste}{ComplexXmpPageFull12}{ComplexXmpPageEmpty12}
\pastebutton{ComplexXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{imag a\free{a }}
\indentrel{3}\begin{verbatim}
         5
   (12)  Ä
         2
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ComplexXmpPageEmpty12}
\begin{paste}{ComplexXmpPageEmpty12}{ComplexXmpPagePatch12}
\pastebutton{ComplexXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{imag a\free{a }}
\end{paste}\end{patch}

\begin{patch}{ComplexXmpPagePatch13}
\begin{paste}{ComplexXmpPageFull13}{ComplexXmpPageEmpty13}
\pastebutton{ComplexXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{gcd(13 - 13*\%i,31 + 27*\%i)}
\indentrel{3}\begin{verbatim}
   (13)  5 + %i
                                  Type: Complex Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ComplexXmpPageEmpty13}
\begin{paste}{ComplexXmpPageEmpty13}{ComplexXmpPagePatch13}
\pastebutton{ComplexXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{gcd(13 - 13*\%i,31 + 27*\%i)}
\end{paste}\end{patch}

\begin{patch}{ComplexXmpPagePatch14}
\begin{paste}{ComplexXmpPageFull14}{ComplexXmpPageEmpty14}
\pastebutton{ComplexXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{lcm(13 - 13*\%i,31 + 27*\%i)}
\indentrel{3}\begin{verbatim}
   (14)  143 - 39%i
                                  Type: Complex Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ComplexXmpPageEmpty14}
\begin{paste}{ComplexXmpPageEmpty14}{ComplexXmpPagePatch14}
\pastebutton{ComplexXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{lcm(13 - 13*\%i,31 + 27*\%i)}
\end{paste}\end{patch}

\begin{patch}{ComplexXmpPagePatch15}
\begin{paste}{ComplexXmpPageFull15}{ComplexXmpPageEmpty15}
\pastebutton{ComplexXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{factor(13 - 13*\%i)}
\indentrel{3}\begin{verbatim}
   (15)  - (1 + %i)(2 + 3%i)(3 + 2%i)
                         Type: Factored Complex Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ComplexXmpPageEmpty15}
\begin{paste}{ComplexXmpPageEmpty15}{ComplexXmpPagePatch15}
\pastebutton{ComplexXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{factor(13 - 13*\%i)}
\end{paste}\end{patch}

\begin{patch}{ComplexXmpPagePatch16}
\begin{paste}{ComplexXmpPageFull16}{ComplexXmpPageEmpty16}
\pastebutton{ComplexXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{factor complex(2,0)}
\indentrel{3}\begin{verbatim}
                      2
   (16)  - %i (1 + %i)
                         Type: Factored Complex Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ComplexXmpPageEmpty16}
\begin{paste}{ComplexXmpPageEmpty16}{ComplexXmpPagePatch16}
\pastebutton{ComplexXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{factor complex(2,0)}
\end{paste}\end{patch}

\end{chunk}
\section{contfrac.ht}
\pagetitle{ContinuedFractionXmpPage}{contfrac.ht}{ContinuedFraction}
\pagepic{ps/v71continuedfractionxmppage.eps}{ContinuedFractionXmpPage}{0.50}
\pagefrom{Axiom Number Types}{NumberPage}
\pageto{Stream}{StreamXmpPage}
\begin{chunk}{contfrac.ht}
\begin{page}{ContinuedFractionXmpPage}{ContinuedFraction}
\beginscroll

Continued fractions have been a fascinating and useful tool in
mathematics for well over three hundred years.  Axiom implements
continued fractions for fractions of any Euclidean domain.  In
practice, this usually means rational numbers.  In this section we
demonstrate some of the operations available for manipulating both
finite and infinite continued fractions.  It may be helpful if you
review \downlink{`Stream'}{StreamXmpPage}\ignore{Stream} to remind
yourself of some of the operations with streams.

The \spadtype{ContinuedFraction} domain is a field and therefore you can
add, subtract, multiply and divide the fractions.
\xtc{
The \spadfunFrom{continuedFraction}{ContinuedFraction} operation
converts its fractional argument to a continued fraction.
}{
\spadpaste{c := continuedFraction(314159/100000) \bound{c}}
}
%
This display is a compact form of the bulkier
\texht{\narrowDisplay{%
3 + {\displaystyle 1 \over {\displaystyle
7 + {1 \over {\displaystyle
15 + {1 \over {\displaystyle
1 + {1 \over {\displaystyle
25 + {1 \over {\displaystyle
1 + {1 \over {\displaystyle
7 + {1 \over 4}}}}}}}}}}}}}}%
}{
\begin{verbatim}
        3 +                 1
            -------------------------------
            7 +               1
                ---------------------------
                15 +            1
                     ----------------------
                     1 +          1
                         ------------------
                         25 +       1
                              -------------
                              1 +     1
                                  ---------
                                  7 +   1
                                      -----
                                        4
\end{verbatim}
}
You can write any rational number in a similar form.  The fraction
will be finite and you can always take the ``numerators'' to be
\spad{1}.  That is, any rational number can be written as a simple,
finite continued fraction of the form
\texht{\narrowDisplay{%
a_1 + {\displaystyle 1 \over {\displaystyle
a_2 + {1 \over {\displaystyle
a_3 + {1 \over {\displaystyle \ddots
a_{n-1} + {1 \over a_n}}}}}}}}%
}{
\begin{verbatim}
        a(1) +           1
               -------------------------
               a(2) +          1
                      --------------------
                      a(3) +
                             .
                              .
                               .
                                     1
                               -------------
                               a(n-1) +  1
                                        ----
                                        a(n)
\end{verbatim}
}
\xtc{
The \texht{$a_i$}{\spad{a(i)}} are called partial quotients and the
operation \spadfunFrom{partialQuotients}{ContinuedFraction} creates a
stream of them.
}{
\spadpaste{partialQuotients c \free{c}}
}
\xtc{
By considering more and more of the fraction, you get the
\spadfunFrom{convergents}{ContinuedFraction}.
For example, the first convergent is \texht{$a_1$}{\spad{a(1)}},
the second is
\texht{$a_1 + 1/a_2$}{\spad{a(1) + 1/a(2)}} and so on.
}{
\spadpaste{convergents c \free{c}}
}
%
\xtc{
Since this is a finite continued fraction, the last convergent is
the original rational number, in reduced form.
The result of \spadfunFrom{approximants}{ContinuedFraction}
is always an infinite stream, though it may just repeat the ``last''
value.
}{
\spadpaste{approximants c \free{c}}
}
\xtc{
Inverting \spad{c} only changes the partial quotients of its fraction
by inserting a \spad{0} at the beginning of the list.
}{
\spadpaste{pq := partialQuotients(1/c) \free{c}\bound{pq}}
}
\xtc{
Do this to recover the original continued fraction from this list of
partial quotients.
The three-argument form of the
\spadfunFrom{continuedFraction}{ContinuedFraction} operation takes an
element which is the whole part of the fraction, a stream of elements
which are the numerators of the fraction, and a stream of elements which
are the denominators of the fraction.
}{
\spadpaste{continuedFraction(first pq,repeating [1],rest pq) \free{pq}}
}
\xtc{
The streams need not be finite for
\spadfunFrom{continuedFraction}{ContinuedFraction}.
Can you guess which irrational number has the following continued
fraction?
See the end of this section for the answer.
}{
\spadpaste{z:=continuedFraction(3,repeating [1],repeating [3,6]) \bound{z}}
}
%

In 1737 Euler discovered the infinite continued fraction expansion
\texht{\narrowDisplay{%
{{e - 1} \over 2} =
{1 \over {\displaystyle
1 + {1 \over {\displaystyle
6 + {1 \over {\displaystyle
10 + {1 \over {\displaystyle
14 + \cdots}}}}}}}}}%
}{
\begin{verbatim}
        e - 1             1
        ----- = ---------------------
          2     1 +         1
                    -----------------
                    6 +       1
                        -------------
                        10 +    1
                             --------
                             14 + ...
\end{verbatim}
}
We use this expansion to compute rational and floating point
approximations of \spad{e}.\footnote{For this and other interesting
expansions, see C. D. Olds, {\it Continued Fractions,}
New Mathematical Library, (New York: Random House, 1963), pp.
134--139.}

\xtc{
By looking at the above expansion, we see that the whole part is
\spad{0} and the numerators are all equal to \spad{1}.  This
constructs the stream of denominators.
}{
\spadpaste{dens:Stream Integer := cons(1,generate((x+->x+4),6)) 
\bound{dens}}
}
\xtc{
Therefore this is the continued fraction expansion for
\texht{$(e - 1) / 2$}{\spad{(e-1)/2}}.
}{
\spadpaste{cf := continuedFraction(0,repeating [1],dens) 
\free{dens}\bound{cf}}
}
\xtc{
These are the rational number convergents.
}{
\spadpaste{ccf := convergents cf \free{cf}\bound{ccf}}
}
\xtc{
You can get rational convergents for \spad{e} by multiplying by \spad{2} and
adding \spad{1}.
}{
\spadpaste{eConvergents := [2*e + 1 for e in ccf] \bound{ec}\free{ccf}}
}
%
\xtc{
You can also compute the floating point approximations to these convergents.
}{
\spadpaste{eConvergents :: Stream Float \free{ec}}
}
\xtc{
Compare this to the value of \spad{e} computed by the
\spadfunFrom{exp}{Float} operation in \spadtype{Float}.
}{
\spadpaste{exp 1.0}
}

In about 1658, Lord Brouncker established the following expansion
for \texht{$4 / \pi$}{\spad{4/pi}}.
\texht{\narrowDisplay{%
1 + {\displaystyle
1 \over {\displaystyle
2 + {9 \over {\displaystyle
2 + {25 \over {\displaystyle
2 + {49 \over {\displaystyle
2 + {81 \over {\displaystyle
2 + \cdots}}}}}}}}}}}%
}{
\begin{verbatim}
        1 +            1
            -----------------------
            2 +          9
                -------------------
                2 +        25
                    ---------------
                    2 +      49
                        -----------
                        2 +    81
                            -------
                            2 + ...
\end{verbatim}
}
\xtc{
Let's use this expansion to compute rational and floating point
approximations for \texht{$\pi$}{\spad{pi}}.
}{
\spadpaste{
cf := continuedFraction(1,[(2*i+1)**2 for i in 0..],repeating [2])
\bound{cf1}}
}
\xtc{
}{
\spadpaste{ccf := convergents cf \free{cf1}\bound{ccf1}}
}
\xtc{
}{
\spadpaste{
piConvergents := [4/p for p in ccf] \bound{piConvergents}\free{ccf1}}
}
\xtc{
As you can see, the values are converging to
\texht{$\pi$}{\spad{pi}} = 3.14159265358979323846...,
but not very quickly.
}{
\spadpaste{piConvergents :: Stream Float \free{piConvergents}}
}

\xtc{
You need not restrict yourself to continued fractions of integers.
Here is an expansion for a quotient of Gaussian integers.
}{
\spadpaste{continuedFraction((- 122 + 597*\%i)/(4 - 4*\%i))}
}
\xtc{
This is an expansion for a quotient of polynomials in one variable
with rational number coefficients.
}{
\spadpaste{r : Fraction UnivariatePolynomial(x,Fraction Integer) 
\bound{rdec}}
}
\xtc{
}{
\spadpaste{r := ((x - 1) * (x - 2)) / ((x-3) * (x-4)) \free{rdec}
\bound{r}}
}
\xtc{
}{
\spadpaste{continuedFraction r \free{r}}
}

To conclude this section, we give you evidence that
\texht{\narrowDisplay{%
z =
{3+\zag{1}{3}+\zag{1}{6}+\zag{1}{3}+\zag{1}{6}+\zag{1}{3}+\zag{1}{6}+
\zag{1}{3}+\zag{1}{6}+\zag{1}{3}+\zag{1}{6}+...}}%
}{
\begin{verbatim}
    z = 3 +            1
            -----------------------
            3 +          1
                -------------------
                6 +        1
                    ---------------
                    3 +      1
                        -----------
                        6 +    1
                            -------
                            3 + ...
\end{verbatim}
}
is the expansion of \texht{$\sqrt{11}$}{the square root of \spad{11}}.
%
\xtc{
}{
\spadpaste{[i*i for i in convergents(z) :: Stream Float] \free{z}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ContinuedFractionXmpPagePatch1}
\begin{paste}{ContinuedFractionXmpPageFull1}{ContinuedFractionXmpPageEmpty1}
\pastebutton{ContinuedFractionXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{c := continuedFraction(314159/100000)\bound{c }}
\indentrel{3}\begin{verbatim}
   (1)
           1 ³     1  ³     1 ³     1  ³     1 ³     1 ³
     3 + ÚÄÄÄÙ + ÚÄÄÄÄÙ + ÚÄÄÄÙ + ÚÄÄÄÄÙ + ÚÄÄÄÙ + ÚÄÄÄÙ
         ³ 7     ³ 15     ³ 1     ³ 25     ³ 1     ³ 7
   + 
       1 ³
     ÚÄÄÄÙ
     ³ 4
                        Type: ContinuedFraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPageEmpty1}
\begin{paste}{ContinuedFractionXmpPageEmpty1}
{ContinuedFractionXmpPagePatch1}
\pastebutton{ContinuedFractionXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{c := continuedFraction(314159/100000)\bound{c }}
\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPagePatch2}
\begin{paste}{ContinuedFractionXmpPageFull2}
{ContinuedFractionXmpPageEmpty2}
\pastebutton{ContinuedFractionXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{partialQuotients c\free{c }}
\indentrel{3}\begin{verbatim}
   (2)  [3,7,15,1,25,1,7,4]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPageEmpty2}
\begin{paste}{ContinuedFractionXmpPageEmpty2}
{ContinuedFractionXmpPagePatch2}
\pastebutton{ContinuedFractionXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{partialQuotients c\free{c }}
\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPagePatch3}
\begin{paste}{ContinuedFractionXmpPageFull3}
{ContinuedFractionXmpPageEmpty3}
\pastebutton{ContinuedFractionXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{convergents c\free{c }}
\indentrel{3}\begin{verbatim}
           22 333 355 9208 9563 76149 314159
   (3)  [3,ÄÄ,ÄÄÄ,ÄÄÄ,ÄÄÄÄ,ÄÄÄÄ,ÄÄÄÄÄ,ÄÄÄÄÄÄ]
            7 106 113 2931 3044 24239 100000
                          Type: Stream Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPageEmpty3}
\begin{paste}{ContinuedFractionXmpPageEmpty3}
{ContinuedFractionXmpPagePatch3}
\pastebutton{ContinuedFractionXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{convergents c\free{c }}
\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPagePatch4}
\begin{paste}{ContinuedFractionXmpPageFull4}
{ContinuedFractionXmpPageEmpty4}
\pastebutton{ContinuedFractionXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{approximants c\free{c }}
\indentrel{3}\begin{verbatim}
                                      ______
           22 333 355 9208 9563 76149 314159
   (4)  [3,ÄÄ,ÄÄÄ,ÄÄÄ,ÄÄÄÄ,ÄÄÄÄ,ÄÄÄÄÄ,ÄÄÄÄÄÄ]
            7 106 113 2931 3044 24239 100000
                          Type: Stream Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPageEmpty4}
\begin{paste}{ContinuedFractionXmpPageEmpty4}
{ContinuedFractionXmpPagePatch4}
\pastebutton{ContinuedFractionXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{approximants c\free{c }}
\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPagePatch5}
\begin{paste}{ContinuedFractionXmpPageFull5}
{ContinuedFractionXmpPageEmpty5}
\pastebutton{ContinuedFractionXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{pq := partialQuotients(1/c)\free{c }\bound{pq }}
\indentrel{3}\begin{verbatim}
   (5)  [0,3,7,15,1,25,1,7,4]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPageEmpty5}
\begin{paste}{ContinuedFractionXmpPageEmpty5}
{ContinuedFractionXmpPagePatch5}
\pastebutton{ContinuedFractionXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{pq := partialQuotients(1/c)\free{c }\bound{pq }}
\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPagePatch6}
\begin{paste}{ContinuedFractionXmpPageFull6}
{ContinuedFractionXmpPageEmpty6}
\pastebutton{ContinuedFractionXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{
continuedFraction(first pq,repeating [1],rest pq)\free{pq }}
\indentrel{3}\begin{verbatim}
   (6)
       1 ³     1 ³     1  ³     1 ³     1  ³     1 ³
     ÚÄÄÄÙ + ÚÄÄÄÙ + ÚÄÄÄÄÙ + ÚÄÄÄÙ + ÚÄÄÄÄÙ + ÚÄÄÄÙ
     ³ 3     ³ 7     ³ 15     ³ 1     ³ 25     ³ 1
   + 
       1 ³     1 ³
     ÚÄÄÄÙ + ÚÄÄÄÙ
     ³ 7     ³ 4
                        Type: ContinuedFraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPageEmpty6}
\begin{paste}{ContinuedFractionXmpPageEmpty6}
{ContinuedFractionXmpPagePatch6}
\pastebutton{ContinuedFractionXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{
continuedFraction(first pq,repeating [1],rest pq)\free{pq }}
\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPagePatch7}
\begin{paste}{ContinuedFractionXmpPageFull7}
{ContinuedFractionXmpPageEmpty7}
\pastebutton{ContinuedFractionXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{
z:=continuedFraction(3,repeating [1],repeating [3,6])\bound{z }}
\indentrel{3}\begin{verbatim}
   (7)
           1 ³     1 ³     1 ³     1 ³     1 ³     1 ³
     3 + ÚÄÄÄÙ + ÚÄÄÄÙ + ÚÄÄÄÙ + ÚÄÄÄÙ + ÚÄÄÄÙ + ÚÄÄÄÙ
         ³ 3     ³ 6     ³ 3     ³ 6     ³ 3     ³ 6
   + 
       1 ³     1 ³     1 ³     1 ³
     ÚÄÄÄÙ + ÚÄÄÄÙ + ÚÄÄÄÙ + ÚÄÄÄÙ + ...
     ³ 3     ³ 6     ³ 3     ³ 6
                        Type: ContinuedFraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPageEmpty7}
\begin{paste}{ContinuedFractionXmpPageEmpty7}
{ContinuedFractionXmpPagePatch7}
\pastebutton{ContinuedFractionXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{
z:=continuedFraction(3,repeating [1],repeating [3,6])\bound{z }}
\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPagePatch8}
\begin{paste}{ContinuedFractionXmpPageFull8}
{ContinuedFractionXmpPageEmpty8}
\pastebutton{ContinuedFractionXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{
dens:Stream Integer := cons(1,generate((x+->x+4),6))\bound{dens }}
\indentrel{3}\begin{verbatim}
   (8)  [1,6,10,14,18,22,26,30,34,38,...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPageEmpty8}
\begin{paste}{ContinuedFractionXmpPageEmpty8}
{ContinuedFractionXmpPagePatch8}
\pastebutton{ContinuedFractionXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{
dens:Stream Integer := cons(1,generate((x+->x+4),6))\bound{dens }}
\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPagePatch9}
\begin{paste}{ContinuedFractionXmpPageFull9}
{ContinuedFractionXmpPageEmpty9}
\pastebutton{ContinuedFractionXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{
cf := continuedFraction(0,repeating [1],dens)\free{dens }\bound{cf }}
\indentrel{3}\begin{verbatim}
   (9)
       1 ³     1 ³     1  ³     1  ³     1  ³     1  ³
     ÚÄÄÄÙ + ÚÄÄÄÙ + ÚÄÄÄÄÙ + ÚÄÄÄÄÙ + ÚÄÄÄÄÙ + ÚÄÄÄÄÙ
     ³ 1     ³ 6     ³ 10     ³ 14     ³ 18     ³ 22
   + 
       1  ³     1  ³     1  ³     1  ³
     ÚÄÄÄÄÙ + ÚÄÄÄÄÙ + ÚÄÄÄÄÙ + ÚÄÄÄÄÙ + ...
     ³ 26     ³ 30     ³ 34     ³ 38
                        Type: ContinuedFraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPageEmpty9}
\begin{paste}{ContinuedFractionXmpPageEmpty9}
{ContinuedFractionXmpPagePatch9}
\pastebutton{ContinuedFractionXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{
cf := continuedFraction(0,repeating [1],dens)\free{dens }\bound{cf }}
\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPagePatch10}
\begin{paste}{ContinuedFractionXmpPageFull10}
{ContinuedFractionXmpPageEmpty10}
\pastebutton{ContinuedFractionXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{ccf := convergents cf\free{cf }\bound{ccf }}
\indentrel{3}\begin{verbatim}
   (10)
          6  61   860  15541  342762   8927353
   [0, 1, Ä, ÄÄ, ÄÄÄÄ, ÄÄÄÄÄ, ÄÄÄÄÄÄ, ÄÄÄÄÄÄÄÄ,
          7  71  1001  18089  398959  10391023
    268163352   9126481321
    ÄÄÄÄÄÄÄÄÄ, ÄÄÄÄÄÄÄÄÄÄÄ, ...]
    312129649  10622799089
                          Type: Stream Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPageEmpty10}
\begin{paste}{ContinuedFractionXmpPageEmpty10}
{ContinuedFractionXmpPagePatch10}
\pastebutton{ContinuedFractionXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{ccf := convergents cf\free{cf }\bound{ccf }}
\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPagePatch11}
\begin{paste}{ContinuedFractionXmpPageFull11}
{ContinuedFractionXmpPageEmpty11}
\pastebutton{ContinuedFractionXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{
eConvergents := [2*e + 1 for e in ccf]\bound{ec }\free{ccf }}
\indentrel{3}\begin{verbatim}
   (11)
          19  193  2721  49171  1084483  28245729
   [1, 3, ÄÄ, ÄÄÄ, ÄÄÄÄ, ÄÄÄÄÄ, ÄÄÄÄÄÄÄ, ÄÄÄÄÄÄÄÄ,
           7   71  1001  18089   398959  10391023
    848456353  28875761731
    ÄÄÄÄÄÄÄÄÄ, ÄÄÄÄÄÄÄÄÄÄÄ, ...]
    312129649  10622799089
                          Type: Stream Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPageEmpty11}
\begin{paste}{ContinuedFractionXmpPageEmpty11}
{ContinuedFractionXmpPagePatch11}
\pastebutton{ContinuedFractionXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{
eConvergents := [2*e + 1 for e in ccf]\bound{ec }\free{ccf }}
\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPagePatch12}
\begin{paste}{ContinuedFractionXmpPageFull12}
{ContinuedFractionXmpPageEmpty12}
\pastebutton{ContinuedFractionXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{eConvergents :: Stream Float\free{ec }}
\indentrel{3}\begin{verbatim}
   (12)
   [1.0, 3.0, 2.7142857142 857142857,
    2.7183098591 549295775, 2.7182817182 817182817,
    2.7182818287 356957267, 2.7182818284 585634113,
    2.7182818284 590458514, 2.7182818284 590452348,
    2.7182818284 590452354, ...]
                                     Type: Stream Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPageEmpty12}
\begin{paste}{ContinuedFractionXmpPageEmpty12}
{ContinuedFractionXmpPagePatch12}
\pastebutton{ContinuedFractionXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{eConvergents :: Stream Float\free{ec }}
\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPagePatch13}
\begin{paste}{ContinuedFractionXmpPageFull13}
{ContinuedFractionXmpPageEmpty13}
\pastebutton{ContinuedFractionXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{exp 1.0}
\indentrel{3}\begin{verbatim}
   (13)  2.7182818284 590452354
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPageEmpty13}
\begin{paste}{ContinuedFractionXmpPageEmpty13}
{ContinuedFractionXmpPagePatch13}
\pastebutton{ContinuedFractionXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{exp 1.0}
\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPagePatch14}
\begin{paste}{ContinuedFractionXmpPageFull14}
{ContinuedFractionXmpPageEmpty14}
\pastebutton{ContinuedFractionXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{
cf := continuedFraction(1,[(2*i+1)**2 for i in 0..],repeating [2])
\bound{cf1 }}
\indentrel{3}\begin{verbatim}
   (14)
           1 ³     9 ³     25 ³     49 ³     81 ³
     1 + ÚÄÄÄÙ + ÚÄÄÄÙ + ÚÄÄÄÄÙ + ÚÄÄÄÄÙ + ÚÄÄÄÄÙ
         ³ 2     ³ 2     ³ 2      ³ 2      ³ 2
   + 
     121 ³     169 ³     225 ³     289 ³     361 ³
   ÚÄÄÄÄÄÙ + ÚÄÄÄÄÄÙ + ÚÄÄÄÄÄÙ + ÚÄÄÄÄÄÙ + ÚÄÄÄÄÄÙ + ...
   ³  2      ³  2      ³  2      ³  2      ³  2
                        Type: ContinuedFraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPageEmpty14}
\begin{paste}{ContinuedFractionXmpPageEmpty14}
{ContinuedFractionXmpPagePatch14}
\pastebutton{ContinuedFractionXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{
cf := continuedFraction(1,[(2*i+1)**2 for i in 0..],repeating [2])
\bound{cf1 }}
\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPagePatch15}
\begin{paste}{ContinuedFractionXmpPageFull15}
{ContinuedFractionXmpPageEmpty15}
\pastebutton{ContinuedFractionXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{ccf := convergents cf\free{cf1 }\bound{ccf1 }}
\indentrel{3}\begin{verbatim}
   (15)
      3 15 105 315 3465 45045 45045 765765 14549535
   [1,Ä,ÄÄ,ÄÄÄ,ÄÄÄ,ÄÄÄÄ,ÄÄÄÄÄ,ÄÄÄÄÄ,ÄÄÄÄÄÄ,ÄÄÄÄÄÄÄÄ,...]
      2 13  76 263 2578 36979 33976 622637 11064338
                          Type: Stream Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPageEmpty15}
\begin{paste}{ContinuedFractionXmpPageEmpty15}
{ContinuedFractionXmpPagePatch15}
\pastebutton{ContinuedFractionXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{ccf := convergents cf\free{cf1 }\bound{ccf1 }}
\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPagePatch16}
\begin{paste}{ContinuedFractionXmpPageFull16}
{ContinuedFractionXmpPageEmpty16}
\pastebutton{ContinuedFractionXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{
piConvergents := [4/p for p in ccf]\bound{piConvergents }\free{ccf1 }}
\indentrel{3}\begin{verbatim}
   (16)
       8  52  304  1052  10312  147916  135904  2490548
   [4, Ä, ÄÄ, ÄÄÄ, ÄÄÄÄ, ÄÄÄÄÄ, ÄÄÄÄÄÄ, ÄÄÄÄÄÄ, ÄÄÄÄÄÄÄ,
       3  15  105   315   3465   45045   45045   765765
    44257352
    ÄÄÄÄÄÄÄÄ, ...]
    14549535
                          Type: Stream Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPageEmpty16}
\begin{paste}{ContinuedFractionXmpPageEmpty16}
{ContinuedFractionXmpPagePatch16}
\pastebutton{ContinuedFractionXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{
piConvergents := [4/p for p in ccf]\bound{piConvergents }\free{ccf1 }}
\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPagePatch17}
\begin{paste}{ContinuedFractionXmpPageFull17}
{ContinuedFractionXmpPageEmpty17}
\pastebutton{ContinuedFractionXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{piConvergents :: Stream Float\free{piConvergents }}
\indentrel{3}\begin{verbatim}
   (17)
   [4.0, 2.6666666666 666666667, 3.4666666666 666666667,
    2.8952380952 380952381, 3.3396825396 825396825,
    2.9760461760 461760462, 3.2837384837 384837385,
    3.0170718170 718170718, 3.2523659347 188758953,
    3.0418396189 294022111, ...]
                                     Type: Stream Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPageEmpty17}
\begin{paste}{ContinuedFractionXmpPageEmpty17}
{ContinuedFractionXmpPagePatch17}
\pastebutton{ContinuedFractionXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{piConvergents :: Stream Float\free{piConvergents }}
\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPagePatch18}
\begin{paste}{ContinuedFractionXmpPageFull18}
{ContinuedFractionXmpPageEmpty18}
\pastebutton{ContinuedFractionXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{continuedFraction((- 122 + 597*\%i)/(4 - 4*\%i))}
\indentrel{3}\begin{verbatim}
                            1    ³         1     ³
   (18)  - 90 + 59%i + ÚÄÄÄÄÄÄÄÄÄÙ + ÚÄÄÄÄÄÄÄÄÄÄÄÙ
                       ³ 1 - 2%i     ³ - 1 + 2%i
                Type: ContinuedFraction Complex Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPageEmpty18}
\begin{paste}{ContinuedFractionXmpPageEmpty18}
{ContinuedFractionXmpPagePatch18}
\pastebutton{ContinuedFractionXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{continuedFraction((- 122 + 597*\%i)/(4 - 4*\%i))}
\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPagePatch19}
\begin{paste}{ContinuedFractionXmpPageFull19}
{ContinuedFractionXmpPageEmpty19}
\pastebutton{ContinuedFractionXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{
r : Fraction UnivariatePolynomial(x,Fraction Integer)\bound{rdec }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPageEmpty19}
\begin{paste}{ContinuedFractionXmpPageEmpty19}
{ContinuedFractionXmpPagePatch19}
\pastebutton{ContinuedFractionXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{
r : Fraction UnivariatePolynomial(x,Fraction Integer)\bound{rdec }}
\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPagePatch20}
\begin{paste}{ContinuedFractionXmpPageFull20}
{ContinuedFractionXmpPageEmpty20}
\pastebutton{ContinuedFractionXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{
r := ((x - 1) * (x - 2)) / ((x-3) * (x-4))\free{rdec }\bound{r }}
\indentrel{3}\begin{verbatim}
           2
          x  - 3x + 2
   (20)  ÄÄÄÄÄÄÄÄÄÄÄÄ
          2
         x  - 7x + 12
Type: Fraction UnivariatePolynomial(x,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPageEmpty20}
\begin{paste}{ContinuedFractionXmpPageEmpty20}
{ContinuedFractionXmpPagePatch20}
\pastebutton{ContinuedFractionXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{
r := ((x - 1) * (x - 2)) / ((x-3) * (x-4))\free{rdec }\bound{r }}
\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPagePatch21}
\begin{paste}{ContinuedFractionXmpPageFull21}
{ContinuedFractionXmpPageEmpty21}
\pastebutton{ContinuedFractionXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{continuedFraction r\free{r }}
\indentrel{3}\begin{verbatim}
                  1    ³         1     ³
   (21)  1 + ÚÄÄÄÄÄÄÄÄÄÙ + ÚÄÄÄÄÄÄÄÄÄÄÄÙ
             ³ 1     9     ³ 16     40
             ³ Ä x - Ä     ³ ÄÄ x - ÄÄ
             ³ 4     8     ³  3      3
Type: ContinuedFraction UnivariatePolynomial(x,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPageEmpty21}
\begin{paste}{ContinuedFractionXmpPageEmpty21}
{ContinuedFractionXmpPagePatch21}
\pastebutton{ContinuedFractionXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{continuedFraction r\free{r }}
\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPagePatch22}
\begin{paste}{ContinuedFractionXmpPageFull22}
{ContinuedFractionXmpPageEmpty22}
\pastebutton{ContinuedFractionXmpPageFull22}{\hidepaste}
\tab{5}\spadcommand{
[i*i for i in convergents(z) :: Stream Float]\free{z }}
\indentrel{3}\begin{verbatim}
   (22)
   [9.0, 11.1111111111 11111111, 10.9944598337 9501385,
    11.0002777777 77777778, 10.9999860763 98799786,
    11.0000006979 29731039, 10.9999999650 15834446,
    11.0000000017 53603304, 10.9999999999 12099531,
    11.0000000000 04406066, ...]
                                     Type: Stream Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ContinuedFractionXmpPageEmpty22}
\begin{paste}{ContinuedFractionXmpPageEmpty22}
{ContinuedFractionXmpPagePatch22}
\pastebutton{ContinuedFractionXmpPageEmpty22}{\showpaste}
\tab{5}\spadcommand{
[i*i for i in convergents(z) :: Stream Float]\free{z }}
\end{paste}\end{patch}

\end{chunk}
\section{cphelp.ht}
\pagetitle{CPHelp}{cphelp.ht}{Control Panel Bits}
\begin{chunk}{cphelp.ht}
\begin{page}{CPHelp}{Control Panel Bits}
\beginscroll

Here are some stuff from a Three Dimensional Viewport's Control Panel 
\newline

Main Control Panel: \newline \newline

Rotate: \helpbit{rotate3D}
Zoom: \helpbit{zoom3D}
Translate up/down left/right in the window: \helpbit{translate3D}
Changing the color of the rendered surface: \helpbit{color3D}
Turn the axes on and off: \helpbit{axes3D}
Display surface as a transparent wire mesh: \helpbit{transparent3D}
Display surface with hidden surface removed and the core dumped: 
\helpbit{opaque3D}
Display rendered surface: \helpbit{render3D}
Show region within which the function is defined: \helpbit{region3D}
Change position of light source: \helpbit{lighting3D}
Change Perspective/Clipping of surface: \helpbit{volume3D}
Reset to original viewpoint: \helpbit{reset3D}
Show grid lines on the rendered surface: \helpbit{outline3D}
Hide the menu: \helpbit{hide3D}
Close the viewport: \helpbit{close3D}

\newline
\newline
\endscroll
\autobuttons
\end{page}

\end{chunk}
\section{cycles.ht}
\pagetitle{CycleIndicatorsXmpPage}{cycles.ht}{CycleIndicators}
\begin{chunk}{cycles.ht}
\begin{page}{CycleIndicatorsXmpPage}{CycleIndicators}
\beginscroll
This section is based upon the paper
J. H. Redfield, ``The Theory of Group-Reduced Distributions'',
and is an application of group theory to enumeration problems.
It is a development of the work by P. A. MacMahon on the

The theory is based upon the power sum symmetric functions
\subscriptIt{s}{i}
which are the sum of the \eth{\it i} powers of the variables.
The cycle index of a permutation is an expression that specifies
the sizes of the cycles of a permutation, and
may be represented as a partition.
A partition of a non-negative integer \spad{n} is a collection
of positive integers called its parts whose sum is \spad{n}.
For example, the partition
\texht{$(3^2 \  2 \ 1^2)$}{\spad{3**2 2 1**2)}}
will be used to represent
\texht{$s^2_3 s_2 s^2_1$}{\spad{(s_3)**2 s_2 (s_1)**2}}
and will indicate that the permutation has two cycles of length 3,
one of length 2 and two of length 1.
The cycle index of a permutation group is the sum of the cycle indices
of its permutations divided by the number of permutations.
The cycle indices of certain groups are provided.
\xtc{
We first expose something from the library.
}{
\spadpaste{)expose EVALCYC}
}
\xtc{
The operation \spadfun{complete} returns the cycle index of the
symmetric group of order \spad{n} for argument \spad{n}.
Alternatively, it is the \eth{\spad{n}} complete homogeneous symmetric
function expressed in terms of power sum symmetric functions.
}{
\spadpaste{complete 1}
}
\xtc{
}{
\spadpaste{complete 2}
}
\xtc{
}{
\spadpaste{complete 3}
}
\xtc{
}{
\spadpaste{complete 7}
}
\xtc{
The operation \spadfun{elementary} computes the \eth{\spad{n}}
elementary symmetric function for argument \spad{n.}
}{
\spadpaste{elementary 7}
}
\xtc{
The operation \spadfun{alternating} returns
the cycle index of the alternating group
having an even number of even parts in each cycle partition.
}{
\spadpaste{alternating 7}
}
\xtc{
The operation \spadfun{cyclic} returns the cycle index of the cyclic group.
}{
\spadpaste{cyclic 7}
}
\xtc{
The operation \spadfun{dihedral} is the cycle index of the
dihedral group.
}{
\spadpaste{dihedral 7}
}
\xtc{
The operation \spadfun{graphs} for argument \spad{n} returns
the cycle index of the group of permutations on
the edges of the complete graph with \spad{n} nodes induced by
applying the symmetric group to the nodes.
}{
\spadpaste{graphs 5}
}

The cycle index of a direct product of two groups is the product
of the cycle indices of the groups.
Redfield provided two operations on two cycle indices which will
be called ``cup'' and ``cap'' here.
The \spadfun{cup} of two cycle indices is a kind of scalar product
that combines monomials for permutations with the same cycles.
The \spadfun{cap} operation provides the sum of the coefficients
of the result of the \spadfun{cup} operation which will be an
integer that enumerates what Redfield called
group-reduced distributions.

We can, for example, represent  \spad{complete 2 * complete 2}
as the set of objects \spad{a a b b} and
\spad{complete 2 * complete 1 * complete 1} as \spad{c c d e.}

\xtc{
This integer
is the number of different sets of four pairs.
}{
\spadpaste{cap(complete 2**2, complete 2*complete 1**2)}
}
For example,
\begin{verbatim}
a a b b     a a b b    a a b b   a a b b
c c d e     c d c e    c e c d   d e c c
\end{verbatim}

\xtc{
This integer
is the number of different sets of four pairs no two pairs being equal.
}{
\spadpaste{cap(elementary 2**2, complete 2*complete 1**2)}
}
For example,
\begin{verbatim}
a a b b    a a b b
c d c e    c e c d
\end{verbatim}
In this case the configurations enumerated are easily constructed,
however the theory merely enumerates them providing little help in
actually constructing them.
\xtc{
Here are the
number of 6-pairs, first from \spad{a a a b b c,} second from
\spad{d d e e f g.}
}{
\spadpaste{cap(complete 3*complete 2*complete 1,
complete 2**2*complete 1**2)}
}
\xtc{
Here it is again, but with no equal pairs.
}{
\spadpaste{cap(elementary 3*elementary 2*elementary 1,
complete 2**2*complete 1**2)}
}
\xtc{
}{
\spadpaste{cap(complete 3*complete 2*complete 1,
elementary 2**2*elementary 1**2)}
}
\xtc{
The number of 6-triples, first from \spad{a a a b b c,} second from
\spad{d d e e f g,} third from \spad{h h i i j j.}
}{
\spadpaste{eval(cup(complete 3*complete 2*complete 1, 
cup(complete 2**2*complete 1**2,complete 2**3)))}
}
\xtc{
The cycle index of vertices of a square is dihedral 4.
}{
\spadpaste{square:=dihedral 4}
}
\xtc{
The number of different squares with 2 red vertices and 2 blue vertices.
}{
\spadpaste{cap(complete 2**2,square)}
}
\xtc{
The number of necklaces with 3 red beads, 2 blue beads and 2 green beads.
}{
\spadpaste{cap(complete 3*complete 2**2,dihedral 7)}
}
\xtc{
The number of graphs with 5 nodes and 7 edges.
}{
\spadpaste{cap(graphs 5,complete 7*complete 3)}
}
\xtc{
The cycle index of rotations of vertices of a cube.
}{
\spadpaste{s(x) == powerSum(x)}
}
\xtc{
}{
\spadpaste{cube:=(1/24)*(s 1**8+9*s 2**4 + 8*s 3**2*s 1**2+6*s 4**2)}
}
\xtc{
The number of cubes with 4 red vertices and 4 blue vertices.
}{
\spadpaste{cap(complete 4**2,cube)}
}
\xtc{
The number of labeled graphs with degree sequence \spad{2 2 2 1 1}
with no loops or multiple edges.
}{
\spadpaste{
cap(complete 2**3*complete 1**2,wreath(elementary 4,elementary 2))}
}
\xtc{
Again, but
with loops allowed but not multiple edges.
}{
\spadpaste{
cap(complete 2**3*complete 1**2,wreath(elementary 4,complete 2))}
}
\xtc{
Again, but
with multiple edges allowed, but not loops
}{
\spadpaste{cap(complete 2**3*complete 1**2,wreath(complete 4,elementary 2))}
}
\xtc{
Again, but
with both multiple edges and loops allowed
}{
\spadpaste{cap(complete 2**3*complete 1**2,wreath(complete 4,complete 2))}
}

Having constructed a cycle index for a configuration
we are at liberty to evaluate the
\subscriptIt{s}{i}
components any way we please.
For example we can produce enumerating generating functions.
{CycleIndicators}
This is done by providing a function \spad{f} on an integer \spad{i} 
to the value required of \subscriptIt{s}{i},
and then evaluating \spad{eval(f, cycleindex)}.
\xtc{
}{
\spadpaste{x: ULS(FRAC INT,'x,0) := 'x \bound{x}}
}
\xtc{
}{
\spadpaste{ZeroOrOne: INT -> ULS(FRAC INT, 'x, 0) \bound{zodec}}
}
\xtc{
}{
\spadpaste{Integers: INT -> ULS(FRAC INT, 'x, 0) \bound{idec}}
}
\xtc{
For the integers 0 and 1, or two colors.
}{
\spadpaste{ZeroOrOne n == 1+x**n \free{x zodec}\bound{zo}}
}
\xtc{
}{
\spadpaste{ZeroOrOne 5 \free{zo}}
}
\xtc{
For the integers \spad{0, 1, 2, ...} we have this.
}{
\spadpaste{Integers n == 1/(1-x**n) \free{x idec}\bound{i}}
}
\xtc{
}{
\spadpaste{Integers 5 \free{i}}
}

\xtc{
The coefficient of \texht{$x^n$}{\spad{x**n}}
is the number of graphs with 5 nodes
and \spad{n} edges.
}{
\spadpaste{eval(ZeroOrOne, graphs 5) \free{zo}}
}
\xtc{
The coefficient of \texht{$x^n$}{\spad{x**n}}  is the number of 
necklaces with \spad{n} red beads and \spad{n-8} green beads.
}{
\spadpaste{eval(ZeroOrOne,dihedral 8) \free{zo}}
}
\xtc{
The coefficient of \texht{$x^n$}{\spad{x**n}} is the number of 
partitions of \spad{n} into 4 or fewer parts.
}{
\spadpaste{eval(Integers,complete 4) \free{i}}
}
\xtc{
The coefficient of \texht{$x^n$}{\spad{x**n}} is the number of
partitions of \spad{n} into 4
boxes containing ordered distinct parts.
}{
\spadpaste{eval(Integers,elementary 4) \free{i}}
}
\xtc{
The coefficient of \texht{$x^n$}{\spad{x**n}} is the number of
different cubes with \spad{n} red vertices and \spad{8-n} green ones.
}{
\spadpaste{eval(ZeroOrOne,cube) \free{zo}}
}
\xtc{
The coefficient of \texht{$x^n$}{\spad{x**n}} 
is the number of different cubes with integers
on the vertices whose sum is \spad{n.}
}{
\spadpaste{eval(Integers,cube) \free{i}}
}
\xtc{
The coefficient of \texht{$x^n$}{\spad{x**n}} is the number of
graphs with 5 nodes and with integers on the edges whose sum is
\spad{n.}
In other words, the enumeration is of multigraphs with 5 nodes and
\spad{n} edges.
}{
\spadpaste{eval(Integers,graphs 5) \free{i}}
}
\xtc{
Graphs with 15 nodes enumerated with respect to number of edges.
}{
\spadpaste{eval(ZeroOrOne ,graphs 15) \free{zo}}
}
\xtc{
Necklaces with 7 green beads, 8 white beads, 5 yellow beads and 10
red beads.
}{
\spadpaste{cap(dihedral 30,complete 7*complete 8*complete 5*complete 10)}
}
The operation \spadfun{SFunction} is the S-function or Schur function
of a partition written
as a descending list of integers expressed in terms of power sum
symmetric functions.
\xtc{
In this case the argument partition represents a tableau shape.
For example \spad{3,2,2,1} represents a tableau with three boxes in the
first row, two boxes in the second and third rows, and one box in the
fourth row.
\spad{SFunction [3,2,2,1]}
counts the number of different tableaux of shape \spad{3, 2, 2, 1} filled
with objects with an ascending order in the columns and a
non-descending order in the rows.
}{
\spadpaste{sf3221:= SFunction [3,2,2,1] \bound{sf3221}}
}
\xtc{
This is the number filled with \spad{a a b b c c d d.}
}{
\spadpaste{cap(sf3221,complete 2**4) \free{sf3221}}
}
The configurations enumerated above are:
\begin{verbatim}
a a b    a a c    a a d
b c      b b      b b
c d      c d      c c
d        d        d
\end{verbatim}
\xtc{
This is the number of tableaux filled with \spad{1..8.}
}{
\spadpaste{cap(sf3221, powerSum 1**8)\free{sf3221}}
}
\xtc{
The coefficient of \texht{$x^n$}{\spad{x**n}} is the number
of column strict reverse plane partitions of \spad{n} of shape
\spad{3 2 2 1.}
}{
\spadpaste{eval(Integers, sf3221)\free{i sf3221}}
}
The smallest is
\begin{verbatim}
0 0 0
1 1
2 2
3
\end{verbatim}
\endscroll
\autobuttons
\end{page}

\begin{patch}{CycleIndicatorsXmpPagePatch1}
\begin{paste}{CycleIndicatorsXmpPageFull1}{CycleIndicatorsXmpPageEmpty1}
\pastebutton{CycleIndicatorsXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{)expose EVALCYC}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty1}
\begin{paste}{CycleIndicatorsXmpPageEmpty1}{CycleIndicatorsXmpPagePatch1}
\pastebutton{CycleIndicatorsXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{)expose EVALCYC}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch2}
\begin{paste}{CycleIndicatorsXmpPageFull2}{CycleIndicatorsXmpPageEmpty2}
\pastebutton{CycleIndicatorsXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{complete 1}
\indentrel{3}\begin{verbatim}
   (1)  (1)
             Type: SymmetricPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty2}
\begin{paste}{CycleIndicatorsXmpPageEmpty2}{CycleIndicatorsXmpPagePatch2}
\pastebutton{CycleIndicatorsXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{complete 1}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch3}
\begin{paste}{CycleIndicatorsXmpPageFull3}{CycleIndicatorsXmpPageEmpty3}
\pastebutton{CycleIndicatorsXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{complete 2}
\indentrel{3}\begin{verbatim}
        1       1   2
   (2)  Ä (2) + Ä (1 )
        2       2
             Type: SymmetricPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty3}
\begin{paste}{CycleIndicatorsXmpPageEmpty3}{CycleIndicatorsXmpPagePatch3}
\pastebutton{CycleIndicatorsXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{complete 2}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch4}
\begin{paste}{CycleIndicatorsXmpPageFull4}{CycleIndicatorsXmpPageEmpty4}
\pastebutton{CycleIndicatorsXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{complete 3}
\indentrel{3}\begin{verbatim}
        1       1         1   3
   (3)  Ä (3) + Ä (2 1) + Ä (1 )
        3       2         6
             Type: SymmetricPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty4}
\begin{paste}{CycleIndicatorsXmpPageEmpty4}{CycleIndicatorsXmpPagePatch4}
\pastebutton{CycleIndicatorsXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{complete 3}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch5}
\begin{paste}{CycleIndicatorsXmpPageFull5}{CycleIndicatorsXmpPageEmpty5}
\pastebutton{CycleIndicatorsXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{complete 7}
\indentrel{3}\begin{verbatim}
   (4)
     1       1          1          1     2     1
     Ä (7) + Ä (6 1) + ÄÄ (5 2) + ÄÄ (5 1 ) + ÄÄ (4 3)
     7       6         10         10          12
   + 
     1            1     3     1   2      1     2
     Ä (4 2 1) + ÄÄ (4 1 ) + ÄÄ (3 1) + ÄÄ (3 2 )
     8           24          18         24
   + 
      1       2     1     4     1   3      1   2 3
     ÄÄ (3 2 1 ) + ÄÄ (3 1 ) + ÄÄ (2 1) + ÄÄ (2 1 )
     12            72          48         48
   + 
      1      5      1    7
     ÄÄÄ (2 1 ) + ÄÄÄÄ (1 )
     240          5040
             Type: SymmetricPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty5}
\begin{paste}{CycleIndicatorsXmpPageEmpty5}{CycleIndicatorsXmpPagePatch5}
\pastebutton{CycleIndicatorsXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{complete 7}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch6}
\begin{paste}{CycleIndicatorsXmpPageFull6}{CycleIndicatorsXmpPageEmpty6}
\pastebutton{CycleIndicatorsXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{elementary 7}
\indentrel{3}\begin{verbatim}
   (5)
     1       1          1          1     2     1
     Ä (7) - Ä (6 1) - ÄÄ (5 2) + ÄÄ (5 1 ) - ÄÄ (4 3)
     7       6         10         10          12
   + 
     1            1     3     1   2      1     2
     Ä (4 2 1) - ÄÄ (4 1 ) + ÄÄ (3 1) + ÄÄ (3 2 )
     8           24          18         24
   + 
        1       2     1     4     1   3      1   2 3
     - ÄÄ (3 2 1 ) + ÄÄ (3 1 ) - ÄÄ (2 1) + ÄÄ (2 1 )
       12            72          48         48
   + 
        1      5      1    7
     - ÄÄÄ (2 1 ) + ÄÄÄÄ (1 )
       240          5040
             Type: SymmetricPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty6}
\begin{paste}{CycleIndicatorsXmpPageEmpty6}{CycleIndicatorsXmpPagePatch6}
\pastebutton{CycleIndicatorsXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{elementary 7}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch7}
\begin{paste}{CycleIndicatorsXmpPageFull7}{CycleIndicatorsXmpPageEmpty7}
\pastebutton{CycleIndicatorsXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{alternating 7}
\indentrel{3}\begin{verbatim}
   (6)
     2       1     2    1           1   2      1     2
     Ä (7) + Ä (5 1 ) + Ä (4 2 1) + Ä (3 1) + ÄÄ (3 2 )
     7       5          4           9         12
   + 
      1     4     1   2 3      1    7
     ÄÄ (3 1 ) + ÄÄ (2 1 ) + ÄÄÄÄ (1 )
     36          24          2520
             Type: SymmetricPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty7}
\begin{paste}{CycleIndicatorsXmpPageEmpty7}{CycleIndicatorsXmpPagePatch7}
\pastebutton{CycleIndicatorsXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{alternating 7}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch8}
\begin{paste}{CycleIndicatorsXmpPageFull8}{CycleIndicatorsXmpPageEmpty8}
\pastebutton{CycleIndicatorsXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{cyclic 7}
\indentrel{3}\begin{verbatim}
        6       1   7
   (7)  Ä (7) + Ä (1 )
        7       7
             Type: SymmetricPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty8}
\begin{paste}{CycleIndicatorsXmpPageEmpty8}{CycleIndicatorsXmpPagePatch8}
\pastebutton{CycleIndicatorsXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{cyclic 7}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch9}
\begin{paste}{CycleIndicatorsXmpPageFull9}{CycleIndicatorsXmpPageEmpty9}
\pastebutton{CycleIndicatorsXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{dihedral 7}
\indentrel{3}\begin{verbatim}
        3       1   3      1   7
   (8)  Ä (7) + Ä (2 1) + ÄÄ (1 )
        7       2         14
             Type: SymmetricPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty9}
\begin{paste}{CycleIndicatorsXmpPageEmpty9}{CycleIndicatorsXmpPagePatch9}
\pastebutton{CycleIndicatorsXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{dihedral 7}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch10}
\begin{paste}{CycleIndicatorsXmpPageFull10}{CycleIndicatorsXmpPageEmpty10}
\pastebutton{CycleIndicatorsXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{graphs 5}
\indentrel{3}\begin{verbatim}
   (9)
     1           1   2    1   2     1   3     1   4 2
     Ä (6 3 1) + Ä (5 ) + Ä (4 2) + Ä (3 1) + Ä (2 1 )
     6           5        4         6         8
   + 
      1   3 4     1    10
     ÄÄ (2 1 ) + ÄÄÄ (1  )
     12          120
             Type: SymmetricPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty10}
\begin{paste}{CycleIndicatorsXmpPageEmpty10}{CycleIndicatorsXmpPagePatch10}
\pastebutton{CycleIndicatorsXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{graphs 5}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch11}
\begin{paste}{CycleIndicatorsXmpPageFull11}{CycleIndicatorsXmpPageEmpty11}
\pastebutton{CycleIndicatorsXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{cap(complete 2**2, complete 2*complete 1**2)}
\indentrel{3}\begin{verbatim}
   (10)  4
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty11}
\begin{paste}{CycleIndicatorsXmpPageEmpty11}{CycleIndicatorsXmpPagePatch11}
\pastebutton{CycleIndicatorsXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{cap(complete 2**2, complete 2*complete 1**2)}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch12}
\begin{paste}{CycleIndicatorsXmpPageFull12}{CycleIndicatorsXmpPageEmpty12}
\pastebutton{CycleIndicatorsXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{cap(elementary 2**2, complete 2*complete 1**2)}
\indentrel{3}\begin{verbatim}
   (11)  2
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty12}
\begin{paste}{CycleIndicatorsXmpPageEmpty12}{CycleIndicatorsXmpPagePatch12}
\pastebutton{CycleIndicatorsXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{cap(elementary 2**2, complete 2*complete 1**2)}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch13}
\begin{paste}{CycleIndicatorsXmpPageFull13}{CycleIndicatorsXmpPageEmpty13}
\pastebutton{CycleIndicatorsXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{
cap(complete 3*complete 2*complete 1,complete 2**2*complete 1**2)}
\indentrel{3}\begin{verbatim}
   (12)  24
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty13}
\begin{paste}{CycleIndicatorsXmpPageEmpty13}{CycleIndicatorsXmpPagePatch13}
\pastebutton{CycleIndicatorsXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{
cap(complete 3*complete 2*complete 1,complete 2**2*complete 1**2)}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch14}
\begin{paste}{CycleIndicatorsXmpPageFull14}{CycleIndicatorsXmpPageEmpty14}
\pastebutton{CycleIndicatorsXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{
cap(elementary 3*elementary 2*elementary 1,complete 2**2*complete 1**2)}
\indentrel{3}\begin{verbatim}
   (13)  8
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty14}
\begin{paste}{CycleIndicatorsXmpPageEmpty14}{CycleIndicatorsXmpPagePatch14}
\pastebutton{CycleIndicatorsXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{
cap(elementary 3*elementary 2*elementary 1,complete 2**2*complete 1**2)}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch15}
\begin{paste}{CycleIndicatorsXmpPageFull15}{CycleIndicatorsXmpPageEmpty15}
\pastebutton{CycleIndicatorsXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{
cap(complete 3*complete 2*complete 1,elementary 2**2*elementary 1**2)}
\indentrel{3}\begin{verbatim}
   (14)  8
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty15}
\begin{paste}{CycleIndicatorsXmpPageEmpty15}{CycleIndicatorsXmpPagePatch15}
\pastebutton{CycleIndicatorsXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{
cap(complete 3*complete 2*complete 1,elementary 2**2*elementary 1**2)}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch16}
\begin{paste}{CycleIndicatorsXmpPageFull16}{CycleIndicatorsXmpPageEmpty16}
\pastebutton{CycleIndicatorsXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{
eval(cup(complete 3*complete 2*complete 1, _
     cup(complete 2**2*complete 1**2,complete 2**3)))}
\indentrel{3}\begin{verbatim}
   (15)  1500
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty16}
\begin{paste}{CycleIndicatorsXmpPageEmpty16}{CycleIndicatorsXmpPagePatch16}
\pastebutton{CycleIndicatorsXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{
eval(cup(complete 3*complete 2*complete 1, _
     cup(complete 2**2*complete 1**2,complete 2**3)))}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch17}
\begin{paste}{CycleIndicatorsXmpPageFull17}{CycleIndicatorsXmpPageEmpty17}
\pastebutton{CycleIndicatorsXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{square:=dihedral 4}
\indentrel{3}\begin{verbatim}
         1       3   2    1     2    1   4
   (16)  Ä (4) + Ä (2 ) + Ä (2 1 ) + Ä (1 )
         4       8        4          8
             Type: SymmetricPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty17}
\begin{paste}{CycleIndicatorsXmpPageEmpty17}{CycleIndicatorsXmpPagePatch17}
\pastebutton{CycleIndicatorsXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{square:=dihedral 4}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch18}
\begin{paste}{CycleIndicatorsXmpPageFull18}{CycleIndicatorsXmpPageEmpty18}
\pastebutton{CycleIndicatorsXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{cap(complete 2**2,square)}
\indentrel{3}\begin{verbatim}
   (17)  2
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty18}
\begin{paste}{CycleIndicatorsXmpPageEmpty18}{CycleIndicatorsXmpPagePatch18}
\pastebutton{CycleIndicatorsXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{cap(complete 2**2,square)}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch19}
\begin{paste}{CycleIndicatorsXmpPageFull19}{CycleIndicatorsXmpPageEmpty19}
\pastebutton{CycleIndicatorsXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{cap(complete 3*complete 2**2,dihedral 7)}
\indentrel{3}\begin{verbatim}
   (18)  18
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty19}
\begin{paste}{CycleIndicatorsXmpPageEmpty19}{CycleIndicatorsXmpPagePatch19}
\pastebutton{CycleIndicatorsXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{cap(complete 3*complete 2**2,dihedral 7)}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch20}
\begin{paste}{CycleIndicatorsXmpPageFull20}{CycleIndicatorsXmpPageEmpty20}
\pastebutton{CycleIndicatorsXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{cap(graphs 5,complete 7*complete 3)}
\indentrel{3}\begin{verbatim}
   (19)  4
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty20}
\begin{paste}{CycleIndicatorsXmpPageEmpty20}{CycleIndicatorsXmpPagePatch20}
\pastebutton{CycleIndicatorsXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{cap(graphs 5,complete 7*complete 3)}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch21}
\begin{paste}{CycleIndicatorsXmpPageFull21}{CycleIndicatorsXmpPageEmpty21}
\pastebutton{CycleIndicatorsXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{s(x) == powerSum(x)}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty21}
\begin{paste}{CycleIndicatorsXmpPageEmpty21}{CycleIndicatorsXmpPagePatch21}
\pastebutton{CycleIndicatorsXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{s(x) == powerSum(x)}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch22}
\begin{paste}{CycleIndicatorsXmpPageFull22}{CycleIndicatorsXmpPageEmpty22}
\pastebutton{CycleIndicatorsXmpPageFull22}{\hidepaste}
\tab{5}\spadcommand{
cube:=(1/24)*(s 1**8+9*s 2**4 + 8*s 3**2*s 1**2+6*s 4**2)}
\indentrel{3}\begin{verbatim}
         1   2    1   2 2    3   4     1   8
   (21)  Ä (4 ) + Ä (3 1 ) + Ä (2 ) + ÄÄ (1 )
         4        3          8        24
             Type: SymmetricPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty22}
\begin{paste}{CycleIndicatorsXmpPageEmpty22}{CycleIndicatorsXmpPagePatch22}
\pastebutton{CycleIndicatorsXmpPageEmpty22}{\showpaste}
\tab{5}\spadcommand{
cube:=(1/24)*(s 1**8+9*s 2**4 + 8*s 3**2*s 1**2+6*s 4**2)}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch23}
\begin{paste}{CycleIndicatorsXmpPageFull23}{CycleIndicatorsXmpPageEmpty23}
\pastebutton{CycleIndicatorsXmpPageFull23}{\hidepaste}
\tab{5}\spadcommand{cap(complete 4**2,cube)}
\indentrel{3}\begin{verbatim}
   (22)  7
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty23}
\begin{paste}{CycleIndicatorsXmpPageEmpty23}{CycleIndicatorsXmpPagePatch23}
\pastebutton{CycleIndicatorsXmpPageEmpty23}{\showpaste}
\tab{5}\spadcommand{cap(complete 4**2,cube)}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch24}
\begin{paste}{CycleIndicatorsXmpPageFull24}{CycleIndicatorsXmpPageEmpty24}
\pastebutton{CycleIndicatorsXmpPageFull24}{\hidepaste}
\tab{5}\spadcommand{
cap(complete 2**3*complete 1**2,wreath(elementary 4,elementary 2))}
\indentrel{3}\begin{verbatim}
   (23)  7
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty24}
\begin{paste}{CycleIndicatorsXmpPageEmpty24}{CycleIndicatorsXmpPagePatch24}
\pastebutton{CycleIndicatorsXmpPageEmpty24}{\showpaste}
\tab{5}\spadcommand{
cap(complete 2**3*complete 1**2,wreath(elementary 4,elementary 2))}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch25}
\begin{paste}{CycleIndicatorsXmpPageFull25}{CycleIndicatorsXmpPageEmpty25}
\pastebutton{CycleIndicatorsXmpPageFull25}{\hidepaste}
\tab{5}\spadcommand{
cap(complete 2**3*complete 1**2,wreath(elementary 4,complete 2))}
\indentrel{3}\begin{verbatim}
   (24)  17
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty25}
\begin{paste}{CycleIndicatorsXmpPageEmpty25}{CycleIndicatorsXmpPagePatch25}
\pastebutton{CycleIndicatorsXmpPageEmpty25}{\showpaste}
\tab{5}\spadcommand{
cap(complete 2**3*complete 1**2,wreath(elementary 4,complete 2))}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch26}
\begin{paste}{CycleIndicatorsXmpPageFull26}{CycleIndicatorsXmpPageEmpty26}
\pastebutton{CycleIndicatorsXmpPageFull26}{\hidepaste}
\tab{5}\spadcommand{
cap(complete 2**3*complete 1**2,wreath(complete 4,elementary 2))}
\indentrel{3}\begin{verbatim}
   (25)  10
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty26}
\begin{paste}{CycleIndicatorsXmpPageEmpty26}{CycleIndicatorsXmpPagePatch26}
\pastebutton{CycleIndicatorsXmpPageEmpty26}{\showpaste}
\tab{5}\spadcommand{
cap(complete 2**3*complete 1**2,wreath(complete 4,elementary 2))}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch27}
\begin{paste}{CycleIndicatorsXmpPageFull27}{CycleIndicatorsXmpPageEmpty27}
\pastebutton{CycleIndicatorsXmpPageFull27}{\hidepaste}
\tab{5}\spadcommand{
cap(complete 2**3*complete 1**2,wreath(complete 4,complete 2))}
\indentrel{3}\begin{verbatim}
   (26)  23
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty27}
\begin{paste}{CycleIndicatorsXmpPageEmpty27}{CycleIndicatorsXmpPagePatch27}
\pastebutton{CycleIndicatorsXmpPageEmpty27}{\showpaste}
\tab{5}\spadcommand{
cap(complete 2**3*complete 1**2,wreath(complete 4,complete 2))}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch28}
\begin{paste}{CycleIndicatorsXmpPageFull28}{CycleIndicatorsXmpPageEmpty28}
\pastebutton{CycleIndicatorsXmpPageFull28}{\hidepaste}
\tab{5}\spadcommand{x: ULS(FRAC INT,'x,0) := 'x\bound{x }}
\indentrel{3}\begin{verbatim}
   (27)  x
    Type: UnivariateLaurentSeries(Fraction Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty28}
\begin{paste}{CycleIndicatorsXmpPageEmpty28}{CycleIndicatorsXmpPagePatch28}
\pastebutton{CycleIndicatorsXmpPageEmpty28}{\showpaste}
\tab{5}\spadcommand{x: ULS(FRAC INT,'x,0) := 'x\bound{x }}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch29}
\begin{paste}{CycleIndicatorsXmpPageFull29}{CycleIndicatorsXmpPageEmpty29}
\pastebutton{CycleIndicatorsXmpPageFull29}{\hidepaste}
\tab{5}\spadcommand{ZeroOrOne: INT -> ULS(FRAC INT, 'x, 0)\bound{zodec }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty29}
\begin{paste}{CycleIndicatorsXmpPageEmpty29}{CycleIndicatorsXmpPagePatch29}
\pastebutton{CycleIndicatorsXmpPageEmpty29}{\showpaste}
\tab{5}\spadcommand{ZeroOrOne: INT -> ULS(FRAC INT, 'x, 0)\bound{zodec }}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch30}
\begin{paste}{CycleIndicatorsXmpPageFull30}{CycleIndicatorsXmpPageEmpty30}
\pastebutton{CycleIndicatorsXmpPageFull30}{\hidepaste}
\tab{5}\spadcommand{Integers: INT -> ULS(FRAC INT, 'x, 0)\bound{idec }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty30}
\begin{paste}{CycleIndicatorsXmpPageEmpty30}{CycleIndicatorsXmpPagePatch30}
\pastebutton{CycleIndicatorsXmpPageEmpty30}{\showpaste}
\tab{5}\spadcommand{Integers: INT -> ULS(FRAC INT, 'x, 0)\bound{idec }}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch31}
\begin{paste}{CycleIndicatorsXmpPageFull31}{CycleIndicatorsXmpPageEmpty31}
\pastebutton{CycleIndicatorsXmpPageFull31}{\hidepaste}
\tab{5}\spadcommand{ZeroOrOne n == 1+x**n\free{x zodec }\bound{zo }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty31}
\begin{paste}{CycleIndicatorsXmpPageEmpty31}{CycleIndicatorsXmpPagePatch31}
\pastebutton{CycleIndicatorsXmpPageEmpty31}{\showpaste}
\tab{5}\spadcommand{ZeroOrOne n == 1+x**n\free{x zodec }\bound{zo }}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch32}
\begin{paste}{CycleIndicatorsXmpPageFull32}{CycleIndicatorsXmpPageEmpty32}
\pastebutton{CycleIndicatorsXmpPageFull32}{\hidepaste}
\tab{5}\spadcommand{ZeroOrOne 5\free{zo }}
\indentrel{3}\begin{verbatim}
              5
   (31)  1 + x
    Type: UnivariateLaurentSeries(Fraction Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty32}
\begin{paste}{CycleIndicatorsXmpPageEmpty32}{CycleIndicatorsXmpPagePatch32}
\pastebutton{CycleIndicatorsXmpPageEmpty32}{\showpaste}
\tab{5}\spadcommand{ZeroOrOne 5\free{zo }}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch33}
\begin{paste}{CycleIndicatorsXmpPageFull33}{CycleIndicatorsXmpPageEmpty33}
\pastebutton{CycleIndicatorsXmpPageFull33}{\hidepaste}
\tab{5}\spadcommand{Integers n == 1/(1-x**n)\free{x idec }\bound{i }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty33}
\begin{paste}{CycleIndicatorsXmpPageEmpty33}{CycleIndicatorsXmpPagePatch33}
\pastebutton{CycleIndicatorsXmpPageEmpty33}{\showpaste}
\tab{5}\spadcommand{Integers n == 1/(1-x**n)\free{x idec }\bound{i }}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch34}
\begin{paste}{CycleIndicatorsXmpPageFull34}{CycleIndicatorsXmpPageEmpty34}
\pastebutton{CycleIndicatorsXmpPageFull34}{\hidepaste}
\tab{5}\spadcommand{Integers 5\free{i }}
\indentrel{3}\begin{verbatim}
              5    10      11
   (33)  1 + x  + x   + O(x  )
    Type: UnivariateLaurentSeries(Fraction Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty34}
\begin{paste}{CycleIndicatorsXmpPageEmpty34}{CycleIndicatorsXmpPagePatch34}
\pastebutton{CycleIndicatorsXmpPageEmpty34}{\showpaste}
\tab{5}\spadcommand{Integers 5\free{i }}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch35}
\begin{paste}{CycleIndicatorsXmpPageFull35}{CycleIndicatorsXmpPageEmpty35}
\pastebutton{CycleIndicatorsXmpPageFull35}{\hidepaste}
\tab{5}\spadcommand{eval(ZeroOrOne, graphs 5)\free{zo }}
\indentrel{3}\begin{verbatim}
   (34)
               2     3     4     5     6     7     8    9
     1 + x + 2x  + 4x  + 6x  + 6x  + 6x  + 4x  + 2x  + x
   + 
      10      11
     x   + O(x  )
    Type: UnivariateLaurentSeries(Fraction Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty35}
\begin{paste}{CycleIndicatorsXmpPageEmpty35}{CycleIndicatorsXmpPagePatch35}
\pastebutton{CycleIndicatorsXmpPageEmpty35}{\showpaste}
\tab{5}\spadcommand{eval(ZeroOrOne, graphs 5)\free{zo }}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch36}
\begin{paste}{CycleIndicatorsXmpPageFull36}{CycleIndicatorsXmpPageEmpty36}
\pastebutton{CycleIndicatorsXmpPageFull36}{\hidepaste}
\tab{5}\spadcommand{eval(ZeroOrOne,dihedral 8)\free{zo }}
\indentrel{3}\begin{verbatim}
                   2     3     4     5     6    7    8
   (35)  1 + x + 4x  + 5x  + 8x  + 5x  + 4x  + x  + x
    Type: UnivariateLaurentSeries(Fraction Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty36}
\begin{paste}{CycleIndicatorsXmpPageEmpty36}{CycleIndicatorsXmpPagePatch36}
\pastebutton{CycleIndicatorsXmpPageEmpty36}{\showpaste}
\tab{5}\spadcommand{eval(ZeroOrOne,dihedral 8)\free{zo }}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch37}
\begin{paste}{CycleIndicatorsXmpPageFull37}{CycleIndicatorsXmpPageEmpty37}
\pastebutton{CycleIndicatorsXmpPageFull37}{\hidepaste}
\tab{5}\spadcommand{eval(Integers,complete 4)\free{i }}
\indentrel{3}\begin{verbatim}
   (36)
               2     3     4     5     6      7      8
     1 + x + 2x  + 3x  + 5x  + 6x  + 9x  + 11x  + 15x
   + 
        9      10      11
     18x  + 23x   + O(x  )
    Type: UnivariateLaurentSeries(Fraction Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty37}
\begin{paste}{CycleIndicatorsXmpPageEmpty37}{CycleIndicatorsXmpPagePatch37}
\pastebutton{CycleIndicatorsXmpPageEmpty37}{\showpaste}
\tab{5}\spadcommand{eval(Integers,complete 4)\free{i }}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch38}
\begin{paste}{CycleIndicatorsXmpPageFull38}{CycleIndicatorsXmpPageEmpty38}
\pastebutton{CycleIndicatorsXmpPageFull38}{\hidepaste}
\tab{5}\spadcommand{eval(Integers,elementary 4)\free{i }}
\indentrel{3}\begin{verbatim}
   (37)
      6    7     8     9     10     11     12      13
     x  + x  + 2x  + 3x  + 5x   + 6x   + 9x   + 11x
   + 
        14      15      16      17
     15x   + 18x   + 23x   + O(x  )
    Type: UnivariateLaurentSeries(Fraction Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty38}
\begin{paste}{CycleIndicatorsXmpPageEmpty38}{CycleIndicatorsXmpPagePatch38}
\pastebutton{CycleIndicatorsXmpPageEmpty38}{\showpaste}
\tab{5}\spadcommand{eval(Integers,elementary 4)\free{i }}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch39}
\begin{paste}{CycleIndicatorsXmpPageFull39}{CycleIndicatorsXmpPageEmpty39}
\pastebutton{CycleIndicatorsXmpPageFull39}{\hidepaste}
\tab{5}\spadcommand{eval(ZeroOrOne,cube)\free{zo }}
\indentrel{3}\begin{verbatim}
                   2     3     4     5     6    7    8
   (38)  1 + x + 3x  + 3x  + 7x  + 3x  + 3x  + x  + x
    Type: UnivariateLaurentSeries(Fraction Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty39}
\begin{paste}{CycleIndicatorsXmpPageEmpty39}{CycleIndicatorsXmpPagePatch39}
\pastebutton{CycleIndicatorsXmpPageEmpty39}{\showpaste}
\tab{5}\spadcommand{eval(ZeroOrOne,cube)\free{zo }}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch40}
\begin{paste}{CycleIndicatorsXmpPageFull40}{CycleIndicatorsXmpPageEmpty40}
\pastebutton{CycleIndicatorsXmpPageFull40}{\hidepaste}
\tab{5}\spadcommand{eval(Integers,cube)\free{i }}
\indentrel{3}\begin{verbatim}
   (39)
               2     3      4      5      6       7
     1 + x + 4x  + 7x  + 21x  + 37x  + 85x  + 151x
   + 
         8       9       10      11
     292x  + 490x  + 848x   + O(x  )
    Type: UnivariateLaurentSeries(Fraction Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty40}
\begin{paste}{CycleIndicatorsXmpPageEmpty40}{CycleIndicatorsXmpPagePatch40}
\pastebutton{CycleIndicatorsXmpPageEmpty40}{\showpaste}
\tab{5}\spadcommand{eval(Integers,cube)\free{i }}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch41}
\begin{paste}{CycleIndicatorsXmpPageFull41}{CycleIndicatorsXmpPageEmpty41}
\pastebutton{CycleIndicatorsXmpPageFull41}{\hidepaste}
\tab{5}\spadcommand{eval(Integers,graphs 5)\free{i }}
\indentrel{3}\begin{verbatim}
   (40)
               2     3      4      5      6       7
     1 + x + 3x  + 7x  + 17x  + 35x  + 76x  + 149x
   + 
         8       9       10      11
     291x  + 539x  + 974x   + O(x  )
    Type: UnivariateLaurentSeries(Fraction Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty41}
\begin{paste}{CycleIndicatorsXmpPageEmpty41}{CycleIndicatorsXmpPagePatch41}
\pastebutton{CycleIndicatorsXmpPageEmpty41}{\showpaste}
\tab{5}\spadcommand{eval(Integers,graphs 5)\free{i }}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch42}
\begin{paste}{CycleIndicatorsXmpPageFull42}{CycleIndicatorsXmpPageEmpty42}
\pastebutton{CycleIndicatorsXmpPageFull42}{\hidepaste}
\tab{5}\spadcommand{eval(ZeroOrOne ,graphs 15)\free{zo }}
\indentrel{3}\begin{verbatim}
   (41)
               2     3      4      5      6       7
     1 + x + 2x  + 5x  + 11x  + 26x  + 68x  + 177x
   + 
         8        9        10      11
     496x  + 1471x  + 4583x   + O(x  )
    Type: UnivariateLaurentSeries(Fraction Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty42}
\begin{paste}{CycleIndicatorsXmpPageEmpty42}{CycleIndicatorsXmpPagePatch42}
\pastebutton{CycleIndicatorsXmpPageEmpty42}{\showpaste}
\tab{5}\spadcommand{eval(ZeroOrOne ,graphs 15)\free{zo }}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch43}
\begin{paste}{CycleIndicatorsXmpPageFull43}{CycleIndicatorsXmpPageEmpty43}
\pastebutton{CycleIndicatorsXmpPageFull43}{\hidepaste}
\tab{5}\spadcommand{cap(dihedral 30,complete 7*complete 8*complete 5*complete 10)}
\indentrel{3}\begin{verbatim}
   (42)  49958972383320
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty43}
\begin{paste}{CycleIndicatorsXmpPageEmpty43}{CycleIndicatorsXmpPagePatch43}
\pastebutton{CycleIndicatorsXmpPageEmpty43}{\showpaste}
\tab{5}\spadcommand{
cap(dihedral 30,complete 7*complete 8*complete 5*complete 10)}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch44}
\begin{paste}{CycleIndicatorsXmpPageFull44}{CycleIndicatorsXmpPageEmpty44}
\pastebutton{CycleIndicatorsXmpPageFull44}{\hidepaste}
\tab{5}\spadcommand{sf3221:= SFunction [3,2,2,1]\bound{sf3221 }}
\indentrel{3}\begin{verbatim}
   (43)
      1          1     2     1   2     1
     ÄÄ (6 2) - ÄÄ (6 1 ) - ÄÄ (4 ) + ÄÄ (4 3 1)
     12         12          16        12
   + 
      1     4     1   2      1   2 2     1     2
     ÄÄ (4 1 ) - ÄÄ (3 2) + ÄÄ (3 1 ) - ÄÄ (3 2 1)
     24          36         36          24
   + 
        1       3     1     5     1    4     1   3 2
     - ÄÄ (3 2 1 ) - ÄÄ (3 1 ) - ÄÄÄ (2 ) + ÄÄ (2 1 )
       36            72          192        48
   + 
      1   2 4     1      6     1    8
     ÄÄ (2 1 ) - ÄÄÄ (2 1 ) + ÄÄÄ (1 )
     96          144          576
             Type: SymmetricPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty44}
\begin{paste}{CycleIndicatorsXmpPageEmpty44}{CycleIndicatorsXmpPagePatch44}
\pastebutton{CycleIndicatorsXmpPageEmpty44}{\showpaste}
\tab{5}\spadcommand{sf3221:= SFunction [3,2,2,1]\bound{sf3221 }}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch45}
\begin{paste}{CycleIndicatorsXmpPageFull45}{CycleIndicatorsXmpPageEmpty45}
\pastebutton{CycleIndicatorsXmpPageFull45}{\hidepaste}
\tab{5}\spadcommand{cap(sf3221,complete 2**4)\free{sf3221 }}
\indentrel{3}\begin{verbatim}
   (44)  3
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty45}
\begin{paste}{CycleIndicatorsXmpPageEmpty45}{CycleIndicatorsXmpPagePatch45}
\pastebutton{CycleIndicatorsXmpPageEmpty45}{\showpaste}
\tab{5}\spadcommand{cap(sf3221,complete 2**4)\free{sf3221 }}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch46}
\begin{paste}{CycleIndicatorsXmpPageFull46}{CycleIndicatorsXmpPageEmpty46}
\pastebutton{CycleIndicatorsXmpPageFull46}{\hidepaste}
\tab{5}\spadcommand{cap(sf3221, powerSum 1**8)\free{sf3221 }}
\indentrel{3}\begin{verbatim}
   (45)  70
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty46}
\begin{paste}{CycleIndicatorsXmpPageEmpty46}{CycleIndicatorsXmpPagePatch46}
\pastebutton{CycleIndicatorsXmpPageEmpty46}{\showpaste}
\tab{5}\spadcommand{cap(sf3221, powerSum 1**8)\free{sf3221 }}
\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPagePatch47}
\begin{paste}{CycleIndicatorsXmpPageFull47}{CycleIndicatorsXmpPageEmpty47}
\pastebutton{CycleIndicatorsXmpPageFull47}{\hidepaste}
\tab{5}\spadcommand{eval(Integers, sf3221)\free{i sf3221 }}
\indentrel{3}\begin{verbatim}
   (46)
      9     10     11      12      13      14      15
     x  + 3x   + 7x   + 14x   + 27x   + 47x   + 79x
   + 
         16       17       18       19      20
     126x   + 196x   + 294x   + 432x   + O(x  )
    Type: UnivariateLaurentSeries(Fraction Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{CycleIndicatorsXmpPageEmpty47}
\begin{paste}{CycleIndicatorsXmpPageEmpty47}{CycleIndicatorsXmpPagePatch47}
\pastebutton{CycleIndicatorsXmpPageEmpty47}{\showpaste}
\tab{5}\spadcommand{eval(Integers, sf3221)\free{i sf3221 }}
\end{paste}\end{patch}

\end{chunk}
\section{coverex.ht}
\pagetitle{ExampleCoverPage}{coverex.ht}{Examples Of Axiom Commands}
\pageto{Differentiation}{Menuexdiff}
\pageto{Integration}{Menuexint}
\pageto{Laplace Transforms}{Menuexlap}
\pageto{Limits}{Menuexlimit}
\pageto{Matrices}{Menuexmatrix}
\pageto{2-D Graphics}{Menuexplot2d}
\pageto{3-D Graphics}{Menuexplot3d}
\pageto{Series}{Menuexseries}
\pageto{Summations}{Menuexsum}
\begin{chunk}{coverex.ht}
\begin{page}{ExampleCoverPage}{Examples Of Axiom Commands}
\beginscroll\table{
{\downlink{Differentiation}{Menuexdiff}}
{\downlink{Integration}{Menuexint}}
{\downlink{Laplace Transforms}{Menuexlap}}
{\downlink{Limits}{Menuexlimit}}
{\downlink{Matrices}{Menuexmatrix}}
{\downlink{2-D Graphics}{Menuexplot2d}}
{\downlink{3-D Graphics}{Menuexplot3d}}
{\downlink{Series}{Menuexseries}}
{\downlink{Summations}{Menuexsum}}
}\endscroll\end{page}

\end{chunk}
\pagetitle{Menuexdiff}{coverex.ht}{Differentiation}
\pageto{Computing Derivatives}{ExDiffBasic}
\pageto{Derivatives of Functions of Several Variables}
{ExDiffSeveralVariables}
\pageto{Derivatives of Higher Order}{ExDiffHigherOrder}
\pageto{Multiple Derivatives I}{ExDiffMultipleI}
\pageto{Multiple Derivatives II}{ExDiffMultipleII}
\pageto{Derivatives of Functions Involving Formal Integrals}
{ExDiffFormalIntegral}
\begin{chunk}{coverex.ht}
\begin{page}{Menuexdiff}{Differentiation}
\beginscroll\beginmenu
\menudownlink{Computing Derivatives}{ExDiffBasic}
\spadpaste{differentiate(sin(x) * exp(x**2),x)}
\menudownlink{Derivatives of Functions of Several Variables}
{ExDiffSeveralVariables}
\spadpaste{differentiate(sin(x) * tan(y)/(x**2 + y**2),x)}
\spadpaste{differentiate(sin(x) * tan(y)/(x**2 + y**2),y)}
\menudownlink{Derivatives of Higher Order}{ExDiffHigherOrder}
\spadpaste{differentiate(exp(x**2),x,4)}
\menudownlink{Multiple Derivatives I}{ExDiffMultipleI}
\spadpaste{differentiate(sin(x)/(x**2 + y**2),[x,y])}
\spadpaste{differentiate(sin(x)/(x**2 + y**2),[x,y,y])}
\menudownlink{Multiple Derivatives II}{ExDiffMultipleII}
\spadpaste{differentiate(cos(z)/(x**2 + y**3),[x,y,z],[1,2,3])}
\menudownlink{Derivatives of Functions Involving Formal Integrals}
{ExDiffFormalIntegral}
\spadpaste{f := integrate(sqrt(1 + t**3),t) \bound{f}}
\spadpaste{differentiate(f,t) \free{f}}
\spadpaste{differentiate(f * t**2,t) \free{f}}
\endmenu\endscroll
\end{page}

\begin{patch}{MenuexdiffPatch1}
\begin{paste}{MenuexdiffFull1}{MenuexdiffEmpty1}
\pastebutton{MenuexdiffFull1}{\hidepaste}
\tab{5}\spadcommand{differentiate(sin(x) * exp(x**2),x)}
\indentrel{3}\begin{verbatim}
              2                  2
             x                  x
   (1)  2x %e  sin(x) + cos(x)%e
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexdiffEmpty1}
\begin{paste}{MenuexdiffEmpty1}{MenuexdiffPatch1}
\pastebutton{MenuexdiffEmpty1}{\showpaste}
\tab{5}\spadcommand{differentiate(sin(x) * exp(x**2),x)}
\end{paste}\end{patch}

\begin{patch}{MenuexdiffPatch2}
\begin{paste}{MenuexdiffFull2}{MenuexdiffEmpty2}
\pastebutton{MenuexdiffFull2}{\hidepaste}
\tab{5}\spadcommand{differentiate(sin(x) * tan(y)/(x**2 + y**2),x)}
\indentrel{3}\begin{verbatim}
                         2    2
        (- 2x sin(x) + (y  + x )cos(x))tan(y)
   (2)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                    4     2 2    4
                   y  + 2x y  + x
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexdiffEmpty2}
\begin{paste}{MenuexdiffEmpty2}{MenuexdiffPatch2}
\pastebutton{MenuexdiffEmpty2}{\showpaste}
\tab{5}\spadcommand{differentiate(sin(x) * tan(y)/(x**2 + y**2),x)}
\end{paste}\end{patch}

\begin{patch}{MenuexdiffPatch3}
\begin{paste}{MenuexdiffFull3}{MenuexdiffEmpty3}
\pastebutton{MenuexdiffFull3}{\hidepaste}
\tab{5}\spadcommand{differentiate(sin(x) * tan(y)/(x**2 + y**2),y)}
\indentrel{3}\begin{verbatim}
   (3)
         2    2             2
       (y  + x )sin(x)tan(y)  - 2y sin(x)tan(y)
     + 
         2    2
       (y  + x )sin(x)
  /
      4     2 2    4
     y  + 2x y  + x
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexdiffEmpty3}
\begin{paste}{MenuexdiffEmpty3}{MenuexdiffPatch3}
\pastebutton{MenuexdiffEmpty3}{\showpaste}
\tab{5}\spadcommand{differentiate(sin(x) * tan(y)/(x**2 + y**2),y)}
\end{paste}\end{patch}

\begin{patch}{MenuexdiffPatch4}
\begin{paste}{MenuexdiffFull4}{MenuexdiffEmpty4}
\pastebutton{MenuexdiffFull4}{\hidepaste}
\tab{5}\spadcommand{differentiate(exp(x**2),x,4)}
\indentrel{3}\begin{verbatim}
                             2
            4      2        x
   (4)  (16x  + 48x  + 12)%e
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexdiffEmpty4}
\begin{paste}{MenuexdiffEmpty4}{MenuexdiffPatch4}
\pastebutton{MenuexdiffEmpty4}{\showpaste}
\tab{5}\spadcommand{differentiate(exp(x**2),x,4)}
\end{paste}\end{patch}

\begin{patch}{MenuexdiffPatch5}
\begin{paste}{MenuexdiffFull5}{MenuexdiffEmpty5}
\pastebutton{MenuexdiffFull5}{\hidepaste}
\tab{5}\spadcommand{differentiate(sin(x)/(x**2 + y**2),[x,y])}
\indentrel{3}\begin{verbatim}
                           3     2
        8x y sin(x) + (- 2y  - 2x y)cos(x)
   (5)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
               6     2 4     4 2    6
              y  + 3x y  + 3x y  + x
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexdiffEmpty5}
\begin{paste}{MenuexdiffEmpty5}{MenuexdiffPatch5}
\pastebutton{MenuexdiffEmpty5}{\showpaste}
\tab{5}\spadcommand{differentiate(sin(x)/(x**2 + y**2),[x,y])}
\end{paste}\end{patch}

\begin{patch}{MenuexdiffPatch6}
\begin{paste}{MenuexdiffFull6}{MenuexdiffEmpty6}
\pastebutton{MenuexdiffFull6}{\hidepaste}
\tab{5}\spadcommand{differentiate(sin(x)/(x**2 + y**2),[x,y,y])}
\indentrel{3}\begin{verbatim}
   (6)
           2     3             4     2 2     4
   (- 40x y  + 8x )sin(x) + (6y  + 4x y  - 2x )cos(x)
   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
              8     2 6     4 4     6 2    8
             y  + 4x y  + 6x y  + 4x y  + x
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexdiffEmpty6}
\begin{paste}{MenuexdiffEmpty6}{MenuexdiffPatch6}
\pastebutton{MenuexdiffEmpty6}{\showpaste}
\tab{5}\spadcommand{differentiate(sin(x)/(x**2 + y**2),[x,y,y])}
\end{paste}\end{patch}

\begin{patch}{MenuexdiffPatch7}
\begin{paste}{MenuexdiffFull7}{MenuexdiffEmpty7}
\pastebutton{MenuexdiffFull7}{\hidepaste}
\tab{5}\spadcommand{differentiate(cos(z)/(x**2 + y**3),[x,y,z],[1,2,3])}
\indentrel{3}\begin{verbatim}
                    4      3
            (- 84x y  + 24x y)sin(z)
   (7)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
         12     2 9     4 6     6 3    8
        y   + 4x y  + 6x y  + 4x y  + x
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexdiffEmpty7}
\begin{paste}{MenuexdiffEmpty7}{MenuexdiffPatch7}
\pastebutton{MenuexdiffEmpty7}{\showpaste}
\tab{5}\spadcommand{differentiate(cos(z)/(x**2 + y**3),[x,y,z],[1,2,3])}
\end{paste}\end{patch}

\begin{patch}{MenuexdiffPatch8}
\begin{paste}{MenuexdiffFull8}{MenuexdiffEmpty8}
\pastebutton{MenuexdiffFull8}{\hidepaste}
\tab{5}\spadcommand{f := integrate(sqrt(1 + t**3),t)\bound{f }}
\indentrel{3}\begin{verbatim}
           t  ÚÄÄÄÄÄÄÄ¿
         Ú¿   ³  3
   (8)   ³   \³%N  + 1 d%N
        ÀÙ
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexdiffEmpty8}
\begin{paste}{MenuexdiffEmpty8}{MenuexdiffPatch8}
\pastebutton{MenuexdiffEmpty8}{\showpaste}
\tab{5}\spadcommand{f := integrate(sqrt(1 + t**3),t)\bound{f }}
\end{paste}\end{patch}

\begin{patch}{MenuexdiffPatch9}
\begin{paste}{MenuexdiffFull9}{MenuexdiffEmpty9}
\pastebutton{MenuexdiffFull9}{\hidepaste}
\tab{5}\spadcommand{differentiate(f,t)\free{f }}
\indentrel{3}\begin{verbatim}
         ÚÄÄÄÄÄÄ¿
         ³ 3
   (9)  \³t  + 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexdiffEmpty9}
\begin{paste}{MenuexdiffEmpty9}{MenuexdiffPatch9}
\pastebutton{MenuexdiffEmpty9}{\showpaste}
\tab{5}\spadcommand{differentiate(f,t)\free{f }}
\end{paste}\end{patch}

\begin{patch}{MenuexdiffPatch10}
\begin{paste}{MenuexdiffFull10}{MenuexdiffEmpty10}
\pastebutton{MenuexdiffFull10}{\hidepaste}
\tab{5}\spadcommand{differentiate(f * t**2,t)\free{f }}
\indentrel{3}\begin{verbatim}
              t  ÚÄÄÄÄÄÄÄ¿          ÚÄÄÄÄÄÄ¿
            Ú¿   ³  3             2 ³ 3
   (10)  2t ³   \³%N  + 1 d%N  + t \³t  + 1
           ÀÙ
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexdiffEmpty10}
\begin{paste}{MenuexdiffEmpty10}{MenuexdiffPatch10}
\pastebutton{MenuexdiffEmpty10}{\showpaste}
\tab{5}\spadcommand{differentiate(f * t**2,t)\free{f }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{Menuexint}{coverex.ht}{Integration}
\pageto{Integral of a Rational Function}{ExIntRationalFunction}
\pageto{Integral of a Rational Function with a Real Parameter}
{ExIntRationalWithRealParameter}
\pageto{Integral of a Rational Function with a Complex Parameter}
{ExIntRationalWithComplexParameter}
\pageto{Two Similar Integrands Producing Very Different Results}
{ExIntTwoSimilarIntegrands}
\pageto{An Integral Which Does Not Exist}{ExIntNoSolution}
\pageto{A Trigonometric Function of a Quadratic}{ExIntTrig}
\pageto{Integrating a Function with a Hidden Algebraic Relation}
{ExIntAlgebraicRelation}
\pageto{Details for integrating a function with a Hidden Algebraic Relation}
{ExIntAlgebraicRelationExplain}
\pageto{An Integral Involving a Root of a Transcendental Function}
{ExIntRadicalOfTranscendental}
\pageto{An Integral of a Non-elementary Function}{ExIntNonElementary}
\begin{chunk}{coverex.ht}
\begin{page}{Menuexint}{Integration}
\beginscroll\beginmenu
\menudownlink{Integral of a Rational Function}{ExIntRationalFunction}
\spadpaste{integrate((x**2+2*x+1)/((x+1)**6+1),x)}
\spadpaste{integrate(1/(x**3+x+1),x) \bound{i}}
\spadpaste{definingPolynomial(tower(\%).2::EXPR INT) \free{i}}
\menudownlink{Integral of a Rational Function with a Real Parameter}
{ExIntRationalWithRealParameter}
\spadpaste{integrate(1/(x**2 + a),x)}
\menudownlink{Integral of a Rational Function with a Complex Parameter}
{ExIntRationalWithComplexParameter}
\spadpaste{complexIntegrate(1/(x**2 + a),x)}
\menudownlink{Two Similar Integrands Producing Very Different Results}
{ExIntTwoSimilarIntegrands}
\spadpaste{integrate(x**3 / (a+b*x)**(1/3),x)}
\spadpaste{integrate(1 / (x**3 * (a+b*x)**(1/3)),x)}
\menudownlink{An Integral Which Does Not Exist}{ExIntNoSolution}
\spadpaste{integrate(log(1 + sqrt(a*x + b)) / x,x)}
\menudownlink{A Trigonometric Function of a Quadratic}{ExIntTrig}
\spadpaste{integrate((sinh(1+sqrt(x+b))+2*sqrt(x+b))/
(sqrt(x+b)*(x+cosh(1+sqrt(x+b)))),x)}
\menudownlink{Integrating a Function with a Hidden Algebraic Relation}
{ExIntAlgebraicRelation}
\spadpaste{integrate(tan(atan(x)/3),x)}
\menudownlink
{Details for integrating a function with a Hidden Algebraic Relation}
{ExIntAlgebraicRelationExplain}
\menudownlink{An Integral Involving a Root of a Transcendental Function}
{ExIntRadicalOfTranscendental}
\spadpaste{integrate((x + 1) / (x * (x + log x)**(3/2)),x)}
\menudownlink{An Integral of a Non-elementary Function}{ExIntNonElementary}
\spadpaste{integrate(exp(-x**2) * erf(x) / 
(erf(x)**3 - erf(x)**2 - erf(x) + 1),x)}
\endmenu\endscroll
\end{page}

\begin{patch}{MenuexintPatch1}
\begin{paste}{MenuexintFull1}{MenuexintEmpty1}
\pastebutton{MenuexintFull1}{\hidepaste}
\tab{5}\spadcommand{integrate((x**2+2*x+1)/((x+1)**6+1),x)}
\indentrel{3}\begin{verbatim}
              3     2
        atan(x  + 3x  + 3x + 1)
   (1)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                   3
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexintEmpty1}
\begin{paste}{MenuexintEmpty1}{MenuexintPatch1}
\pastebutton{MenuexintEmpty1}{\showpaste}
\tab{5}\spadcommand{integrate((x**2+2*x+1)/((x+1)**6+1),x)}
\end{paste}\end{patch}

\begin{patch}{MenuexintPatch2}
\begin{paste}{MenuexintFull2}{MenuexintEmpty2}
\pastebutton{MenuexintFull2}{\hidepaste}
\tab{5}\spadcommand{integrate(1/(x**3+x+1),x)\bound{i }}
\indentrel{3}\begin{verbatim}
   (2)
           ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
           ³         2
           ³- 93%%CE0  + 12
         ( ³ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ  - %%CE0)
          \³       31
      *
         log
                             ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
                             ³         2
                             ³- 93%%CE0  + 12           2
              (62%%CE0 + 31) ³ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ  + 62%%CE0
                            \³       31
            + 
              - 31%%CE0 + 18x - 4
     + 
             ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
             ³         2
             ³- 93%%CE0  + 12
         (-  ³ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ  - %%CE0)
            \³       31
      *
         log
                               ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
                               ³         2
                               ³- 93%%CE0  + 12
              (- 62%%CE0 - 31) ³ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                              \³       31
            + 
                     2
              62%%CE0  - 31%%CE0 + 18x - 4
     + 
                           2
       2%%CE0 log(- 62%%CE0  + 31%%CE0 + 9x + 4)
  /
     2
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexintEmpty2}
\begin{paste}{MenuexintEmpty2}{MenuexintPatch2}
\pastebutton{MenuexintEmpty2}{\showpaste}
\tab{5}\spadcommand{integrate(1/(x**3+x+1),x)\bound{i }}
\end{paste}\end{patch}

\begin{patch}{MenuexintPatch3}
\begin{paste}{MenuexintFull3}{MenuexintEmpty3}
\pastebutton{MenuexintFull3}{\hidepaste}
\tab{5}\spadcommand{definingPolynomial(tower(\%).2::EXPR INT)\free{i }}
\indentrel{3}\begin{verbatim}
               3
        31%%CE0  - 3%%CE0 - 1
   (3)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                  31
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexintEmpty3}
\begin{paste}{MenuexintEmpty3}{MenuexintPatch3}
\pastebutton{MenuexintEmpty3}{\showpaste}
\tab{5}\spadcommand{definingPolynomial(tower(\%).2::EXPR INT)\free{i }}
\end{paste}\end{patch}

\begin{patch}{MenuexintPatch4}
\begin{paste}{MenuexintFull4}{MenuexintEmpty4}
\pastebutton{MenuexintFull4}{\hidepaste}
\tab{5}\spadcommand{integrate(1/(x**2 + a),x)}
\indentrel{3}\begin{verbatim}
               2      ÚÄÄÄ¿
             (x  - a)\³- a  + 2a x         ÚÄ¿
         log(ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ)      x\³a
                      2             atan(ÄÄÄÄÄ)
                     x  + a                a
   (4)  [ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ,ÄÄÄÄÄÄÄÄÄÄÄ]
                     ÚÄÄÄ¿               ÚÄ¿
                   2\³- a               \³a
               Type: Union(List Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexintEmpty4}
\begin{paste}{MenuexintEmpty4}{MenuexintPatch4}
\pastebutton{MenuexintEmpty4}{\showpaste}
\tab{5}\spadcommand{integrate(1/(x**2 + a),x)}
\end{paste}\end{patch}

\begin{patch}{MenuexintPatch5}
\begin{paste}{MenuexintFull5}{MenuexintEmpty5}
\pastebutton{MenuexintFull5}{\hidepaste}
\tab{5}\spadcommand{complexIntegrate(1/(x**2 + a),x)}
\indentrel{3}\begin{verbatim}
              ÚÄÄÄ¿              ÚÄÄÄ¿
            x\³- a  + a        x\³- a  - a
        log(ÄÄÄÄÄÄÄÄÄÄÄ) - log(ÄÄÄÄÄÄÄÄÄÄÄ)
                ÚÄÄÄ¿              ÚÄÄÄ¿
               \³- a              \³- a
   (5)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                        ÚÄÄÄ¿
                      2\³- a
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexintEmpty5}
\begin{paste}{MenuexintEmpty5}{MenuexintPatch5}
\pastebutton{MenuexintEmpty5}{\showpaste}
\tab{5}\spadcommand{complexIntegrate(1/(x**2 + a),x)}
\end{paste}\end{patch}

\begin{patch}{MenuexintPatch6}
\begin{paste}{MenuexintFull6}{MenuexintEmpty6}
\pastebutton{MenuexintFull6}{\hidepaste}
\tab{5}\spadcommand{integrate(x**3 / (a+b*x)**(1/3),x)}
\indentrel{3}\begin{verbatim}
   (6)
        3 3         2 2       2          3 3ÚÄÄÄÄÄÄÄ¿2
   (120b x  - 135a b x  + 162a b x - 243a )\³b x + a
   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                              4
                          440b
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexintEmpty6}
\begin{paste}{MenuexintEmpty6}{MenuexintPatch6}
\pastebutton{MenuexintEmpty6}{\showpaste}
\tab{5}\spadcommand{integrate(x**3 / (a+b*x)**(1/3),x)}
\end{paste}\end{patch}

\begin{patch}{MenuexintPatch7}
\begin{paste}{MenuexintFull7}{MenuexintEmpty7}
\pastebutton{MenuexintFull7}{\hidepaste}
\tab{5}\spadcommand{integrate(1 / (x**3 * (a+b*x)**(1/3)),x)}
\indentrel{3}\begin{verbatim}
   (7)
       -
              2 2 ÚÄ¿
            2b x \³3
         *
                3ÚÄ¿3ÚÄÄÄÄÄÄÄ¿2   3ÚÄ¿2 3ÚÄÄÄÄÄÄÄ¿
            log(\³a \³b x + a   + \³a   \³b x + a + a)
     + 
         2 2 ÚÄ¿    3ÚÄ¿2 3ÚÄÄÄÄÄÄÄ¿
       4b x \³3 log(\³a   \³b x + a - a)
     + 
                    ÚÄ¿3ÚÄ¿2 3ÚÄÄÄÄÄÄÄ¿    ÚÄ¿
          2 2     2\³3 \³a   \³b x + a + a\³3
       12b x atan(ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ)
                               3a
     + 
                    ÚÄ¿3ÚÄ¿3ÚÄÄÄÄÄÄÄ¿2
       (12b x - 9a)\³3 \³a \³b x + a
  /
        2 2 ÚÄ¿3ÚÄ¿
     18a x \³3 \³a
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexintEmpty7}
\begin{paste}{MenuexintEmpty7}{MenuexintPatch7}
\pastebutton{MenuexintEmpty7}{\showpaste}
\tab{5}\spadcommand{integrate(1 / (x**3 * (a+b*x)**(1/3)),x)}
\end{paste}\end{patch}

\begin{patch}{MenuexintPatch8}
\begin{paste}{MenuexintFull8}{MenuexintEmpty8}
\pastebutton{MenuexintFull8}{\hidepaste}
\tab{5}\spadcommand{integrate(log(1 + sqrt(a*x + b)) / x,x)}
\indentrel{3}\begin{verbatim}
           x      ÚÄÄÄÄÄÄÄÄ¿
         Ú¿  log(\³b + %N a  + 1)
   (8)   ³   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ d%N
        ÀÙ            %N
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexintEmpty8}
\begin{paste}{MenuexintEmpty8}{MenuexintPatch8}
\pastebutton{MenuexintEmpty8}{\showpaste}
\tab{5}\spadcommand{integrate(log(1 + sqrt(a*x + b)) / x,x)}
\end{paste}\end{patch}

\begin{patch}{MenuexintPatch9}
\begin{paste}{MenuexintFull9}{MenuexintEmpty9}
\pastebutton{MenuexintFull9}{\hidepaste}
\tab{5}\spadcommand{
integrate((sinh(1+sqrt(x+b))+2*sqrt(x+b))/_
          (sqrt(x+b)*(x+cosh(1+sqrt(x+b)))),x)}
\indentrel{3}\begin{verbatim}
   (9)
                          ÚÄÄÄÄÄ¿
                 - 2cosh(\³x + b  + 1) - 2x
     2log(ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ)
                ÚÄÄÄÄÄ¿              ÚÄÄÄÄÄ¿
          sinh(\³x + b  + 1) - cosh(\³x + b  + 1)
   + 
         ÚÄÄÄÄÄ¿
     - 2\³x + b
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexintEmpty9}
\begin{paste}{MenuexintEmpty9}{MenuexintPatch9}
\pastebutton{MenuexintEmpty9}{\showpaste}
\tab{5}\spadcommand{
integrate((sinh(1+sqrt(x+b))+2*sqrt(x+b))/_
          (sqrt(x+b)*(x+cosh(1+sqrt(x+b)))),x)}
\end{paste}\end{patch}

\begin{patch}{MenuexintPatch10}
\begin{paste}{MenuexintFull10}{MenuexintEmpty10}
\pastebutton{MenuexintFull10}{\hidepaste}
\tab{5}\spadcommand{integrate(tan(atan(x)/3),x)}
\indentrel{3}\begin{verbatim}
   (10)
                 atan(x) 2             atan(x) 2
       8log(3tan(ÄÄÄÄÄÄÄ)  - 1) - 3tan(ÄÄÄÄÄÄÄ)
                    3                     3
     + 
               atan(x)
       18x tan(ÄÄÄÄÄÄÄ)
                  3
  /
     18
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexintEmpty10}
\begin{paste}{MenuexintEmpty10}{MenuexintPatch10}
\pastebutton{MenuexintEmpty10}{\showpaste}
\tab{5}\spadcommand{integrate(tan(atan(x)/3),x)}
\end{paste}\end{patch}

\begin{patch}{MenuexintPatch11}
\begin{paste}{MenuexintFull11}{MenuexintEmpty11}
\pastebutton{MenuexintFull11}{\hidepaste}
\tab{5}\spadcommand{integrate((x + 1) / (x * (x + log x)**(3/2)),x)}
\indentrel{3}\begin{verbatim}
             ÚÄÄÄÄÄÄÄÄÄÄ¿
           2\³log(x) + x
   (11)  - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
             log(x) + x
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexintEmpty11}
\begin{paste}{MenuexintEmpty11}{MenuexintPatch11}
\pastebutton{MenuexintEmpty11}{\showpaste}
\tab{5}\spadcommand{integrate((x + 1) / (x * (x + log x)**(3/2)),x)}
\end{paste}\end{patch}

\begin{patch}{MenuexintPatch12}
\begin{paste}{MenuexintFull12}{MenuexintEmpty12}
\pastebutton{MenuexintFull12}{\hidepaste}
\tab{5}\spadcommand{integrate(exp(-x**2) * erf(x) / (erf(x)**3 - erf(x)**2 - erf(x) + 1),x)}
\indentrel{3}\begin{verbatim}
                      ÚÄÄÄ¿    erf(x) - 1      ÚÄÄÄ¿
         (erf(x) - 1)\³%pi log(ÄÄÄÄÄÄÄÄÄÄ) - 2\³%pi
                               erf(x) + 1
   (12)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                         8erf(x) - 8
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexintEmpty12}
\begin{paste}{MenuexintEmpty12}{MenuexintPatch12}
\pastebutton{MenuexintEmpty12}{\showpaste}
\tab{5}\spadcommand{integrate(exp(-x**2) * erf(x) /
 (erf(x)**3 - erf(x)**2 - erf(x) + 1),x)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{Menuexlap}{coverex.ht}{Laplace Transforms}
\pageto{Laplace transform with a single pole}{ExLapSimplePole}
\pageto{Laplace transform of a trigonometric function}
{ExLapTrigTrigh}
\pageto{Laplace transform requiring a definite integration}
{ExLapDefInt}
\pageto{Laplace transform of exponentials}{ExLapExpExp}
\pageto{Laplace transform of an exponential integral}{ExLapSpecial1}
\pageto{Laplace transform of special functions}{ExLapSpecial2}
\begin{chunk}{coverex.ht}
\begin{page}{Menuexlap}{Laplace Transforms}
\beginscroll\beginmenu
\menudownlink
\spadpaste{laplace(t**4 * exp(-a*t) / factorial(4), t, s)}
\menudownlink{Laplace transform of a trigonometric function}
{ExLapTrigTrigh}
\spadpaste{laplace(sin(a*t) * cosh(a*t) - cos(a*t) * sinh(a*t), t, s)}
\menudownlink{Laplace transform requiring a definite integration}
{ExLapDefInt}
\spadpaste{laplace(2/t * (1 - cos(a*t)), t, s)}
\menudownlink{Laplace transform of exponentials}{ExLapExpExp}
\spadpaste{laplace((exp(a*t) - exp(b*t))/t, t, s)}
\menudownlink{Laplace transform of an exponential integral}{ExLapSpecial1}
\spadpaste{laplace(exp(a*t+b)*Ei(c*t), t, s)}
\menudownlink{Laplace transform of special functions}{ExLapSpecial2}
\spadpaste{laplace(a*Ci(b*t) + c*Si(d*t), t, s)}
\endmenu\endscroll
\end{page}

\begin{patch}{MenuexlapPatch1}
\begin{paste}{MenuexlapFull1}{MenuexlapEmpty1}
\pastebutton{MenuexlapFull1}{\hidepaste}
\tab{5}\spadcommand{laplace(t**4 * exp(-a*t) / factorial(4), t, s)}
\indentrel{3}\begin{verbatim}
                            1
   (1)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
         5       4      2 3      3 2     4     5
        s  + 5a s  + 10a s  + 10a s  + 5a s + a
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexlapEmpty1}
\begin{paste}{MenuexlapEmpty1}{MenuexlapPatch1}
\pastebutton{MenuexlapEmpty1}{\showpaste}
\tab{5}\spadcommand{laplace(t**4 * exp(-a*t) / factorial(4), t, s)}
\end{paste}\end{patch}

\begin{patch}{MenuexlapPatch2}
\begin{paste}{MenuexlapFull2}{MenuexlapEmpty2}
\pastebutton{MenuexlapFull2}{\hidepaste}
\tab{5}\spadcommand{laplace(sin(a*t) * cosh(a*t) - cos(a*t) * sinh(a*t), t, s)}
\indentrel{3}\begin{verbatim}
             3
           4a
   (2)  ÄÄÄÄÄÄÄÄ
         4     4
        s  + 4a
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexlapEmpty2}
\begin{paste}{MenuexlapEmpty2}{MenuexlapPatch2}
\pastebutton{MenuexlapEmpty2}{\showpaste}
\tab{5}\spadcommand{laplace(sin(a*t) * cosh(a*t) - cos(a*t) * sinh(a*t), t, s)}
\end{paste}\end{patch}

\begin{patch}{MenuexlapPatch3}
\begin{paste}{MenuexlapFull3}{MenuexlapEmpty3}
\pastebutton{MenuexlapFull3}{\hidepaste}
\tab{5}\spadcommand{laplace(2/t * (1 - cos(a*t)), t, s)}
\indentrel{3}\begin{verbatim}
             2    2
   (3)  log(s  + a ) - 2log(s)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexlapEmpty3}
\begin{paste}{MenuexlapEmpty3}{MenuexlapPatch3}
\pastebutton{MenuexlapEmpty3}{\showpaste}
\tab{5}\spadcommand{laplace(2/t * (1 - cos(a*t)), t, s)}
\end{paste}\end{patch}

\begin{patch}{MenuexlapPatch4}
\begin{paste}{MenuexlapFull4}{MenuexlapEmpty4}
\pastebutton{MenuexlapFull4}{\hidepaste}
\tab{5}\spadcommand{laplace((exp(a*t) - exp(b*t))/t, t, s)}
\indentrel{3}\begin{verbatim}
   (4)  - log(s - a) + log(s - b)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexlapEmpty4}
\begin{paste}{MenuexlapEmpty4}{MenuexlapPatch4}
\pastebutton{MenuexlapEmpty4}{\showpaste}
\tab{5}\spadcommand{laplace((exp(a*t) - exp(b*t))/t, t, s)}
\end{paste}\end{patch}

\begin{patch}{MenuexlapPatch5}
\begin{paste}{MenuexlapFull5}{MenuexlapEmpty5}
\pastebutton{MenuexlapFull5}{\hidepaste}
\tab{5}\spadcommand{laplace(exp(a*t+b)*Ei(c*t), t, s)}
\indentrel{3}\begin{verbatim}
          b    s + c - a
        %e log(ÄÄÄÄÄÄÄÄÄ)
                   c
   (5)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
              s - a
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexlapEmpty5}
\begin{paste}{MenuexlapEmpty5}{MenuexlapPatch5}
\pastebutton{MenuexlapEmpty5}{\showpaste}
\tab{5}\spadcommand{laplace(exp(a*t+b)*Ei(c*t), t, s)}
\end{paste}\end{patch}

\begin{patch}{MenuexlapPatch6}
\begin{paste}{MenuexlapFull6}{MenuexlapEmpty6}
\pastebutton{MenuexlapFull6}{\hidepaste}
\tab{5}\spadcommand{laplace(a*Ci(b*t) + c*Si(d*t), t, s)}
\indentrel{3}\begin{verbatim}
               2    2
              s  + b             d
        a log(ÄÄÄÄÄÄÄ) + 2c atan(Ä)
                  2              s
                 b
   (6)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                     2s
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexlapEmpty6}
\begin{paste}{MenuexlapEmpty6}{MenuexlapPatch6}
\pastebutton{MenuexlapEmpty6}{\showpaste}
\tab{5}\spadcommand{laplace(a*Ci(b*t) + c*Si(d*t), t, s)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{Menuexlimit}{coverex.ht}{Limits}
\pageto{Computing Limits}{ExLimitBasic}
\pageto{Limits of Functions with Parameters}{ExLimitParameter}
\pageto{One-sided Limits}{ExLimitOneSided}
\pageto{Two-sided Limits}{ExLimitTwoSided}
\pageto{Limits at Infinity}{ExLimitInfinite}
\pageto{Real Limits vs. Complex Limits}{ExLimitRealComplex}
\pageto{Complex Limits at Infinity}{ExLimitComplexInfinite}
\begin{chunk}{coverex.ht}
\begin{page}{Menuexlimit}{Limits}
\beginscroll\beginmenu
\menudownlink{Computing Limits}{ExLimitBasic}
\spadpaste{limit((x**2 - 3*x + 2)/(x**2 - 1),x = 1)}
\menudownlink{Limits of Functions with Parameters}{ExLimitParameter}
\spadpaste{limit(sinh(a*x)/tan(b*x),x = 0)}
\menudownlink{One-sided Limits}{ExLimitOneSided}
\spadpaste{limit(x * log(x),x = 0,"right")}
\spadpaste{limit(x * log(x),x = 0)}
\menudownlink{Two-sided Limits}{ExLimitTwoSided}
\spadpaste{limit(sqrt(y**2)/y,y = 0)}
\spadpaste{limit(sqrt(1 - cos(t))/t,t = 0)}
\menudownlink{Limits at Infinity}{ExLimitInfinite}
\spadpaste{limit(sqrt(3*x**2 + 1)/(5*x),x = \%plusInfinity)}
\spadpaste{limit(sqrt(3*x**2 + 1)/(5*x),x = \%minusInfinity)}
\menudownlink{Real Limits vs. Complex Limits}{ExLimitRealComplex}
\spadpaste{limit(z * sin(1/z),z = 0)}
\spadpaste{complexLimit(z * sin(1/z),z = 0)}
\menudownlink{Complex Limits at Infinity}{ExLimitComplexInfinite}
\spadpaste{complexLimit((2 + z)/(1 - z),z = \%infinity)}
\spadpaste{limit(sin(x)/x,x = \%plusInfinity)}
\spadpaste{complexLimit(sin(x)/x,x = \%infinity)}
\endmenu\endscroll
\end{page}

\begin{patch}{MenuexlimitPatch1}
\begin{paste}{MenuexlimitFull1}{MenuexlimitEmpty1}
\pastebutton{MenuexlimitFull1}{\hidepaste}
\tab{5}\spadcommand{limit((x**2 - 3*x + 2)/(x**2 - 1),x = 1)}
\indentrel{3}\begin{verbatim}
          1
   (1)  - Ä
          2
Type: Union(OrderedCompletion Fraction Polynomial Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexlimitEmpty1}
\begin{paste}{MenuexlimitEmpty1}{MenuexlimitPatch1}
\pastebutton{MenuexlimitEmpty1}{\showpaste}
\tab{5}\spadcommand{limit((x**2 - 3*x + 2)/(x**2 - 1),x = 1)}
\end{paste}\end{patch}

\begin{patch}{MenuexlimitPatch2}
\begin{paste}{MenuexlimitFull2}{MenuexlimitEmpty2}
\pastebutton{MenuexlimitFull2}{\hidepaste}
\tab{5}\spadcommand{limit(sinh(a*x)/tan(b*x),x = 0)}
\indentrel{3}\begin{verbatim}
        a
   (2)  Ä
        b
  Type: Union(OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexlimitEmpty2}
\begin{paste}{MenuexlimitEmpty2}{MenuexlimitPatch2}
\pastebutton{MenuexlimitEmpty2}{\showpaste}
\tab{5}\spadcommand{limit(sinh(a*x)/tan(b*x),x = 0)}
\end{paste}\end{patch}

\begin{patch}{MenuexlimitPatch3}
\begin{paste}{MenuexlimitFull3}{MenuexlimitEmpty3}
\pastebutton{MenuexlimitFull3}{\hidepaste}
\tab{5}\spadcommand{limit(x * log(x),x = 0,"right")}
\indentrel{3}\begin{verbatim}
   (3)  0
  Type: Union(OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexlimitEmpty3}
\begin{paste}{MenuexlimitEmpty3}{MenuexlimitPatch3}
\pastebutton{MenuexlimitEmpty3}{\showpaste}
\tab{5}\spadcommand{limit(x * log(x),x = 0,"right")}
\end{paste}\end{patch}

\begin{patch}{MenuexlimitPatch4}
\begin{paste}{MenuexlimitFull4}{MenuexlimitEmpty4}
\pastebutton{MenuexlimitFull4}{\hidepaste}
\tab{5}\spadcommand{limit(x * log(x),x = 0)}
\indentrel{3}\begin{verbatim}
   (4)  [leftHandLimit= "failed",rightHandLimit= 0]
Type: Union(Record(leftHandLimit: Union(OrderedCompletion Expression Integer,"failed"),rightHandLimit: Union(OrderedCompletion Expression Integer,"failed")),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexlimitEmpty4}
\begin{paste}{MenuexlimitEmpty4}{MenuexlimitPatch4}
\pastebutton{MenuexlimitEmpty4}{\showpaste}
\tab{5}\spadcommand{limit(x * log(x),x = 0)}
\end{paste}\end{patch}

\begin{patch}{MenuexlimitPatch5}
\begin{paste}{MenuexlimitFull5}{MenuexlimitEmpty5}
\pastebutton{MenuexlimitFull5}{\hidepaste}
\tab{5}\spadcommand{limit(sqrt(y**2)/y,y = 0)}
\indentrel{3}\begin{verbatim}
   (5)  [leftHandLimit= - 1,rightHandLimit= 1]
Type: Union(Record(leftHandLimit: Union(OrderedCompletion Expression Integer,"failed"),rightHandLimit: Union(OrderedCompletion Expression Integer,"failed")),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexlimitEmpty5}
\begin{paste}{MenuexlimitEmpty5}{MenuexlimitPatch5}
\pastebutton{MenuexlimitEmpty5}{\showpaste}
\tab{5}\spadcommand{limit(sqrt(y**2)/y,y = 0)}
\end{paste}\end{patch}

\begin{patch}{MenuexlimitPatch6}
\begin{paste}{MenuexlimitFull6}{MenuexlimitEmpty6}
\pastebutton{MenuexlimitFull6}{\hidepaste}
\tab{5}\spadcommand{limit(sqrt(1 - cos(t))/t,t = 0)}
\indentrel{3}\begin{verbatim}
                            1                    1
   (6)  [leftHandLimit= - ÄÄÄÄ,rightHandLimit= ÄÄÄÄ]
                           ÚÄ¿                  ÚÄ¿
                          \³2                  \³2
Type: Union(Record(leftHandLimit: Union(OrderedCompletion Expression Integer,"failed"),rightHandLimit: Union(OrderedCompletion Expression Integer,"failed")),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexlimitEmpty6}
\begin{paste}{MenuexlimitEmpty6}{MenuexlimitPatch6}
\pastebutton{MenuexlimitEmpty6}{\showpaste}
\tab{5}\spadcommand{limit(sqrt(1 - cos(t))/t,t = 0)}
\end{paste}\end{patch}

\begin{patch}{MenuexlimitPatch7}
\begin{paste}{MenuexlimitFull7}{MenuexlimitEmpty7}
\pastebutton{MenuexlimitFull7}{\hidepaste}
\tab{5}\spadcommand{limit(sqrt(3*x**2 + 1)/(5*x),x = \%plusInfinity)}
\indentrel{3}\begin{verbatim}
         ÚÄ¿
        \³3
   (7)  ÄÄÄÄ
          5
  Type: Union(OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexlimitEmpty7}
\begin{paste}{MenuexlimitEmpty7}{MenuexlimitPatch7}
\pastebutton{MenuexlimitEmpty7}{\showpaste}
\tab{5}\spadcommand{limit(sqrt(3*x**2 + 1)/(5*x),x = \%plusInfinity)}
\end{paste}\end{patch}

\begin{patch}{MenuexlimitPatch8}
\begin{paste}{MenuexlimitFull8}{MenuexlimitEmpty8}
\pastebutton{MenuexlimitFull8}{\hidepaste}
\tab{5}\spadcommand{limit(sqrt(3*x**2 + 1)/(5*x),x = \%minusInfinity)}
\indentrel{3}\begin{verbatim}
           ÚÄ¿
          \³3
   (8)  - ÄÄÄÄ
            5
  Type: Union(OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexlimitEmpty8}
\begin{paste}{MenuexlimitEmpty8}{MenuexlimitPatch8}
\pastebutton{MenuexlimitEmpty8}{\showpaste}
\tab{5}\spadcommand{limit(sqrt(3*x**2 + 1)/(5*x),x = \%minusInfinity)}
\end{paste}\end{patch}

\begin{patch}{MenuexlimitPatch9}
\begin{paste}{MenuexlimitFull9}{MenuexlimitEmpty9}
\pastebutton{MenuexlimitFull9}{\hidepaste}
\tab{5}\spadcommand{limit(z * sin(1/z),z = 0)}
\indentrel{3}\begin{verbatim}
   (9)  0
  Type: Union(OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexlimitEmpty9}
\begin{paste}{MenuexlimitEmpty9}{MenuexlimitPatch9}
\pastebutton{MenuexlimitEmpty9}{\showpaste}
\tab{5}\spadcommand{limit(z * sin(1/z),z = 0)}
\end{paste}\end{patch}

\begin{patch}{MenuexlimitPatch10}
\begin{paste}{MenuexlimitFull10}{MenuexlimitEmpty10}
\pastebutton{MenuexlimitFull10}{\hidepaste}
\tab{5}\spadcommand{complexLimit(z * sin(1/z),z = 0)}
\indentrel{3}\begin{verbatim}
   (10)  "failed"
                              Type: Union("failed",...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexlimitEmpty10}
\begin{paste}{MenuexlimitEmpty10}{MenuexlimitPatch10}
\pastebutton{MenuexlimitEmpty10}{\showpaste}
\tab{5}\spadcommand{complexLimit(z * sin(1/z),z = 0)}
\end{paste}\end{patch}

\begin{patch}{MenuexlimitPatch11}
\begin{paste}{MenuexlimitFull11}{MenuexlimitEmpty11}
\pastebutton{MenuexlimitFull11}{\hidepaste}
\tab{5}\spadcommand{complexLimit((2 + z)/(1 - z),z = \%infinity)}
\indentrel{3}\begin{verbatim}
   (11)  - 1
   Type: OnePointCompletion Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexlimitEmpty11}
\begin{paste}{MenuexlimitEmpty11}{MenuexlimitPatch11}
\pastebutton{MenuexlimitEmpty11}{\showpaste}
\tab{5}\spadcommand{complexLimit((2 + z)/(1 - z),z = \%infinity)}
\end{paste}\end{patch}

\begin{patch}{MenuexlimitPatch12}
\begin{paste}{MenuexlimitFull12}{MenuexlimitEmpty12}
\pastebutton{MenuexlimitFull12}{\hidepaste}
\tab{5}\spadcommand{limit(sin(x)/x,x = \%plusInfinity)}
\indentrel{3}\begin{verbatim}
   (12)  0
  Type: Union(OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexlimitEmpty12}
\begin{paste}{MenuexlimitEmpty12}{MenuexlimitPatch12}
\pastebutton{MenuexlimitEmpty12}{\showpaste}
\tab{5}\spadcommand{limit(sin(x)/x,x = \%plusInfinity)}
\end{paste}\end{patch}

\begin{patch}{MenuexlimitPatch13}
\begin{paste}{MenuexlimitFull13}{MenuexlimitEmpty13}
\pastebutton{MenuexlimitFull13}{\hidepaste}
\tab{5}\spadcommand{complexLimit(sin(x)/x,x = \%infinity)}
\indentrel{3}\begin{verbatim}
   (13)  "failed"
                              Type: Union("failed",...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexlimitEmpty13}
\begin{paste}{MenuexlimitEmpty13}{MenuexlimitPatch13}
\pastebutton{MenuexlimitEmpty13}{\showpaste}
\tab{5}\spadcommand{complexLimit(sin(x)/x,x = \%infinity)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{Menuexmatrix}{coverex.ht}{Matrices}
\pageto{Basic Arithmetic Operations on Matrices}
{ExMatrixBasicFunction}
\pageto{Constructing new Matrices}{ExConstructMatrix}
\pageto{Trace of a Matrix}{ExTraceMatrix}
\pageto{Determinant of a Matrix}{ExDeterminantMatrix}
\pageto{Inverse of a Matrix}{ExInverseMatrix}
\pageto{Rank of a Matrix}{ExRankMatrix}
\begin{chunk}{coverex.ht}
\begin{page}{Menuexmatrix}{Matrices}
\beginscroll\beginmenu
\menudownlink{Basic Arithmetic Operations on Matrices}
{ExMatrixBasicFunction}
\spadpaste{m1 := matrix([[1,-2,1],[4,2,-4]]) \bound{m1}}
\spadpaste{m2 := matrix([[1,0,2],[20,30,10],[0,200,100]]) \bound{m2}}
\spadpaste{m3 := matrix([[1,2,3],[2,4,6]]) \bound{m3}}
\spadpaste{m1 + m3 \free{m1} \free{m3}}
\spadpaste{100 * m1 \free{m1}}
\spadpaste{m1 * m2 \free{m1} \free{m2}}
\spadpaste{-m1 + m3 * m2 \free{m1} \free{m2} \free{m3}}
\spadpaste{m3 *vector([1,0,1]) \free{m3}}
\menudownlink{Constructing new Matrices}{ExConstructMatrix}
\spadpaste{diagonalMatrix([1,2,3,2,1])}
\spadpaste{subMatrix(matrix([[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14]]), 
1,3,2,4)}
\spadpaste{horizConcat(matrix([[1,2,3],[6,7,8]]),
matrix([[11,12,13],[55,77,88]])) }
\spadpaste{vertConcat(matrix([[1,2,3],[6,7,8]]),
matrix([[11,12,13],[55,77,88]])) }
\spadpaste{b:=matrix([[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14]]) \bound{b}}
\spadpaste{setsubMatrix!(b,1,1,transpose(subMatrix(b,1,3,1,3)))\free{b}}
\menudownlink{Trace of a Matrix}{ExTraceMatrix}
\spadpaste{trace( 
matrix([[1,x,x**2,x**3],[1,y,y**2,y**3],
[1,z,z**2,z**3],[1,u,u**2,u**3]]) )}
\menudownlink{Determinant of a Matrix}{ExDeterminantMatrix}
\spadpaste{
determinant(matrix([[1,2,3,4],[2,3,2,5],[3,4,5,6],[4,1,6,7]]))}
\menudownlink{Inverse of a Matrix}{ExInverseMatrix}
\spadpaste{inverse(matrix([[1,2,1],[-2,3,4],[-1,5,6]])) }
\menudownlink{Rank of a Matrix}{ExRankMatrix}
\spadpaste{rank(matrix([[0,4,1],[5,3,-7],[-5,5,9]]))}
\endmenu\endscroll
\end{page}

\begin{patch}{MenuexmatrixPatch1}
\begin{paste}{MenuexmatrixFull1}{MenuexmatrixEmpty1}
\pastebutton{MenuexmatrixFull1}{\hidepaste}
\tab{5}\spadcommand{m1 := matrix([[1,-2,1],[4,2,-4]])\bound{m1 }}
\indentrel{3}\begin{verbatim}
        Ú1  - 2   1 ¿
   (1)  ³           ³
        À4   2   - 4Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexmatrixEmpty1}
\begin{paste}{MenuexmatrixEmpty1}{MenuexmatrixPatch1}
\pastebutton{MenuexmatrixEmpty1}{\showpaste}
\tab{5}\spadcommand{m1 := matrix([[1,-2,1],[4,2,-4]])\bound{m1 }}
\end{paste}\end{patch}

\begin{patch}{MenuexmatrixPatch2}
\begin{paste}{MenuexmatrixFull2}{MenuexmatrixEmpty2}
\pastebutton{MenuexmatrixFull2}{\hidepaste}
\tab{5}\spadcommand{m2 := matrix([[1,0,2],[20,30,10],[0,200,100]])\bound{m2 }}
\indentrel{3}\begin{verbatim}
        Ú1    0    2 ¿
        ³            ³
   (2)  ³20  30   10 ³
        ³            ³
        À0   200  100Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexmatrixEmpty2}
\begin{paste}{MenuexmatrixEmpty2}{MenuexmatrixPatch2}
\pastebutton{MenuexmatrixEmpty2}{\showpaste}
\tab{5}\spadcommand{m2 := matrix([[1,0,2],[20,30,10],[0,200,100]])\bound{m2 }}
\end{paste}\end{patch}

\begin{patch}{MenuexmatrixPatch3}
\begin{paste}{MenuexmatrixFull3}{MenuexmatrixEmpty3}
\pastebutton{MenuexmatrixFull3}{\hidepaste}
\tab{5}\spadcommand{m3 := matrix([[1,2,3],[2,4,6]])\bound{m3 }}
\indentrel{3}\begin{verbatim}
        Ú1  2  3¿
   (3)  ³       ³
        À2  4  6Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexmatrixEmpty3}
\begin{paste}{MenuexmatrixEmpty3}{MenuexmatrixPatch3}
\pastebutton{MenuexmatrixEmpty3}{\showpaste}
\tab{5}\spadcommand{m3 := matrix([[1,2,3],[2,4,6]])\bound{m3 }}
\end{paste}\end{patch}

\begin{patch}{MenuexmatrixPatch4}
\begin{paste}{MenuexmatrixFull4}{MenuexmatrixEmpty4}
\pastebutton{MenuexmatrixFull4}{\hidepaste}
\tab{5}\spadcommand{m1 + m3\free{m1 }\free{m3 }}
\indentrel{3}\begin{verbatim}
        Ú2  0  4¿
   (4)  ³       ³
        À6  6  2Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexmatrixEmpty4}
\begin{paste}{MenuexmatrixEmpty4}{MenuexmatrixPatch4}
\pastebutton{MenuexmatrixEmpty4}{\showpaste}
\tab{5}\spadcommand{m1 + m3\free{m1 }\free{m3 }}
\end{paste}\end{patch}

\begin{patch}{MenuexmatrixPatch5}
\begin{paste}{MenuexmatrixFull5}{MenuexmatrixEmpty5}
\pastebutton{MenuexmatrixFull5}{\hidepaste}
\tab{5}\spadcommand{100 * m1\free{m1 }}
\indentrel{3}\begin{verbatim}
        Ú100  - 200   100 ¿
   (5)  ³                 ³
        À400   200   - 400Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexmatrixEmpty5}
\begin{paste}{MenuexmatrixEmpty5}{MenuexmatrixPatch5}
\pastebutton{MenuexmatrixEmpty5}{\showpaste}
\tab{5}\spadcommand{100 * m1\free{m1 }}
\end{paste}\end{patch}

\begin{patch}{MenuexmatrixPatch6}
\begin{paste}{MenuexmatrixFull6}{MenuexmatrixEmpty6}
\pastebutton{MenuexmatrixFull6}{\hidepaste}
\tab{5}\spadcommand{m1 * m2\free{m1 }\free{m2 }}
\indentrel{3}\begin{verbatim}
        Ú- 39   140    82  ¿
   (6)  ³                  ³
        À 44   - 740  - 372Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexmatrixEmpty6}
\begin{paste}{MenuexmatrixEmpty6}{MenuexmatrixPatch6}
\pastebutton{MenuexmatrixEmpty6}{\showpaste}
\tab{5}\spadcommand{m1 * m2\free{m1 }\free{m2 }}
\end{paste}\end{patch}

\begin{patch}{MenuexmatrixPatch7}
\begin{paste}{MenuexmatrixFull7}{MenuexmatrixEmpty7}
\pastebutton{MenuexmatrixFull7}{\hidepaste}
\tab{5}\spadcommand{-m1 + m3 * m2\free{m1 }\free{m2 }\free{m3 }}
\indentrel{3}\begin{verbatim}
        Ú40  662   321¿
   (7)  ³             ³
        À78  1318  648Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexmatrixEmpty7}
\begin{paste}{MenuexmatrixEmpty7}{MenuexmatrixPatch7}
\pastebutton{MenuexmatrixEmpty7}{\showpaste}
\tab{5}\spadcommand{-m1 + m3 * m2\free{m1 }\free{m2 }\free{m3 }}
\end{paste}\end{patch}

\begin{patch}{MenuexmatrixPatch8}
\begin{paste}{MenuexmatrixFull8}{MenuexmatrixEmpty8}
\pastebutton{MenuexmatrixFull8}{\hidepaste}
\tab{5}\spadcommand{m3 *vector([1,0,1])\free{m3 }}
\indentrel{3}\begin{verbatim}
   (8)  [4,8]
                                   Type: Vector Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexmatrixEmpty8}
\begin{paste}{MenuexmatrixEmpty8}{MenuexmatrixPatch8}
\pastebutton{MenuexmatrixEmpty8}{\showpaste}
\tab{5}\spadcommand{m3 *vector([1,0,1])\free{m3 }}
\end{paste}\end{patch}

\begin{patch}{MenuexmatrixPatch9}
\begin{paste}{MenuexmatrixFull9}{MenuexmatrixEmpty9}
\pastebutton{MenuexmatrixFull9}{\hidepaste}
\tab{5}\spadcommand{diagonalMatrix([1,2,3,2,1])}
\indentrel{3}\begin{verbatim}
        Ú1  0  0  0  0¿
        ³             ³
        ³0  2  0  0  0³
        ³             ³
   (9)  ³0  0  3  0  0³
        ³             ³
        ³0  0  0  2  0³
        ³             ³
        À0  0  0  0  1Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexmatrixEmpty9}
\begin{paste}{MenuexmatrixEmpty9}{MenuexmatrixPatch9}
\pastebutton{MenuexmatrixEmpty9}{\showpaste}
\tab{5}\spadcommand{diagonalMatrix([1,2,3,2,1])}
\end{paste}\end{patch}

\begin{patch}{MenuexmatrixPatch10}
\begin{paste}{MenuexmatrixFull10}{MenuexmatrixEmpty10}
\pastebutton{MenuexmatrixFull10}{\hidepaste}
\tab{5}\spadcommand{subMatrix(matrix([[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14]]), 1,3,2,4)}
\indentrel{3}\begin{verbatim}
         Ú1   2   3 ¿
         ³          ³
   (10)  ³6   7   8 ³
         ³          ³
         À11  12  13Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexmatrixEmpty10}
\begin{paste}{MenuexmatrixEmpty10}{MenuexmatrixPatch10}
\pastebutton{MenuexmatrixEmpty10}{\showpaste}
\tab{5}\spadcommand{subMatrix(matrix([[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14]]), 1,3,2,4)}
\end{paste}\end{patch}

\begin{patch}{MenuexmatrixPatch11}
\begin{paste}{MenuexmatrixFull11}{MenuexmatrixEmpty11}
\pastebutton{MenuexmatrixFull11}{\hidepaste}
\tab{5}\spadcommand{horizConcat(matrix([[1,2,3],[6,7,8]]),matrix([[11,12,13],[55,77,88]]))}
\indentrel{3}\begin{verbatim}
         Ú1  2  3  11  12  13¿
   (11)  ³                   ³
         À6  7  8  55  77  88Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexmatrixEmpty11}
\begin{paste}{MenuexmatrixEmpty11}{MenuexmatrixPatch11}
\pastebutton{MenuexmatrixEmpty11}{\showpaste}
\tab{5}\spadcommand{horizConcat(matrix([[1,2,3],[6,7,8]]),matrix([[11,12,13],[55,77,88]]))}
\end{paste}\end{patch}

\begin{patch}{MenuexmatrixPatch12}
\begin{paste}{MenuexmatrixFull12}{MenuexmatrixEmpty12}
\pastebutton{MenuexmatrixFull12}{\hidepaste}
\tab{5}\spadcommand{vertConcat(matrix([[1,2,3],[6,7,8]]),matrix([[11,12,13],[55,77,88]]))}
\indentrel{3}\begin{verbatim}
         Ú1   2   3 ¿
         ³          ³
         ³6   7   8 ³
   (12)  ³          ³
         ³11  12  13³
         ³          ³
         À55  77  88Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexmatrixEmpty12}
\begin{paste}{MenuexmatrixEmpty12}{MenuexmatrixPatch12}
\pastebutton{MenuexmatrixEmpty12}{\showpaste}
\tab{5}\spadcommand{vertConcat(matrix([[1,2,3],[6,7,8]]),matrix([[11,12,13],[55,77,88]]))}
\end{paste}\end{patch}

\begin{patch}{MenuexmatrixPatch13}
\begin{paste}{MenuexmatrixFull13}{MenuexmatrixEmpty13}
\pastebutton{MenuexmatrixFull13}{\hidepaste}
\tab{5}\spadcommand{b:=matrix([[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14]])\bound{b }}
\indentrel{3}\begin{verbatim}
         Ú0   1   2   3   4 ¿
         ³                  ³
   (13)  ³5   6   7   8   9 ³
         ³                  ³
         À10  11  12  13  14Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexmatrixEmpty13}
\begin{paste}{MenuexmatrixEmpty13}{MenuexmatrixPatch13}
\pastebutton{MenuexmatrixEmpty13}{\showpaste}
\tab{5}\spadcommand{b:=matrix([[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14]])\bound{b }}
\end{paste}\end{patch}

\begin{patch}{MenuexmatrixPatch14}
\begin{paste}{MenuexmatrixFull14}{MenuexmatrixEmpty14}
\pastebutton{MenuexmatrixFull14}{\hidepaste}
\tab{5}\spadcommand{setsubMatrix!(b,1,1,transpose(subMatrix(b,1,3,1,3)))\free{b }}
\indentrel{3}\begin{verbatim}
         Ú0  5  10  3   4 ¿
         ³                ³
   (14)  ³1  6  11  8   9 ³
         ³                ³
         À2  7  12  13  14Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexmatrixEmpty14}
\begin{paste}{MenuexmatrixEmpty14}{MenuexmatrixPatch14}
\pastebutton{MenuexmatrixEmpty14}{\showpaste}
\tab{5}\spadcommand{setsubMatrix!(b,1,1,transpose(subMatrix(b,1,3,1,3)))\free{b }}
\end{paste}\end{patch}

\begin{patch}{MenuexmatrixPatch15}
\begin{paste}{MenuexmatrixFull15}{MenuexmatrixEmpty15}
\pastebutton{MenuexmatrixFull15}{\hidepaste}
\tab{5}\spadcommand{trace( matrix([[1,x,x**2,x**3],[1,y,y**2,y**3],[1,z,z**2,z**3],[1,u,u**2,u**3]]) )}
\indentrel{3}\begin{verbatim}
          2        3
   (15)  z  + y + u  + 1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexmatrixEmpty15}
\begin{paste}{MenuexmatrixEmpty15}{MenuexmatrixPatch15}
\pastebutton{MenuexmatrixEmpty15}{\showpaste}
\tab{5}\spadcommand{trace( matrix([[1,x,x**2,x**3],[1,y,y**2,y**3],[1,z,z**2,z**3],[1,u,u**2,u**3]]) )}
\end{paste}\end{patch}

\begin{patch}{MenuexmatrixPatch16}
\begin{paste}{MenuexmatrixFull16}{MenuexmatrixEmpty16}
\pastebutton{MenuexmatrixFull16}{\hidepaste}
\tab{5}\spadcommand{determinant(matrix([[1,2,3,4],[2,3,2,5],[3,4,5,6],[4,1,6,7]]))}
\indentrel{3}\begin{verbatim}
   (16)  - 48
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexmatrixEmpty16}
\begin{paste}{MenuexmatrixEmpty16}{MenuexmatrixPatch16}
\pastebutton{MenuexmatrixEmpty16}{\showpaste}
\tab{5}\spadcommand{determinant(matrix([[1,2,3,4],[2,3,2,5],[3,4,5,6],[4,1,6,7]]))}
\end{paste}\end{patch}

\begin{patch}{MenuexmatrixPatch17}
\begin{paste}{MenuexmatrixFull17}{MenuexmatrixEmpty17}
\pastebutton{MenuexmatrixFull17}{\hidepaste}
\tab{5}\spadcommand{inverse(matrix([[1,2,1],[-2,3,4],[-1,5,6]]))}
\indentrel{3}\begin{verbatim}
         Ú  2        5 ¿
         ³- Ä  - 1   Ä ³
         ³  7        7 ³
         ³             ³
   (17)  ³ 8          6³
         ³ Ä    1   - Ä³
         ³ 7          7³
         ³             ³
         À- 1  - 1   1 Ù
               Type: Union(Matrix Fraction Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexmatrixEmpty17}
\begin{paste}{MenuexmatrixEmpty17}{MenuexmatrixPatch17}
\pastebutton{MenuexmatrixEmpty17}{\showpaste}
\tab{5}\spadcommand{inverse(matrix([[1,2,1],[-2,3,4],[-1,5,6]]))}
\end{paste}\end{patch}

\begin{patch}{MenuexmatrixPatch18}
\begin{paste}{MenuexmatrixFull18}{MenuexmatrixEmpty18}
\pastebutton{MenuexmatrixFull18}{\hidepaste}
\tab{5}\spadcommand{rank(matrix([[0,4,1],[5,3,-7],[-5,5,9]]))}
\indentrel{3}\begin{verbatim}
   (18)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexmatrixEmpty18}
\begin{paste}{MenuexmatrixEmpty18}{MenuexmatrixPatch18}
\pastebutton{MenuexmatrixEmpty18}{\showpaste}
\tab{5}\spadcommand{rank(matrix([[0,4,1],[5,3,-7],[-5,5,9]]))}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{Menuexplot2d}{coverex.ht}{2-D Graphics}
\pageto{Plotting Functions of One Variable}{ExPlot2DFunctions}
\pageto{Plotting Parametric Curves}{ExPlot2DParametric}
\pageto{Plotting Using Polar Coordinates}{ExPlot2DPolar}
\pageto{Plotting Plane Algebraic Curves}{ExPlot2DAlgebraic}
\begin{chunk}{coverex.ht}
\begin{page}{Menuexplot2d}{2-D Graphics}
\beginscroll\beginmenu
\menudownlink{Plotting Functions of One Variable}{ExPlot2DFunctions}
\graphpaste{draw(sin(tan(x)) - tan(sin(x)),x = 0..6)}
\menudownlink{Plotting Parametric Curves}{ExPlot2DParametric}
\graphpaste{draw(curve(9 * sin(3*t/4),8 * sin(t)),t = -4*\%pi..4*\%pi)}
\menudownlink{Plotting Using Polar Coordinates}{ExPlot2DPolar}
\graphpaste{draw(sin(4*t/7),t = 0..14*\%pi,coordinates == polar)}
\menudownlink{Plotting Plane Algebraic Curves}{ExPlot2DAlgebraic}
\graphpaste{draw(y**2 + y - (x**3 - x) = 0, x, y, range == [-2..2,-2..1])}
\endmenu\endscroll
\end{page}

\begin{patch}{Menuexplot2dPatch1}
\begin{paste}{Menuexplot2dFull1}{Menuexplot2dEmpty1}
\pastebutton{Menuexplot2dFull1}{\hidepaste}
\tab{5}\spadgraph{draw(sin(tan(x)) - tan(sin(x)),x = 0..6)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/menuexplot2d1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/menuexplot2d1}}
\end{paste}\end{patch}

\begin{patch}{Menuexplot2dEmpty1}
\begin{paste}{Menuexplot2dEmpty1}{Menuexplot2dPatch1}
\pastebutton{Menuexplot2dEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(sin(tan(x)) - tan(sin(x)),x = 0..6)}
\end{paste}\end{patch}

\begin{patch}{Menuexplot2dPatch2}
\begin{paste}{Menuexplot2dFull2}{Menuexplot2dEmpty2}
\pastebutton{Menuexplot2dFull2}{\hidepaste}
\tab{5}\spadgraph{draw(curve(9 * sin(3*t/4),8 * sin(t)),t = -4*\%pi..4*\%pi)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/menuexplot2d2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/menuexplot2d2}}
\end{paste}\end{patch}

\begin{patch}{Menuexplot2dEmpty2}
\begin{paste}{Menuexplot2dEmpty2}{Menuexplot2dPatch2}
\pastebutton{Menuexplot2dEmpty2}{\showpaste}
\tab{5}\spadgraph{draw(curve(9 * sin(3*t/4),8 * sin(t)),t = -4*\%pi..4*\%pi)}
\end{paste}\end{patch}

\begin{patch}{Menuexplot2dPatch3}
\begin{paste}{Menuexplot2dFull3}{Menuexplot2dEmpty3}
\pastebutton{Menuexplot2dFull3}{\hidepaste}
\tab{5}\spadgraph{draw(sin(4*t/7),t = 0..14*\%pi,coordinates == polar)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/menuexplot2d3.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/menuexplot2d3}}
\end{paste}\end{patch}

\begin{patch}{Menuexplot2dEmpty3}
\begin{paste}{Menuexplot2dEmpty3}{Menuexplot2dPatch3}
\pastebutton{Menuexplot2dEmpty3}{\showpaste}
\tab{5}\spadgraph{draw(sin(4*t/7),t = 0..14*\%pi,coordinates == polar)}
\end{paste}\end{patch}

\begin{patch}{Menuexplot2dPatch4}
\begin{paste}{Menuexplot2dFull4}{Menuexplot2dEmpty4}
\pastebutton{Menuexplot2dFull4}{\hidepaste}
\tab{5}\spadgraph{draw(y**2 + y - (x**3 - x) = 0, x, y, range == [-2..2,-2..1])}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/menuexplot2d4.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/menuexplot2d4}}
\end{paste}\end{patch}

\begin{patch}{Menuexplot2dEmpty4}
\begin{paste}{Menuexplot2dEmpty4}{Menuexplot2dPatch4}
\pastebutton{Menuexplot2dEmpty4}{\showpaste}
\tab{5}\spadgraph{draw(y**2 + y - (x**3 - x) = 0, x, y, range == [-2..2,-2..1])}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{Menuexplot3d}{coverex.ht}{3-D Graphics}
\pageto{Plotting Functions of Two Variables}{ExPlot3DFunctions}
\pageto{Plotting Parametric Surfaces}{ExPlot3DParametricSurface}
\pageto{Plotting Parametric Curves}{ExPlot3DParametricCurve}
\begin{chunk}{coverex.ht}
\begin{page}{Menuexplot3d}{3-D Graphics}
\beginscroll\beginmenu
\menudownlink{Plotting Functions of Two Variables}{ExPlot3DFunctions}
\graphpaste{draw(cos(x*y),x = -3..3,y = -3..3)}
\menudownlink{Plotting Parametric Surfaces}{ExPlot3DParametricSurface}
\graphpaste{draw(surface(5*sin(u)*cos(v),4*sin(u)*sin(v),3*cos(u)),
u=0..\%pi,v=0..2*\%pi)}
\graphpaste{draw(surface(u*cos(v),u*sin(v),u),u=0..4,v=0..2*\%pi)}
\menudownlink{Plotting Parametric Curves}{ExPlot3DParametricCurve}
\graphpaste{draw(curve(cos(t),sin(t),t),t=0..6)}
\graphpaste{draw(curve(t,t**2,t**3),t=-3..3)}
\endmenu\endscroll
\end{page}

\begin{patch}{Menuexplot3dPatch1}
\begin{paste}{Menuexplot3dFull1}{Menuexplot3dEmpty1}
\pastebutton{Menuexplot3dFull1}{\hidepaste}
\tab{5}\spadgraph{draw(cos(x*y),x = -3..3,y = -3..3)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/menuexplot3d1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/menuexplot3d1}}
\end{paste}\end{patch}

\begin{patch}{Menuexplot3dEmpty1}
\begin{paste}{Menuexplot3dEmpty1}{Menuexplot3dPatch1}
\pastebutton{Menuexplot3dEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(cos(x*y),x = -3..3,y = -3..3)}
\end{paste}\end{patch}

\begin{patch}{Menuexplot3dPatch2}
\begin{paste}{Menuexplot3dFull2}{Menuexplot3dEmpty2}
\pastebutton{Menuexplot3dFull2}{\hidepaste}
\tab{5}\spadgraph{draw(surface(5*sin(u)*cos(v),4*sin(u)*sin(v),3*cos(u)),u=0..\%pi,v=0..2*\%pi)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/menuexplot3d2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/menuexplot3d2}}
\end{paste}\end{patch}

\begin{patch}{Menuexplot3dEmpty2}
\begin{paste}{Menuexplot3dEmpty2}{Menuexplot3dPatch2}
\pastebutton{Menuexplot3dEmpty2}{\showpaste}
\tab{5}\spadgraph{draw(surface(5*sin(u)*cos(v),4*sin(u)*sin(v),3*cos(u)),u=0..\%pi,v=0..2*\%pi)}
\end{paste}\end{patch}

\begin{patch}{Menuexplot3dPatch3}
\begin{paste}{Menuexplot3dFull3}{Menuexplot3dEmpty3}
\pastebutton{Menuexplot3dFull3}{\hidepaste}
\tab{5}\spadgraph{draw(surface(u*cos(v),u*sin(v),u),u=0..4,v=0..2*\%pi)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/menuexplot3d3.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/menuexplot3d3}}
\end{paste}\end{patch}

\begin{patch}{Menuexplot3dEmpty3}
\begin{paste}{Menuexplot3dEmpty3}{Menuexplot3dPatch3}
\pastebutton{Menuexplot3dEmpty3}{\showpaste}
\tab{5}\spadgraph{draw(surface(u*cos(v),u*sin(v),u),u=0..4,v=0..2*\%pi)}
\end{paste}\end{patch}

\begin{patch}{Menuexplot3dPatch4}
\begin{paste}{Menuexplot3dFull4}{Menuexplot3dEmpty4}
\pastebutton{Menuexplot3dFull4}{\hidepaste}
\tab{5}\spadgraph{draw(curve(cos(t),sin(t),t),t=0..6)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/menuexplot3d4.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/menuexplot3d4}}
\end{paste}\end{patch}

\begin{patch}{Menuexplot3dEmpty4}
\begin{paste}{Menuexplot3dEmpty4}{Menuexplot3dPatch4}
\pastebutton{Menuexplot3dEmpty4}{\showpaste}
\tab{5}\spadgraph{draw(curve(cos(t),sin(t),t),t=0..6)}
\end{paste}\end{patch}

\begin{patch}{Menuexplot3dPatch5}
\begin{paste}{Menuexplot3dFull5}{Menuexplot3dEmpty5}
\pastebutton{Menuexplot3dFull5}{\hidepaste}
\tab{5}\spadgraph{draw(curve(t,t**2,t**3),t=-3..3)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/menuexplot3d5.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/menuexplot3d5}}
\end{paste}\end{patch}

\begin{patch}{Menuexplot3dEmpty5}
\begin{paste}{Menuexplot3dEmpty5}{Menuexplot3dPatch5}
\pastebutton{Menuexplot3dEmpty5}{\showpaste}
\tab{5}\spadgraph{draw(curve(t,t**2,t**3),t=-3..3)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{Menuexseries}{coverex.ht}{Series}
\pageto{Converting Expressions to Series}{ExSeriesConvert}
\pageto{Manipulating Power Series}{ExSeriesManipulate}
\pageto{Functions on Power Series}{ExSeriesFunctions}
\pageto{Substituting Numerical Values in Power Series}
{ExSeriesSubstitution}
\begin{chunk}{coverex.ht}
\begin{page}{Menuexseries}{Series}
\beginscroll\beginmenu
\menudownlink{Converting Expressions to Series}{ExSeriesConvert}
\spadpaste{series(sin(a*x),x = 0)}
\spadpaste{series(sin(a*x),a = \%pi/4)}
\menudownlink{Manipulating Power Series}{ExSeriesManipulate}
\spadpaste{f := series(1/(1-x),x = 0) \bound{f}}
\spadpaste{f ** 2 \free{f}}
\menudownlink{Functions on Power Series}{ExSeriesFunctions}
\spadpaste{f := series(1/(1-x),x = 0) \bound{f1}}
\spadpaste{g := log(f) \free{f1} \bound{g}}
\spadpaste{exp(g) \free{g}}
\menudownlink{Substituting Numerical Values in Power Series}
{ExSeriesSubstitution}
\spadpaste{f := taylor(exp(x)) \bound{f2}}
\spadpaste{eval(f,1.0) \free{f2}}
\endmenu\endscroll
\end{page}

\begin{patch}{MenuexseriesPatch1}
\begin{paste}{MenuexseriesFull1}{MenuexseriesEmpty1}
\pastebutton{MenuexseriesFull1}{\hidepaste}
\tab{5}\spadcommand{series(sin(a*x),x = 0)}
\indentrel{3}\begin{verbatim}
   (1)
            3        5        7          9
           a   3    a   5    a    7     a     9
     a x - ÄÄ x  + ÄÄÄ x  - ÄÄÄÄ x  + ÄÄÄÄÄÄ x
            6      120      5040      362880
   + 
           11
          a      11      12
     - ÄÄÄÄÄÄÄÄ x   + O(x  )
       39916800
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexseriesEmpty1}
\begin{paste}{MenuexseriesEmpty1}{MenuexseriesPatch1}
\pastebutton{MenuexseriesEmpty1}{\showpaste}
\tab{5}\spadcommand{series(sin(a*x),x = 0)}
\end{paste}\end{patch}

\begin{patch}{MenuexseriesPatch2}
\begin{paste}{MenuexseriesFull2}{MenuexseriesEmpty2}
\pastebutton{MenuexseriesFull2}{\hidepaste}
\tab{5}\spadcommand{series(sin(a*x),a = \%pi/4)}
\indentrel{3}\begin{verbatim}
   (2)
         %pi x          %pi x      %pi
     sin(ÄÄÄÄÄ) + x cos(ÄÄÄÄÄ)(a - ÄÄÄ)
           4              4         4
   + 
        2    %pi x                3    %pi x
       x sin(ÄÄÄÄÄ)              x cos(ÄÄÄÄÄ)
               4         %pi 2           4         %pi 3
     - ÄÄÄÄÄÄÄÄÄÄÄÄ (a - ÄÄÄ)  - ÄÄÄÄÄÄÄÄÄÄÄÄ (a - ÄÄÄ)
             2            4            6            4
   + 
      4    %pi x                5    %pi x
     x sin(ÄÄÄÄÄ)              x cos(ÄÄÄÄÄ)
             4         %pi 4           4         %pi 5
     ÄÄÄÄÄÄÄÄÄÄÄÄ (a - ÄÄÄ)  + ÄÄÄÄÄÄÄÄÄÄÄÄ (a - ÄÄÄ)
          24            4           120           4
   + 
        6    %pi x                7    %pi x
       x sin(ÄÄÄÄÄ)              x cos(ÄÄÄÄÄ)
               4         %pi 6           4         %pi 7
     - ÄÄÄÄÄÄÄÄÄÄÄÄ (a - ÄÄÄ)  - ÄÄÄÄÄÄÄÄÄÄÄÄ (a - ÄÄÄ)
            720           4          5040           4
   + 
      8    %pi x                9    %pi x
     x sin(ÄÄÄÄÄ)              x cos(ÄÄÄÄÄ)
             4         %pi 8           4         %pi 9
     ÄÄÄÄÄÄÄÄÄÄÄÄ (a - ÄÄÄ)  + ÄÄÄÄÄÄÄÄÄÄÄÄ (a - ÄÄÄ)
         40320          4         362880          4
   + 
        10    %pi x
       x  sin(ÄÄÄÄÄ)
                4         %pi 10          %pi 11
     - ÄÄÄÄÄÄÄÄÄÄÄÄÄ (a - ÄÄÄ)   + O((a - ÄÄÄ)  )
          3628800          4               4
Type: UnivariatePuiseuxSeries(Expression Integer,a,pi/4)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexseriesEmpty2}
\begin{paste}{MenuexseriesEmpty2}{MenuexseriesPatch2}
\pastebutton{MenuexseriesEmpty2}{\showpaste}
\tab{5}\spadcommand{series(sin(a*x),a = \%pi/4)}
\end{paste}\end{patch}

\begin{patch}{MenuexseriesPatch3}
\begin{paste}{MenuexseriesFull3}{MenuexseriesEmpty3}
\pastebutton{MenuexseriesFull3}{\hidepaste}
\tab{5}\spadcommand{f := series(1/(1-x),x = 0)\bound{f }}
\indentrel{3}\begin{verbatim}
   (3)
              2    3    4    5    6    7    8    9    10
     1 + x + x  + x  + x  + x  + x  + x  + x  + x  + x
   + 
        11
     O(x  )
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexseriesEmpty3}
\begin{paste}{MenuexseriesEmpty3}{MenuexseriesPatch3}
\pastebutton{MenuexseriesEmpty3}{\showpaste}
\tab{5}\spadcommand{f := series(1/(1-x),x = 0)\bound{f }}
\end{paste}\end{patch}

\begin{patch}{MenuexseriesPatch4}
\begin{paste}{MenuexseriesFull4}{MenuexseriesEmpty4}
\pastebutton{MenuexseriesFull4}{\hidepaste}
\tab{5}\spadcommand{f ** 2\free{f }}
\indentrel{3}\begin{verbatim}
   (4)
                2     3     4     5     6     7     8
     1 + 2x + 3x  + 4x  + 5x  + 6x  + 7x  + 8x  + 9x
   + 
        9      10      11
     10x  + 11x   + O(x  )
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexseriesEmpty4}
\begin{paste}{MenuexseriesEmpty4}{MenuexseriesPatch4}
\pastebutton{MenuexseriesEmpty4}{\showpaste}
\tab{5}\spadcommand{f ** 2\free{f }}
\end{paste}\end{patch}

\begin{patch}{MenuexseriesPatch5}
\begin{paste}{MenuexseriesFull5}{MenuexseriesEmpty5}
\pastebutton{MenuexseriesFull5}{\hidepaste}
\tab{5}\spadcommand{f := series(1/(1-x),x = 0)\bound{f1 }}
\indentrel{3}\begin{verbatim}
   (5)
              2    3    4    5    6    7    8    9    10
     1 + x + x  + x  + x  + x  + x  + x  + x  + x  + x
   + 
        11
     O(x  )
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexseriesEmpty5}
\begin{paste}{MenuexseriesEmpty5}{MenuexseriesPatch5}
\pastebutton{MenuexseriesEmpty5}{\showpaste}
\tab{5}\spadcommand{f := series(1/(1-x),x = 0)\bound{f1 }}
\end{paste}\end{patch}

\begin{patch}{MenuexseriesPatch6}
\begin{paste}{MenuexseriesFull6}{MenuexseriesEmpty6}
\pastebutton{MenuexseriesFull6}{\hidepaste}
\tab{5}\spadcommand{g := log(f)\free{f1 }\bound{g }}
\indentrel{3}\begin{verbatim}
   (6)
         1  2   1  3   1  4   1  5   1  6   1  7   1  8
     x + Ä x  + Ä x  + Ä x  + Ä x  + Ä x  + Ä x  + Ä x
         2      3      4      5      6      7      8
   + 
     1  9    1  10    1  11      12
     Ä x  + ÄÄ x   + ÄÄ x   + O(x  )
     9      10       11
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexseriesEmpty6}
\begin{paste}{MenuexseriesEmpty6}{MenuexseriesPatch6}
\pastebutton{MenuexseriesEmpty6}{\showpaste}
\tab{5}\spadcommand{g := log(f)\free{f1 }\bound{g }}
\end{paste}\end{patch}

\begin{patch}{MenuexseriesPatch7}
\begin{paste}{MenuexseriesFull7}{MenuexseriesEmpty7}
\pastebutton{MenuexseriesFull7}{\hidepaste}
\tab{5}\spadcommand{exp(g)\free{g }}
\indentrel{3}\begin{verbatim}
   (7)
              2    3    4    5    6    7    8    9    10
     1 + x + x  + x  + x  + x  + x  + x  + x  + x  + x
   + 
        11
     O(x  )
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexseriesEmpty7}
\begin{paste}{MenuexseriesEmpty7}{MenuexseriesPatch7}
\pastebutton{MenuexseriesEmpty7}{\showpaste}
\tab{5}\spadcommand{exp(g)\free{g }}
\end{paste}\end{patch}

\begin{patch}{MenuexseriesPatch8}
\begin{paste}{MenuexseriesFull8}{MenuexseriesEmpty8}
\pastebutton{MenuexseriesFull8}{\hidepaste}
\tab{5}\spadcommand{f := taylor(exp(x))\bound{f2 }}
\indentrel{3}\begin{verbatim}
   (8)
             1  2   1  3    1  4    1   5    1   6
     1 + x + Ä x  + Ä x  + ÄÄ x  + ÄÄÄ x  + ÄÄÄ x
             2      6      24      120      720
   + 
     1   7     1    8      1    9      1     10      11
   ÄÄÄÄ x  + ÄÄÄÄÄ x  + ÄÄÄÄÄÄ x  + ÄÄÄÄÄÄÄ x   + O(x  )
   5040      40320      362880      3628800
   Type: UnivariateTaylorSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexseriesEmpty8}
\begin{paste}{MenuexseriesEmpty8}{MenuexseriesPatch8}
\pastebutton{MenuexseriesEmpty8}{\showpaste}
\tab{5}\spadcommand{f := taylor(exp(x))\bound{f2 }}
\end{paste}\end{patch}

\begin{patch}{MenuexseriesPatch9}
\begin{paste}{MenuexseriesFull9}{MenuexseriesEmpty9}
\pastebutton{MenuexseriesFull9}{\hidepaste}
\tab{5}\spadcommand{eval(f,1.0)\free{f2 }}
\indentrel{3}\begin{verbatim}
   (9)
   [1.0, 2.0, 2.5, 2.6666666666 666666667,
    2.7083333333 333333333, 2.7166666666 666666667,
    2.7180555555 555555556, 2.7182539682 53968254,
    2.7182787698 412698413, 2.7182815255 731922399, ...]
                          Type: Stream Expression Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexseriesEmpty9}
\begin{paste}{MenuexseriesEmpty9}{MenuexseriesPatch9}
\pastebutton{MenuexseriesEmpty9}{\showpaste}
\tab{5}\spadcommand{eval(f,1.0)\free{f2 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{Menuexsum}{coverex.ht}{Summations}
\pageto{notitle}{ExSumListEntriesI}
\pageto{notitle}{ExSumListEntriesII}
\pageto{notitle}{ExSumApproximateE}
\pageto{notitle}{ExSumClosedForm}
\pageto{notitle}{ExSumCubes}
\pageto{notitle}{ExSumPolynomial}
\pageto{notitle}{ExSumGeneralFunction}
\pageto{notitle}{ExSumInfinite}
\begin{chunk}{coverex.ht}
\begin{page}{Menuexsum}{Summations}
\beginscroll\beginmenu
\menudownlink{Summing the Entries of a List I}{ExSumListEntriesI}
\spadpaste{[i for i in 1..15]}
\spadpaste{reduce(+,[i for i in 1..15])}
\menudownlink{Summing the Entries of a List II}{ExSumListEntriesII}
\spadpaste{[n**2 for n in 5..20]}
\spadpaste{reduce(+,[n**2 for n in 5..20])}
\menudownlink{Approximating e}{ExSumApproximateE}
\spadpaste{reduce(+,[1.0/factorial(n) for n in 0..20])}
\menudownlink{Closed Form Summations}{ExSumClosedForm}
\spadpaste{s := sum(k**2,k = a..b) \bound{s}}
\spadpaste{eval(s,[a,b],[1,25]) \free{s}}
\spadpaste{reduce(+,[i**2 for i in 1..25])}
\menudownlink{Sums of Cubes}{ExSumCubes}
\spadpaste{sum(k**3,k = 1..n)}
\spadpaste{sum(k,k = 1..n) ** 2}
\menudownlink{Sums of Polynomials}{ExSumPolynomial}
\spadpaste{sum(3*k**2/(c**2 + 1) + 12*k/d,k = (3*a)..(4*b))}
\menudownlink{Sums of General Functions}{ExSumGeneralFunction}
\spadpaste{sum(k * x**k,k = 1..n)}
\menudownlink{Infinite Sums}{ExSumInfinite}
\spadpaste{limit( sum(1/(k * (k + 2)),k = 1..n) ,n = \%plusInfinity)}
\endmenu\endscroll
\end{page}

\begin{patch}{MenuexsumPatch1}
\begin{paste}{MenuexsumFull1}{MenuexsumEmpty1}
\pastebutton{MenuexsumFull1}{\hidepaste}
\tab{5}\spadcommand{[i for i in 1..15]}
\indentrel{3}\begin{verbatim}
   (1)  [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexsumEmpty1}
\begin{paste}{MenuexsumEmpty1}{MenuexsumPatch1}
\pastebutton{MenuexsumEmpty1}{\showpaste}
\tab{5}\spadcommand{[i for i in 1..15]}
\end{paste}\end{patch}

\begin{patch}{MenuexsumPatch2}
\begin{paste}{MenuexsumFull2}{MenuexsumEmpty2}
\pastebutton{MenuexsumFull2}{\hidepaste}
\tab{5}\spadcommand{reduce(+,[i for i in 1..15])}
\indentrel{3}\begin{verbatim}
   (2)  120
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexsumEmpty2}
\begin{paste}{MenuexsumEmpty2}{MenuexsumPatch2}
\pastebutton{MenuexsumEmpty2}{\showpaste}
\tab{5}\spadcommand{reduce(+,[i for i in 1..15])}
\end{paste}\end{patch}

\begin{patch}{MenuexsumPatch3}
\begin{paste}{MenuexsumFull3}{MenuexsumEmpty3}
\pastebutton{MenuexsumFull3}{\hidepaste}
\tab{5}\spadcommand{[n**2 for n in 5..20]}
\indentrel{3}\begin{verbatim}
   (3)
   [25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225,
    256, 289, 324, 361, 400]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexsumEmpty3}
\begin{paste}{MenuexsumEmpty3}{MenuexsumPatch3}
\pastebutton{MenuexsumEmpty3}{\showpaste}
\tab{5}\spadcommand{[n**2 for n in 5..20]}
\end{paste}\end{patch}

\begin{patch}{MenuexsumPatch4}
\begin{paste}{MenuexsumFull4}{MenuexsumEmpty4}
\pastebutton{MenuexsumFull4}{\hidepaste}
\tab{5}\spadcommand{reduce(+,[n**2 for n in 5..20])}
\indentrel{3}\begin{verbatim}
   (4)  2840
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexsumEmpty4}
\begin{paste}{MenuexsumEmpty4}{MenuexsumPatch4}
\pastebutton{MenuexsumEmpty4}{\showpaste}
\tab{5}\spadcommand{reduce(+,[n**2 for n in 5..20])}
\end{paste}\end{patch}

\begin{patch}{MenuexsumPatch5}
\begin{paste}{MenuexsumFull5}{MenuexsumEmpty5}
\pastebutton{MenuexsumFull5}{\hidepaste}
\tab{5}\spadcommand{reduce(+,[1.0/factorial(n) for n in 0..20])}
\indentrel{3}\begin{verbatim}
   (5)  2.7182818284 590452354
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexsumEmpty5}
\begin{paste}{MenuexsumEmpty5}{MenuexsumPatch5}
\pastebutton{MenuexsumEmpty5}{\showpaste}
\tab{5}\spadcommand{reduce(+,[1.0/factorial(n) for n in 0..20])}
\end{paste}\end{patch}

\begin{patch}{MenuexsumPatch6}
\begin{paste}{MenuexsumFull6}{MenuexsumEmpty6}
\pastebutton{MenuexsumFull6}{\hidepaste}
\tab{5}\spadcommand{s := sum(k**2,k = a..b)\bound{s }}
\indentrel{3}\begin{verbatim}
          3     2         3     2
        2b  + 3b  + b - 2a  + 3a  - a
   (6)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                      6
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexsumEmpty6}
\begin{paste}{MenuexsumEmpty6}{MenuexsumPatch6}
\pastebutton{MenuexsumEmpty6}{\showpaste}
\tab{5}\spadcommand{s := sum(k**2,k = a..b)\bound{s }}
\end{paste}\end{patch}

\begin{patch}{MenuexsumPatch7}
\begin{paste}{MenuexsumFull7}{MenuexsumEmpty7}
\pastebutton{MenuexsumFull7}{\hidepaste}
\tab{5}\spadcommand{eval(s,[a,b],[1,25])\free{s }}
\indentrel{3}\begin{verbatim}
   (7)  5525
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexsumEmpty7}
\begin{paste}{MenuexsumEmpty7}{MenuexsumPatch7}
\pastebutton{MenuexsumEmpty7}{\showpaste}
\tab{5}\spadcommand{eval(s,[a,b],[1,25])\free{s }}
\end{paste}\end{patch}

\begin{patch}{MenuexsumPatch8}
\begin{paste}{MenuexsumFull8}{MenuexsumEmpty8}
\pastebutton{MenuexsumFull8}{\hidepaste}
\tab{5}\spadcommand{reduce(+,[i**2 for i in 1..25])}
\indentrel{3}\begin{verbatim}
   (8)  5525
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexsumEmpty8}
\begin{paste}{MenuexsumEmpty8}{MenuexsumPatch8}
\pastebutton{MenuexsumEmpty8}{\showpaste}
\tab{5}\spadcommand{reduce(+,[i**2 for i in 1..25])}
\end{paste}\end{patch}

\begin{patch}{MenuexsumPatch9}
\begin{paste}{MenuexsumFull9}{MenuexsumEmpty9}
\pastebutton{MenuexsumFull9}{\hidepaste}
\tab{5}\spadcommand{sum(k**3,k = 1..n)}
\indentrel{3}\begin{verbatim}
         4     3    2
        n  + 2n  + n
   (9)  ÄÄÄÄÄÄÄÄÄÄÄÄÄ
              4
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexsumEmpty9}
\begin{paste}{MenuexsumEmpty9}{MenuexsumPatch9}
\pastebutton{MenuexsumEmpty9}{\showpaste}
\tab{5}\spadcommand{sum(k**3,k = 1..n)}
\end{paste}\end{patch}

\begin{patch}{MenuexsumPatch10}
\begin{paste}{MenuexsumFull10}{MenuexsumEmpty10}
\pastebutton{MenuexsumFull10}{\hidepaste}
\tab{5}\spadcommand{sum(k,k = 1..n) ** 2}
\indentrel{3}\begin{verbatim}
          4     3    2
         n  + 2n  + n
   (10)  ÄÄÄÄÄÄÄÄÄÄÄÄÄ
               4
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexsumEmpty10}
\begin{paste}{MenuexsumEmpty10}{MenuexsumPatch10}
\pastebutton{MenuexsumEmpty10}{\showpaste}
\tab{5}\spadcommand{sum(k,k = 1..n) ** 2}
\end{paste}\end{patch}

\begin{patch}{MenuexsumPatch11}
\begin{paste}{MenuexsumFull11}{MenuexsumEmpty11}
\pastebutton{MenuexsumFull11}{\hidepaste}
\tab{5}\spadcommand{sum(3*k**2/(c**2 + 1) + 12*k/d,k = (3*a)..(4*b))}
\indentrel{3}\begin{verbatim}
   (11)
            3      2           3      2
       (128b  + 48b  + 4b - 54a  + 27a  - 3a)d
     + 
            2             2        2       2             2
       (192b  + 48b - 108a  + 36a)c  + 192b  + 48b - 108a
     + 
       36a
  /
        2
     (2c  + 2)d
           Type: Union(Fraction Polynomial Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexsumEmpty11}
\begin{paste}{MenuexsumEmpty11}{MenuexsumPatch11}
\pastebutton{MenuexsumEmpty11}{\showpaste}
\tab{5}\spadcommand{sum(3*k**2/(c**2 + 1) + 12*k/d,k = (3*a)..(4*b))}
\end{paste}\end{patch}

\begin{patch}{MenuexsumPatch12}
\begin{paste}{MenuexsumFull12}{MenuexsumEmpty12}
\pastebutton{MenuexsumFull12}{\hidepaste}
\tab{5}\spadcommand{sum(k * x**k,k = 1..n)}
\indentrel{3}\begin{verbatim}
             2               n
         (n x  + (- n - 1)x)x  + x
   (12)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                 2
                x  - 2x + 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexsumEmpty12}
\begin{paste}{MenuexsumEmpty12}{MenuexsumPatch12}
\pastebutton{MenuexsumEmpty12}{\showpaste}
\tab{5}\spadcommand{sum(k * x**k,k = 1..n)}
\end{paste}\end{patch}

\begin{patch}{MenuexsumPatch13}
\begin{paste}{MenuexsumFull13}{MenuexsumEmpty13}
\pastebutton{MenuexsumFull13}{\hidepaste}
\tab{5}\spadcommand{limit( sum(1/(k * (k + 2)),k = 1..n) ,n = \%plusInfinity)}
\indentrel{3}\begin{verbatim}
         3
   (13)  Ä
         4
Type: Union(OrderedCompletion Fraction Polynomial Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MenuexsumEmpty13}
\begin{paste}{MenuexsumEmpty13}{MenuexsumPatch13}
\pastebutton{MenuexsumEmpty13}{\showpaste}
\tab{5}\spadcommand{limit( sum(1/(k * (k + 2)),k = 1..n) ,n = \%plusInfinity)}
\end{paste}\end{patch}

\end{chunk}
\section{decimal.ht}
\pagetitle{DecimalExpansionXmpPage}{decimal.ht}{Decimal Expansion}
\pagepic{ps/v71decimalexpansionxmppage.eps}{DecimalExpansionXmpPage}{0.50}
\pagefrom{Axiom Number Types}{NumberPage}
\pagefrom{Integer}{IntegerXmpPage}
\pageto{BinaryExpansion}{BinaryExpansionXmpPage}
\pageto{HexadecimalExpansion}{HexExpansionXmpPage}
\pageto{RadixExpansion}{RadixExpansionXmpPage}
\begin{chunk}{decimal.ht}
\begin{page}{DecimalExpansionXmpPage}{Decimal Expansion}
\beginscroll
All rationals have repeating decimal expansions.
Operations to access the individual digits of a decimal expansion can
be obtained by converting the value to \spadtype{RadixExpansion(10)}.
More examples of expansions are available in
\downlink{`BinaryExpansion'}{BinaryExpansionXmpPage}
\ignore{BinaryExpansion},
\downlink{`HexadecimalExpansion'}{HexExpansionXmpPage}
\ignore{HexadecimalExpansion}, and
\downlink{`RadixExpansion'}{RadixExpansionXmpPage}\ignore{RadixExpansion}.
\showBlurb{DecimalExpansion}

\xtc{
The operation \spadfunFrom{decimal}{DecimalExpansion} is used to create
this expansion of type \spadtype{DecimalExpansion}.
}{
\spadpaste{r := decimal(22/7) \bound{r}}
}
\xtc{
Arithmetic is exact.
}{
\spadpaste{r + decimal(6/7) \free{r}}
}
\xtc{
The period of the expansion can be short or long \ldots
}{
\spadpaste{[decimal(1/i) for i in 350..354] }
}
\xtc{
or very long.
}{
\spadpaste{decimal(1/2049) }
}
\xtc{
These numbers are bona fide algebraic objects.
}{
\spadpaste{p := decimal(1/4)*x**2 + decimal(2/3)*x + decimal(4/9)  
\bound{p}}
}
\xtc{
}{
\spadpaste{q := differentiate(p, x) \free{p}\bound{q}}
}
\xtc{
}{
\spadpaste{g := gcd(p, q)            \free{p q} \bound{g}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{DecimalExpansionXmpPagePatch1}
\begin{paste}{DecimalExpansionXmpPageFull1}{DecimalExpansionXmpPageEmpty1}
\pastebutton{DecimalExpansionXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{r := decimal(22/7)\bound{r }}
\indentrel{3}\begin{verbatim}
          ______
   (1)  3.142857
                                 Type: DecimalExpansion
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DecimalExpansionXmpPageEmpty1}
\begin{paste}{DecimalExpansionXmpPageEmpty1}{DecimalExpansionXmpPagePatch1}
\pastebutton{DecimalExpansionXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{r := decimal(22/7)\bound{r }}
\end{paste}\end{patch}

\begin{patch}{DecimalExpansionXmpPagePatch2}
\begin{paste}{DecimalExpansionXmpPageFull2}{DecimalExpansionXmpPageEmpty2}
\pastebutton{DecimalExpansionXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{r + decimal(6/7)\free{r }}
\indentrel{3}\begin{verbatim}
   (2)  4
                                 Type: DecimalExpansion
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DecimalExpansionXmpPageEmpty2}
\begin{paste}{DecimalExpansionXmpPageEmpty2}{DecimalExpansionXmpPagePatch2}
\pastebutton{DecimalExpansionXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{r + decimal(6/7)\free{r }}
\end{paste}\end{patch}

\begin{patch}{DecimalExpansionXmpPagePatch3}
\begin{paste}{DecimalExpansionXmpPageFull3}{DecimalExpansionXmpPageEmpty3}
\pastebutton{DecimalExpansionXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{[decimal(1/i) for i in 350..354]}
\indentrel{3}\begin{verbatim}
   (3)
        ______    ______         __
   [0.00285714, 0.002849, 0.0028409,
      ________________________________
    0.00283286118980169971671388101983,

     0.0
       OVERBAR
          02824858757062146892655367231638418079096045197
            74011299435
     ]
                            Type: List DecimalExpansion
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DecimalExpansionXmpPageEmpty3}
\begin{paste}{DecimalExpansionXmpPageEmpty3}{DecimalExpansionXmpPagePatch3}
\pastebutton{DecimalExpansionXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{[decimal(1/i) for i in 350..354]}
\end{paste}\end{patch}

\begin{patch}{DecimalExpansionXmpPagePatch4}
\begin{paste}{DecimalExpansionXmpPageFull4}{DecimalExpansionXmpPageEmpty4}
\pastebutton{DecimalExpansionXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{decimal(1/2049)}
\indentrel{3}\begin{verbatim}
   (4)
   0.
     OVERBAR
        0004880429477794045876037091264031234748657881893
          60663738408979990239141044411908247925817471937
          53050268423621278672523182040019521717911176183
          50414836505612493899463152757442654953635919960
          95656417764763299170326988775012201073694485114
          69009272816007808687164470473401659346022449975
          59785261102977061981454367984382625671059053196
          6813079551
                                 Type: DecimalExpansion
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DecimalExpansionXmpPageEmpty4}
\begin{paste}{DecimalExpansionXmpPageEmpty4}{DecimalExpansionXmpPagePatch4}
\pastebutton{DecimalExpansionXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{decimal(1/2049)}
\end{paste}\end{patch}

\begin{patch}{DecimalExpansionXmpPagePatch5}
\begin{paste}{DecimalExpansionXmpPageFull5}{DecimalExpansionXmpPageEmpty5}
\pastebutton{DecimalExpansionXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{p := decimal(1/4)*x**2 + decimal(2/3)*x + decimal(4/9)\bound{p }}
\indentrel{3}\begin{verbatim}
             2     _      _
   (5)  0.25x  + 0.6x + 0.4
                      Type: Polynomial DecimalExpansion
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DecimalExpansionXmpPageEmpty5}
\begin{paste}{DecimalExpansionXmpPageEmpty5}{DecimalExpansionXmpPagePatch5}
\pastebutton{DecimalExpansionXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{p := decimal(1/4)*x**2 + decimal(2/3)*x + decimal(4/9)\bound{p }}
\end{paste}\end{patch}

\begin{patch}{DecimalExpansionXmpPagePatch6}
\begin{paste}{DecimalExpansionXmpPageFull6}{DecimalExpansionXmpPageEmpty6}
\pastebutton{DecimalExpansionXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{q := differentiate(p, x)\free{p }\bound{q }}
\indentrel{3}\begin{verbatim}
                 _
   (6)  0.5x + 0.6
                      Type: Polynomial DecimalExpansion
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DecimalExpansionXmpPageEmpty6}
\begin{paste}{DecimalExpansionXmpPageEmpty6}{DecimalExpansionXmpPagePatch6}
\pastebutton{DecimalExpansionXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{q := differentiate(p, x)\free{p }\bound{q }}
\end{paste}\end{patch}

\begin{patch}{DecimalExpansionXmpPagePatch7}
\begin{paste}{DecimalExpansionXmpPageFull7}{DecimalExpansionXmpPageEmpty7}
\pastebutton{DecimalExpansionXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{g := gcd(p, q)\free{p q }\bound{g }}
\indentrel{3}\begin{verbatim}
              _
   (7)  x + 1.3
                      Type: Polynomial DecimalExpansion
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DecimalExpansionXmpPageEmpty7}
\begin{paste}{DecimalExpansionXmpPageEmpty7}{DecimalExpansionXmpPagePatch7}
\pastebutton{DecimalExpansionXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{g := gcd(p, q)\free{p q }\bound{g }}
\end{paste}\end{patch}

\end{chunk}
\section{derham.ht}
\pagetitle{DeRhamComplexXmpPage}{derham.ht}{DeRhamComplex}
\begin{chunk}{derham.ht}
\begin{page}{DeRhamComplexXmpPage}{DeRhamComplex}
\beginscroll
 
The domain constructor \spadtype{DeRhamComplex} creates the
class of differential forms of arbitrary degree over a coefficient ring.
The De Rham complex constructor takes two arguments: a ring, 
\spad{coefRing,} and a list of coordinate variables.
 
\xtc{
This is the ring of coefficients.
}{
\spadpaste{coefRing := Integer \bound{coefRing}}
}
\xtc{
These are the coordinate variables.
}{
\spadpaste{lv : List Symbol := [x,y,z] \bound{lv}}
}
\xtc{
This is the De Rham complex of Euclidean three-space using
coordinates \spad{x, y} and \spad{z.}
}{
\spadpaste{der := DERHAM(coefRing,lv) \free{coefRing}\free{lv}
\bound{der}}
}
 
This complex allows us to describe differential forms having
expressions of integers as coefficients.
These coefficients can involve any number of variables, for example,
\spad{f(x,t,r,y,u,z).}
As we've chosen to work with ordinary
Euclidean three-space, expressions involving these forms
are treated as functions of
\spad{x, y} and \spad{z} with the additional arguments
\spad{t, r} and \spad{u} regarded as symbolic constants.
\xtc{
Here are some examples of coefficients.
}{
\spadpaste{R := Expression coefRing \free{coefRing}\bound{R}}
}
\xtc{
}{
\spadpaste{f : R := x**2*y*z-5*x**3*y**2*z**5 \free{R}\bound{f}}
}
\xtc{
}{
\spadpaste{g : R := z**2*y*cos(z)-7*sin(x**3*y**2)*z**2 \free{R}\bound{g}}
}
\xtc{
}{
\spadpaste{h : R :=x*y*z-2*x**3*y*z**2 \free{R}\bound{h}}
}
\xtc{
We now define
the multiplicative basis elements for the exterior algebra over \spad{R}.
}{
\spadpaste{dx : der := generator(1) \free{der}\bound{dx}}
}
\xtc{
}{
\spadpaste{dy : der := generator(2)\free{der}\bound{dy}}
}
\xtc{
}{
\spadpaste{dz : der := generator(3)\free{der}\bound{dz}}
}
\xtc{
This is an alternative way to give the above assignments.
}{
\spadpaste{[dx,dy,dz] := [generator(i)\$der for i in 1..3] \free{der}
\bound{dxyz}}
}
\xtc{
Now we define some one-forms.
}{
\spadpaste{alpha : der := f*dx + g*dy + h*dz \bound{alpha}
\free{der f g h dxyz}}
}
\xtc{
}{
\spadpaste{beta  : der := cos(tan(x*y*z)+x*y*z)*dx + x*dy 
\bound{beta}\free{der f g h dxyz}}
}
\xtc{
A well-known theorem states that the composition of
\spadfunFrom{exteriorDifferential}{DeRhamComplex}
with itself is the zero map for continuous forms.
Let's verify this theorem for \spad{alpha}.
}{
\spadpaste{exteriorDifferential alpha; \free{alpha}\bound{ed}}
}
\xtc{
We suppressed the lengthy output of the last expression, but nevertheless, the
composition is zero.
}{
\spadpaste{exteriorDifferential \% \free{ed}}
}
 
\xtc{
Now we check that \spadfunFrom{exteriorDifferential}{DeRhamComplex}
is a ``graded derivation'' \spad{D,} that is, \spad{D} satisfies:
\begin{verbatim}
D(a*b) = D(a)*b + (-1)**degree(a)*a*D(b)
\end{verbatim}
}{
\spadpaste{gamma := alpha * beta \bound{gamma}\free{alpha}\free{beta}}
}
\xtc{
We try this for the one-forms \spad{alpha} and \spad{beta}.
}{
\spadpaste{exteriorDifferential(gamma) - 
(exteriorDifferential(alpha)*beta - alpha * exteriorDifferential(beta)) 
\free{alpha beta gamma}}
}
\xtc{
Now we define some ``basic operators'' (see 
\downlink{`Operator'}{OperatorXmpPage}\ignore{Operator}).
}{
\spadpaste{a : BOP := operator('a) \bound{ao}}
}
\xtc{
}{
\spadpaste{b : BOP := operator('b) \bound{bo}}
}
\xtc{
}{
\spadpaste{c : BOP := operator('c) \bound{co}}
}
\xtc{
We also define
some indeterminate one- and two-forms using these operators.
}{
\spadpaste{sigma := a(x,y,z) * dx + b(x,y,z) * dy + c(x,y,z) * dz 
\bound{sigma}\free{ao bo co dxyz}}
}
\xtc{
}{
\spadpaste{theta  := a(x,y,z) * dx * dy + b(x,y,z) * dx * 
dz + c(x,y,z) * dy * dz \bound{theta}\free{ao bo co dxyz}}
}
 
\xtc{
This allows us to get formal definitions for the ``gradient'' \ldots
}{
\spadpaste{totalDifferential(a(x,y,z))\$der \free{ao der}}
}
\xtc{
the ``curl'' \ldots
}{
\spadpaste{exteriorDifferential sigma \free{sigma}}
}
\xtc{
and the ``divergence.''
}{
\spadpaste{exteriorDifferential theta \free{theta}}
}
 
\xtc{
Note that the De Rham complex is an algebra with unity.
This element \spad{1} is the basis for elements for zero-forms, that is,
functions in our space.
}{
\spadpaste{one : der := 1 \bound{one}\free{der}}
}
 
\xtc{
To convert a function to a function lying in the De Rham complex,
multiply the function by ``one.''
}{
\spadpaste{g1 : der := a([x,t,y,u,v,z,e]) * one \free{der one ao}\bound{g1}}
}
\xtc{
A current limitation of Axiom forces you to write
functions with more than four arguments using square brackets in this way.
}{
\spadpaste{h1 : der := a([x,y,x,t,x,z,y,r,u,x]) * one 
\free{der one ao}\bound{h1}}
}
 
\xtc{
Now note how the system keeps track of where your coordinate functions
are located in expressions.
}{
\spadpaste{exteriorDifferential g1 \free{g1}}
}
\xtc{
}{
\spadpaste{exteriorDifferential h1 \free{h1}}
}
 
\xtc{
In this example of Euclidean three-space, the basis for the De Rham complex
consists of the eight forms: \spad{1}, \spad{dx}, \spad{dy}, \spad{dz},
\spad{dx*dy}, \spad{dx*dz}, \spad{dy*dz}, and \spad{dx*dy*dz}.
}{
\spadpaste{coefficient(gamma, dx*dy) \free{gamma dxyz}}
}
\xtc{
}{
\spadpaste{coefficient(gamma, one) \free{gamma one}}
}
\xtc{
}{
\spadpaste{coefficient(g1,one) \free{g1 one}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{DeRhamComplexXmpPagePatch1}
\begin{paste}{DeRhamComplexXmpPageFull1}{DeRhamComplexXmpPageEmpty1}
\pastebutton{DeRhamComplexXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{coefRing := Integer\bound{coefRing }}
\indentrel{3}\begin{verbatim}
   (1)  Integer
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty1}
\begin{paste}{DeRhamComplexXmpPageEmpty1}{DeRhamComplexXmpPagePatch1}
\pastebutton{DeRhamComplexXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{coefRing := Integer\bound{coefRing }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch2}
\begin{paste}{DeRhamComplexXmpPageFull2}{DeRhamComplexXmpPageEmpty2}
\pastebutton{DeRhamComplexXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{lv : List Symbol := [x,y,z]\bound{lv }}
\indentrel{3}\begin{verbatim}
   (2)  [x,y,z]
                                      Type: List Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty2}
\begin{paste}{DeRhamComplexXmpPageEmpty2}{DeRhamComplexXmpPagePatch2}
\pastebutton{DeRhamComplexXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{lv : List Symbol := [x,y,z]\bound{lv }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch3}
\begin{paste}{DeRhamComplexXmpPageFull3}{DeRhamComplexXmpPageEmpty3}
\pastebutton{DeRhamComplexXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{der := DERHAM(coefRing,lv)\free{coefRing }\free{lv }\bound{der }}
\indentrel{3}\begin{verbatim}
   (3)  DeRhamComplex(Integer,[x,y,z])
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty3}
\begin{paste}{DeRhamComplexXmpPageEmpty3}{DeRhamComplexXmpPagePatch3}
\pastebutton{DeRhamComplexXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{der := DERHAM(coefRing,lv)\free{coefRing }\free{lv }\bound{der }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch4}
\begin{paste}{DeRhamComplexXmpPageFull4}{DeRhamComplexXmpPageEmpty4}
\pastebutton{DeRhamComplexXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{R := Expression coefRing\free{coefRing }\bound{R }}
\indentrel{3}\begin{verbatim}
   (4)  Expression Integer
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty4}
\begin{paste}{DeRhamComplexXmpPageEmpty4}{DeRhamComplexXmpPagePatch4}
\pastebutton{DeRhamComplexXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{R := Expression coefRing\free{coefRing }\bound{R }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch5}
\begin{paste}{DeRhamComplexXmpPageFull5}{DeRhamComplexXmpPageEmpty5}
\pastebutton{DeRhamComplexXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{f : R := x**2*y*z-5*x**3*y**2*z**5\free{R }\bound{f }}
\indentrel{3}\begin{verbatim}
            3 2 5    2
   (5)  - 5x y z  + x y z
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty5}
\begin{paste}{DeRhamComplexXmpPageEmpty5}{DeRhamComplexXmpPagePatch5}
\pastebutton{DeRhamComplexXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{f : R := x**2*y*z-5*x**3*y**2*z**5\free{R }\bound{f }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch6}
\begin{paste}{DeRhamComplexXmpPageFull6}{DeRhamComplexXmpPageEmpty6}
\pastebutton{DeRhamComplexXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{g : R := z**2*y*cos(z)-7*sin(x**3*y**2)*z**2\free{R }\bound{g }}
\indentrel{3}\begin{verbatim}
            2     3 2       2
   (6)  - 7z sin(x y ) + y z cos(z)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty6}
\begin{paste}{DeRhamComplexXmpPageEmpty6}{DeRhamComplexXmpPagePatch6}
\pastebutton{DeRhamComplexXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{g : R := z**2*y*cos(z)-7*sin(x**3*y**2)*z**2\free{R }\bound{g }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch7}
\begin{paste}{DeRhamComplexXmpPageFull7}{DeRhamComplexXmpPageEmpty7}
\pastebutton{DeRhamComplexXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{h : R :=x*y*z-2*x**3*y*z**2\free{R }\bound{h }}
\indentrel{3}\begin{verbatim}
            3   2
   (7)  - 2x y z  + x y z
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty7}
\begin{paste}{DeRhamComplexXmpPageEmpty7}{DeRhamComplexXmpPagePatch7}
\pastebutton{DeRhamComplexXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{h : R :=x*y*z-2*x**3*y*z**2\free{R }\bound{h }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch8}
\begin{paste}{DeRhamComplexXmpPageFull8}{DeRhamComplexXmpPageEmpty8}
\pastebutton{DeRhamComplexXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{dx : der := generator(1)\free{der }\bound{dx }}
\indentrel{3}\begin{verbatim}
   (8)  dx
                   Type: DeRhamComplex(Integer,[x,y,z])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty8}
\begin{paste}{DeRhamComplexXmpPageEmpty8}{DeRhamComplexXmpPagePatch8}
\pastebutton{DeRhamComplexXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{dx : der := generator(1)\free{der }\bound{dx }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch9}
\begin{paste}{DeRhamComplexXmpPageFull9}{DeRhamComplexXmpPageEmpty9}
\pastebutton{DeRhamComplexXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{dy : der := generator(2)\free{der }\bound{dy }}
\indentrel{3}\begin{verbatim}
   (9)  dy
                   Type: DeRhamComplex(Integer,[x,y,z])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty9}
\begin{paste}{DeRhamComplexXmpPageEmpty9}{DeRhamComplexXmpPagePatch9}
\pastebutton{DeRhamComplexXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{dy : der := generator(2)\free{der }\bound{dy }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch10}
\begin{paste}{DeRhamComplexXmpPageFull10}{DeRhamComplexXmpPageEmpty10}
\pastebutton{DeRhamComplexXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{dz : der := generator(3)\free{der }\bound{dz }}
\indentrel{3}\begin{verbatim}
   (10)  dz
                   Type: DeRhamComplex(Integer,[x,y,z])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty10}
\begin{paste}{DeRhamComplexXmpPageEmpty10}{DeRhamComplexXmpPagePatch10}
\pastebutton{DeRhamComplexXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{dz : der := generator(3)\free{der }\bound{dz }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch11}
\begin{paste}{DeRhamComplexXmpPageFull11}{DeRhamComplexXmpPageEmpty11}
\pastebutton{DeRhamComplexXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{[dx,dy,dz] := [generator(i)$der for i in 1..3]\free{der }\bound{dxyz }}
\indentrel{3}\begin{verbatim}
   (11)  [dx,dy,dz]
              Type: List DeRhamComplex(Integer,[x,y,z])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty11}
\begin{paste}{DeRhamComplexXmpPageEmpty11}{DeRhamComplexXmpPagePatch11}
\pastebutton{DeRhamComplexXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{[dx,dy,dz] := [generator(i)$der for i in 1..3]\free{der }\bound{dxyz }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch12}
\begin{paste}{DeRhamComplexXmpPageFull12}{DeRhamComplexXmpPageEmpty12}
\pastebutton{DeRhamComplexXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{alpha : der := f*dx + g*dy + h*dz\bound{alpha }\free{der f g h dxyz }}
\indentrel{3}\begin{verbatim}
   (12)
          3   2
     (- 2x y z  + x y z)dz
   + 
        2     3 2       2                 3 2 5    2
   (- 7z sin(x y ) + y z cos(z))dy + (- 5x y z  + x y z)dx
                   Type: DeRhamComplex(Integer,[x,y,z])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty12}
\begin{paste}{DeRhamComplexXmpPageEmpty12}{DeRhamComplexXmpPagePatch12}
\pastebutton{DeRhamComplexXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{alpha : der := f*dx + g*dy + h*dz\bound{alpha }\free{der f g h dxyz }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch13}
\begin{paste}{DeRhamComplexXmpPageFull13}{DeRhamComplexXmpPageEmpty13}
\pastebutton{DeRhamComplexXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{beta : der := cos(tan(x*y*z)+x*y*z)*dx + x*dy\bound{beta }\free{der f g h dxyz }}
\indentrel{3}\begin{verbatim}
   (13)  x dy + cos(tan(x y z) + x y z)dx
                   Type: DeRhamComplex(Integer,[x,y,z])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty13}
\begin{paste}{DeRhamComplexXmpPageEmpty13}{DeRhamComplexXmpPagePatch13}
\pastebutton{DeRhamComplexXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{beta : der := cos(tan(x*y*z)+x*y*z)*dx + x*dy\bound{beta }\free{der f g h dxyz }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch14}
\begin{paste}{DeRhamComplexXmpPageFull14}{DeRhamComplexXmpPageEmpty14}
\pastebutton{DeRhamComplexXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{exteriorDifferential alpha;\free{alpha }\bound{ed }}
\indentrel{3}\begin{verbatim}
                   Type: DeRhamComplex(Integer,[x,y,z])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty14}
\begin{paste}{DeRhamComplexXmpPageEmpty14}{DeRhamComplexXmpPagePatch14}
\pastebutton{DeRhamComplexXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{exteriorDifferential alpha;\free{alpha }\bound{ed }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch15}
\begin{paste}{DeRhamComplexXmpPageFull15}{DeRhamComplexXmpPageEmpty15}
\pastebutton{DeRhamComplexXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{exteriorDifferential \%\free{ed }}
\indentrel{3}\begin{verbatim}
   (15)  0
                   Type: DeRhamComplex(Integer,[x,y,z])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty15}
\begin{paste}{DeRhamComplexXmpPageEmpty15}{DeRhamComplexXmpPagePatch15}
\pastebutton{DeRhamComplexXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{exteriorDifferential \%\free{ed }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch16}
\begin{paste}{DeRhamComplexXmpPageFull16}{DeRhamComplexXmpPageEmpty16}
\pastebutton{DeRhamComplexXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{gamma := alpha * beta\bound{gamma }\free{alpha }\free{beta }}
\indentrel{3}\begin{verbatim}
   (16)
        4   2    2
     (2x y z  - x y z)dy dz
   + 
        3   2
     (2x y z  - x y z)cos(tan(x y z) + x y z)dx dz
   + 
              2     3 2       2
           (7z sin(x y ) - y z cos(z))
        *
           cos(tan(x y z) + x y z)
       + 
             4 2 5    3
         - 5x y z  + x y z
    *
       dx dy
                   Type: DeRhamComplex(Integer,[x,y,z])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty16}
\begin{paste}{DeRhamComplexXmpPageEmpty16}{DeRhamComplexXmpPagePatch16}
\pastebutton{DeRhamComplexXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{gamma := alpha * beta\bound{gamma }\free{alpha }\free{beta }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch17}
\begin{paste}{DeRhamComplexXmpPageFull17}{DeRhamComplexXmpPageEmpty17}
\pastebutton{DeRhamComplexXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{exteriorDifferential(gamma) - (exteriorDifferential(alpha)*beta - alpha * exteriorDifferential(beta))\free{alpha beta gamma }}
\indentrel{3}\begin{verbatim}
   (17)  0
                   Type: DeRhamComplex(Integer,[x,y,z])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty17}
\begin{paste}{DeRhamComplexXmpPageEmpty17}{DeRhamComplexXmpPagePatch17}
\pastebutton{DeRhamComplexXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{exteriorDifferential(gamma) - (exteriorDifferential(alpha)*beta - alpha * exteriorDifferential(beta))\free{alpha beta gamma }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch18}
\begin{paste}{DeRhamComplexXmpPageFull18}{DeRhamComplexXmpPageEmpty18}
\pastebutton{DeRhamComplexXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{a : BOP := operator('a)\bound{ao }}
\indentrel{3}\begin{verbatim}
   (18)  a
                                    Type: BasicOperator
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty18}
\begin{paste}{DeRhamComplexXmpPageEmpty18}{DeRhamComplexXmpPagePatch18}
\pastebutton{DeRhamComplexXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{a : BOP := operator('a)\bound{ao }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch19}
\begin{paste}{DeRhamComplexXmpPageFull19}{DeRhamComplexXmpPageEmpty19}
\pastebutton{DeRhamComplexXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{b : BOP := operator('b)\bound{bo }}
\indentrel{3}\begin{verbatim}
   (19)  b
                                    Type: BasicOperator
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty19}
\begin{paste}{DeRhamComplexXmpPageEmpty19}{DeRhamComplexXmpPagePatch19}
\pastebutton{DeRhamComplexXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{b : BOP := operator('b)\bound{bo }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch20}
\begin{paste}{DeRhamComplexXmpPageFull20}{DeRhamComplexXmpPageEmpty20}
\pastebutton{DeRhamComplexXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{c : BOP := operator('c)\bound{co }}
\indentrel{3}\begin{verbatim}
   (20)  c
                                    Type: BasicOperator
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty20}
\begin{paste}{DeRhamComplexXmpPageEmpty20}{DeRhamComplexXmpPagePatch20}
\pastebutton{DeRhamComplexXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{c : BOP := operator('c)\bound{co }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch21}
\begin{paste}{DeRhamComplexXmpPageFull21}{DeRhamComplexXmpPageEmpty21}
\pastebutton{DeRhamComplexXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{sigma := a(x,y,z) * dx + b(x,y,z) * dy + c(x,y,z) * dz\bound{sigma }\free{ao bo co dxyz }}
\indentrel{3}\begin{verbatim}
   (21)  c(x,y,z)dz + b(x,y,z)dy + a(x,y,z)dx
                   Type: DeRhamComplex(Integer,[x,y,z])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty21}
\begin{paste}{DeRhamComplexXmpPageEmpty21}{DeRhamComplexXmpPagePatch21}
\pastebutton{DeRhamComplexXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{sigma := a(x,y,z) * dx + b(x,y,z) * dy + c(x,y,z) * dz\bound{sigma }\free{ao bo co dxyz }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch22}
\begin{paste}{DeRhamComplexXmpPageFull22}{DeRhamComplexXmpPageEmpty22}
\pastebutton{DeRhamComplexXmpPageFull22}{\hidepaste}
\tab{5}\spadcommand{theta := a(x,y,z) * dx * dy + b(x,y,z) * dx * dz + c(x,y,z) * dy * dz\bound{theta }\free{ao bo co dxyz }}
\indentrel{3}\begin{verbatim}
   (22)  c(x,y,z)dy dz + b(x,y,z)dx dz + a(x,y,z)dx dy
                   Type: DeRhamComplex(Integer,[x,y,z])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty22}
\begin{paste}{DeRhamComplexXmpPageEmpty22}{DeRhamComplexXmpPagePatch22}
\pastebutton{DeRhamComplexXmpPageEmpty22}{\showpaste}
\tab{5}\spadcommand{theta := a(x,y,z) * dx * dy + b(x,y,z) * dx * dz + c(x,y,z) * dy * dz\bound{theta }\free{ao bo co dxyz }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch23}
\begin{paste}{DeRhamComplexXmpPageFull23}{DeRhamComplexXmpPageEmpty23}
\pastebutton{DeRhamComplexXmpPageFull23}{\hidepaste}
\tab{5}\spadcommand{totalDifferential(a(x,y,z))$der\free{ao der }}
\indentrel{3}\begin{verbatim}
   (23)  a  (x,y,z)dz + a  (x,y,z)dy + a  (x,y,z)dx
          ,3             ,2             ,1
                   Type: DeRhamComplex(Integer,[x,y,z])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty23}
\begin{paste}{DeRhamComplexXmpPageEmpty23}{DeRhamComplexXmpPagePatch23}
\pastebutton{DeRhamComplexXmpPageEmpty23}{\showpaste}
\tab{5}\spadcommand{totalDifferential(a(x,y,z))$der\free{ao der }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch24}
\begin{paste}{DeRhamComplexXmpPageFull24}{DeRhamComplexXmpPageEmpty24}
\pastebutton{DeRhamComplexXmpPageFull24}{\hidepaste}
\tab{5}\spadcommand{exteriorDifferential sigma\free{sigma }}
\indentrel{3}\begin{verbatim}
   (24)
     (c  (x,y,z) - b  (x,y,z))dy dz
       ,2           ,3
   + 
     (c  (x,y,z) - a  (x,y,z))dx dz
       ,1           ,3
   + 
     (b  (x,y,z) - a  (x,y,z))dx dy
       ,1           ,2
                   Type: DeRhamComplex(Integer,[x,y,z])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty24}
\begin{paste}{DeRhamComplexXmpPageEmpty24}{DeRhamComplexXmpPagePatch24}
\pastebutton{DeRhamComplexXmpPageEmpty24}{\showpaste}
\tab{5}\spadcommand{exteriorDifferential sigma\free{sigma }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch25}
\begin{paste}{DeRhamComplexXmpPageFull25}{DeRhamComplexXmpPageEmpty25}
\pastebutton{DeRhamComplexXmpPageFull25}{\hidepaste}
\tab{5}\spadcommand{exteriorDifferential theta\free{theta }}
\indentrel{3}\begin{verbatim}
   (25)  (c  (x,y,z) - b  (x,y,z) + a  (x,y,z))dx dy dz
           ,1           ,2           ,3
                   Type: DeRhamComplex(Integer,[x,y,z])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty25}
\begin{paste}{DeRhamComplexXmpPageEmpty25}{DeRhamComplexXmpPagePatch25}
\pastebutton{DeRhamComplexXmpPageEmpty25}{\showpaste}
\tab{5}\spadcommand{exteriorDifferential theta\free{theta }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch26}
\begin{paste}{DeRhamComplexXmpPageFull26}{DeRhamComplexXmpPageEmpty26}
\pastebutton{DeRhamComplexXmpPageFull26}{\hidepaste}
\tab{5}\spadcommand{one : der := 1\bound{one }\free{der }}
\indentrel{3}\begin{verbatim}
   (26)  1
                   Type: DeRhamComplex(Integer,[x,y,z])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty26}
\begin{paste}{DeRhamComplexXmpPageEmpty26}{DeRhamComplexXmpPagePatch26}
\pastebutton{DeRhamComplexXmpPageEmpty26}{\showpaste}
\tab{5}\spadcommand{one : der := 1\bound{one }\free{der }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch27}
\begin{paste}{DeRhamComplexXmpPageFull27}{DeRhamComplexXmpPageEmpty27}
\pastebutton{DeRhamComplexXmpPageFull27}{\hidepaste}
\tab{5}\spadcommand{g1 : der := a([x,t,y,u,v,z,e]) * one\free{der one ao }\bound{g1 }}
\indentrel{3}\begin{verbatim}
   (27)  a(x,t,y,u,v,z,e)
                   Type: DeRhamComplex(Integer,[x,y,z])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty27}
\begin{paste}{DeRhamComplexXmpPageEmpty27}{DeRhamComplexXmpPagePatch27}
\pastebutton{DeRhamComplexXmpPageEmpty27}{\showpaste}
\tab{5}\spadcommand{g1 : der := a([x,t,y,u,v,z,e]) * one\free{der one ao }\bound{g1 }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch28}
\begin{paste}{DeRhamComplexXmpPageFull28}{DeRhamComplexXmpPageEmpty28}
\pastebutton{DeRhamComplexXmpPageFull28}{\hidepaste}
\tab{5}\spadcommand{h1 : der := a([x,y,x,t,x,z,y,r,u,x]) * one\free{der one ao }\bound{h1 }}
\indentrel{3}\begin{verbatim}
   (28)  a(x,y,x,t,x,z,y,r,u,x)
                   Type: DeRhamComplex(Integer,[x,y,z])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty28}
\begin{paste}{DeRhamComplexXmpPageEmpty28}{DeRhamComplexXmpPagePatch28}
\pastebutton{DeRhamComplexXmpPageEmpty28}{\showpaste}
\tab{5}\spadcommand{h1 : der := a([x,y,x,t,x,z,y,r,u,x]) * one\free{der one ao }\bound{h1 }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch29}
\begin{paste}{DeRhamComplexXmpPageFull29}{DeRhamComplexXmpPageEmpty29}
\pastebutton{DeRhamComplexXmpPageFull29}{\hidepaste}
\tab{5}\spadcommand{exteriorDifferential g1\free{g1 }}
\indentrel{3}\begin{verbatim}
   (29)
     a  (x,t,y,u,v,z,e)dz + a  (x,t,y,u,v,z,e)dy
      ,6                     ,3
   + 
     a  (x,t,y,u,v,z,e)dx
      ,1
                   Type: DeRhamComplex(Integer,[x,y,z])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty29}
\begin{paste}{DeRhamComplexXmpPageEmpty29}{DeRhamComplexXmpPagePatch29}
\pastebutton{DeRhamComplexXmpPageEmpty29}{\showpaste}
\tab{5}\spadcommand{exteriorDifferential g1\free{g1 }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch30}
\begin{paste}{DeRhamComplexXmpPageFull30}{DeRhamComplexXmpPageEmpty30}
\pastebutton{DeRhamComplexXmpPageFull30}{\hidepaste}
\tab{5}\spadcommand{exteriorDifferential h1\free{h1 }}
\indentrel{3}\begin{verbatim}
   (30)
     a  (x,y,x,t,x,z,y,r,u,x)dz
      ,6
   + 
           a  (x,y,x,t,x,z,y,r,u,x)
            ,7
         + 
           a  (x,y,x,t,x,z,y,r,u,x)
            ,2
    *
       dy
   + 
         a   (x,y,x,t,x,z,y,r,u,x)
          ,10
       + 
         a  (x,y,x,t,x,z,y,r,u,x)
          ,5
       + 
       a  (x,y,x,t,x,z,y,r,u,x) + a  (x,y,x,t,x,z,y,r,u,x)
        ,3                         ,1
    *
       dx
                   Type: DeRhamComplex(Integer,[x,y,z])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty30}
\begin{paste}{DeRhamComplexXmpPageEmpty30}{DeRhamComplexXmpPagePatch30}
\pastebutton{DeRhamComplexXmpPageEmpty30}{\showpaste}
\tab{5}\spadcommand{exteriorDifferential h1\free{h1 }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch31}
\begin{paste}{DeRhamComplexXmpPageFull31}{DeRhamComplexXmpPageEmpty31}
\pastebutton{DeRhamComplexXmpPageFull31}{\hidepaste}
\tab{5}\spadcommand{coefficient(gamma, dx*dy)\free{gamma dxyz }}
\indentrel{3}\begin{verbatim}
   (31)
        2     3 2       2
     (7z sin(x y ) - y z cos(z))cos(tan(x y z) + x y z)
   + 
         4 2 5    3
     - 5x y z  + x y z
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty31}
\begin{paste}{DeRhamComplexXmpPageEmpty31}{DeRhamComplexXmpPagePatch31}
\pastebutton{DeRhamComplexXmpPageEmpty31}{\showpaste}
\tab{5}\spadcommand{coefficient(gamma, dx*dy)\free{gamma dxyz }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch32}
\begin{paste}{DeRhamComplexXmpPageFull32}{DeRhamComplexXmpPageEmpty32}
\pastebutton{DeRhamComplexXmpPageFull32}{\hidepaste}
\tab{5}\spadcommand{coefficient(gamma, one)\free{gamma one }}
\indentrel{3}\begin{verbatim}
   (32)  0
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty32}
\begin{paste}{DeRhamComplexXmpPageEmpty32}{DeRhamComplexXmpPagePatch32}
\pastebutton{DeRhamComplexXmpPageEmpty32}{\showpaste}
\tab{5}\spadcommand{coefficient(gamma, one)\free{gamma one }}
\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPagePatch33}
\begin{paste}{DeRhamComplexXmpPageFull33}{DeRhamComplexXmpPageEmpty33}
\pastebutton{DeRhamComplexXmpPageFull33}{\hidepaste}
\tab{5}\spadcommand{coefficient(g1,one)\free{g1 one }}
\indentrel{3}\begin{verbatim}
   (33)  a(x,t,y,u,v,z,e)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DeRhamComplexXmpPageEmpty33}
\begin{paste}{DeRhamComplexXmpPageEmpty33}{DeRhamComplexXmpPagePatch33}
\pastebutton{DeRhamComplexXmpPageEmpty33}{\showpaste}
\tab{5}\spadcommand{coefficient(g1,one)\free{g1 one }}
\end{paste}\end{patch}

\end{chunk}
\section{dfloat.ht}
\pagetitle{DoubleFloatXmpPage}{dfloat.ht}{DoubleFloat}
\pagepic{ps/v71doublefloatxmppage.eps}{DoubleFloatXmpPage}{0.50}
\pagefrom{Axiom Number Types}{NumberPage}
\pageto{Graphics}{ugGraphPage}
\pageto{Numeric Functions}{ugProblemNumericPage}
\pageto{Float}{FloatXmpPage}
\begin{chunk}{dfloat.ht}
\begin{page}{DoubleFloatXmpPage}{DoubleFloat}
\beginscroll
Axiom provides two kinds of floating point numbers.
The domain \spadtype{Float} (abbreviation \spadtype{FLOAT})
implements a model of arbitrary
precision floating point numbers.
The domain \spadtype{DoubleFloat} (abbreviation \spadtype{DFLOAT})
is intended to make available
hardware floating point arithmetic in Axiom.
The actual model of floating point \spadtype{DoubleFloat} that provides is
system-dependent.
For example, on the IBM system 370 Axiom uses IBM double
precision which has fourteen hexadecimal digits of precision or roughly
sixteen decimal digits.
Arbitrary precision floats allow the user to specify the
precision at which arithmetic operations are computed.
Although this is an attractive facility, it comes at a cost.
Arbitrary-precision floating-point arithmetic typically takes
twenty to two hundred times more time than hardware floating point.

The usual arithmetic and elementary functions are available for
\spadtype{DoubleFloat}.
Use \spadsys{)show DoubleFloat} to get a list of operations or
the Hyperdoc \Browse{} facility to get more extensive
documentation about \spadtype{DoubleFloat}.

\xtc{
By default, floating point numbers that you enter into Axiom
are of type \spadtype{Float}.
}{
\spadpaste{2.71828}
}
You must therefore tell Axiom that you want to use
\spadtype{DoubleFloat} values and operations.
The following are some conservative guidelines for getting
Axiom to use \spadtype{DoubleFloat}.

\xtc{
To get a value of type \spadtype{DoubleFloat}, use a target with
\spadSyntax{@}, \ldots
}{
\spadpaste{2.71828@DoubleFloat}
}
\xtc{
a conversion, \ldots
}{
\spadpaste{2.71828 :: DoubleFloat}
}
\xtc{
or an assignment to a declared variable.
It is more efficient if you use a target rather than an explicit or
implicit conversion.
}{
\spadpaste{eApprox : DoubleFloat := 2.71828 \bound{eApprox}}
}

\xtc{
You also need to declare functions that work with
\spadtype{DoubleFloat}.
}{
\spadpaste{avg : List DoubleFloat -> DoubleFloat \bound{avgDec}}
}
\xtc{
}{
\begin{spadsrc}[\bound{avg}\free{avgDec}]
avg l ==
  empty? l => 0 :: DoubleFloat
  reduce(_+,l) / #l
\end{spadsrc}
}
\xtc{
}{
\spadpaste{avg [] \free{avg}}
}
\xtc{
}{
\spadpaste{avg [3.4,9.7,-6.8] \free{avg}}
}
\xtc{
Use package-calling for operations from \spadtype{DoubleFloat} unless
the arguments themselves are already of type \spadtype{DoubleFloat}.
}{
\spadpaste{cos(3.1415926)\$DoubleFloat}
}
\xtc{
}{
\spadpaste{cos(3.1415926 :: DoubleFloat)}
}

By far, the most common usage of \spadtype{DoubleFloat} is for functions
to be graphed.
For more information about Axiom's numerical and graphical
facilities, see
\downlink{``Graphics''}{ugGraphPage} in Section 7.
\ignore{ugGraph},
\downlink{``Numeric Functions''}{ugProblemNumericPage} in 
Section 8.1\ignore{ugProblemNumeric}, and
\downlink{`Float'}{FloatXmpPage}\ignore{Float}.
\endscroll
\autobuttons
\end{page}

\begin{patch}{DoubleFloatXmpPagePatch1}
\begin{paste}{DoubleFloatXmpPageFull1}{DoubleFloatXmpPageEmpty1}
\pastebutton{DoubleFloatXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{2.71828}
\indentrel{3}\begin{verbatim}
   (1)  2.71828
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DoubleFloatXmpPageEmpty1}
\begin{paste}{DoubleFloatXmpPageEmpty1}{DoubleFloatXmpPagePatch1}
\pastebutton{DoubleFloatXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{2.71828}
\end{paste}\end{patch}

\begin{patch}{DoubleFloatXmpPagePatch2}
\begin{paste}{DoubleFloatXmpPageFull2}{DoubleFloatXmpPageEmpty2}
\pastebutton{DoubleFloatXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{2.71828@DoubleFloat}
\indentrel{3}\begin{verbatim}
   (2)  2.71828
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DoubleFloatXmpPageEmpty2}
\begin{paste}{DoubleFloatXmpPageEmpty2}{DoubleFloatXmpPagePatch2}
\pastebutton{DoubleFloatXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{2.71828@DoubleFloat}
\end{paste}\end{patch}

\begin{patch}{DoubleFloatXmpPagePatch3}
\begin{paste}{DoubleFloatXmpPageFull3}{DoubleFloatXmpPageEmpty3}
\pastebutton{DoubleFloatXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{2.71828 :: DoubleFloat}
\indentrel{3}\begin{verbatim}
   (3)  2.71828
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DoubleFloatXmpPageEmpty3}
\begin{paste}{DoubleFloatXmpPageEmpty3}{DoubleFloatXmpPagePatch3}
\pastebutton{DoubleFloatXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{2.71828 :: DoubleFloat}
\end{paste}\end{patch}

\begin{patch}{DoubleFloatXmpPagePatch4}
\begin{paste}{DoubleFloatXmpPageFull4}{DoubleFloatXmpPageEmpty4}
\pastebutton{DoubleFloatXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{eApprox : DoubleFloat := 2.71828\bound{eApprox }}
\indentrel{3}\begin{verbatim}
   (4)  2.71828
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DoubleFloatXmpPageEmpty4}
\begin{paste}{DoubleFloatXmpPageEmpty4}{DoubleFloatXmpPagePatch4}
\pastebutton{DoubleFloatXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{eApprox : DoubleFloat := 2.71828\bound{eApprox }}
\end{paste}\end{patch}

\begin{patch}{DoubleFloatXmpPagePatch5}
\begin{paste}{DoubleFloatXmpPageFull5}{DoubleFloatXmpPageEmpty5}
\pastebutton{DoubleFloatXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{avg : List DoubleFloat -> DoubleFloat\bound{avgDec }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DoubleFloatXmpPageEmpty5}
\begin{paste}{DoubleFloatXmpPageEmpty5}{DoubleFloatXmpPagePatch5}
\pastebutton{DoubleFloatXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{avg : List DoubleFloat -> DoubleFloat\bound{avgDec }}
\end{paste}\end{patch}

\begin{patch}{DoubleFloatXmpPagePatch6}
\begin{paste}{DoubleFloatXmpPageFull6}{DoubleFloatXmpPageEmpty6}
\pastebutton{DoubleFloatXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{avg l ==
  empty? l => 0 :: DoubleFloat
  reduce(_+,l) / \#l
\bound{avg }\free{avgDec }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DoubleFloatXmpPageEmpty6}
\begin{paste}{DoubleFloatXmpPageEmpty6}{DoubleFloatXmpPagePatch6}
\pastebutton{DoubleFloatXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{avg l ==
  empty? l => 0 :: DoubleFloat
  reduce(_+,l) / \#l
\bound{avg }\free{avgDec }}
\end{paste}\end{patch}

\begin{patch}{DoubleFloatXmpPagePatch7}
\begin{paste}{DoubleFloatXmpPageFull7}{DoubleFloatXmpPageEmpty7}
\pastebutton{DoubleFloatXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{avg []\free{avg }}
\indentrel{3}\begin{verbatim}
   (7)  0.0
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DoubleFloatXmpPageEmpty7}
\begin{paste}{DoubleFloatXmpPageEmpty7}{DoubleFloatXmpPagePatch7}
\pastebutton{DoubleFloatXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{avg []\free{avg }}
\end{paste}\end{patch}

\begin{patch}{DoubleFloatXmpPagePatch8}
\begin{paste}{DoubleFloatXmpPageFull8}{DoubleFloatXmpPageEmpty8}
\pastebutton{DoubleFloatXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{avg [3.4,9.7,-6.8]\free{avg }}
\indentrel{3}\begin{verbatim}
   (8)  2.1
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DoubleFloatXmpPageEmpty8}
\begin{paste}{DoubleFloatXmpPageEmpty8}{DoubleFloatXmpPagePatch8}
\pastebutton{DoubleFloatXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{avg [3.4,9.7,-6.8]\free{avg }}
\end{paste}\end{patch}

\begin{patch}{DoubleFloatXmpPagePatch9}
\begin{paste}{DoubleFloatXmpPageFull9}{DoubleFloatXmpPageEmpty9}
\pastebutton{DoubleFloatXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{cos(3.1415926)$DoubleFloat}
\indentrel{3}\begin{verbatim}
   (9)  - 0.999999999999999
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DoubleFloatXmpPageEmpty9}
\begin{paste}{DoubleFloatXmpPageEmpty9}{DoubleFloatXmpPagePatch9}
\pastebutton{DoubleFloatXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{cos(3.1415926)$DoubleFloat}
\end{paste}\end{patch}

\begin{patch}{DoubleFloatXmpPagePatch10}
\begin{paste}{DoubleFloatXmpPageFull10}{DoubleFloatXmpPageEmpty10}
\pastebutton{DoubleFloatXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{cos(3.1415926 :: DoubleFloat)}
\indentrel{3}\begin{verbatim}
   (10)  - 0.999999999999999
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DoubleFloatXmpPageEmpty10}
\begin{paste}{DoubleFloatXmpPageEmpty10}{DoubleFloatXmpPagePatch10}
\pastebutton{DoubleFloatXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{cos(3.1415926 :: DoubleFloat)}
\end{paste}\end{patch}

\end{chunk}
\section{dmp.ht}
\pagetitle{DistributedMultivariatePolyXmpPage}{dmp.ht}
{DistributedMultivariatePoly}
\pageto{notitle}{ugIntroVariablesPage}
\pageto{notitle}{ugTypesConvertPage}
\pageto{notitle}{PolynomialXmpPage}
\pageto{notitle}{UnivariatePolyXmpPage}
\pageto{notitle}{MultivariatePolyXmpPage}
\begin{chunk}{dmp.ht}
\begin{page}{DistributedMultivariatePolyXmpPage}
{DistributedMultivariatePoly}
\beginscroll

\texht{\hyphenation{
Homo-gen-eous-Dis-tributed-Multi-var-i-ate-Pol-y-nomial
}}{}

\spadtype{DistributedMultivariatePoly} and
\spadtype{HomogeneousDistributedMultivariatePoly}, abbreviated
\spadtype{DMP} and \spadtype{HDMP}, respectively, are very similar to
\spadtype{MultivariatePolynomial} except that they are represented and
displayed in a non-recursive manner.
\xtc{
}{
\spadpaste{(d1,d2,d3) : DMP([z,y,x],FRAC INT) \bound{d1dec d2dec d3dec}}
}
\xtc{
The constructor
\spadtype{DMP} orders its monomials lexicographically while
\spadtype{HDMP} orders them by total order refined by reverse
lexicographic order.
}{
\spadpaste{d1 := -4*z + 4*y**2*x + 16*x**2 + 1 \bound{d1}\free{d1dec}}
}
\xtc{
}{
\spadpaste{d2 := 2*z*y**2 + 4*x + 1 \bound{d2}\free{d2dec}}
}
\xtc{
}{
\spadpaste{d3 := 2*z*x**2 - 2*y**2 - x \bound{d3}\free{d3dec}}
}
\xtc{
These constructors are mostly used in \texht{Gr\"{o}bner}{Groebner}
basis calculations.
}{
\spadpaste{groebner [d1,d2,d3] \free{d1 d2 d3}}
}
\xtc{
}{
\spadpaste{(n1,n2,n3) : HDMP([z,y,x],FRAC INT) \bound{ndec}}
}
\xtc{
}{
\spadpaste{(n1,n2,n3) := (d1,d2,d3) \free{ndec}\bound{n}\free{d1 d2 d3}}
}
\xtc{
Note that we get a different
\texht{Gr\"{o}bner}{Groebner} basis
when we use the \spadtype{HDMP} polynomials, as expected.
}{
\spadpaste{groebner [n1,n2,n3] \free{n}}
}

\spadtype{GeneralDistributedMultivariatePoly} is somewhat
more flexible in the sense that as well as accepting a list of
variables to specify the variable ordering, it also takes a
predicate on exponent vectors to specify the term ordering.
With this polynomial type the user can experiment with the effect
of using completely arbitrary term orderings.
This flexibility is mostly important for algorithms such as
\texht{Gr\"{o}bner}{Groebner} basis calculations which can be very
sensitive to term ordering.

For more information on related topics, see
\downlink{``Polynomials''}{ugIntroVariablesPage} 
in Section 1.9\ignore{ugIntroVariables},
\downlink{``Conversion''}{ugTypesConvertPage} 
in Section 2.7\ignore{ugTypesConvert},
\downlink{`Polynomial'}{PolynomialXmpPage}\ignore{Polynomial},
\downlink{`UnivariatePolynomial'}{UnivariatePolyXmpPage}
\ignore{UnivariatePolynomial}, and
\downlink{`MultivariatePolynomial'}{MultivariatePolyXmpPage}
\ignore{MultivariatePolynomial}.
%
\showBlurb{DistributedMultivariatePoly}
\endscroll
\autobuttons
\end{page}

\begin{patch}{DistributedMultivariatePolynomialXmpPagePatch1}
\begin{paste}{DistributedMultivariatePolynomialXmpPageFull1}{DistributedMultivariatePolynomialXmpPageEmpty1}
\pastebutton{DistributedMultivariatePolynomialXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{(d1,d2,d3) : DMP([z,y,x],FRAC INT)\bound{d1dec d2dec d3dec }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DistributedMultivariatePolynomialXmpPageEmpty1}
\begin{paste}{DistributedMultivariatePolynomialXmpPageEmpty1}{DistributedMultivariatePolynomialXmpPagePatch1}
\pastebutton{DistributedMultivariatePolynomialXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{(d1,d2,d3) : DMP([z,y,x],FRAC INT)\bound{d1dec d2dec d3dec }}
\end{paste}\end{patch}

\begin{patch}{DistributedMultivariatePolynomialXmpPagePatch2}
\begin{paste}{DistributedMultivariatePolynomialXmpPageFull2}{DistributedMultivariatePolynomialXmpPageEmpty2}
\pastebutton{DistributedMultivariatePolynomialXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{d1 := -4*z + 4*y**2*x + 16*x**2 + 1\bound{d1 }\free{d1dec }}
\indentrel{3}\begin{verbatim}
                 2       2
   (2)  - 4z + 4y x + 16x  + 1
Type: DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DistributedMultivariatePolynomialXmpPageEmpty2}
\begin{paste}{DistributedMultivariatePolynomialXmpPageEmpty2}{DistributedMultivariatePolynomialXmpPagePatch2}
\pastebutton{DistributedMultivariatePolynomialXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{d1 := -4*z + 4*y**2*x + 16*x**2 + 1\bound{d1 }\free{d1dec }}
\end{paste}\end{patch}

\begin{patch}{DistributedMultivariatePolynomialXmpPagePatch3}
\begin{paste}{DistributedMultivariatePolynomialXmpPageFull3}{DistributedMultivariatePolynomialXmpPageEmpty3}
\pastebutton{DistributedMultivariatePolynomialXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{d2 := 2*z*y**2 + 4*x + 1\bound{d2 }\free{d2dec }}
\indentrel{3}\begin{verbatim}
            2
   (3)  2z y  + 4x + 1
Type: DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DistributedMultivariatePolynomialXmpPageEmpty3}
\begin{paste}{DistributedMultivariatePolynomialXmpPageEmpty3}{DistributedMultivariatePolynomialXmpPagePatch3}
\pastebutton{DistributedMultivariatePolynomialXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{d2 := 2*z*y**2 + 4*x + 1\bound{d2 }\free{d2dec }}
\end{paste}\end{patch}

\begin{patch}{DistributedMultivariatePolynomialXmpPagePatch4}
\begin{paste}{DistributedMultivariatePolynomialXmpPageFull4}{DistributedMultivariatePolynomialXmpPageEmpty4}
\pastebutton{DistributedMultivariatePolynomialXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{d3 := 2*z*x**2 - 2*y**2 - x\bound{d3 }\free{d3dec }}
\indentrel{3}\begin{verbatim}
            2     2
   (4)  2z x  - 2y  - x
Type: DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DistributedMultivariatePolynomialXmpPageEmpty4}
\begin{paste}{DistributedMultivariatePolynomialXmpPageEmpty4}{DistributedMultivariatePolynomialXmpPagePatch4}
\pastebutton{DistributedMultivariatePolynomialXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{d3 := 2*z*x**2 - 2*y**2 - x\bound{d3 }\free{d3dec }}
\end{paste}\end{patch}

\begin{patch}{DistributedMultivariatePolynomialXmpPagePatch5}
\begin{paste}{DistributedMultivariatePolynomialXmpPageFull5}{DistributedMultivariatePolynomialXmpPageEmpty5}
\pastebutton{DistributedMultivariatePolynomialXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{groebner [d1,d2,d3]\free{d1 d2 d3 }}
\indentrel{3}\begin{verbatim}
   (5)
   [
           1568  6   1264  5    6   4   182  3   2047  2
       z - ÄÄÄÄ x  - ÄÄÄÄ x  + ÄÄÄ x  + ÄÄÄ x  - ÄÄÄÄ x
           2745       305      305      549       610
     + 
          103      2857
       - ÄÄÄÄ x - ÄÄÄÄÄ
         2745     10980
     ,

        2    112  6    84  5   1264  4    13  3    84  2
       y  + ÄÄÄÄ x  - ÄÄÄ x  - ÄÄÄÄ x  - ÄÄÄ x  + ÄÄÄ x
            2745      305       305      549      305
     + 
       1772       2
       ÄÄÄÄ x + ÄÄÄÄ
       2745     2745
     ,
     7   29  6   17  4   11  3    1  2   15     1
    x  + ÄÄ x  - ÄÄ x  - ÄÄ x  + ÄÄ x  + ÄÄ x + Ä]
          4      16       8      32      16     4
Type: List DistributedMultivariatePolynomial([z,y,x],Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DistributedMultivariatePolynomialXmpPageEmpty5}
\begin{paste}{DistributedMultivariatePolynomialXmpPageEmpty5}{DistributedMultivariatePolynomialXmpPagePatch5}
\pastebutton{DistributedMultivariatePolynomialXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{groebner [d1,d2,d3]\free{d1 d2 d3 }}
\end{paste}\end{patch}

\begin{patch}{DistributedMultivariatePolynomialXmpPagePatch6}
\begin{paste}{DistributedMultivariatePolynomialXmpPageFull6}{DistributedMultivariatePolynomialXmpPageEmpty6}
\pastebutton{DistributedMultivariatePolynomialXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{(n1,n2,n3) : HDMP([z,y,x],FRAC INT)\bound{ndec }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DistributedMultivariatePolynomialXmpPageEmpty6}
\begin{paste}{DistributedMultivariatePolynomialXmpPageEmpty6}{DistributedMultivariatePolynomialXmpPagePatch6}
\pastebutton{DistributedMultivariatePolynomialXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{(n1,n2,n3) : HDMP([z,y,x],FRAC INT)\bound{ndec }}
\end{paste}\end{patch}

\begin{patch}{DistributedMultivariatePolynomialXmpPagePatch7}
\begin{paste}{DistributedMultivariatePolynomialXmpPageFull7}{DistributedMultivariatePolynomialXmpPageEmpty7}
\pastebutton{DistributedMultivariatePolynomialXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{(n1,n2,n3) := (d1,d2,d3)\free{ndec }\bound{n }\free{d1 d2 d3 }}
\indentrel{3}\begin{verbatim}
            2     2
   (7)  2z x  - 2y  - x
Type: HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DistributedMultivariatePolynomialXmpPageEmpty7}
\begin{paste}{DistributedMultivariatePolynomialXmpPageEmpty7}{DistributedMultivariatePolynomialXmpPagePatch7}
\pastebutton{DistributedMultivariatePolynomialXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{(n1,n2,n3) := (d1,d2,d3)\free{ndec }\bound{n }\free{d1 d2 d3 }}
\end{paste}\end{patch}

\begin{patch}{DistributedMultivariatePolynomialXmpPagePatch8}
\begin{paste}{DistributedMultivariatePolynomialXmpPageFull8}{DistributedMultivariatePolynomialXmpPageEmpty8}
\pastebutton{DistributedMultivariatePolynomialXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{groebner [n1,n2,n3]\free{n }}
\indentrel{3}\begin{verbatim}
   (8)
     4     3   3  2   1     1
   [y  + 2x  - Ä x  + Ä z - Ä,
               2      2     8
     4   29  3   1  2   7        9     1     2        1
    x  + ÄÄ x  - Ä y  - Ä z x - ÄÄ x - Ä, z y  + 2x + Ä,
          4      8      4       16     4              2
     2      2       1     2    2   1
    y x + 4x  - z + Ä, z x  - y  - Ä x,
                    4              2
     2     2     2   1     3
    z  - 4y  + 2x  - Ä z - Ä x]
                     4     2
Type: List HomogeneousDistributedMultivariatePolynomial([z,y,x],Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{DistributedMultivariatePolynomialXmpPageEmpty8}
\begin{paste}{DistributedMultivariatePolynomialXmpPageEmpty8}{DistributedMultivariatePolynomialXmpPagePatch8}
\pastebutton{DistributedMultivariatePolynomialXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{groebner [n1,n2,n3]\free{n }}
\end{paste}\end{patch}

\end{chunk}
\section{eq.ht}
\pagetitle{EquationXmpPage}{eq.ht}{Equation}
\begin{chunk}{eq.ht}
\begin{page}{EquationXmpPage}{Equation}
\beginscroll

The \spadtype{Equation} domain provides equations as mathematical objects.
These are used, for example, as the input to various
\spadfunFrom{solve}{TransSolvePackage} operations.

\xtc{
Equations are created using the equals symbol, \spadopFrom{=}{Equation}.
}{
\spadpaste{eq1 := 3*x + 4*y = 5 \bound{eq1}}
}
\xtc{
}{
\spadpaste{eq2 := 2*x + 2*y = 3 \bound{eq2}}
}
\xtc{
The left- and right-hand sides of an equation are accessible using
the operations \spadfunFrom{lhs}{Equation} and \spadfunFrom{rhs}{Equation}.
}{
\spadpaste{lhs eq1 \free{eq1}}
}
\xtc{
}{
\spadpaste{rhs eq1 \free{eq1}}
}

\xtc{
Arithmetic operations are supported
and operate on both sides of the equation.
}{
\spadpaste{eq1 + eq2   \free{eq1 eq2}}
}
\xtc{
}{
\spadpaste{eq1 * eq2   \free{eq1 eq2}}
}
\xtc{
}{
\spadpaste{2*eq2 - eq1 \free{eq1 eq2}}
}
\xtc{
Equations may be created for any type so the arithmetic operations
will be defined only when they make sense.  For example,
exponentiation is not defined for equations involving non-square matrices.
}{
\spadpaste{eq1**2 \free{eq1}}
}

\xtc{
Note that an equals symbol is also used to {\it test}
for equality of values in certain contexts.
For example, \spad{x+1} and \spad{y} are unequal as polynomials.
}{
\spadpaste{if x+1 = y then "equal" else "unequal"}
}
\xtc{
}{
\spadpaste{eqpol := x+1 = y \bound{eqpol}}
}
\xtc{
If an equation is used where a \spadtype{Boolean} value
is required, then it is evaluated using the equality
test from the operand type.
}{
\spadpaste{if eqpol then "equal" else "unequal" \free{eqpol}}
}
\xtc{
If one wants a \spadtype{Boolean} value rather than an equation,
all one has to do is ask!
}{
\spadpaste{eqpol::Boolean \free{eqpol}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{EquationXmpPagePatch1}
\begin{paste}{EquationXmpPageFull1}{EquationXmpPageEmpty1}
\pastebutton{EquationXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{eq1 := 3*x + 4*y = 5\bound{eq1 }}
\indentrel{3}\begin{verbatim}
   (1)  4y + 3x= 5
                      Type: Equation Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{EquationXmpPageEmpty1}
\begin{paste}{EquationXmpPageEmpty1}{EquationXmpPagePatch1}
\pastebutton{EquationXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{eq1 := 3*x + 4*y = 5\bound{eq1 }}
\end{paste}\end{patch}

\begin{patch}{EquationXmpPagePatch2}
\begin{paste}{EquationXmpPageFull2}{EquationXmpPageEmpty2}
\pastebutton{EquationXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{eq2 := 2*x + 2*y = 3\bound{eq2 }}
\indentrel{3}\begin{verbatim}
   (2)  2y + 2x= 3
                      Type: Equation Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{EquationXmpPageEmpty2}
\begin{paste}{EquationXmpPageEmpty2}{EquationXmpPagePatch2}
\pastebutton{EquationXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{eq2 := 2*x + 2*y = 3\bound{eq2 }}
\end{paste}\end{patch}

\begin{patch}{EquationXmpPagePatch3}
\begin{paste}{EquationXmpPageFull3}{EquationXmpPageEmpty3}
\pastebutton{EquationXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{lhs eq1\free{eq1 }}
\indentrel{3}\begin{verbatim}
   (3)  4y + 3x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{EquationXmpPageEmpty3}
\begin{paste}{EquationXmpPageEmpty3}{EquationXmpPagePatch3}
\pastebutton{EquationXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{lhs eq1\free{eq1 }}
\end{paste}\end{patch}

\begin{patch}{EquationXmpPagePatch4}
\begin{paste}{EquationXmpPageFull4}{EquationXmpPageEmpty4}
\pastebutton{EquationXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{rhs eq1\free{eq1 }}
\indentrel{3}\begin{verbatim}
   (4)  5
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{EquationXmpPageEmpty4}
\begin{paste}{EquationXmpPageEmpty4}{EquationXmpPagePatch4}
\pastebutton{EquationXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{rhs eq1\free{eq1 }}
\end{paste}\end{patch}

\begin{patch}{EquationXmpPagePatch5}
\begin{paste}{EquationXmpPageFull5}{EquationXmpPageEmpty5}
\pastebutton{EquationXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{eq1 + eq2\free{eq1 eq2 }}
\indentrel{3}\begin{verbatim}
   (5)  6y + 5x= 8
                      Type: Equation Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{EquationXmpPageEmpty5}
\begin{paste}{EquationXmpPageEmpty5}{EquationXmpPagePatch5}
\pastebutton{EquationXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{eq1 + eq2\free{eq1 eq2 }}
\end{paste}\end{patch}

\begin{patch}{EquationXmpPagePatch6}
\begin{paste}{EquationXmpPageFull6}{EquationXmpPageEmpty6}
\pastebutton{EquationXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{eq1 * eq2\free{eq1 eq2 }}
\indentrel{3}\begin{verbatim}
          2             2
   (6)  8y  + 14x y + 6x = 15
                      Type: Equation Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{EquationXmpPageEmpty6}
\begin{paste}{EquationXmpPageEmpty6}{EquationXmpPagePatch6}
\pastebutton{EquationXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{eq1 * eq2\free{eq1 eq2 }}
\end{paste}\end{patch}

\begin{patch}{EquationXmpPagePatch7}
\begin{paste}{EquationXmpPageFull7}{EquationXmpPageEmpty7}
\pastebutton{EquationXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{2*eq2 - eq1\free{eq1 eq2 }}
\indentrel{3}\begin{verbatim}
   (7)  x= 1
                      Type: Equation Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{EquationXmpPageEmpty7}
\begin{paste}{EquationXmpPageEmpty7}{EquationXmpPagePatch7}
\pastebutton{EquationXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{2*eq2 - eq1\free{eq1 eq2 }}
\end{paste}\end{patch}

\begin{patch}{EquationXmpPagePatch8}
\begin{paste}{EquationXmpPageFull8}{EquationXmpPageEmpty8}
\pastebutton{EquationXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{eq1**2\free{eq1 }}
\indentrel{3}\begin{verbatim}
           2             2
   (8)  16y  + 24x y + 9x = 25
                      Type: Equation Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{EquationXmpPageEmpty8}
\begin{paste}{EquationXmpPageEmpty8}{EquationXmpPagePatch8}
\pastebutton{EquationXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{eq1**2\free{eq1 }}
\end{paste}\end{patch}

\begin{patch}{EquationXmpPagePatch9}
\begin{paste}{EquationXmpPageFull9}{EquationXmpPageEmpty9}
\pastebutton{EquationXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{if x+1 = y then "equal" else "unequal"}
\indentrel{3}\begin{verbatim}
   (9)  "unequal"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{EquationXmpPageEmpty9}
\begin{paste}{EquationXmpPageEmpty9}{EquationXmpPagePatch9}
\pastebutton{EquationXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{if x+1 = y then "equal" else "unequal"}
\end{paste}\end{patch}

\begin{patch}{EquationXmpPagePatch10}
\begin{paste}{EquationXmpPageFull10}{EquationXmpPageEmpty10}
\pastebutton{EquationXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{eqpol := x+1 = y\bound{eqpol }}
\indentrel{3}\begin{verbatim}
   (10)  x + 1= y
                      Type: Equation Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{EquationXmpPageEmpty10}
\begin{paste}{EquationXmpPageEmpty10}{EquationXmpPagePatch10}
\pastebutton{EquationXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{eqpol := x+1 = y\bound{eqpol }}
\end{paste}\end{patch}

\begin{patch}{EquationXmpPagePatch11}
\begin{paste}{EquationXmpPageFull11}{EquationXmpPageEmpty11}
\pastebutton{EquationXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{if eqpol then "equal" else "unequal"\free{eqpol }}
\indentrel{3}\begin{verbatim}
   (11)  "unequal"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{EquationXmpPageEmpty11}
\begin{paste}{EquationXmpPageEmpty11}{EquationXmpPagePatch11}
\pastebutton{EquationXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{if eqpol then "equal" else "unequal"\free{eqpol }}
\end{paste}\end{patch}

\begin{patch}{EquationXmpPagePatch12}
\begin{paste}{EquationXmpPageFull12}{EquationXmpPageEmpty12}
\pastebutton{EquationXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{eqpol::Boolean\free{eqpol }}
\indentrel{3}\begin{verbatim}
   (12)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{EquationXmpPageEmpty12}
\begin{paste}{EquationXmpPageEmpty12}{EquationXmpPagePatch12}
\pastebutton{EquationXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{eqpol::Boolean\free{eqpol }}
\end{paste}\end{patch}

\end{chunk}
\section{eqtbl.ht}
\pagetitle{EqTableXmpPage}{eqtbl.ht}{EqTable}
\pageto{notitle}{TableXmpPage}
\begin{chunk}{eqtbl.ht}
\begin{page}{EqTableXmpPage}{EqTable}
\beginscroll

The \spadtype{EqTable} domain provides tables where the keys are compared
using \spadfunFrom{eq?}{EqTable}.
Keys are considered equal only if they are the same instance of a
structure.
This is useful if the keys are themselves updatable structures.
Otherwise, all operations are the same as for type \spadtype{Table}.
See \downlink{`Table'}{TableXmpPage}\ignore{Table} 
for general information about tables.
\showBlurb{EqTable}

\xtc{
The operation \spadfunFrom{table}{EqTable} is here used to create a table
where the keys are lists of integers.
}{
\spadpaste{e: EqTable(List Integer, Integer) := table() \bound{e}}
}
\xtc{
These two lists are equal according to \spadopFrom{=}{List},
but not according to \spadfunFrom{eq?}{List}.
}{
\spadpaste{l1 := [1,2,3] \bound{l1}}
}
\xtc{
}{
\spadpaste{l2 := [1,2,3] \bound{l2}}
}
\xtc{
Because the two lists are not \spadfunFrom{eq?}{List}, separate values
can be stored under each.
}{
\spadpaste{e.l1 := 111   \free{e l1} \bound{e1}}
}
\xtc{
}{
\spadpaste{e.l2 := 222   \free{e1 l2} \bound{e2}}
}
\xtc{
}{
\spadpaste{e.l1          \free{e2 l1}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{EqTableXmpPagePatch1}
\begin{paste}{EqTableXmpPageFull1}{EqTableXmpPageEmpty1}
\pastebutton{EqTableXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{e: EqTable(List Integer, Integer) := table()\bound{e }}
\indentrel{3}\begin{verbatim}
   (1)  table()
                    Type: EqTable(List Integer,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{EqTableXmpPageEmpty1}
\begin{paste}{EqTableXmpPageEmpty1}{EqTableXmpPagePatch1}
\pastebutton{EqTableXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{e: EqTable(List Integer, Integer) := table()\bound{e }}
\end{paste}\end{patch}

\begin{patch}{EqTableXmpPagePatch2}
\begin{paste}{EqTableXmpPageFull2}{EqTableXmpPageEmpty2}
\pastebutton{EqTableXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{l1 := [1,2,3]\bound{l1 }}
\indentrel{3}\begin{verbatim}
   (2)  [1,2,3]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{EqTableXmpPageEmpty2}
\begin{paste}{EqTableXmpPageEmpty2}{EqTableXmpPagePatch2}
\pastebutton{EqTableXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{l1 := [1,2,3]\bound{l1 }}
\end{paste}\end{patch}

\begin{patch}{EqTableXmpPagePatch3}
\begin{paste}{EqTableXmpPageFull3}{EqTableXmpPageEmpty3}
\pastebutton{EqTableXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{l2 := [1,2,3]\bound{l2 }}
\indentrel{3}\begin{verbatim}
   (3)  [1,2,3]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{EqTableXmpPageEmpty3}
\begin{paste}{EqTableXmpPageEmpty3}{EqTableXmpPagePatch3}
\pastebutton{EqTableXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{l2 := [1,2,3]\bound{l2 }}
\end{paste}\end{patch}

\begin{patch}{EqTableXmpPagePatch4}
\begin{paste}{EqTableXmpPageFull4}{EqTableXmpPageEmpty4}
\pastebutton{EqTableXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{e.l1 := 111\free{e l1 }\bound{e1 }}
\indentrel{3}\begin{verbatim}
   (4)  111
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{EqTableXmpPageEmpty4}
\begin{paste}{EqTableXmpPageEmpty4}{EqTableXmpPagePatch4}
\pastebutton{EqTableXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{e.l1 := 111\free{e l1 }\bound{e1 }}
\end{paste}\end{patch}

\begin{patch}{EqTableXmpPagePatch5}
\begin{paste}{EqTableXmpPageFull5}{EqTableXmpPageEmpty5}
\pastebutton{EqTableXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{e.l2 := 222\free{e1 l2 }\bound{e2 }}
\indentrel{3}\begin{verbatim}
   (5)  222
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{EqTableXmpPageEmpty5}
\begin{paste}{EqTableXmpPageEmpty5}{EqTableXmpPagePatch5}
\pastebutton{EqTableXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{e.l2 := 222\free{e1 l2 }\bound{e2 }}
\end{paste}\end{patch}

\begin{patch}{EqTableXmpPagePatch6}
\begin{paste}{EqTableXmpPageFull6}{EqTableXmpPageEmpty6}
\pastebutton{EqTableXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{e.l1\free{e2 l1 }}
\indentrel{3}\begin{verbatim}
   (6)  111
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{EqTableXmpPageEmpty6}
\begin{paste}{EqTableXmpPageEmpty6}{EqTableXmpPagePatch6}
\pastebutton{EqTableXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{e.l1\free{e2 l1 }}
\end{paste}\end{patch}

\end{chunk}
\section{evalex.ht}
\pagetitle{PrefixEval}{evalex.ht}{Example of Standard Evaluation}
\begin{chunk}{evalex.ht}
\begin{page}{PrefixEval}{Example of Standard Evaluation}
\beginscroll
We illustrate the general evaluation of {\em op a} for some
prefix operator {\em op} and operand {\em a}
by the example: {\em cos(2)}.
The evaluation steps are as follows:
\vspace{1}\newline
1.\tab{3}{\em a} evaluates to a value of some type.
\newline\tab{3}{\em Example:} {\em 2} evaluates to {\em 2} of type 
\spadtype{Integer}
\newline
2.\tab{3}Axiom then chooses a function {\em op} based on the 
type of {\em a}.
\newline\tab{3}{\em Example:} The function {\em cos:} \spadtype{Float} {\em ->}
\spadtype{Float} is chosen.
\newline
3.\tab{3}If the argument type of the function is different from that 
of {\em a},
then the system coerces
%\downlink{coerces}{Coercion}
the value of {\em a} to the
argument type.
\newline\tab{3}{\em Example:} The integer {\em 2} is coerced to the 
float {\em 2.0}.
\newline
4.\tab{3}The function is then applied to the value of {\em a} to 
produce the value
for {\em op a}.
\newline\tab{3}{\em Example:} The function {\em cos} is applied to {\em 2.0}.
\vspace{1}\newline
Try it:
\example{cos(2)}
\endscroll
\autobuttons
\end{page}

\begin{patch}{PrefixEvalPatch1}
\begin{paste}{PrefixEvalFull1}{PrefixEvalEmpty1}
\pastebutton{PrefixEvalFull1}{\hidepaste}
\tab{5}\spadcommand{cos(2)}
\indentrel{3}\begin{verbatim}
   (1)  cos(2)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PrefixEvalEmpty1}
\begin{paste}{PrefixEvalEmpty1}{PrefixEvalPatch1}
\pastebutton{PrefixEvalEmpty1}{\showpaste}
\tab{5}\spadcommand{cos(2)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{InfixEval}{evalex.ht}{Example of Standard Evaluation}
\begin{chunk}{evalex.ht}
\begin{page}{InfixEval}{Example of Standard Evaluation}
\beginscroll
We illustrate the general evaluation of {\em a op b} for some
infix operator {\em op} with operands {\em a} and {\em b}
by the example: {\em 2 + 3.4}.
The evaluation steps are as follows:
\vspace{1}\newline
1.\tab{3}{\em a} and {\em b} are evaluated, each producing 
a value and a type.
\newline\tab{3}{\em Example:} {\em 2} evaluates to {\em 2} of type 
\spadtype{Integer};
{\em 3.4} evaluates to {\em 3.4} of type \spadtype{Float}.
\vspace{1}\newline
2.\tab{3}Axiom then chooses a function {\em op} based on the 
types of {\em a} and {\em b}.
\newline\tab{3}{\em Example:} The function {\em +: (D,D) -> D}
is chosen requiring a common type {\em D} for both arguments to {\em +}.
An operation called {\em resolve} determines the `smallest common 
type' \spadtype{Float}.
\vspace{1}\newline
3.\tab{3}If the argument types for the function are different from
those of {\em a} and {\em b},
then the system coerces
%\downlink{coerces}{Coercion}
the values to the argument types.
\newline\tab{3}{\em Example:} The integer {\em 2} is coerced to the 
float {\em 2.0}.
\vspace{1}\newline
4.\tab{3}The function is then applied to the values of {\em a} and {\em b}
to produce the value for {\em a op b}.
\newline\tab{3}{\em Example:} The function {\em +: (D,D) -> D}, where
{\em D} = \spadtype{Float} is applied to {\em 2.0} and {\em 3.4} to 
produce {\em 5.4}.
\vspace{1}\newline
Try it:
\example{2 + 3.4}
\endscroll
\autobuttons
\end{page}

\begin{patch}{InfixEvalPatch1}
\begin{paste}{InfixEvalFull1}{InfixEvalEmpty1}
\pastebutton{InfixEvalFull1}{\hidepaste}
\tab{5}\spadcommand{2 + 3.4}
\indentrel{3}\begin{verbatim}
   (1)  5.4
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{InfixEvalEmpty1}
\begin{paste}{InfixEvalEmpty1}{InfixEvalPatch1}
\pastebutton{InfixEvalEmpty1}{\showpaste}
\tab{5}\spadcommand{2 + 3.4}
\end{paste}\end{patch}

\end{chunk}
\section{exdiff.ht}
\pagetitle{ExDiffBasic}{exdiff.ht}{Computing Derivatives}
\begin{chunk}{exdiff.ht}
\begin{page}{ExDiffBasic}{Computing Derivatives}
\beginscroll
To compute a derivative, you must specify an expression and a variable
of differentiation.
For example, to compute the derivative of {\em sin(x) * exp(x**2)} 
with respect to the variable {\em x}, issue the following command:
\spadpaste{differentiate(sin(x) * exp(x**2),x)}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExDiffBasicPatch1}
\begin{paste}{ExDiffBasicFull1}{ExDiffBasicEmpty1}
\pastebutton{ExDiffBasicFull1}{\hidepaste}
\tab{5}\spadcommand{differentiate(sin(x) * exp(x**2),x)}
\indentrel{3}\begin{verbatim}
              2                  2
             x                  x
   (1)  2x %e  sin(x) + cos(x)%e
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExDiffBasicEmpty1}
\begin{paste}{ExDiffBasicEmpty1}{ExDiffBasicPatch1}
\pastebutton{ExDiffBasicEmpty1}{\showpaste}
\tab{5}\spadcommand{differentiate(sin(x) * exp(x**2),x)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExDiffSeveralVariables}{exdiff.ht}
{Derivatives of Functions of Several Variables}
\begin{chunk}{exdiff.ht}
\begin{page}{ExDiffSeveralVariables}
{Derivatives of Functions of Several Variables}
\beginscroll
Partial derivatives are computed in the same way as derivatives of functions
of one variable: you specify the function and a variable of differentiation.
For example:
\spadpaste{differentiate(sin(x) * tan(y)/(x**2 + y**2),x)}
\spadpaste{differentiate(sin(x) * tan(y)/(x**2 + y**2),y)}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExDiffSeveralVariablesPatch1}
\begin{paste}{ExDiffSeveralVariablesFull1}{ExDiffSeveralVariablesEmpty1}
\pastebutton{ExDiffSeveralVariablesFull1}{\hidepaste}
\tab{5}\spadcommand{differentiate(sin(x) * tan(y)/(x**2 + y**2),x)}
\indentrel{3}\begin{verbatim}
                         2    2
        (- 2x sin(x) + (y  + x )cos(x))tan(y)
   (1)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                    4     2 2    4
                   y  + 2x y  + x
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExDiffSeveralVariablesEmpty1}
\begin{paste}{ExDiffSeveralVariablesEmpty1}{ExDiffSeveralVariablesPatch1}
\pastebutton{ExDiffSeveralVariablesEmpty1}{\showpaste}
\tab{5}\spadcommand{differentiate(sin(x) * tan(y)/(x**2 + y**2),x)}
\end{paste}\end{patch}

\begin{patch}{ExDiffSeveralVariablesPatch2}
\begin{paste}{ExDiffSeveralVariablesFull2}{ExDiffSeveralVariablesEmpty2}
\pastebutton{ExDiffSeveralVariablesFull2}{\hidepaste}
\tab{5}\spadcommand{differentiate(sin(x) * tan(y)/(x**2 + y**2),y)}
\indentrel{3}\begin{verbatim}
   (2)
         2    2             2
       (y  + x )sin(x)tan(y)  - 2y sin(x)tan(y)
     + 
         2    2
       (y  + x )sin(x)
  /
      4     2 2    4
     y  + 2x y  + x
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExDiffSeveralVariablesEmpty2}
\begin{paste}{ExDiffSeveralVariablesEmpty2}{ExDiffSeveralVariablesPatch2}
\pastebutton{ExDiffSeveralVariablesEmpty2}{\showpaste}
\tab{5}\spadcommand{differentiate(sin(x) * tan(y)/(x**2 + y**2),y)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExDiffHigherOrder}{exdiff.ht}{Derivatives of Higher Order}
\begin{chunk}{exdiff.ht}
\begin{page}{ExDiffHigherOrder}{Derivatives of Higher Order}
\beginscroll
To compute a derivative of higher order (e.g. a second or third derivative),
pass the order as the third argument of the function 'differentiate'.
For example, to compute the fourth derivative of {\em exp(x**2)}, issue the
following command:
\spadpaste{differentiate(exp(x**2),x,4)}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExDiffHigherOrderPatch1}
\begin{paste}{ExDiffHigherOrderFull1}{ExDiffHigherOrderEmpty1}
\pastebutton{ExDiffHigherOrderFull1}{\hidepaste}
\tab{5}\spadcommand{differentiate(exp(x**2),x,4)}
\indentrel{3}\begin{verbatim}
                             2
            4      2        x
   (1)  (16x  + 48x  + 12)%e
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExDiffHigherOrderEmpty1}
\begin{paste}{ExDiffHigherOrderEmpty1}{ExDiffHigherOrderPatch1}
\pastebutton{ExDiffHigherOrderEmpty1}{\showpaste}
\tab{5}\spadcommand{differentiate(exp(x**2),x,4)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExDiffMultipleI}{exdiff.ht}{Multiple Derivatives I}
\begin{chunk}{exdiff.ht}
\begin{page}{ExDiffMultipleI}{Multiple Derivatives I}
\beginscroll
When given a function of several variables, you may take derivatives 
repeatedly and with respect to different variables.
The following command differentiates the function 
{\em sin(x)/(x**2 + y**2)} first with respect to {\em x} and then with 
respect to {\em y}:
\spadpaste{differentiate(sin(x)/(x**2 + y**2),[x,y])}
As you can see, we first specify the function and then a list of 
the variables of differentiation.
Variables may appear on the list more than once.
For example, the following command differentiates the same function with
respect to {\em x} and then twice with respect to {\em y}.
\spadpaste{differentiate(sin(x)/(x**2 + y**2),[x,y,y])}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExDiffMultipleIPatch1}
\begin{paste}{ExDiffMultipleIFull1}{ExDiffMultipleIEmpty1}
\pastebutton{ExDiffMultipleIFull1}{\hidepaste}
\tab{5}\spadcommand{differentiate(sin(x)/(x**2 + y**2),[x,y])}
\indentrel{3}\begin{verbatim}
                           3     2
        8x y sin(x) + (- 2y  - 2x y)cos(x)
   (1)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
               6     2 4     4 2    6
              y  + 3x y  + 3x y  + x
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExDiffMultipleIEmpty1}
\begin{paste}{ExDiffMultipleIEmpty1}{ExDiffMultipleIPatch1}
\pastebutton{ExDiffMultipleIEmpty1}{\showpaste}
\tab{5}\spadcommand{differentiate(sin(x)/(x**2 + y**2),[x,y])}
\end{paste}\end{patch}

\begin{patch}{ExDiffMultipleIPatch2}
\begin{paste}{ExDiffMultipleIFull2}{ExDiffMultipleIEmpty2}
\pastebutton{ExDiffMultipleIFull2}{\hidepaste}
\tab{5}\spadcommand{differentiate(sin(x)/(x**2 + y**2),[x,y,y])}
\indentrel{3}\begin{verbatim}
   (2)
           2     3             4     2 2     4
   (- 40x y  + 8x )sin(x) + (6y  + 4x y  - 2x )cos(x)
   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
              8     2 6     4 4     6 2    8
             y  + 4x y  + 6x y  + 4x y  + x
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExDiffMultipleIEmpty2}
\begin{paste}{ExDiffMultipleIEmpty2}{ExDiffMultipleIPatch2}
\pastebutton{ExDiffMultipleIEmpty2}{\showpaste}
\tab{5}\spadcommand{differentiate(sin(x)/(x**2 + y**2),[x,y,y])}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExDiffMultipleII}{exdiff.ht}{Multiple Derivatives II}
\begin{chunk}{exdiff.ht}
\begin{page}{ExDiffMultipleII}{Multiple Derivatives II}
\beginscroll
You may also compute multiple derivatives by specifying a list of 
variables together with a list of multiplicities.
For example, to differentiate {\em cos(z)/(x**2 + y**3)}
first with respect to {\em x}, then twice with respect to {\em y}, 
then three times with respect to {\em z},
issue the following command:
\spadpaste{differentiate(cos(z)/(x**2 + y**3),[x,y,z],[1,2,3])}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExDiffMultipleIIPatch1}
\begin{paste}{ExDiffMultipleIIFull1}{ExDiffMultipleIIEmpty1}
\pastebutton{ExDiffMultipleIIFull1}{\hidepaste}
\tab{5}\spadcommand{differentiate(cos(z)/(x**2 + y**3),[x,y,z],[1,2,3])}
\indentrel{3}\begin{verbatim}
                    4      3
            (- 84x y  + 24x y)sin(z)
   (1)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
         12     2 9     4 6     6 3    8
        y   + 4x y  + 6x y  + 4x y  + x
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExDiffMultipleIIEmpty1}
\begin{paste}{ExDiffMultipleIIEmpty1}{ExDiffMultipleIIPatch1}
\pastebutton{ExDiffMultipleIIEmpty1}{\showpaste}
\tab{5}\spadcommand{differentiate(cos(z)/(x**2 + y**3),[x,y,z],[1,2,3])}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExDiffFormalIntegral}{exdiff.ht}
{Derivatives of Functions Involving Formal Integrals}
\begin{chunk}{exdiff.ht}
\begin{page}{ExDiffFormalIntegral}
{Derivatives of Functions Involving Formal Integrals}
\beginscroll
When a function does not have a closed-form antiderivative, Axiom
returns a formal integral.
A typical example is
\spadpaste{f := integrate(sqrt(1 + t**3),t) \bound{f}}
This formal integral may be differentiated, either by itself or in any
combination with other functions:
\spadpaste{differentiate(f,t) \free{f}}
\spadpaste{differentiate(f * t**2,t) \free{f}}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExDiffFormalIntegralPatch1}
\begin{paste}{ExDiffFormalIntegralFull1}{ExDiffFormalIntegralEmpty1}
\pastebutton{ExDiffFormalIntegralFull1}{\hidepaste}
\tab{5}\spadcommand{f := integrate(sqrt(1 + t**3),t)\bound{f }}
\indentrel{3}\begin{verbatim}
           t  ÚÄÄÄÄÄÄÄ¿
         Ú¿   ³  3
   (1)   ³   \³%N  + 1 d%N
        ÀÙ
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExDiffFormalIntegralEmpty1}
\begin{paste}{ExDiffFormalIntegralEmpty1}{ExDiffFormalIntegralPatch1}
\pastebutton{ExDiffFormalIntegralEmpty1}{\showpaste}
\tab{5}\spadcommand{f := integrate(sqrt(1 + t**3),t)\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ExDiffFormalIntegralPatch2}
\begin{paste}{ExDiffFormalIntegralFull2}{ExDiffFormalIntegralEmpty2}
\pastebutton{ExDiffFormalIntegralFull2}{\hidepaste}
\tab{5}\spadcommand{differentiate(f,t)\free{f }}
\indentrel{3}\begin{verbatim}
         ÚÄÄÄÄÄÄ¿
         ³ 3
   (2)  \³t  + 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExDiffFormalIntegralEmpty2}
\begin{paste}{ExDiffFormalIntegralEmpty2}{ExDiffFormalIntegralPatch2}
\pastebutton{ExDiffFormalIntegralEmpty2}{\showpaste}
\tab{5}\spadcommand{differentiate(f,t)\free{f }}
\end{paste}\end{patch}

\begin{patch}{ExDiffFormalIntegralPatch3}
\begin{paste}{ExDiffFormalIntegralFull3}{ExDiffFormalIntegralEmpty3}
\pastebutton{ExDiffFormalIntegralFull3}{\hidepaste}
\tab{5}\spadcommand{differentiate(f * t**2,t)\free{f }}
\indentrel{3}\begin{verbatim}
             t  ÚÄÄÄÄÄÄÄ¿          ÚÄÄÄÄÄÄ¿
           Ú¿   ³  3             2 ³ 3
   (3)  2t ³   \³%N  + 1 d%N  + t \³t  + 1
          ÀÙ
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExDiffFormalIntegralEmpty3}
\begin{paste}{ExDiffFormalIntegralEmpty3}{ExDiffFormalIntegralPatch3}
\pastebutton{ExDiffFormalIntegralEmpty3}{\showpaste}
\tab{5}\spadcommand{differentiate(f * t**2,t)\free{f }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExitXmpPage}{exit.ht}{Exit}
\begin{chunk}{exit.ht}
\begin{page}{ExitXmpPage}{Exit}
\beginscroll

A function that does not return directly to its caller has
\spadtype{Exit} as its return type.
The operation \spadfun{error} is an example of one which does not return
to its caller.
Instead, it causes a return to top-level.
\xtc{
}{
\spadpaste{n := 0 \bound{n}}
}
\xtc{
The function \userfun{gasp} is given return type \spadtype{Exit} since 
it is guaranteed never to return a value to its caller.
}{
\begin{spadsrc}[\bound{gasp}\free{n}]
gasp(): Exit ==
    free n
    n := n + 1
    error "Oh no!"
\end{spadsrc}
}
\xtc{
The return type of \userfun{half} is determined by resolving the 
types of the two branches of the \spad{if}.
}{
\begin{spadsrc}[\bound{half}\free{gasp}]
half(k) ==
  if odd? k then gasp()
  else k quo 2
\end{spadsrc}
}
\xtc{
Because
\userfun{gasp} has the return type \spadtype{Exit}, the type of 
\spad{if} in \userfun{half} is resolved to be \spadtype{Integer}.
}{
\spadpaste{half 4 \free{half}\bound{app1}}
}
\xtc{
}{
\spadpaste{half 3 \free{half app1}\bound{app2}}
}
\xtc{
}{
\spadpaste{n \free{app2}}
}

For functions which return no value at all, use \spadtype{Void}.
See \downlink{``User-Defined Functions, Macros and Rules''}
{ugUserPage} in Section 6\ignore{ugUser} and 
\downlink{`Void'}{VoidXmpPage}\ignore{Void} for more information.
%
\showBlurb{Exit}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExitXmpPagePatch1}
\begin{paste}{ExitXmpPageFull1}{ExitXmpPageEmpty1}
\pastebutton{ExitXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{n := 0\bound{n }}
\indentrel{3}\begin{verbatim}
   (1)  0
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExitXmpPageEmpty1}
\begin{paste}{ExitXmpPageEmpty1}{ExitXmpPagePatch1}
\pastebutton{ExitXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{n := 0\bound{n }}
\end{paste}\end{patch}

\begin{patch}{ExitXmpPagePatch2}
\begin{paste}{ExitXmpPageFull2}{ExitXmpPageEmpty2}
\pastebutton{ExitXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{gasp(): Exit ==
    free n
    n := n + 1
    error "Oh no!"
\bound{gasp }\free{n }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExitXmpPageEmpty2}
\begin{paste}{ExitXmpPageEmpty2}{ExitXmpPagePatch2}
\pastebutton{ExitXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{gasp(): Exit ==
    free n
    n := n + 1
    error "Oh no!"
\bound{gasp }\free{n }}
\end{paste}\end{patch}

\begin{patch}{ExitXmpPagePatch3}
\begin{paste}{ExitXmpPageFull3}{ExitXmpPageEmpty3}
\pastebutton{ExitXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{half(k) ==
  if odd? k then gasp()
  else k quo 2
\bound{half }\free{gasp }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExitXmpPageEmpty3}
\begin{paste}{ExitXmpPageEmpty3}{ExitXmpPagePatch3}
\pastebutton{ExitXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{half(k) ==
  if odd? k then gasp()
  else k quo 2
\bound{half }\free{gasp }}
\end{paste}\end{patch}

\begin{patch}{ExitXmpPagePatch4}
\begin{paste}{ExitXmpPageFull4}{ExitXmpPageEmpty4}
\pastebutton{ExitXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{half 4\free{half }\bound{app1 }}
\indentrel{3}\begin{verbatim}
   (4)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExitXmpPageEmpty4}
\begin{paste}{ExitXmpPageEmpty4}{ExitXmpPagePatch4}
\pastebutton{ExitXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{half 4\free{half }\bound{app1 }}
\end{paste}\end{patch}

\begin{patch}{ExitXmpPagePatch5}
\begin{paste}{ExitXmpPageFull5}{ExitXmpPageEmpty5}
\pastebutton{ExitXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{half 3\free{half app1 }\bound{app2 }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExitXmpPageEmpty5}
\begin{paste}{ExitXmpPageEmpty5}{ExitXmpPagePatch5}
\pastebutton{ExitXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{half 3\free{half app1 }\bound{app2 }}
\end{paste}\end{patch}

\begin{patch}{ExitXmpPagePatch6}
\begin{paste}{ExitXmpPageFull6}{ExitXmpPageEmpty6}
\pastebutton{ExitXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{n\free{app2 }}
\indentrel{3}\begin{verbatim}
   (5)  1
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExitXmpPageEmpty6}
\begin{paste}{ExitXmpPageEmpty6}{ExitXmpPagePatch6}
\pastebutton{ExitXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{n\free{app2 }}
\end{paste}\end{patch}

\end{chunk}
\section{exlap.ht}
\pagetitle{ExLapSimplePole}{exlap.ht}{Laplace transform with a single pole}
\begin{chunk}{exlap.ht}
\begin{page}{ExLapSimplePole}{Laplace transform with a single pole}
\beginscroll
The Laplace transform of t^n e^(a t) has a pole of order n+1 at x = a
and no other pole. We divide by n! to get a monic denominator in the
answer.
\spadpaste{laplace(t**4 * exp(-a*t) / factorial(4), t, s)}
\endscroll
\autobuttons\end{page}

\begin{patch}{ExLapSimplePolePatch1}
\begin{paste}{ExLapSimplePoleFull1}{ExLapSimplePoleEmpty1}
\pastebutton{ExLapSimplePoleFull1}{\hidepaste}
\tab{5}\spadcommand{laplace(t**4 * exp(-a*t) / factorial(4), t, s)}
\indentrel{3}\begin{verbatim}
                            1
   (1)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
         5       4      2 3      3 2     4     5
        s  + 5a s  + 10a s  + 10a s  + 5a s + a
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExLapSimplePoleEmpty1}
\begin{paste}{ExLapSimplePoleEmpty1}{ExLapSimplePolePatch1}
\pastebutton{ExLapSimplePoleEmpty1}{\showpaste}
\tab{5}\spadcommand{laplace(t**4 * exp(-a*t) / factorial(4), t, s)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExLapTrigTrigh}{exlap.ht}
{Laplace transform of a trigonometric function}
\begin{chunk}{exlap.ht}
\begin{page}{ExLapTrigTrigh}{Laplace transform of a trigonometric function}
\beginscroll
Rather than looking up into a table, we use the normalizer to rewrite
the trigs and hyperbolic trigs to complex exponentials and
logarithms.
\spadpaste{laplace(sin(a*t) * cosh(a*t) - cos(a*t) * sinh(a*t), t, s)}
\endscroll
\autobuttons\end{page}

\begin{patch}{ExLapTrigTrighPatch1}
\begin{paste}{ExLapTrigTrighFull1}{ExLapTrigTrighEmpty1}
\pastebutton{ExLapTrigTrighFull1}{\hidepaste}
\tab{5}\spadcommand{laplace(sin(a*t) * cosh(a*t) - cos(a*t) * sinh(a*t), t, s)}
\indentrel{3}\begin{verbatim}
             3
           4a
   (1)  ÄÄÄÄÄÄÄÄ
         4     4
        s  + 4a
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExLapTrigTrighEmpty1}
\begin{paste}{ExLapTrigTrighEmpty1}{ExLapTrigTrighPatch1}
\pastebutton{ExLapTrigTrighEmpty1}{\showpaste}
\tab{5}\spadcommand{laplace(sin(a*t) * cosh(a*t) - cos(a*t) * sinh(a*t), t, s)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExLapDefInt}{exlap.ht}
{Laplace transform requiring a definite integration}
\begin{chunk}{exlap.ht}
\begin{page}{ExLapDefInt}
{Laplace transform requiring a definite integration}
\beginscroll
When powers of t appear in the denominator, computing the laplace 
transform requires integrating the result of another laplace 
transform between a symbol and infinity. We use the full power of 
Axiom's integrator in such cases.
\spadpaste{laplace(2/t * (1 - cos(a*t)), t, s)}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExLapDefIntPatch1}
\begin{paste}{ExLapDefIntFull1}{ExLapDefIntEmpty1}
\pastebutton{ExLapDefIntFull1}{\hidepaste}
\tab{5}\spadcommand{laplace(2/t * (1 - cos(a*t)), t, s)}
\indentrel{3}\begin{verbatim}
             2    2
   (1)  log(s  + a ) - 2log(s)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExLapDefIntEmpty1}
\begin{paste}{ExLapDefIntEmpty1}{ExLapDefIntPatch1}
\pastebutton{ExLapDefIntEmpty1}{\showpaste}
\tab{5}\spadcommand{laplace(2/t * (1 - cos(a*t)), t, s)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExLapExpExp}{exlap.ht}{Laplace transform of exponentials}
\begin{chunk}{exlap.ht}
\begin{page}{ExLapExpExp}{Laplace transform of exponentials}
\beginscroll
This is another example where it is necessary to
integrate the result of another laplace transform.
\spadpaste{laplace((exp(a*t) - exp(b*t))/t, t, s)}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExLapExpExpPatch1}
\begin{paste}{ExLapExpExpFull1}{ExLapExpExpEmpty1}
\pastebutton{ExLapExpExpFull1}{\hidepaste}
\tab{5}\spadcommand{laplace((exp(a*t) - exp(b*t))/t, t, s)}
\indentrel{3}\begin{verbatim}
   (1)  - log(s - a) + log(s - b)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExLapExpExpEmpty1}
\begin{paste}{ExLapExpExpEmpty1}{ExLapExpExpPatch1}
\pastebutton{ExLapExpExpEmpty1}{\showpaste}
\tab{5}\spadcommand{laplace((exp(a*t) - exp(b*t))/t, t, s)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExLapSpecial1}{exlap.ht}
{Laplace transform of an exponential integral}
\begin{chunk}{exlap.ht}
\begin{page}{ExLapSpecial1}
{Laplace transform of an exponential integral}
We can handle some restricted cases of special functions, 
linear exponential integrals among them.
\beginscroll
\spadpaste{laplace(exp(a*t+b)*Ei(c*t), t, s)}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExLapSpecial1Patch1}
\begin{paste}{ExLapSpecial1Full1}{ExLapSpecial1Empty1}
\pastebutton{ExLapSpecial1Full1}{\hidepaste}
\tab{5}\spadcommand{laplace(exp(a*t+b)*Ei(c*t), t, s)}
\indentrel{3}\begin{verbatim}
          b    s + c - a
        %e log(ÄÄÄÄÄÄÄÄÄ)
                   c
   (1)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
              s - a
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExLapSpecial1Empty1}
\begin{paste}{ExLapSpecial1Empty1}{ExLapSpecial1Patch1}
\pastebutton{ExLapSpecial1Empty1}{\showpaste}
\tab{5}\spadcommand{laplace(exp(a*t+b)*Ei(c*t), t, s)}
\end{paste}\end{patch}

\begin{patch}{ExLapSpecial2Patch1}
\begin{paste}{ExLapSpecial2Full1}{ExLapSpecial2Empty1}
\pastebutton{ExLapSpecial2Full1}{\hidepaste}
\tab{5}\spadcommand{laplace(a*Ci(b*t) + c*Si(d*t), t, s)}
\indentrel{3}\begin{verbatim}
               2    2
              s  + b             d
        a log(ÄÄÄÄÄÄÄ) + 2c atan(Ä)
                  2              s
                 b
   (1)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                     2s
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExLapSpecial2Empty1}
\begin{paste}{ExLapSpecial2Empty1}{ExLapSpecial2Patch1}
\pastebutton{ExLapSpecial2Empty1}{\showpaste}
\tab{5}\spadcommand{laplace(a*Ci(b*t) + c*Si(d*t), t, s)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExLapSpecial2}{exlap.ht}{Laplace transform of special functions}
\begin{chunk}{exlap.ht}
\begin{page}{ExLapSpecial2}{Laplace transform of special functions}
\beginscroll
An example with some interesting special functions.
\spadpaste{laplace(a*Ci(b*t) + c*Si(d*t), t, s)}
\endscroll
\autobuttons\end{page}

\end{chunk}
\section{exint.ht}
\pagetitle{ExIntRationalFunction}{exint.ht}{Integral of a Rational Function}
\begin{chunk}{exint.ht}
\begin{page}{ExIntRationalFunction}{Integral of a Rational Function}
\beginscroll
The following fraction has a denominator which factors into
a quadratic and a quartic irreducible polynomial. The usual
partial fraction approach used by most other computer algebra
systems either fails or introduces expensive unneeded algebraic
numbers.
We use a factorization-free algorithm.
\spadpaste{integrate((x**2+2*x+1)/((x+1)**6+1),x)}
There are cases where algebraic numbers are absolutely necessary.
In that case the answer to the \spadfun{integrate} command will contain
symbols like \spad{\%\%F0} denoting the algebraic numbers used.
To find out what the definitions for these numbers is use the
\spadfun{definingPolynomial} operation on these numbers.
\spadpaste{integrate(1/(x**3+x+1),x) \bound{i}}
For example, if a symbol like \spad{\%\%F0} appears in the result of this last
integration, then \spad{definingPolynomial \%\%F0} will return the
polynomial that \spad{\%\%F0} is a root of. The next command isolates the
algebraic number from the expression and displays its defining polynomial.
\spadpaste{definingPolynomial(tower(\%).2::EXPR INT) \free{i}}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ExIntRationalFunctionPatch1}
\begin{paste}{ExIntRationalFunctionFull1}{ExIntRationalFunctionEmpty1}
\pastebutton{ExIntRationalFunctionFull1}{\hidepaste}
\tab{5}\spadcommand{integrate((x**2+2*x+1)/((x+1)**6+1),x)}
\indentrel{3}\begin{verbatim}
              3     2
        atan(x  + 3x  + 3x + 1)
   (1)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                   3
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExIntRationalFunctionEmpty1}
\begin{paste}{ExIntRationalFunctionEmpty1}{ExIntRationalFunctionPatch1}
\pastebutton{ExIntRationalFunctionEmpty1}{\showpaste}
\tab{5}\spadcommand{integrate((x**2+2*x+1)/((x+1)**6+1),x)}
\end{paste}\end{patch}

\begin{patch}{ExIntRationalFunctionPatch2}
\begin{paste}{ExIntRationalFunctionFull2}{ExIntRationalFunctionEmpty2}
\pastebutton{ExIntRationalFunctionFull2}{\hidepaste}
\tab{5}\spadcommand{integrate(1/(x**3+x+1),x)\bound{i }}
\indentrel{3}\begin{verbatim}
   (2)
           ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
           ³        2
           ³- 93%%H0  + 12
         ( ³ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ  - %%H0)
          \³      31
      *
         log
                            ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
                            ³        2
                            ³- 93%%H0  + 12          2
              (62%%H0 + 31) ³ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ  + 62%%H0
                           \³      31
            + 
              - 31%%H0 + 18x - 4
     + 
             ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
             ³        2
             ³- 93%%H0  + 12
         (-  ³ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ  - %%H0)
            \³      31
      *
         log
                              ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
                              ³        2
                              ³- 93%%H0  + 12          2
              (- 62%%H0 - 31) ³ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ  + 62%%H0
                             \³      31
            + 
              - 31%%H0 + 18x - 4
     + 
                         2
       2%%H0 log(- 62%%H0  + 31%%H0 + 9x + 4)
  /
     2
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExIntRationalFunctionEmpty2}
\begin{paste}{ExIntRationalFunctionEmpty2}{ExIntRationalFunctionPatch2}
\pastebutton{ExIntRationalFunctionEmpty2}{\showpaste}
\tab{5}\spadcommand{integrate(1/(x**3+x+1),x)\bound{i }}
\end{paste}\end{patch}

\begin{patch}{ExIntRationalFunctionPatch3}
\begin{paste}{ExIntRationalFunctionFull3}{ExIntRationalFunctionEmpty3}
\pastebutton{ExIntRationalFunctionFull3}{\hidepaste}
\tab{5}\spadcommand{definingPolynomial(tower(\%).2::EXPR INT)\free{i }}
\indentrel{3}\begin{verbatim}
              3
        31%%H0  - 3%%H0 - 1
   (3)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                 31
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExIntRationalFunctionEmpty3}
\begin{paste}{ExIntRationalFunctionEmpty3}{ExIntRationalFunctionPatch3}
\pastebutton{ExIntRationalFunctionEmpty3}{\showpaste}
\tab{5}\spadcommand{definingPolynomial(tower(\%).2::EXPR INT)\free{i }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExIntRationalWithRealParameter}{exint.ht}
{Integral of a Rational Function with a Real Parameter}
\begin{chunk}{exint.ht}
\begin{page}{ExIntRationalWithRealParameter}
{Integral of a Rational Function with a Real Parameter}
\beginscroll
When real parameters are present, the form of the integral can depend on
the signs of some expressions. Rather than query the user or make
sign assumptions, Axiom returns all possible answers.
\spadpaste{integrate(1/(x**2 + a),x)}
The integrate command generally assumes that all parameters are real.
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExIntRationalWithRealParameterPatch1}
\begin{paste}{ExIntRationalWithRealParameterFull1}{ExIntRationalWithRealParameterEmpty1}
\pastebutton{ExIntRationalWithRealParameterFull1}{\hidepaste}
\tab{5}\spadcommand{integrate(1/(x**2 + a),x)}
\indentrel{3}\begin{verbatim}
               2      ÚÄÄÄ¿
             (x  - a)\³- a  + 2a x         ÚÄ¿
         log(ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ)      x\³a
                      2             atan(ÄÄÄÄÄ)
                     x  + a                a
   (1)  [ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ,ÄÄÄÄÄÄÄÄÄÄÄ]
                     ÚÄÄÄ¿               ÚÄ¿
                   2\³- a               \³a
               Type: Union(List Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExIntRationalWithRealParameterEmpty1}
\begin{paste}{ExIntRationalWithRealParameterEmpty1}{ExIntRationalWithRealParameterPatch1}
\pastebutton{ExIntRationalWithRealParameterEmpty1}{\showpaste}
\tab{5}\spadcommand{integrate(1/(x**2 + a),x)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExIntRationalWithComplexParameter}{exint.ht}
{Integral of a Rational Function with a Complex Parameter}
\begin{chunk}{exint.ht}
\begin{page}{ExIntRationalWithComplexParameter}
{Integral of a Rational Function with a Complex Parameter}
\beginscroll
If the parameter is complex instead of real, then the notion of
sign is undefined and there is a unique answer.
You can request
this answer by prepending the word `complex' to the command name:
\spadpaste{complexIntegrate(1/(x**2 + a),x)}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExIntRationalWithComplexParameterPatch1}
\begin{paste}{ExIntRationalWithComplexParameterFull1}{ExIntRationalWithComplexParameterEmpty1}
\pastebutton{ExIntRationalWithComplexParameterFull1}{\hidepaste}
\tab{5}\spadcommand{complexIntegrate(1/(x**2 + a),x)}
\indentrel{3}\begin{verbatim}
              ÚÄÄÄ¿              ÚÄÄÄ¿
            x\³- a  + a        x\³- a  - a
        log(ÄÄÄÄÄÄÄÄÄÄÄ) - log(ÄÄÄÄÄÄÄÄÄÄÄ)
                ÚÄÄÄ¿              ÚÄÄÄ¿
               \³- a              \³- a
   (1)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                        ÚÄÄÄ¿
                      2\³- a
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExIntRationalWithComplexParameterEmpty1}
\begin{paste}{ExIntRationalWithComplexParameterEmpty1}{ExIntRationalWithComplexParameterPatch1}
\pastebutton{ExIntRationalWithComplexParameterEmpty1}{\showpaste}
\tab{5}\spadcommand{complexIntegrate(1/(x**2 + a),x)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExIntTwoSimilarIntegrands}{exint.ht}
{Two Similar Integrands Producing Very Different Results}
\begin{chunk}{exint.ht}
\begin{page}{ExIntTwoSimilarIntegrands}
{Two Similar Integrands Producing Very Different Results}
\beginscroll
The following two examples illustrate the limitations of table based
approaches. The two integrands are very similar, but the answer to one
of them requires the addition of two new algebraic numbers.
This one is the easy one:
\spadpaste{integrate(x**3 / (a+b*x)**(1/3),x)}
The next one looks very similar
but the answer is much more complicated. Only an algorithmic approach
is guaranteed to find what new constants must be added in order to
find a solution:
\spadpaste{integrate(1 / (x**3 * (a+b*x)**(1/3)),x)}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExIntTwoSimilarIntegrandsPatch1}
\begin{paste}{ExIntTwoSimilarIntegrandsFull1}{ExIntTwoSimilarIntegrandsEmpty1}
\pastebutton{ExIntTwoSimilarIntegrandsFull1}{\hidepaste}
\tab{5}\spadcommand{integrate(x**3 / (a+b*x)**(1/3),x)}
\indentrel{3}\begin{verbatim}
   (1)
        3 3         2 2       2          3 3ÚÄÄÄÄÄÄÄ¿2
   (120b x  - 135a b x  + 162a b x - 243a )\³b x + a
   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                              4
                          440b
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExIntTwoSimilarIntegrandsEmpty1}
\begin{paste}{ExIntTwoSimilarIntegrandsEmpty1}{ExIntTwoSimilarIntegrandsPatch1}
\pastebutton{ExIntTwoSimilarIntegrandsEmpty1}{\showpaste}
\tab{5}\spadcommand{integrate(x**3 / (a+b*x)**(1/3),x)}
\end{paste}\end{patch}

\begin{patch}{ExIntTwoSimilarIntegrandsPatch2}
\begin{paste}{ExIntTwoSimilarIntegrandsFull2}{ExIntTwoSimilarIntegrandsEmpty2}
\pastebutton{ExIntTwoSimilarIntegrandsFull2}{\hidepaste}
\tab{5}\spadcommand{integrate(1 / (x**3 * (a+b*x)**(1/3)),x)}
\indentrel{3}\begin{verbatim}
   (2)
       -
              2 2 ÚÄ¿
            2b x \³3
         *
                3ÚÄ¿3ÚÄÄÄÄÄÄÄ¿2   3ÚÄ¿2 3ÚÄÄÄÄÄÄÄ¿
            log(\³a \³b x + a   + \³a   \³b x + a + a)
     + 
         2 2 ÚÄ¿    3ÚÄ¿2 3ÚÄÄÄÄÄÄÄ¿
       4b x \³3 log(\³a   \³b x + a - a)
     + 
                    ÚÄ¿3ÚÄ¿2 3ÚÄÄÄÄÄÄÄ¿    ÚÄ¿
          2 2     2\³3 \³a   \³b x + a + a\³3
       12b x atan(ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ)
                               3a
     + 
                    ÚÄ¿3ÚÄ¿3ÚÄÄÄÄÄÄÄ¿2
       (12b x - 9a)\³3 \³a \³b x + a
  /
        2 2 ÚÄ¿3ÚÄ¿
     18a x \³3 \³a
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExIntTwoSimilarIntegrandsEmpty2}
\begin{paste}{ExIntTwoSimilarIntegrandsEmpty2}{ExIntTwoSimilarIntegrandsPatch2}
\pastebutton{ExIntTwoSimilarIntegrandsEmpty2}{\showpaste}
\tab{5}\spadcommand{integrate(1 / (x**3 * (a+b*x)**(1/3)),x)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExIntNoSolution}{exint.ht}{An Integral Which Does Not Exist}
\begin{chunk}{exint.ht}
\begin{page}{ExIntNoSolution}{An Integral Which Does Not Exist}
\beginscroll
Most computer algebra systems use heuristics or table-driven
approaches to integration. When these systems cannot determine
the answer to an integration problem, they reply "I don't know".
Axiom uses a complete algorithm for integration.
It will conclusively prove that an integral
cannot be expressed in terms of elementary functions.
When Axiom returns an integral sign, it has proved
that no answer exists as an elementary function.
\spadpaste{integrate(log(1 + sqrt(a*x + b)) / x,x)}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExIntNoSolutionPatch1}
\begin{paste}{ExIntNoSolutionFull1}{ExIntNoSolutionEmpty1}
\pastebutton{ExIntNoSolutionFull1}{\hidepaste}
\tab{5}\spadcommand{integrate(log(1 + sqrt(a*x + b)) / x,x)}
\indentrel{3}\begin{verbatim}
           x      ÚÄÄÄÄÄÄÄÄ¿
         Ú¿  log(\³b + %T a  + 1)
   (1)   ³   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ d%T
        ÀÙ            %T
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExIntNoSolutionEmpty1}
\begin{paste}{ExIntNoSolutionEmpty1}{ExIntNoSolutionPatch1}
\pastebutton{ExIntNoSolutionEmpty1}{\showpaste}
\tab{5}\spadcommand{integrate(log(1 + sqrt(a*x + b)) / x,x)}
\end{paste}\end{patch}

\end{chunk}
\begin{verbatim}
%% This example is broken
%\begin{page}{ExIntChangeOfVariables}{No Change of Variables is Required}
%\beginscroll
%Unlike computer algebra systems which rely on heuristics and
%table-lookup, the algorithmic integration facility
%of Axiom never requires you to make a change of variables
%in order to integrate a function.
%\spadpaste{integrate(sec(x)**(4/5)*csc(x)**(6/5),x)}
%\endscroll
%\autobuttons\end{page}
\end{verbatim}

\pagetitle{ExIntTrig}{exint.ht}{A Trigonometric Function of a Quadratic}
\begin{chunk}{exint.ht}
\begin{page}{ExIntTrig}{A Trigonometric Function of a Quadratic}
\beginscroll
Axiom can handle complicated mixed functions way beyond what you can
find in tables:
\spadpaste{integrate((sinh(1+sqrt(x+b))+2*sqrt(x+b))/
(sqrt(x+b)*(x+cosh(1+sqrt(x+b)))),x)}
Whenever possible, Axiom tries to express the answer using the functions
present in the integrand.
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExIntTrigPatch1}
\begin{paste}{ExIntTrigFull1}{ExIntTrigEmpty1}
\pastebutton{ExIntTrigFull1}{\hidepaste}
\tab{5}\spadcommand{integrate((sinh(1+sqrt(x+b))+2*sqrt(x+b))/(sqrt(x+b)*(x+cosh(1+sqrt(x+b)))),x)}
\indentrel{3}\begin{verbatim}
   (1)
                          ÚÄÄÄÄÄ¿
                 - 2cosh(\³x + b  + 1) - 2x
     2log(ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ)
                ÚÄÄÄÄÄ¿              ÚÄÄÄÄÄ¿
          sinh(\³x + b  + 1) - cosh(\³x + b  + 1)
   + 
         ÚÄÄÄÄÄ¿
     - 2\³x + b
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExIntTrigEmpty1}
\begin{paste}{ExIntTrigEmpty1}{ExIntTrigPatch1}
\pastebutton{ExIntTrigEmpty1}{\showpaste}
\tab{5}\spadcommand{integrate((sinh(1+sqrt(x+b))+2*sqrt(x+b))/(sqrt(x+b)*(x+cosh(1+sqrt(x+b)))),x)}
\end{paste}
\end{patch}

\end{chunk}
\pagetitle{ExIntAlgebraicRelation}{exint.ht}
{Integrating a Function with a Hidden Algebraic Relation}
\pageto{notitle}{ExIntAlgebraicRelationExplain}
\begin{chunk}{exint.ht}
\begin{page}{ExIntAlgebraicRelation}
{Integrating a Function with a Hidden Algebraic Relation}
\beginscroll
A strong structure checking algorithm in Axiom finds hidden algebraic
relationships between functions.
\spadpaste{integrate(tan(atan(x)/3),x)}
The discovery of this algebraic relationship is necessary
for correctly integrating this function.
\downlink{Details.}{ExIntAlgebraicRelationExplain} \space{1}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExIntAlgebraicRelationPatch1}
\begin{paste}{ExIntAlgebraicRelationFull1}{ExIntAlgebraicRelationEmpty1}
\pastebutton{ExIntAlgebraicRelationFull1}{\hidepaste}
\tab{5}\spadcommand{integrate(tan(atan(x)/3),x)}
\indentrel{3}\begin{verbatim}
   (1)
                 atan(x) 2             atan(x) 2
       8log(3tan(ÄÄÄÄÄÄÄ)  - 1) - 3tan(ÄÄÄÄÄÄÄ)
                    3                     3
     + 
               atan(x)
       18x tan(ÄÄÄÄÄÄÄ)
                  3
  /
     18
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExIntAlgebraicRelationEmpty1}
\begin{paste}{ExIntAlgebraicRelationEmpty1}{ExIntAlgebraicRelationPatch1}
\pastebutton{ExIntAlgebraicRelationEmpty1}{\showpaste}
\tab{5}\spadcommand{integrate(tan(atan(x)/3),x)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExIntAlgebraicRelationExplain}{exint.ht}
{Details for integrating a function with a Hidden Algebraic Relation}
\begin{chunk}{exint.ht}
\begin{page}{ExIntAlgebraicRelationExplain}
{Details for integrating a function with a Hidden Algebraic Relation}
\beginscroll
Steps taken for integration of:
\centerline{{\em f := tan(atan(x)/3)}}
\beginitems
\item
1. Replace {\em f} by an equivalent algebraic function {\em g}
satisfying the algebraic relation:
\centerline{{\em g**3 - 3*x*g - 3*g + x = 0}}
\item
2. Integrate {\em g} using using this algebraic relation; this produces:
\centerline{{\em (24g**2 - 8)log(3g**2 - 1) + (81x**2 + 24)g**2 + 72xg - 27x**2 - 16}}
\centerline{{\em /   (54g**2 - 18)}}
\item
3. Rationalize the denominator, producing:
\centerline{{\em (8log(3g**2-1) - 3g**2 + 18xg + 15)/18}}
\item
4. Replace {\em g} by the initial {\em f} to produce the final result:
\centerline{{\em (8log(3tan(atan(x/3))**2-1) - 3tan(atan(x/3))**2 - 
18xtan(atan(x/3) + 16)/18)}}
\enditems
\endscroll
\autobuttons\end{page}

\end{chunk}
\pagetitle{ExIntRadicalOfTranscendental}{exint.ht}
{An Integral Involving a Root of a Transcendental Function}
\begin{chunk}{exint.ht}
\begin{page}{ExIntRadicalOfTranscendental}
{An Integral Involving a Root of a Transcendental Function}
\beginscroll
This is an example of a mixed function where
the algebraic layer is over the transcendental one.
\spadpaste{integrate((x + 1) / (x * (x + log x)**(3/2)),x)}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExIntRadicalOfTranscendentalPatch1}
\begin{paste}{ExIntRadicalOfTranscendentalFull1}{ExIntRadicalOfTranscendentalEmpty1}
\pastebutton{ExIntRadicalOfTranscendentalFull1}{\hidepaste}
\tab{5}\spadcommand{integrate((x + 1) / (x * (x + log x)**(3/2)),x)}
\indentrel{3}\begin{verbatim}
            ÚÄÄÄÄÄÄÄÄÄÄ¿
          2\³log(x) + x
   (1)  - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
            log(x) + x
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExIntRadicalOfTranscendentalEmpty1}
\begin{paste}{ExIntRadicalOfTranscendentalEmpty1}{ExIntRadicalOfTranscendentalPatch1}
\pastebutton{ExIntRadicalOfTranscendentalEmpty1}{\showpaste}
\tab{5}\spadcommand{integrate((x + 1) / (x * (x + log x)**(3/2)),x)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExIntNonElementary}{exint.ht}
{An Integral of a Non-elementary Function}
\begin{chunk}{exint.ht}
\begin{page}{ExIntNonElementary}{An Integral of a Non-elementary Function}
\beginscroll
While incomplete for non-elementary functions, Axiom can
handle some of them:
\spadpaste{integrate(exp(-x**2) * erf(x) / 
(erf(x)**3 - erf(x)**2 - erf(x) + 1),x)}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExIntNonElementaryPatch1}
\begin{paste}{ExIntNonElementaryFull1}{ExIntNonElementaryEmpty1}
\pastebutton{ExIntNonElementaryFull1}{\hidepaste}
\tab{5}\spadcommand{integrate(exp(-x**2) * erf(x) / (erf(x)**3 - erf(x)**2 - erf(x) + 1),x)}
\indentrel{3}\begin{verbatim}
                     ÚÄÄÄ¿    erf(x) - 1      ÚÄÄÄ¿
        (erf(x) - 1)\³%pi log(ÄÄÄÄÄÄÄÄÄÄ) - 2\³%pi
                              erf(x) + 1
   (1)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                        8erf(x) - 8
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExIntNonElementaryEmpty1}
\begin{paste}{ExIntNonElementaryEmpty1}{ExIntNonElementaryPatch1}
\pastebutton{ExIntNonElementaryEmpty1}{\showpaste}
\tab{5}\spadcommand{integrate(exp(-x**2) * erf(x) / (erf(x)**3 - erf(x)**2 - erf(x) + 1),x)}
\end{paste}\end{patch}

\end{chunk}
\section{exlimit.ht}
\pagetitle{ExLimitBasic}{exlimit.ht}{Computing Limits}
\pageto{notitle}{ExLimitTwoSided}
\pageto{notitle}{ExLimitOneSided}
\begin{chunk}{exlimit.ht}
\begin{page}{ExLimitBasic}{Computing Limits}
\beginscroll
To compute a limit, you must specify a functional expression,
a variable, and a limiting value for that variable.
For example, to compute the limit of (x**2 - 3*x + 2)/(x**2 - 1)
as x approaches 1, issue the following command:
\spadpaste{limit((x**2 - 3*x + 2)/(x**2 - 1),x = 1)}
% answer := -1/2
Since you have not specified a direction, Axiom will attempt
to compute a two-sided limit. Sometimes the limit when approached from
the left is different from the limit from the right.
\downlink{Example}{ExLimitTwoSided}. In this case, you may
wish to ask for a one-sided limit.
\downlink{How.  }{ExLimitOneSided}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExLimitBasicPatch1}
\begin{paste}{ExLimitBasicFull1}{ExLimitBasicEmpty1}
\pastebutton{ExLimitBasicFull1}{\hidepaste}
\tab{5}\spadcommand{limit((x**2 - 3*x + 2)/(x**2 - 1),x = 1)}
\indentrel{3}\begin{verbatim}
          1
   (1)  - Ä
          2
Type: Union(OrderedCompletion Fraction Polynomial Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExLimitBasicEmpty1}
\begin{paste}{ExLimitBasicEmpty1}{ExLimitBasicPatch1}
\pastebutton{ExLimitBasicEmpty1}{\showpaste}
\tab{5}\spadcommand{limit((x**2 - 3*x + 2)/(x**2 - 1),x = 1)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExLimitParameter}{exlimit.ht}{Limits of Functions with Parameters}
\begin{chunk}{exlimit.ht}
\begin{page}{ExLimitParameter}{Limits of Functions with Parameters}
\beginscroll
You may also take limits of functions with parameters. The limit
will be expressed in terms of those parameters.
Here's an example:
\spadpaste{limit(sinh(a*x)/tan(b*x),x = 0)}
% answer := a/b
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExLimitParameterPatch1}
\begin{paste}{ExLimitParameterFull1}{ExLimitParameterEmpty1}
\pastebutton{ExLimitParameterFull1}{\hidepaste}
\tab{5}\spadcommand{limit(sinh(a*x)/tan(b*x),x = 0)}
\indentrel{3}\begin{verbatim}
        a
   (1)  Ä
        b
  Type: Union(OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExLimitParameterEmpty1}
\begin{paste}{ExLimitParameterEmpty1}{ExLimitParameterPatch1}
\pastebutton{ExLimitParameterEmpty1}{\showpaste}
\tab{5}\spadcommand{limit(sinh(a*x)/tan(b*x),x = 0)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExLimitOneSided}{exlimit.ht}{One-sided Limits}
\begin{chunk}{exlimit.ht}
\begin{page}{ExLimitOneSided}{One-sided Limits}
\beginscroll
If you have a function which is only defined on one side of a particular value,
you may wish to compute a one-sided limit.
For instance, the function \spad{log(x)} is only defined to the right of zero,
i.e. for \spad{x > 0}.
Thus, when computing limits of functions involving \spad{log(x)}, you probably
will want a 'right-hand' limit.
Here's an example:
\spadpaste{limit(x * log(x),x = 0,"right")}
% answer := 0
When you do not specify \spad{right} or \spad{left} as an optional fourth
argument, the function \spadfun{limit} will try to compute a two-sided limit.
In the above case, the limit from the left does not exist, as Axiom
will indicate when you try to take a two-sided limit:
\spadpaste{limit(x * log(x),x = 0)}
% answer := [left = "failed",right = 0]
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExLimitOneSidedPatch1}
\begin{paste}{ExLimitOneSidedFull1}{ExLimitOneSidedEmpty1}
\pastebutton{ExLimitOneSidedFull1}{\hidepaste}
\tab{5}\spadcommand{limit(x * log(x),x = 0,"right")}
\indentrel{3}\begin{verbatim}
   (1)  0
  Type: Union(OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExLimitOneSidedEmpty1}
\begin{paste}{ExLimitOneSidedEmpty1}{ExLimitOneSidedPatch1}
\pastebutton{ExLimitOneSidedEmpty1}{\showpaste}
\tab{5}\spadcommand{limit(x * log(x),x = 0,"right")}
\end{paste}\end{patch}

\begin{patch}{ExLimitOneSidedPatch2}
\begin{paste}{ExLimitOneSidedFull2}{ExLimitOneSidedEmpty2}
\pastebutton{ExLimitOneSidedFull2}{\hidepaste}
\tab{5}\spadcommand{limit(x * log(x),x = 0)}
\indentrel{3}\begin{verbatim}
   (2)  [leftHandLimit= "failed",rightHandLimit= 0]
Type: Union(Record(leftHandLimit: Union(OrderedCompletion Expression Integer,"failed"),rightHandLimit: Union(OrderedCompletion Expression Integer,"failed")),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExLimitOneSidedEmpty2}
\begin{paste}{ExLimitOneSidedEmpty2}{ExLimitOneSidedPatch2}
\pastebutton{ExLimitOneSidedEmpty2}{\showpaste}
\tab{5}\spadcommand{limit(x * log(x),x = 0)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExLimitTwoSided}{exlimit.ht}{Two-sided Limits}
\begin{chunk}{exlimit.ht}
\begin{page}{ExLimitTwoSided}{Two-sided Limits}
\beginscroll
A function may be defined on both sides of a particular value, but will
tend to different limits as its variable tends to that value from the
left and from the right.
We can construct an example of this as follows:
Since { \em sqrt(y**2)} is simply the absolute value of \spad{y},
the function \spad{sqrt(y**2)/y}
is simply the sign (+1 or -1) of the real number \spad{y}.
Therefore, \spad{sqrt(y**2)/y = -1} for \spad{y < 0} and
\spad{sqrt(y**2)/y = +1} for \spad{y > 0}.
Watch what happens when we take the limit at \spad{y = 0}.
\spadpaste{limit(sqrt(y**2)/y,y = 0)}
% answer := [left = -1,right = 1]
The answer returned by Axiom gives both a 'left-hand' and a 'right-hand'
limit.
Here's another example, this time using a more complicated function:
\spadpaste{limit(sqrt(1 - cos(t))/t,t = 0)}
% answer := [left = -sqrt(1/2),right = sqrt(1/2)]
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExLimitTwoSidedPatch1}
\begin{paste}{ExLimitTwoSidedFull1}{ExLimitTwoSidedEmpty1}
\pastebutton{ExLimitTwoSidedFull1}{\hidepaste}
\tab{5}\spadcommand{limit(sqrt(y**2)/y,y = 0)}
\indentrel{3}\begin{verbatim}
   (1)  [leftHandLimit= - 1,rightHandLimit= 1]
Type: Union(Record(leftHandLimit: Union(OrderedCompletion Expression Integer,"failed"),rightHandLimit: Union(OrderedCompletion Expression Integer,"failed")),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExLimitTwoSidedEmpty1}
\begin{paste}{ExLimitTwoSidedEmpty1}{ExLimitTwoSidedPatch1}
\pastebutton{ExLimitTwoSidedEmpty1}{\showpaste}
\tab{5}\spadcommand{limit(sqrt(y**2)/y,y = 0)}
\end{paste}\end{patch}

\begin{patch}{ExLimitTwoSidedPatch2}
\begin{paste}{ExLimitTwoSidedFull2}{ExLimitTwoSidedEmpty2}
\pastebutton{ExLimitTwoSidedFull2}{\hidepaste}
\tab{5}\spadcommand{limit(sqrt(1 - cos(t))/t,t = 0)}
\indentrel{3}\begin{verbatim}
                            1                    1
   (2)  [leftHandLimit= - ÄÄÄÄ,rightHandLimit= ÄÄÄÄ]
                           ÚÄ¿                  ÚÄ¿
                          \³2                  \³2
Type: Union(Record(leftHandLimit: Union(OrderedCompletion Expression Integer,"failed"),rightHandLimit: Union(OrderedCompletion Expression Integer,"failed")),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExLimitTwoSidedEmpty2}
\begin{paste}{ExLimitTwoSidedEmpty2}{ExLimitTwoSidedPatch2}
\pastebutton{ExLimitTwoSidedEmpty2}{\showpaste}
\tab{5}\spadcommand{limit(sqrt(1 - cos(t))/t,t = 0)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExLimitInfinite}{exlimit.ht}{Limits at Infinity}
\begin{chunk}{exlimit.ht}
\begin{page}{ExLimitInfinite}{Limits at Infinity}
\beginscroll
You can compute limits at infinity by passing either 'plus infinity'
or 'minus infinity' as the third argument of the function \spadfun{limit}.
To do this, use the constants \spad{\%plusInfinity} and 
\spad{\%minusInfinity}. Here are two examples:
\spadpaste{limit(sqrt(3*x**2 + 1)/(5*x),x = \%plusInfinity)}
\spadpaste{limit(sqrt(3*x**2 + 1)/(5*x),x = \%minusInfinity)}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExLimitInfinitePatch1}
\begin{paste}{ExLimitInfiniteFull1}{ExLimitInfiniteEmpty1}
\pastebutton{ExLimitInfiniteFull1}{\hidepaste}
\tab{5}\spadcommand{limit(sqrt(3*x**2 + 1)/(5*x),x = \%plusInfinity)}
\indentrel{3}\begin{verbatim}
         ÚÄ¿
        \³3
   (1)  ÄÄÄÄ
          5
  Type: Union(OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExLimitInfiniteEmpty1}
\begin{paste}{ExLimitInfiniteEmpty1}{ExLimitInfinitePatch1}
\pastebutton{ExLimitInfiniteEmpty1}{\showpaste}
\tab{5}\spadcommand{limit(sqrt(3*x**2 + 1)/(5*x),x = \%plusInfinity)}
\end{paste}\end{patch}

\begin{patch}{ExLimitInfinitePatch2}
\begin{paste}{ExLimitInfiniteFull2}{ExLimitInfiniteEmpty2}
\pastebutton{ExLimitInfiniteFull2}{\hidepaste}
\tab{5}\spadcommand{limit(sqrt(3*x**2 + 1)/(5*x),x = \%minusInfinity)}
\indentrel{3}\begin{verbatim}
           ÚÄ¿
          \³3
   (2)  - ÄÄÄÄ
            5
  Type: Union(OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExLimitInfiniteEmpty2}
\begin{paste}{ExLimitInfiniteEmpty2}{ExLimitInfinitePatch2}
\pastebutton{ExLimitInfiniteEmpty2}{\showpaste}
\tab{5}\spadcommand{limit(sqrt(3*x**2 + 1)/(5*x),x = \%minusInfinity)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExLimitRealComplex}{exlimit.ht}{Real Limits vs. Complex Limits}
\begin{chunk}{exlimit.ht}
\begin{page}{ExLimitRealComplex}{Real Limits vs. Complex Limits}
\beginscroll
When you use the function \spadfun{limit}, you will be taking the limit of a real
function of a real variable.
For example, you can compute
\spadpaste{limit(z * sin(1/z),z = 0)}
Axiom returns \spad{0} because as a function of a real variable
\spad{sin(1/z)} is always between \spad{-1} and \spad{1}, so \spad{z * sin(1/z)}
tends to \spad{0} as \spad{z} tends to \spad{0}.
However, as a function of a complex variable, \spad{sin(1/z)} is badly
behaved around \spad{0}
(one says that \spad{sin(1/z)} has an 'essential singularity' at \spad{z = 0}).
When viewed as a function of a complex variable, \spad{z * sin(1/z)}
does not approach any limit as \spad{z} tends to \spad{0} in the complex plane.
Axiom indicates this when we call the function \spadfun{complexLimit}:
\spadpaste{complexLimit(z * sin(1/z),z = 0)}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExLimitRealComplexPatch1}
\begin{paste}{ExLimitRealComplexFull1}{ExLimitRealComplexEmpty1}
\pastebutton{ExLimitRealComplexFull1}{\hidepaste}
\tab{5}\spadcommand{limit(z * sin(1/z),z = 0)}
\indentrel{3}\begin{verbatim}
   (1)  0
  Type: Union(OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExLimitRealComplexEmpty1}
\begin{paste}{ExLimitRealComplexEmpty1}{ExLimitRealComplexPatch1}
\pastebutton{ExLimitRealComplexEmpty1}{\showpaste}
\tab{5}\spadcommand{limit(z * sin(1/z),z = 0)}
\end{paste}\end{patch}

\begin{patch}{ExLimitRealComplexPatch2}
\begin{paste}{ExLimitRealComplexFull2}{ExLimitRealComplexEmpty2}
\pastebutton{ExLimitRealComplexFull2}{\hidepaste}
\tab{5}\spadcommand{complexLimit(z * sin(1/z),z = 0)}
\indentrel{3}\begin{verbatim}
   (2)  "failed"
                              Type: Union("failed",...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExLimitRealComplexEmpty2}
\begin{paste}{ExLimitRealComplexEmpty2}{ExLimitRealComplexPatch2}
\pastebutton{ExLimitRealComplexEmpty2}{\showpaste}
\tab{5}\spadcommand{complexLimit(z * sin(1/z),z = 0)}
\end{paste}
\end{patch}

\end{chunk}
\pagetitle{ExLimitComplexInfinite}{exlimit.ht}{Complex Limits at Infinity}
\begin{chunk}{exlimit.ht}
\begin{page}{ExLimitComplexInfinite}{Complex Limits at Infinity}
\beginscroll
You may also take complex limits at infinity, i.e. limits of a function of
\spad{z} as \spad{z} approaches infinity on the Riemann sphere.
Use the symbol \spad{\%infinity} to denote `complex infinity'.
Also, to compute complex limits rather than real limits, use the
function \spadfun{complexLimit}.
Here is an example:
\spadpaste{complexLimit((2 + z)/(1 - z),z = \%infinity)}
In many cases, a limit of a real function of a real variable will exist
when the corresponding complex limit does not.
For example:
\spadpaste{limit(sin(x)/x,x = \%plusInfinity)}
\spadpaste{complexLimit(sin(x)/x,x = \%infinity)}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExLimitComplexInfinitePatch1}
\begin{paste}{ExLimitComplexInfiniteFull1}{ExLimitComplexInfiniteEmpty1}
\pastebutton{ExLimitComplexInfiniteFull1}{\hidepaste}
\tab{5}\spadcommand{complexLimit((2 + z)/(1 - z),z = \%infinity)}
\indentrel{3}\begin{verbatim}
   (1)  - 1
   Type: OnePointCompletion Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExLimitComplexInfiniteEmpty1}
\begin{paste}{ExLimitComplexInfiniteEmpty1}{ExLimitComplexInfinitePatch1}
\pastebutton{ExLimitComplexInfiniteEmpty1}{\showpaste}
\tab{5}\spadcommand{complexLimit((2 + z)/(1 - z),z = \%infinity)}
\end{paste}\end{patch}

\begin{patch}{ExLimitComplexInfinitePatch2}
\begin{paste}{ExLimitComplexInfiniteFull2}{ExLimitComplexInfiniteEmpty2}
\pastebutton{ExLimitComplexInfiniteFull2}{\hidepaste}
\tab{5}\spadcommand{limit(sin(x)/x,x = \%plusInfinity)}
\indentrel{3}\begin{verbatim}
   (2)  0
  Type: Union(OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExLimitComplexInfiniteEmpty2}
\begin{paste}{ExLimitComplexInfiniteEmpty2}{ExLimitComplexInfinitePatch2}
\pastebutton{ExLimitComplexInfiniteEmpty2}{\showpaste}
\tab{5}\spadcommand{limit(sin(x)/x,x = \%plusInfinity)}
\end{paste}\end{patch}

\begin{patch}{ExLimitComplexInfinitePatch3}
\begin{paste}{ExLimitComplexInfiniteFull3}{ExLimitComplexInfiniteEmpty3}
\pastebutton{ExLimitComplexInfiniteFull3}{\hidepaste}
\tab{5}\spadcommand{complexLimit(sin(x)/x,x = \%infinity)}
\indentrel{3}\begin{verbatim}
   (3)  "failed"
                              Type: Union("failed",...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExLimitComplexInfiniteEmpty3}
\begin{paste}{ExLimitComplexInfiniteEmpty3}{ExLimitComplexInfinitePatch3}
\pastebutton{ExLimitComplexInfiniteEmpty3}{\showpaste}
\tab{5}\spadcommand{complexLimit(sin(x)/x,x = \%infinity)}
\end{paste}\end{patch}

\end{chunk}
\section{exmatrix.ht}
\pagetitle{ExMatrixBasicFunction}{exmatrix.ht}
{Basic Arithmetic Operations on Matrices}
\begin{chunk}{exmatrix.ht}
\begin{page}{ExMatrixBasicFunction}
{Basic Arithmetic Operations on Matrices}
\beginscroll
You can create a matrix using the function \spadfun{matrix}.
The function takes a list of lists of elements of the ring and 
produces a matrix whose \spad{i}th row contains the elements of 
the \spad{i}th list. For example:
\spadpaste{m1 := matrix([[1,-2,1],[4,2,-4]]) \bound{m1}}
\spadpaste{m2 := matrix([[1,0,2],[20,30,10],[0,200,100]]) \bound{m2}}
\spadpaste{m3 := matrix([[1,2,3],[2,4,6]]) \bound{m3}}
Some of the basic arithmetic operations on matrices are:
\spadpaste{m1 + m3 \free{m1} \free{m3}}
\spadpaste{100 * m1 \free{m1}}
\spadpaste{m1 * m2 \free{m1} \free{m2}}
\spadpaste{-m1 + m3 * m2 \free{m1} \free{m2} \free{m3}}
You can also multiply a matrix and a vector provided
that the matrix and vector have compatible dimensions.
\spadpaste{m3 *vector([1,0,1]) \free{m3}}
However, the dimensions of the matrices must be compatible in order for
Axiom to perform an operation - otherwise an error message will occur.
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExMatrixBasicFunctionPatch1}
\begin{paste}{ExMatrixBasicFunctionFull1}{ExMatrixBasicFunctionEmpty1}
\pastebutton{ExMatrixBasicFunctionFull1}{\hidepaste}
\tab{5}\spadcommand{m1 := matrix([[1,-2,1],[4,2,-4]])\bound{m1 }}
\indentrel{3}\begin{verbatim}
        Ú1  - 2   1 ¿
   (1)  ³           ³
        À4   2   - 4Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExMatrixBasicFunctionEmpty1}
\begin{paste}{ExMatrixBasicFunctionEmpty1}{ExMatrixBasicFunctionPatch1}
\pastebutton{ExMatrixBasicFunctionEmpty1}{\showpaste}
\tab{5}\spadcommand{m1 := matrix([[1,-2,1],[4,2,-4]])\bound{m1 }}
\end{paste}\end{patch}

\begin{patch}{ExMatrixBasicFunctionPatch2}
\begin{paste}{ExMatrixBasicFunctionFull2}{ExMatrixBasicFunctionEmpty2}
\pastebutton{ExMatrixBasicFunctionFull2}{\hidepaste}
\tab{5}\spadcommand{m2 := matrix([[1,0,2],[20,30,10],[0,200,100]])\bound{m2 }}
\indentrel{3}\begin{verbatim}
        Ú1    0    2 ¿
        ³            ³
   (2)  ³20  30   10 ³
        ³            ³
        À0   200  100Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExMatrixBasicFunctionEmpty2}
\begin{paste}{ExMatrixBasicFunctionEmpty2}{ExMatrixBasicFunctionPatch2}
\pastebutton{ExMatrixBasicFunctionEmpty2}{\showpaste}
\tab{5}\spadcommand{m2 := matrix([[1,0,2],[20,30,10],[0,200,100]])\bound{m2 }}
\end{paste}\end{patch}

\begin{patch}{ExMatrixBasicFunctionPatch3}
\begin{paste}{ExMatrixBasicFunctionFull3}{ExMatrixBasicFunctionEmpty3}
\pastebutton{ExMatrixBasicFunctionFull3}{\hidepaste}
\tab{5}\spadcommand{m3 := matrix([[1,2,3],[2,4,6]])\bound{m3 }}
\indentrel{3}\begin{verbatim}
        Ú1  2  3¿
   (3)  ³       ³
        À2  4  6Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExMatrixBasicFunctionEmpty3}
\begin{paste}{ExMatrixBasicFunctionEmpty3}{ExMatrixBasicFunctionPatch3}
\pastebutton{ExMatrixBasicFunctionEmpty3}{\showpaste}
\tab{5}\spadcommand{m3 := matrix([[1,2,3],[2,4,6]])\bound{m3 }}
\end{paste}\end{patch}

\begin{patch}{ExMatrixBasicFunctionPatch4}
\begin{paste}{ExMatrixBasicFunctionFull4}{ExMatrixBasicFunctionEmpty4}
\pastebutton{ExMatrixBasicFunctionFull4}{\hidepaste}
\tab{5}\spadcommand{m1 + m3\free{m1 }\free{m3 }}
\indentrel{3}\begin{verbatim}
        Ú2  0  4¿
   (4)  ³       ³
        À6  6  2Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExMatrixBasicFunctionEmpty4}
\begin{paste}{ExMatrixBasicFunctionEmpty4}{ExMatrixBasicFunctionPatch4}
\pastebutton{ExMatrixBasicFunctionEmpty4}{\showpaste}
\tab{5}\spadcommand{m1 + m3\free{m1 }\free{m3 }}
\end{paste}\end{patch}

\begin{patch}{ExMatrixBasicFunctionPatch5}
\begin{paste}{ExMatrixBasicFunctionFull5}{ExMatrixBasicFunctionEmpty5}
\pastebutton{ExMatrixBasicFunctionFull5}{\hidepaste}
\tab{5}\spadcommand{100 * m1\free{m1 }}
\indentrel{3}\begin{verbatim}
        Ú100  - 200   100 ¿
   (5)  ³                 ³
        À400   200   - 400Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExMatrixBasicFunctionEmpty5}
\begin{paste}{ExMatrixBasicFunctionEmpty5}{ExMatrixBasicFunctionPatch5}
\pastebutton{ExMatrixBasicFunctionEmpty5}{\showpaste}
\tab{5}\spadcommand{100 * m1\free{m1 }}
\end{paste}\end{patch}

\begin{patch}{ExMatrixBasicFunctionPatch6}
\begin{paste}{ExMatrixBasicFunctionFull6}{ExMatrixBasicFunctionEmpty6}
\pastebutton{ExMatrixBasicFunctionFull6}{\hidepaste}
\tab{5}\spadcommand{m1 * m2\free{m1 }\free{m2 }}
\indentrel{3}\begin{verbatim}
        Ú- 39   140    82  ¿
   (6)  ³                  ³
        À 44   - 740  - 372Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExMatrixBasicFunctionEmpty6}
\begin{paste}{ExMatrixBasicFunctionEmpty6}{ExMatrixBasicFunctionPatch6}
\pastebutton{ExMatrixBasicFunctionEmpty6}{\showpaste}
\tab{5}\spadcommand{m1 * m2\free{m1 }\free{m2 }}
\end{paste}\end{patch}

\begin{patch}{ExMatrixBasicFunctionPatch7}
\begin{paste}{ExMatrixBasicFunctionFull7}{ExMatrixBasicFunctionEmpty7}
\pastebutton{ExMatrixBasicFunctionFull7}{\hidepaste}
\tab{5}\spadcommand{-m1 + m3 * m2\free{m1 }\free{m2 }\free{m3 }}
\indentrel{3}\begin{verbatim}
        Ú40  662   321¿
   (7)  ³             ³
        À78  1318  648Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExMatrixBasicFunctionEmpty7}
\begin{paste}{ExMatrixBasicFunctionEmpty7}{ExMatrixBasicFunctionPatch7}
\pastebutton{ExMatrixBasicFunctionEmpty7}{\showpaste}
\tab{5}\spadcommand{-m1 + m3 * m2\free{m1 }\free{m2 }\free{m3 }}
\end{paste}\end{patch}

\begin{patch}{ExMatrixBasicFunctionPatch8}
\begin{paste}{ExMatrixBasicFunctionFull8}{ExMatrixBasicFunctionEmpty8}
\pastebutton{ExMatrixBasicFunctionFull8}{\hidepaste}
\tab{5}\spadcommand{m3 *vector([1,0,1])\free{m3 }}
\indentrel{3}\begin{verbatim}
   (8)  [4,8]
                                   Type: Vector Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExMatrixBasicFunctionEmpty8}
\begin{paste}{ExMatrixBasicFunctionEmpty8}{ExMatrixBasicFunctionPatch8}
\pastebutton{ExMatrixBasicFunctionEmpty8}{\showpaste}
\tab{5}\spadcommand{m3 *vector([1,0,1])\free{m3 }}
\end{paste}
\end{patch}

\end{chunk}
\pagetitle{ExConstructMatrix}{exmatrix.ht}{Constructing new Matrices}
\begin{chunk}{exmatrix.ht}
\begin{page}{ExConstructMatrix}{Constructing new Matrices}
\beginscroll
A number of functions exist for constructing new matrices from existing ones.

If you want to create a matrix whose entries are 0 except on the main
diagonal you can use \spadfun{diagonalMatrix}.
This function takes a list of ring elements as an argument and returns a
square matrix which has these elements on the main diagonal.
Consider the following example:
\spadpaste{diagonalMatrix([1,2,3,2,1])}

The function \spadfun{subMatrix}(\spad{a},\spad{i},\spad{j},\spad{k},\spad{l}) 
constructs a new matrix
consisting of rows \spad{i} through \spad{j} and columns \spad{k} through 
\spad{l} of \spad{a} , inclusive.
\spadpaste{subMatrix(matrix([[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14]]), 
1,3,2,4)}


The functions \spadfun{horizConcat} and \spadfun{vertConcat} 
concatenate matrices
horizontally and vertically, respectively.
\spadpaste{horizConcat(matrix([[1,2,3],[6,7,8]]),
matrix([[11,12,13],[55,77,88]])) }
\spadpaste{vertConcat(matrix([[1,2,3],[6,7,8]]),
matrix([[11,12,13],[55,77,88]])) }


The function \spadfunX{setsubMatrix}(\spad{a},\spad{i},\spad{k},\spad{b}) 
replaces the submatrix of \spad{a}
starting at row \spad{i} and column \spad{k} with the elements of the 
matrix i\spad{b}.
\spadpaste{b:=matrix([[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14]]) \bound{b}}
\spadpaste{setsubMatrix!(b,1,1,transpose(subMatrix(b,1,3,1,3)))\free{b}}
changes the submatrix of \spad{b} consisting of the first 3 rows and columns
to its transpose.
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExConstructMatrixPatch1}
\begin{paste}{ExConstructMatrixFull1}{ExConstructMatrixEmpty1}
\pastebutton{ExConstructMatrixFull1}{\hidepaste}
\tab{5}\spadcommand{diagonalMatrix([1,2,3,2,1])}
\indentrel{3}\begin{verbatim}
        Ú1  0  0  0  0¿
        ³             ³
        ³0  2  0  0  0³
        ³             ³
   (1)  ³0  0  3  0  0³
        ³             ³
        ³0  0  0  2  0³
        ³             ³
        À0  0  0  0  1Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExConstructMatrixEmpty1}
\begin{paste}{ExConstructMatrixEmpty1}{ExConstructMatrixPatch1}
\pastebutton{ExConstructMatrixEmpty1}{\showpaste}
\tab{5}\spadcommand{diagonalMatrix([1,2,3,2,1])}
\end{paste}\end{patch}

\begin{patch}{ExConstructMatrixPatch2}
\begin{paste}{ExConstructMatrixFull2}{ExConstructMatrixEmpty2}
\pastebutton{ExConstructMatrixFull2}{\hidepaste}
\tab{5}\spadcommand{subMatrix(matrix([[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14]]), 1,3,2,4)}
\indentrel{3}\begin{verbatim}
        Ú1   2   3 ¿
        ³          ³
   (2)  ³6   7   8 ³
        ³          ³
        À11  12  13Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExConstructMatrixEmpty2}
\begin{paste}{ExConstructMatrixEmpty2}{ExConstructMatrixPatch2}
\pastebutton{ExConstructMatrixEmpty2}{\showpaste}
\tab{5}\spadcommand{subMatrix(matrix([[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14]]), 1,3,2,4)}
\end{paste}\end{patch}

\begin{patch}{ExConstructMatrixPatch3}
\begin{paste}{ExConstructMatrixFull3}{ExConstructMatrixEmpty3}
\pastebutton{ExConstructMatrixFull3}{\hidepaste}
\tab{5}\spadcommand{horizConcat(matrix([[1,2,3],[6,7,8]]),matrix([[11,12,13],[55,77,88]]))}
\indentrel{3}\begin{verbatim}
        Ú1  2  3  11  12  13¿
   (3)  ³                   ³
        À6  7  8  55  77  88Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExConstructMatrixEmpty3}
\begin{paste}{ExConstructMatrixEmpty3}{ExConstructMatrixPatch3}
\pastebutton{ExConstructMatrixEmpty3}{\showpaste}
\tab{5}\spadcommand{horizConcat(matrix([[1,2,3],[6,7,8]]),matrix([[11,12,13],[55,77,88]]))}
\end{paste}\end{patch}

\begin{patch}{ExConstructMatrixPatch4}
\begin{paste}{ExConstructMatrixFull4}{ExConstructMatrixEmpty4}
\pastebutton{ExConstructMatrixFull4}{\hidepaste}
\tab{5}\spadcommand{vertConcat(matrix([[1,2,3],[6,7,8]]),matrix([[11,12,13],[55,77,88]]))}
\indentrel{3}\begin{verbatim}
        Ú1   2   3 ¿
        ³          ³
        ³6   7   8 ³
   (4)  ³          ³
        ³11  12  13³
        ³          ³
        À55  77  88Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExConstructMatrixEmpty4}
\begin{paste}{ExConstructMatrixEmpty4}{ExConstructMatrixPatch4}
\pastebutton{ExConstructMatrixEmpty4}{\showpaste}
\tab{5}\spadcommand{vertConcat(matrix([[1,2,3],[6,7,8]]),matrix([[11,12,13],[55,77,88]]))}
\end{paste}\end{patch}

\begin{patch}{ExConstructMatrixPatch5}
\begin{paste}{ExConstructMatrixFull5}{ExConstructMatrixEmpty5}
\pastebutton{ExConstructMatrixFull5}{\hidepaste}
\tab{5}\spadcommand{b:=matrix([[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14]])\bound{b }}
\indentrel{3}\begin{verbatim}
        Ú0   1   2   3   4 ¿
        ³                  ³
   (5)  ³5   6   7   8   9 ³
        ³                  ³
        À10  11  12  13  14Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExConstructMatrixEmpty5}
\begin{paste}{ExConstructMatrixEmpty5}{ExConstructMatrixPatch5}
\pastebutton{ExConstructMatrixEmpty5}{\showpaste}
\tab{5}\spadcommand{b:=matrix([[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14]])\bound{b }}
\end{paste}\end{patch}

\begin{patch}{ExConstructMatrixPatch6}
\begin{paste}{ExConstructMatrixFull6}{ExConstructMatrixEmpty6}
\pastebutton{ExConstructMatrixFull6}{\hidepaste}
\tab{5}\spadcommand{setsubMatrix!(b,1,1,transpose(subMatrix(b,1,3,1,3)))\free{b }}
\indentrel{3}\begin{verbatim}
        Ú0  5  10  3   4 ¿
        ³                ³
   (6)  ³1  6  11  8   9 ³
        ³                ³
        À2  7  12  13  14Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExConstructMatrixEmpty6}
\begin{paste}{ExConstructMatrixEmpty6}{ExConstructMatrixPatch6}
\pastebutton{ExConstructMatrixEmpty6}{\showpaste}
\tab{5}\spadcommand{setsubMatrix!(b,1,1,transpose(subMatrix(b,1,3,1,3)))\free{b }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExTraceMatrix}{exmatrix.ht}{Trace of a Matrix}
\begin{chunk}{exmatrix.ht}
\begin{page}{ExTraceMatrix}{Trace of a Matrix}
\beginscroll
If you have a square matrix, then you can compute its `trace'.
The function \spadfun{trace} computes the sum of all elements 
on the diagonal of a matrix.
For example `trace' for a four by four Vandermonde matrix.
\spadpaste{trace( matrix([[1,x,x**2,x**3],[1,y,y**2,y**3],
[1,z,z**2,z**3],[1,u,u**2,u**3]]) )}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExTraceMatrixPatch1}
\begin{paste}{ExTraceMatrixFull1}{ExTraceMatrixEmpty1}
\pastebutton{ExTraceMatrixFull1}{\hidepaste}
\tab{5}\spadcommand{trace( matrix([[1,x,x**2,x**3],[1,y,y**2,y**3],[1,z,z**2,z**3],[1,u,u**2,u**3]]) )}
\indentrel{3}\begin{verbatim}
         2        3
   (1)  z  + y + u  + 1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExTraceMatrixEmpty1}
\begin{paste}{ExTraceMatrixEmpty1}{ExTraceMatrixPatch1}
\pastebutton{ExTraceMatrixEmpty1}{\showpaste}
\tab{5}\spadcommand{trace( matrix([[1,x,x**2,x**3],[1,y,y**2,y**3],[1,z,z**2,z**3],[1,u,u**2,u**3]]) )}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExDeterminantMatrix}{exmatrix.ht}{Determinant of a Matrix}
\begin{chunk}{exmatrix.ht}
\begin{page}{ExDeterminantMatrix}{Determinant of a Matrix}
\beginscroll
The function \spadfun{determinant} computes the determinant of a matrix 
over a commutative ring, that is a ring whose multiplication is 
commutative.
\spadpaste{determinant(matrix([[1,2,3,4],[2,3,2,5],[3,4,5,6],[4,1,6,7]]))}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExDeterminantMatrixPatch1}
\begin{paste}{ExDeterminantMatrixFull1}{ExDeterminantMatrixEmpty1}
\pastebutton{ExDeterminantMatrixFull1}{\hidepaste}
\tab{5}\spadcommand{determinant(matrix([[1,2,3,4],[2,3,2,5],[3,4,5,6],[4,1,6,7]]))}
\indentrel{3}\begin{verbatim}
   (1)  - 48
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExDeterminantMatrixEmpty1}
\begin{paste}{ExDeterminantMatrixEmpty1}{ExDeterminantMatrixPatch1}
\pastebutton{ExDeterminantMatrixEmpty1}{\showpaste}
\tab{5}\spadcommand{determinant(matrix([[1,2,3,4],[2,3,2,5],[3,4,5,6],[4,1,6,7]]))}
\end{paste}
\end{patch}

\end{chunk}
\pagetitle{ExInverseMatrix}{exmatrix.ht}{Inverse of a Matrix}
\begin{chunk}{exmatrix.ht}
\begin{page}{ExInverseMatrix}{Inverse of a Matrix}
\beginscroll
The function \spadfun{inverse} computes the inverse of a square matrix.
\spadpaste{inverse(matrix([[1,2,1],[-2,3,4],[-1,5,6]])) }
(If the inverse doesn't exist, then Axiom returns `failed'.)
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExInverseMatrixPatch1}
\begin{paste}{ExInverseMatrixFull1}{ExInverseMatrixEmpty1}
\pastebutton{ExInverseMatrixFull1}{\hidepaste}
\tab{5}\spadcommand{inverse(matrix([[1,2,1],[-2,3,4],[-1,5,6]]))}
\indentrel{3}\begin{verbatim}
        Ú  2        5 ¿
        ³- Ä  - 1   Ä ³
        ³  7        7 ³
        ³             ³
   (1)  ³ 8          6³
        ³ Ä    1   - Ä³
        ³ 7          7³
        ³             ³
        À- 1  - 1   1 Ù
               Type: Union(Matrix Fraction Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExInverseMatrixEmpty1}
\begin{paste}{ExInverseMatrixEmpty1}{ExInverseMatrixPatch1}
\pastebutton{ExInverseMatrixEmpty1}{\showpaste}
\tab{5}\spadcommand{inverse(matrix([[1,2,1],[-2,3,4],[-1,5,6]]))}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExRankMatrix}{exmatrix.ht}{Rank of a Matrix}
\begin{chunk}{exmatrix.ht}
\begin{page}{ExRankMatrix}{Rank of a Matrix}
\beginscroll
The function \spadfun{rank} gives you the rank of a matrix:
\spadpaste{rank(matrix([[0,4,1],[5,3,-7],[-5,5,9]]))}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExRankMatrixPatch1}
\begin{paste}{ExRankMatrixFull1}{ExRankMatrixEmpty1}
\pastebutton{ExRankMatrixFull1}{\hidepaste}
\tab{5}\spadcommand{rank(matrix([[0,4,1],[5,3,-7],[-5,5,9]]))}
\indentrel{3}\begin{verbatim}
   (1)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExRankMatrixEmpty1}
\begin{paste}{ExRankMatrixEmpty1}{ExRankMatrixPatch1}
\pastebutton{ExRankMatrixEmpty1}{\showpaste}
\tab{5}\spadcommand{rank(matrix([[0,4,1],[5,3,-7],[-5,5,9]]))}
\end{paste}\end{patch}

\end{chunk}
\section{expr.ht}
\pagetitle{ExpressionXmpPage}{expr.ht}{Expression}
\pageto{notitle}{KernelXmpPage}
\pageto{notitle}{ugIntroCalcDerivPage}
\pageto{notitle}{ugIntroCalcLimitsPage}
\pageto{notitle}{ugIntroSeriesPage}
\pageto{notitle}{ugProblemDEQPage}
\pageto{notitle}{ugProblemIntegrationPage}
\pageto{notitle}{ugUserRulesPage}
\begin{chunk}{expr.ht}
\begin{page}{ExpressionXmpPage}{Expression}
\beginscroll

\axiomType{Expression} is a constructor that creates domains whose
objects can have very general symbolic forms.
Here are some examples:
\xtc{
This is an object of type \axiomType{Expression Integer}.
}{
\spadpaste{sin(x) + 3*cos(x)**2}
}
\xtc{
This is an object of type \axiomType{Expression Float}.
}{
\spadpaste{tan(x) - 3.45*x}
}
\xtc{
This object contains symbolic function applications, sums,
products, square roots, and a quotient.
}{
\spadpaste{(tan sqrt 7 - sin sqrt 11)**2 / (4 - cos(x - y))}
}
As you can see, \axiomType{Expression} actually takes an argument
domain.
The {\it coefficients} of the terms within the expression belong
to the argument domain.
\axiomType{Integer} and \axiomType{Float}, along with
\axiomType{Complex Integer} and \axiomType{Complex Float}
are the most common coefficient domains.
\xtc{
The choice of whether
to use a \axiomType{Complex} coefficient domain or not is
important since Axiom can perform some simplifications
on real-valued objects
}{
\spadpaste{log(exp  x)@Expression(Integer)} 
}
\xtc{
... which are not valid on complex ones.
}{
\spadpaste{log(exp  x)@Expression(Complex Integer)} 
}
\xtc{
Many potential coefficient domains, such as
\axiomType{AlgebraicNumber}, are not usually used because
\axiomType{Expression} can subsume them.
}{
\spadpaste{sqrt 3 + sqrt(2 + sqrt(-5)) \bound{algnum1}}
}
\xtc{
}{
\spadpaste{\% :: Expression Integer \free{algnum1}}
}
Note that we sometimes talk about ``an object of type
\axiomType{Expression}.'' This is not really correct because we
should say, for example, ``an object of type \axiomType{Expression
Integer}'' or ``an object of type \axiomType{Expression Float}.''
By a similar abuse of language, when we refer to an ``expression''
in this section we will mean an object of type
\axiomType{Expression R} for some domain {\bf R}.

The Axiom documentation contains many examples of the use
of \axiomType{Expression}.
For the rest of this section, we'll give you some pointers to those
examples plus give you some idea of how to manipulate expressions.

It is important for you to know that \axiomType{Expression}
creates domains that have category \axiomType{Field}.
Thus you can invert any non-zero expression and you shouldn't
expect an operation like \axiomFun{factor} to give you much
information.
You can imagine expressions as being represented as quotients of
``multivariate'' polynomials where the ``variables'' are kernels
(see \downlink{`Kernel'}{KernelXmpPage}\ignore{Kernel}).
A kernel can either be a symbol such as \axiom{x} or a symbolic
function application like \axiom{sin(x + 4)}.
The second example is actually a nested kernel since the argument
to \axiomFun{sin} contains the kernel \axiom{x}.
\xtc{
}{
\spadpaste{height mainKernel sin(x + 4)}
}
Actually, the argument to \axiomFun{sin} is an expression, and so
the structure of \axiomType{Expression} is recursive.
\downlink{`Kernel'}{KernelXmpPage}\ignore{Kernel} 
demonstrates how to extract the kernels in an
expression.

Use the Hyperdoc Browse facility to see what operations are
applicable to expression.
At the time of this writing, there were 262 operations with 147
distinct name in \axiomType{Expression Integer}.
For example, \axiomFunFrom{numer}{Expression} and
\axiomFunFrom{denom}{Expression} extract the numerator and
denominator of an expression.
\xtc{
}{
\spadpaste{e := (sin(x) - 4)**2 / ( 1 - 2*y*sqrt(- y) ) \bound{e}}
}
\xtc{
}{
\spadpaste{numer e \free{e}}
}
\xtc{
}{
\spadpaste{denom e \free{e}}
}
\xtc{
Use \axiomFunFrom{D}{Expression} to compute partial derivatives.
}{
\spadpaste{D(e, x) \free{e}}
}
\xtc{
See \downlink{``Derivatives''}{ugIntroCalcDerivPage} in Section 1.12
\ignore{ugIntroCalcDeriv}
for more examples of expressions and derivatives.
}{
\spadpaste{D(e, [x, y], [1, 2]) \free{e}}
}
See \downlink{``Limits''}{ugIntroCalcLimitsPage} 
in Section 1.10\ignore{ugIntroCalcLimits} and
\downlink{``Series''}{ugIntroSeriesPage} in Section 1.11
\ignore{ugIntroSeries}
for more examples of expressions and calculus.
Differential equations involving expressions are discussed in
\downlink{``Solution of Differential Equations''}
{ugProblemDEQPage} in Section 8.10\ignore{ugProblemDEQ}.
Chapter 8 has many advanced examples: see
\downlink{``Integration''}{ugProblemIntegrationPage} 
in Section 8.8\ignore{ugProblemIntegration}
for a discussion of Axiom's integration facilities.

When an expression involves no ``symbol kernels'' (for example,
\axiom{x}), it may be possible to numerically evaluate the
expression.
\xtc{
If you suspect the evaluation will create a complex number,
use \axiomFun{complexNumeric}.
}{
\spadpaste{complexNumeric(cos(2 - 3*\%i))}
}
\xtc{
If you know it will be real, use \axiomFun{numeric}.
}{
\spadpaste{numeric(tan 3.8)}
}
The \axiomFun{numeric} operation will display an error message if
the evaluation yields a calue with an non-zero imaginary part.
Both of these operations have an optional second argument
\axiom{n} which specifies that the accuracy of the approximation
be up to \axiom{n} decimal places.

When an expression involves no ``symbolic application'' kernels,
it may be possible to convert it a polynomial or rational
function in the variables that are present.
\xtc{
}{
\spadpaste{e2 := cos(x**2 - y + 3) \bound{e2}}
}
\xtc{
}{
\spadpaste{e3 := asin(e2) - \%pi/2 \free{e2}\bound{e3}}
}
\xtc{
}{
\spadpaste{e3 :: Polynomial Integer \free{e3}}
}
\xtc{
This also works for the polynomial types where specific variables
and their ordering are given.
}{
\spadpaste{e3 :: DMP([x, y], Integer) \free{e3}}
}

Finally, a certain amount of simplication takes place as
expressions are constructed.
\xtc{
}{
\spadpaste{sin \%pi}
}
\xtc{
}{
\spadpaste{cos(\%pi / 4)}
}
\xtc{
For simplications that involve multiple terms of the expression,
use \axiomFun{simplify}.
}{
\spadpaste{tan(x)**6 + 3*tan(x)**4 + 3*tan(x)**2 + 1 \bound{tan6}}
}
\xtc{
}{
\spadpaste{simplify \% \free{tan6}}
}
See \downlink{``Rules and Pattern Matching''}{ugUserRulesPage} in
Section 6.21\ignore{ugUserRules} for examples of how to write your own
rewrite rules for expressions.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ExpressionXmpPagePatch1}
\begin{paste}{ExpressionXmpPageFull1}{ExpressionXmpPageEmpty1}
\pastebutton{ExpressionXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{sin(x) + 3*cos(x)**2}
\indentrel{3}\begin{verbatim}
                        2
   (1)  sin(x) + 3cos(x)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty1}
\begin{paste}{ExpressionXmpPageEmpty1}{ExpressionXmpPagePatch1}
\pastebutton{ExpressionXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{sin(x) + 3*cos(x)**2}
\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPagePatch2}
\begin{paste}{ExpressionXmpPageFull2}{ExpressionXmpPageEmpty2}
\pastebutton{ExpressionXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{tan(x) - 3.45*x}
\indentrel{3}\begin{verbatim}
   (2)  tan(x) - 3.45 x
                                 Type: Expression Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty2}
\begin{paste}{ExpressionXmpPageEmpty2}{ExpressionXmpPagePatch2}
\pastebutton{ExpressionXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{tan(x) - 3.45*x}
\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPagePatch3}
\begin{paste}{ExpressionXmpPageFull3}{ExpressionXmpPageEmpty3}
\pastebutton{ExpressionXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{(tan sqrt 7 - sin sqrt 11)**2 / (4 - cos(x - y))}
\indentrel{3}\begin{verbatim}
   (3)
          ÚÄ¿ 2         ÚÄÄ¿      ÚÄ¿         ÚÄÄ¿ 2
   - tan(\³7 )  + 2sin(\³11 )tan(\³7 ) - sin(\³11 )
   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                     cos(y - x) - 4
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty3}
\begin{paste}{ExpressionXmpPageEmpty3}{ExpressionXmpPagePatch3}
\pastebutton{ExpressionXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{(tan sqrt 7 - sin sqrt 11)**2 / (4 - cos(x - y))}
\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPagePatch4}
\begin{paste}{ExpressionXmpPageFull4}{ExpressionXmpPageEmpty4}
\pastebutton{ExpressionXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{log(exp x)@Expression(Integer)}
\indentrel{3}\begin{verbatim}
   (4)  x
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty4}
\begin{paste}{ExpressionXmpPageEmpty4}{ExpressionXmpPagePatch4}
\pastebutton{ExpressionXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{log(exp x)@Expression(Integer)}
\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPagePatch5}
\begin{paste}{ExpressionXmpPageFull5}{ExpressionXmpPageEmpty5}
\pastebutton{ExpressionXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{log(exp x)@Expression(Complex Integer)}
\indentrel{3}\begin{verbatim}
              x
   (5)  log(%e )
                       Type: Expression Complex Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty5}
\begin{paste}{ExpressionXmpPageEmpty5}{ExpressionXmpPagePatch5}
\pastebutton{ExpressionXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{log(exp x)@Expression(Complex Integer)}
\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPagePatch6}
\begin{paste}{ExpressionXmpPageFull6}{ExpressionXmpPageEmpty6}
\pastebutton{ExpressionXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{sqrt 3 + sqrt(2 + sqrt(-5))\bound{algnum1 }}
\indentrel{3}\begin{verbatim}
         ÚÄÄÄÄÄÄÄÄÄÄ¿
         ³ ÚÄÄÄ¿         ÚÄ¿
   (6)  \³\³- 5  + 2  + \³3
                                  Type: AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty6}
\begin{paste}{ExpressionXmpPageEmpty6}{ExpressionXmpPagePatch6}
\pastebutton{ExpressionXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{sqrt 3 + sqrt(2 + sqrt(-5))\bound{algnum1 }}
\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPagePatch7}
\begin{paste}{ExpressionXmpPageFull7}{ExpressionXmpPageEmpty7}
\pastebutton{ExpressionXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{\% :: Expression Integer\free{algnum1 }}
\indentrel{3}\begin{verbatim}
         ÚÄÄÄÄÄÄÄÄÄÄ¿
         ³ ÚÄÄÄ¿         ÚÄ¿
   (7)  \³\³- 5  + 2  + \³3
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty7}
\begin{paste}{ExpressionXmpPageEmpty7}{ExpressionXmpPagePatch7}
\pastebutton{ExpressionXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{\% :: Expression Integer\free{algnum1 }}
\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPagePatch8}
\begin{paste}{ExpressionXmpPageFull8}{ExpressionXmpPageEmpty8}
\pastebutton{ExpressionXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{height mainKernel sin(x + 4)}
\indentrel{3}\begin{verbatim}
   (8)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty8}
\begin{paste}{ExpressionXmpPageEmpty8}{ExpressionXmpPagePatch8}
\pastebutton{ExpressionXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{height mainKernel sin(x + 4)}
\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPagePatch9}
\begin{paste}{ExpressionXmpPageFull9}{ExpressionXmpPageEmpty9}
\pastebutton{ExpressionXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{e := (sin(x) - 4)**2 / ( 1 - 2*y*sqrt(- y) )\bound{e }}
\indentrel{3}\begin{verbatim}
                2
        - sin(x)  + 8sin(x) - 16
   (9)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                 ÚÄÄÄ¿
              2y\³- y  - 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty9}
\begin{paste}{ExpressionXmpPageEmpty9}{ExpressionXmpPagePatch9}
\pastebutton{ExpressionXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{e := (sin(x) - 4)**2 / ( 1 - 2*y*sqrt(- y) )\bound{e }}
\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPagePatch10}
\begin{paste}{ExpressionXmpPageFull10}{ExpressionXmpPageEmpty10}
\pastebutton{ExpressionXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{numer e\free{e }}
\indentrel{3}\begin{verbatim}
                 2
   (10)  - sin(x)  + 8sin(x) - 16
Type: SparseMultivariatePolynomial(Integer,Kernel Expression Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty10}
\begin{paste}{ExpressionXmpPageEmpty10}{ExpressionXmpPagePatch10}
\pastebutton{ExpressionXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{numer e\free{e }}
\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPagePatch11}
\begin{paste}{ExpressionXmpPageFull11}{ExpressionXmpPageEmpty11}
\pastebutton{ExpressionXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{denom e\free{e }}
\indentrel{3}\begin{verbatim}
            ÚÄÄÄ¿
   (11)  2y\³- y  - 1
Type: SparseMultivariatePolynomial(Integer,Kernel Expression Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty11}
\begin{paste}{ExpressionXmpPageEmpty11}{ExpressionXmpPagePatch11}
\pastebutton{ExpressionXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{denom e\free{e }}
\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPagePatch12}
\begin{paste}{ExpressionXmpPageFull12}{ExpressionXmpPageEmpty12}
\pastebutton{ExpressionXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{D(e, x)\free{e }}
\indentrel{3}\begin{verbatim}
   (12)
                                      ÚÄÄÄ¿
       (4y cos(x)sin(x) - 16y cos(x))\³- y
     + 
       - 2cos(x)sin(x) + 8cos(x)
  /
        ÚÄÄÄ¿     3
     4y\³- y  + 4y  - 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty12}
\begin{paste}{ExpressionXmpPageEmpty12}{ExpressionXmpPagePatch12}
\pastebutton{ExpressionXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{D(e, x)\free{e }}
\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPagePatch13}
\begin{paste}{ExpressionXmpPageFull13}{ExpressionXmpPageEmpty13}
\pastebutton{ExpressionXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{D(e, [x, y], [1, 2])\free{e }}
\indentrel{3}\begin{verbatim}
   (13)
                   7       4
           (- 2304y  + 960y )cos(x)sin(x)
         + 
                 7        4
           (9216y  - 3840y )cos(x)
      *
          ÚÄÄÄ¿
         \³- y
     + 
              9        6       3
       (- 960y  + 2160y  - 180y  - 3)cos(x)sin(x)
     + 
             9        6       3
       (3840y  - 8640y  + 720y  + 12)cos(x)
  /
            12        9        6       3      ÚÄÄÄ¿
       (256y   - 1792y  + 1120y  - 112y  + 1)\³- y
     + 
              11        8       5      2
       - 1024y   + 1792y  - 448y  + 16y
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty13}
\begin{paste}{ExpressionXmpPageEmpty13}{ExpressionXmpPagePatch13}
\pastebutton{ExpressionXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{D(e, [x, y], [1, 2])\free{e }}
\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPagePatch14}
\begin{paste}{ExpressionXmpPageFull14}{ExpressionXmpPageEmpty14}
\pastebutton{ExpressionXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{complexNumeric(cos(2 - 3*\%i))}
\indentrel{3}\begin{verbatim}
   (14)
   - 4.1896256909 688072301 + 9.1092278937 55336598 %i
                                    Type: Complex Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty14}
\begin{paste}{ExpressionXmpPageEmpty14}{ExpressionXmpPagePatch14}
\pastebutton{ExpressionXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{complexNumeric(cos(2 - 3*\%i))}
\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPagePatch15}
\begin{paste}{ExpressionXmpPageFull15}{ExpressionXmpPageEmpty15}
\pastebutton{ExpressionXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{numeric(tan 3.8)}
\indentrel{3}\begin{verbatim}
   (15)  0.7735560905 0312607286
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty15}
\begin{paste}{ExpressionXmpPageEmpty15}{ExpressionXmpPagePatch15}
\pastebutton{ExpressionXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{numeric(tan 3.8)}
\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPagePatch16}
\begin{paste}{ExpressionXmpPageFull16}{ExpressionXmpPageEmpty16}
\pastebutton{ExpressionXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{e2 := cos(x**2 - y + 3)\bound{e2 }}
\indentrel{3}\begin{verbatim}
                  2
   (16)  cos(y - x  - 3)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty16}
\begin{paste}{ExpressionXmpPageEmpty16}{ExpressionXmpPagePatch16}
\pastebutton{ExpressionXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{e2 := cos(x**2 - y + 3)\bound{e2 }}
\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPagePatch17}
\begin{paste}{ExpressionXmpPageFull17}{ExpressionXmpPageEmpty17}
\pastebutton{ExpressionXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{e3 := asin(e2) - \%pi/2\free{e2 }\bound{e3 }}
\indentrel{3}\begin{verbatim}
                2
   (17)  - y + x  + 3
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty17}
\begin{paste}{ExpressionXmpPageEmpty17}{ExpressionXmpPagePatch17}
\pastebutton{ExpressionXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{e3 := asin(e2) - \%pi/2\free{e2 }\bound{e3 }}
\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPagePatch18}
\begin{paste}{ExpressionXmpPageFull18}{ExpressionXmpPageEmpty18}
\pastebutton{ExpressionXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{e3 :: Polynomial Integer\free{e3 }}
\indentrel{3}\begin{verbatim}
                2
   (18)  - y + x  + 3
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty18}
\begin{paste}{ExpressionXmpPageEmpty18}{ExpressionXmpPagePatch18}
\pastebutton{ExpressionXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{e3 :: Polynomial Integer\free{e3 }}
\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPagePatch19}
\begin{paste}{ExpressionXmpPageFull19}{ExpressionXmpPageEmpty19}
\pastebutton{ExpressionXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{e3 :: DMP([x, y], Integer)\free{e3 }}
\indentrel{3}\begin{verbatim}
          2
   (19)  x  - y + 3
 Type: DistributedMultivariatePolynomial([x,y],Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty19}
\begin{paste}{ExpressionXmpPageEmpty19}{ExpressionXmpPagePatch19}
\pastebutton{ExpressionXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{e3 :: DMP([x, y], Integer)\free{e3 }}
\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPagePatch20}
\begin{paste}{ExpressionXmpPageFull20}{ExpressionXmpPageEmpty20}
\pastebutton{ExpressionXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{sin \%pi}
\indentrel{3}\begin{verbatim}
   (20)  0
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty20}
\begin{paste}{ExpressionXmpPageEmpty20}{ExpressionXmpPagePatch20}
\pastebutton{ExpressionXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{sin \%pi}
\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPagePatch21}
\begin{paste}{ExpressionXmpPageFull21}{ExpressionXmpPageEmpty21}
\pastebutton{ExpressionXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{cos(\%pi / 4)}
\indentrel{3}\begin{verbatim}
          ÚÄ¿
         \³2
   (21)  ÄÄÄÄ
           2
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty21}
\begin{paste}{ExpressionXmpPageEmpty21}{ExpressionXmpPagePatch21}
\pastebutton{ExpressionXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{cos(\%pi / 4)}
\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPagePatch22}
\begin{paste}{ExpressionXmpPageFull22}{ExpressionXmpPageEmpty22}
\pastebutton{ExpressionXmpPageFull22}{\hidepaste}
\tab{5}\spadcommand{tan(x)**6 + 3*tan(x)**4 + 3*tan(x)**2 + 1\bound{tan6 }}
\indentrel{3}\begin{verbatim}
               6          4          2
   (22)  tan(x)  + 3tan(x)  + 3tan(x)  + 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty22}
\begin{paste}{ExpressionXmpPageEmpty22}{ExpressionXmpPagePatch22}
\pastebutton{ExpressionXmpPageEmpty22}{\showpaste}
\tab{5}\spadcommand{tan(x)**6 + 3*tan(x)**4 + 3*tan(x)**2 + 1\bound{tan6 }}
\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPagePatch23}
\begin{paste}{ExpressionXmpPageFull23}{ExpressionXmpPageEmpty23}
\pastebutton{ExpressionXmpPageFull23}{\hidepaste}
\tab{5}\spadcommand{simplify \%\free{tan6 }}
\indentrel{3}\begin{verbatim}
            1
   (23)  ÄÄÄÄÄÄÄ
               6
         cos(x)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExpressionXmpPageEmpty23}
\begin{paste}{ExpressionXmpPageEmpty23}{ExpressionXmpPagePatch23}
\pastebutton{ExpressionXmpPageEmpty23}{\showpaste}
\tab{5}\spadcommand{simplify \%\free{tan6 }}
\end{paste}\end{patch}

\end{chunk}
\section{explot2d.ht}
\pagetitle{ExPlot2DFunctions}{explot2d.ht}{Plotting Functions of One Variable}
\begin{chunk}{explot2d.ht}
\begin{page}{ExPlot2DFunctions}{Plotting Functions of One Variable}
\beginscroll
To plot a function {\em y = f(x)}, you need only specify the function and the
interval on which it is to be plotted.
\graphpaste{draw(sin(tan(x)) - tan(sin(x)),x = 0..6)}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExPlot2DFunctionsPatch1}
\begin{paste}{ExPlot2DFunctionsFull1}{ExPlot2DFunctionsEmpty1}
\pastebutton{ExPlot2DFunctionsFull1}{\hidepaste}
\tab{5}\spadgraph{draw(sin(tan(x)) - tan(sin(x)),x = 0..6)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/explot2dfunctions1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/explot2dfunctions1}}
\end{paste}\end{patch}

\begin{patch}{ExPlot2DFunctionsEmpty1}
\begin{paste}{ExPlot2DFunctionsEmpty1}{ExPlot2DFunctionsPatch1}
\pastebutton{ExPlot2DFunctionsEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(sin(tan(x)) - tan(sin(x)),x = 0..6)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExPlot2DParametric}{explot2d.ht}{Plotting Parametric Curves}
\begin{chunk}{explot2d.ht}
\begin{page}{ExPlot2DParametric}{Plotting Parametric Curves}
\beginscroll
To plot a parametric curve defined by {\em x = f(t)},
{\em y = g(t)}, specify the functions
{\em f(t)} and {\em g(t)}
as arguments of the function `curve', then give
the interval over which {\em t} is to range.
\graphpaste{draw(curve(9 * sin(3*t/4),8 * sin(t)),t = -4*\%pi..4*\%pi)}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExPlot2DParametricPatch1}
\begin{paste}{ExPlot2DParametricFull1}{ExPlot2DParametricEmpty1}
\pastebutton{ExPlot2DParametricFull1}{\hidepaste}
\tab{5}\spadgraph{draw(curve(9 * sin(3*t/4),8 * sin(t)),t = -4*\%pi..4*\%pi)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/explot2dparametric1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/explot2dparametric1}}
\end{paste}\end{patch}

\begin{patch}{ExPlot2DParametricEmpty1}
\begin{paste}{ExPlot2DParametricEmpty1}{ExPlot2DParametricPatch1}
\pastebutton{ExPlot2DParametricEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(curve(9 * sin(3*t/4),8 * sin(t)),t = -4*\%pi..4*\%pi)}
\end{paste}
\end{patch}

\end{chunk}
\pagetitle{ExPlot2DPolar}{explot2d.ht}{Plotting Using Polar Coordinates}
\begin{chunk}{explot2d.ht}
\begin{page}{ExPlot2DPolar}{Plotting Using Polar Coordinates}
\beginscroll
To plot the function {\em r = f(theta)} in polar coordinates,
use the option {\em coordinates == polar}.
As usual,
call the function 'draw' and specify the function {\em f(theta)} and the
interval over which {\em theta} is to range.
\graphpaste{draw(sin(4*t/7),t = 0..14*\%pi,coordinates == polar)}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExPlot2DPolarPatch1}
\begin{paste}{ExPlot2DPolarFull1}{ExPlot2DPolarEmpty1}
\pastebutton{ExPlot2DPolarFull1}{\hidepaste}
\tab{5}\spadgraph{draw(sin(4*t/7),t = 0..14*\%pi,coordinates == polar)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/explot2dpolar1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/explot2dpolar1}}
\end{paste}\end{patch}

\begin{patch}{ExPlot2DPolarEmpty1}
\begin{paste}{ExPlot2DPolarEmpty1}{ExPlot2DPolarPatch1}
\pastebutton{ExPlot2DPolarEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(sin(4*t/7),t = 0..14*\%pi,coordinates == polar)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExPlot2DAlgebraic}{explot2d.ht}{Plotting Plane Algebraic Curves}
\begin{chunk}{explot2d.ht}
\begin{page}{ExPlot2DAlgebraic}{Plotting Plane Algebraic Curves}
\beginscroll
Axiom can also plot plane algebraic curves (i.e. curves defined by
an equation {\em f(x,y) = 0}) provided that the curve is non-singular 
in the region to be sketched.
Here's an example:
\graphpaste{draw(y**2 + y - (x**3 - x) = 0, x, y, range == [-2..2,-2..1])}
Here the region of the sketch is {\em -2 <= x <= 2, -2 <= y <= 1}.
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExPlot2DAlgebraicPatch1}
\begin{paste}{ExPlot2DAlgebraicFull1}{ExPlot2DAlgebraicEmpty1}
\pastebutton{ExPlot2DAlgebraicFull1}{\hidepaste}
\tab{5}\spadgraph{draw(y**2 + y - (x**3 - x) = 0, x, y, range == [-2..2,-2..1])}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/explot2dalgebraic1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/explot2dalgebraic1}}
\end{paste}\end{patch}

\begin{patch}{ExPlot2DAlgebraicEmpty1}
\begin{paste}{ExPlot2DAlgebraicEmpty1}{ExPlot2DAlgebraicPatch1}
\pastebutton{ExPlot2DAlgebraicEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(y**2 + y - (x**3 - x) = 0, x, y, range == [-2..2,-2..1])}
\end{paste}\end{patch}

\end{chunk}
\section{explot3d.ht}
\pagetitle{ExPlot3DFunctions}{explot3d.ht}{Plotting Functions of Two Variables}
\begin{chunk}{explot3d.ht}
\begin{page}{ExPlot3DFunctions}{Plotting Functions of Two Variables}
\beginscroll
To plot a function {\em z = f(x,y)}, you need only specify the function 
and the intervals over which the dependent variables will range.
For example, here's how you plot the function {\em z = cos(x*y)} as the 
variables {\em x} and {\em y} both range between -3 and 3:
\graphpaste{draw(cos(x*y),x = -3..3,y = -3..3)}
\endscroll
\autobuttons
\end{page}
 
\begin{patch}{ExPlot3DFunctionsPatch1}
\begin{paste}{ExPlot3DFunctionsFull1}{ExPlot3DFunctionsEmpty1}
\pastebutton{ExPlot3DFunctionsFull1}{\hidepaste}
\tab{5}\spadgraph{draw(cos(x*y),x = -3..3,y = -3..3)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/explot3dfunctions1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/explot3dfunctions1}}
\end{paste}\end{patch}

\begin{patch}{ExPlot3DFunctionsEmpty1}
\begin{paste}{ExPlot3DFunctionsEmpty1}{ExPlot3DFunctionsPatch1}
\pastebutton{ExPlot3DFunctionsEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(cos(x*y),x = -3..3,y = -3..3)}
\end{paste}
\end{patch}

\end{chunk}
\pagetitle{ExPlot3DParametricSurface}{explot3d.ht}
{Plotting Parametric Surfaces}
\begin{chunk}{explot3d.ht}
\begin{page}{ExPlot3DParametricSurface}{Plotting Parametric Surfaces}
\beginscroll
To plot a parametric surface defined by {\em x = f(u,v)}, 
{\em y = g(u,v)}, {\em z = h(u,v)}, specify the functions
{\em f(u,v)}, {\em g(u,v)}, and {\em h(u,v)}
as arguments of the function `surface', then give
the intervals over which {\em u} and {\em v} are to range.
With parametric surfaces, we can create some interesting graphs.
Here's an egg:
\graphpaste{draw(surface(5*sin(u)*cos(v),4*sin(u)*sin(v),3*cos(u)),
u=0..\%pi,v=0..2*\%pi)}
Here's a cone:
\graphpaste{draw(surface(u*cos(v),u*sin(v),u),u=0..4,v=0..2*\%pi)}
\endscroll
\autobuttons
\end{page}
 
\begin{patch}{ExPlot3DParametricSurfacePatch1}
\begin{paste}{ExPlot3DParametricSurfaceFull1}{ExPlot3DParametricSurfaceEmpty1}
\pastebutton{ExPlot3DParametricSurfaceFull1}{\hidepaste}
\tab{5}\spadgraph{draw(surface(5*sin(u)*cos(v),4*sin(u)*sin(v),3*cos(u)),u=0..\%pi,v=0..2*\%pi)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/explot3dparametricsurface1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/explot3dparametricsurface1}}
\end{paste}\end{patch}

\begin{patch}{ExPlot3DParametricSurfaceEmpty1}
\begin{paste}{ExPlot3DParametricSurfaceEmpty1}{ExPlot3DParametricSurfacePatch1}
\pastebutton{ExPlot3DParametricSurfaceEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(surface(5*sin(u)*cos(v),4*sin(u)*sin(v),3*cos(u)),u=0..\%pi,v=0..2*\%pi)}
\end{paste}\end{patch}

\begin{patch}{ExPlot3DParametricSurfacePatch2}
\begin{paste}{ExPlot3DParametricSurfaceFull2}{ExPlot3DParametricSurfaceEmpty2}
\pastebutton{ExPlot3DParametricSurfaceFull2}{\hidepaste}
\tab{5}\spadgraph{draw(surface(u*cos(v),u*sin(v),u),u=0..4,v=0..2*\%pi)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/explot3dparametricsurface2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/explot3dparametricsurface2}}
\end{paste}\end{patch}

\begin{patch}{ExPlot3DParametricSurfaceEmpty2}
\begin{paste}{ExPlot3DParametricSurfaceEmpty2}{ExPlot3DParametricSurfacePatch2}
\pastebutton{ExPlot3DParametricSurfaceEmpty2}{\showpaste}
\tab{5}\spadgraph{draw(surface(u*cos(v),u*sin(v),u),u=0..4,v=0..2*\%pi)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExPlot3DParametricCurve}{explot3d.ht}{Plotting Parametric Curves}
\begin{chunk}{explot3d.ht}
\begin{page}{ExPlot3DParametricCurve}{Plotting Parametric Curves}
\beginscroll
To plot a parametric curve defined by {\em x = f(t)}, 
{\em y = g(t)}, {\em z = h(t)}, specify the functions
{\em f(t)}, {\em g(t)}, and {\em h(t)}
as arguments of the function `curve', then give
the interval over which {\em t} is to range.
Here is a spiral:
\graphpaste{draw(curve(cos(t),sin(t),t),t=0..6)}
Here is the {\em twisted cubic curve}:
\graphpaste{draw(curve(t,t**2,t**3),t=-3..3)}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExPlot3DParametricCurvePatch1}
\begin{paste}{ExPlot3DParametricCurveFull1}{ExPlot3DParametricCurveEmpty1}
\pastebutton{ExPlot3DParametricCurveFull1}{\hidepaste}
\tab{5}\spadgraph{draw(curve(cos(t),sin(t),t),t=0..6)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/explot3dparametriccurve1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/explot3dparametriccurve1}}
\end{paste}\end{patch}

\begin{patch}{ExPlot3DParametricCurveEmpty1}
\begin{paste}{ExPlot3DParametricCurveEmpty1}{ExPlot3DParametricCurvePatch1}
\pastebutton{ExPlot3DParametricCurveEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(curve(cos(t),sin(t),t),t=0..6)}
\end{paste}\end{patch}

\begin{patch}{ExPlot3DParametricCurvePatch2}
\begin{paste}{ExPlot3DParametricCurveFull2}{ExPlot3DParametricCurveEmpty2}
\pastebutton{ExPlot3DParametricCurveFull2}{\hidepaste}
\tab{5}\spadgraph{draw(curve(t,t**2,t**3),t=-3..3)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/explot3dparametriccurve2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/explot3dparametriccurve2}}
\end{paste}\end{patch}

\begin{patch}{ExPlot3DParametricCurveEmpty2}
\begin{paste}{ExPlot3DParametricCurveEmpty2}{ExPlot3DParametricCurvePatch2}
\pastebutton{ExPlot3DParametricCurveEmpty2}{\showpaste}
\tab{5}\spadgraph{draw(curve(t,t**2,t**3),t=-3..3)}
\end{paste}
\end{patch}

\end{chunk}
\section{expose.ht}
\pagetitle{helpExpose}{expose.ht}{Exposure}
\begin{chunk}{expose.ht}
\begin{page}{helpExpose}{Exposure}
\beginscroll
Exposure determines what part of the Axiom library
is available to you when using Axiom.
At any time during your interactive Axiom session,
each constructor is either {\em exposed} or {\em unexposed}.
If a constructor is exposed, its operations are available to
the interpreter and therefore to you.
If a constructor is unexposed, the operations are not seen
by the interpreter and thus not available to you.
\par
If you are a beginner, you may only want
basic parts of the library exposed.
If you are an expert, you may want to have all parts of the
library exposed.
If you have an application that requires
only a segment of the library, you may want to arrange to expose
only that segment for your use.
\par
\endscroll
Additional Information:
\beginmenu
\menulink{What}{ExposureDef}\tab{8}What is an exposure group?
\menulink{System}{ExposureSystem}\tab{8}What exposure groups are 
system defined?
% \menulink{User}{ExposureUser}\tab{8}How can I define my own?
\menulink{Details}{ExposureDetails}\tab{8}Some details on exposure
\endmenu
\end{page}

\end{chunk}
\pagetitle{ExposureSystem}{expose.ht}{System Defined Exposure Groups}
\begin{chunk}{expose.ht}
\begin{page}{ExposureSystem}{System Defined Exposure Groups}
\beginscroll
Exposure is defined by {\em groups}.
Groups have names.
Seven exposure groups are system-defined:\beginmenu
\item\tab{3}{\em current}\tab{12}The currently active exposure group
\item\tab{3}{\em basic}\tab{12}The default value of {\em current}
\item\tab{3}{\em category}\tab{13}Category constructors not in {\em basic}
\item\tab{3}{\em domain}\tab{13}Domain constructors not in {\em basic}
\item\tab{3}{\em package}\tab{13}Package constructors not in {\em basic}
\item\tab{3}{\em default}\tab{13}Default constructors not in {\em basic}
\item\tab{3}{\em hidden}\tab{13}All constructors not in {\em basic}
\item\tab{3}{\em naglink}\tab{13}All constructors used in the Axiom NAG Link
\endmenu
\par
When you first use Axiom, the {\em current} exposure group is
set to {\em basic} and {\em naglink}. Using Hyperdoc or the system command
{\em expose}, you may
change the current exposure group by
adding or dropping constructors or by setting {\em current}
to an exposure group you have created.
\endscroll
Additional Information:
\beginmenu
\menulink{What}{ExposureDef}\tab{10}What is an exposure group?
%\menulink{User}{ExposureUser}\tab{10}How you can define your own exposure group
\endmenu
\end{page}

\end{chunk}
\pagetitle{ExposureDef}{expose.ht}{What is an Exposure Group?}
\begin{chunk}{expose.ht}
\begin{page}{ExposureDef}{What is an Exposure Group?}
\beginscroll
\par
An exposure group is a list of constructors to be exposed.
Those constructors on the list are exposed;
those not on the list are not exposed.
The library contains 4 kinds of constructors intuitively described as follows:
\beginmenu
\item\menuitemstyle{}{\em domain}\tab{10}Describes computational objects 
and functions defined on these objects
\item\menuitemstyle{}{\em package}\tab{10}Describes functions which will 
work over a variety of domains
\item\menuitemstyle{}{\em category}\tab{10}Names a set of operations
\item\menuitemstyle{}{\em default}\tab{10}Provides default functions for 
a cateogry
\endmenu

An exposure group is defined by three lists:
\beginmenu
\item\menuitemstyle{}{\em groups}
\tab{13}A list of other (more basic) groups
\item\menuitemstyle{}{\em additions}
\tab{13}A list of explicit constructors to be included
\item\menuitemstyle{}{\em subtractions}
\tab{13}A list of explicit constructors to be dropped
\endmenu
You can define your own exposure groups: give them names and define the
three above lists to be anything you like.
Using Hyperdoc, you can conveniently edit your exposure groups,
install them as the {\em current} exposure, and so on.
\endscroll
\end{page}

\end{chunk}
\pagetitle{ExposureDetails}{expose.ht}{Details on Exposure}
\begin{chunk}{expose.ht}
\begin{page}{ExposureDetails}{Details on Exposure}
\beginscroll
Exposure is generally defined by the set of domain and package
constructors you want to have available.  Category and default
constructors are generally implied.  A category constructor is exposed
if mentioned by {\em any} other constructor (including another
category).  A default constructor is exposed if its corresponding
category constructor is exposed.
\par
If you explicitly add a domain or package
constructor, its name will be put in an {\em Additions} list.
The system will also add automatically to the {\em Additions} list
any category explicity exported by that domain or package.
If that category has a corresponding default constructor, that
default constructor will also be added as well.
\par
If you like, you can explicitly drop a constructor.  Any such name is
added to the {\em Subtractions} list.  The system will drop this name
from the {\em Additions} list if it appears.
\par
If the package or domain takes arguments from an unexported
domain or declares that its arguments can come from a domain
which is a member of an unexported category, these constructors
will {\em not} be added.
\endscroll
\end{page}

\end{chunk}
\section{exseries.ht}
\pagetitle{ExSeriesConvert}{exseries.ht}{Converting Expressions to Series}
\begin{chunk}{exseries.ht}
\begin{page}{ExSeriesConvert}{Converting Expressions to Series}
\beginscroll
You can convert a functional expression to a power series by using the
function 'series'.
Here's an example:
\spadpaste{series(sin(a*x),x = 0)}
This causes {\em sin(a*x)} to be expanded in powers of {\em (x - 0)}, 
that is, in powers of {\em x}.
You can have {\em sin(a*x)} expanded in powers of {\em (a - \%pi/4)} by
issuing the following command:
\spadpaste{series(sin(a*x),a = \%pi/4)}
\endscroll
\autobuttons
\end{page}
 
\begin{patch}{ExSeriesConvertPatch1}
\begin{paste}{ExSeriesConvertFull1}{ExSeriesConvertEmpty1}
\pastebutton{ExSeriesConvertFull1}{\hidepaste}
\tab{5}\spadcommand{series(sin(a*x),x = 0)}
\indentrel{3}\begin{verbatim}
   (1)
            3        5        7          9
           a   3    a   5    a    7     a     9
     a x - ÄÄ x  + ÄÄÄ x  - ÄÄÄÄ x  + ÄÄÄÄÄÄ x
            6      120      5040      362880
   + 
           11
          a      11      12
     - ÄÄÄÄÄÄÄÄ x   + O(x  )
       39916800
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExSeriesConvertEmpty1}
\begin{paste}{ExSeriesConvertEmpty1}{ExSeriesConvertPatch1}
\pastebutton{ExSeriesConvertEmpty1}{\showpaste}
\tab{5}\spadcommand{series(sin(a*x),x = 0)}
\end{paste}\end{patch}

\begin{patch}{ExSeriesConvertPatch2}
\begin{paste}{ExSeriesConvertFull2}{ExSeriesConvertEmpty2}
\pastebutton{ExSeriesConvertFull2}{\hidepaste}
\tab{5}\spadcommand{series(sin(a*x),a = \%pi/4)}
\indentrel{3}\begin{verbatim}
   (2)
         %pi x          %pi x      %pi
     sin(ÄÄÄÄÄ) + x cos(ÄÄÄÄÄ)(a - ÄÄÄ)
           4              4         4
   + 
        2    %pi x                3    %pi x
       x sin(ÄÄÄÄÄ)              x cos(ÄÄÄÄÄ)
               4         %pi 2           4         %pi 3
     - ÄÄÄÄÄÄÄÄÄÄÄÄ (a - ÄÄÄ)  - ÄÄÄÄÄÄÄÄÄÄÄÄ (a - ÄÄÄ)
             2            4            6            4
   + 
      4    %pi x                5    %pi x
     x sin(ÄÄÄÄÄ)              x cos(ÄÄÄÄÄ)
             4         %pi 4           4         %pi 5
     ÄÄÄÄÄÄÄÄÄÄÄÄ (a - ÄÄÄ)  + ÄÄÄÄÄÄÄÄÄÄÄÄ (a - ÄÄÄ)
          24            4           120           4
   + 
        6    %pi x                7    %pi x
       x sin(ÄÄÄÄÄ)              x cos(ÄÄÄÄÄ)
               4         %pi 6           4         %pi 7
     - ÄÄÄÄÄÄÄÄÄÄÄÄ (a - ÄÄÄ)  - ÄÄÄÄÄÄÄÄÄÄÄÄ (a - ÄÄÄ)
            720           4          5040           4
   + 
      8    %pi x                9    %pi x
     x sin(ÄÄÄÄÄ)              x cos(ÄÄÄÄÄ)
             4         %pi 8           4         %pi 9
     ÄÄÄÄÄÄÄÄÄÄÄÄ (a - ÄÄÄ)  + ÄÄÄÄÄÄÄÄÄÄÄÄ (a - ÄÄÄ)
         40320          4         362880          4
   + 
        10    %pi x
       x  sin(ÄÄÄÄÄ)
                4         %pi 10          %pi 11
     - ÄÄÄÄÄÄÄÄÄÄÄÄÄ (a - ÄÄÄ)   + O((a - ÄÄÄ)  )
          3628800          4               4
Type: UnivariatePuiseuxSeries(Expression Integer,a,pi/4)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExSeriesConvertEmpty2}
\begin{paste}{ExSeriesConvertEmpty2}{ExSeriesConvertPatch2}
\pastebutton{ExSeriesConvertEmpty2}{\showpaste}
\tab{5}\spadcommand{series(sin(a*x),a = \%pi/4)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExSeriesManipulate}{exseries.ht}{Manipulating Power Series}
\begin{chunk}{exseries.ht}
\begin{page}{ExSeriesManipulate}{Manipulating Power Series}
\beginscroll
Once you have created a power series, you can perform arithmetic 
operations on that series.
First compute the Taylor expansion of {\em 1/(1-x)}:
\spadpaste{f := series(1/(1-x),x = 0) \bound{f}}
Now compute the square of that series:
\spadpaste{f ** 2 \free{f}}
It's as easy as 1, 2, 3,...
\endscroll
\autobuttons
\end{page}
 
\begin{patch}{ExSeriesManipulatePatch1}
\begin{paste}{ExSeriesManipulateFull1}{ExSeriesManipulateEmpty1}
\pastebutton{ExSeriesManipulateFull1}{\hidepaste}
\tab{5}\spadcommand{f := series(1/(1-x),x = 0)\bound{f }}
\indentrel{3}\begin{verbatim}
   (1)
              2    3    4    5    6    7    8    9    10
     1 + x + x  + x  + x  + x  + x  + x  + x  + x  + x
   + 
        11
     O(x  )
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExSeriesManipulateEmpty1}
\begin{paste}{ExSeriesManipulateEmpty1}{ExSeriesManipulatePatch1}
\pastebutton{ExSeriesManipulateEmpty1}{\showpaste}
\tab{5}\spadcommand{f := series(1/(1-x),x = 0)\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ExSeriesManipulatePatch2}
\begin{paste}{ExSeriesManipulateFull2}{ExSeriesManipulateEmpty2}
\pastebutton{ExSeriesManipulateFull2}{\hidepaste}
\tab{5}\spadcommand{f ** 2\free{f }}
\indentrel{3}\begin{verbatim}
   (2)
                2     3     4     5     6     7     8
     1 + 2x + 3x  + 4x  + 5x  + 6x  + 7x  + 8x  + 9x
   + 
        9      10      11
     10x  + 11x   + O(x  )
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExSeriesManipulateEmpty2}
\begin{paste}{ExSeriesManipulateEmpty2}{ExSeriesManipulatePatch2}
\pastebutton{ExSeriesManipulateEmpty2}{\showpaste}
\tab{5}\spadcommand{f ** 2\free{f }}
\end{paste}
\end{patch}

\end{chunk}
\pagetitle{ExSeriesFunctions}{exseries.ht}{Functions on Power Series}
\begin{chunk}{exseries.ht}
\begin{page}{ExSeriesFunctions}{Functions on Power Series}
\beginscroll
The usual elementary functions ({\em log}, {\em exp}, 
trigonometric functions, etc.)
are defined for power series.
You can create a power series:
% Warning: currently there are (interpretor) problems with converting
% rational functions and polynomials to power series.
\spadpaste{f := series(1/(1-x),x = 0) \bound{f1}}
and then apply these functions to the series:
\spadpaste{g := log(f) \free{f1} \bound{g}}
\spadpaste{exp(g) \free{g}}
\endscroll
\autobuttons
\end{page}
 
\begin{patch}{ExSeriesFunctionsPatch1}
\begin{paste}{ExSeriesFunctionsFull1}{ExSeriesFunctionsEmpty1}
\pastebutton{ExSeriesFunctionsFull1}{\hidepaste}
\tab{5}\spadcommand{f := series(1/(1-x),x = 0)\bound{f1 }}
\indentrel{3}\begin{verbatim}
   (1)
              2    3    4    5    6    7    8    9    10
     1 + x + x  + x  + x  + x  + x  + x  + x  + x  + x
   + 
        11
     O(x  )
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExSeriesFunctionsEmpty1}
\begin{paste}{ExSeriesFunctionsEmpty1}{ExSeriesFunctionsPatch1}
\pastebutton{ExSeriesFunctionsEmpty1}{\showpaste}
\tab{5}\spadcommand{f := series(1/(1-x),x = 0)\bound{f1 }}
\end{paste}\end{patch}

\begin{patch}{ExSeriesFunctionsPatch2}
\begin{paste}{ExSeriesFunctionsFull2}{ExSeriesFunctionsEmpty2}
\pastebutton{ExSeriesFunctionsFull2}{\hidepaste}
\tab{5}\spadcommand{g := log(f)\free{f1 }\bound{g }}
\indentrel{3}\begin{verbatim}
   (2)
         1  2   1  3   1  4   1  5   1  6   1  7   1  8
     x + Ä x  + Ä x  + Ä x  + Ä x  + Ä x  + Ä x  + Ä x
         2      3      4      5      6      7      8
   + 
     1  9    1  10    1  11      12
     Ä x  + ÄÄ x   + ÄÄ x   + O(x  )
     9      10       11
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExSeriesFunctionsEmpty2}
\begin{paste}{ExSeriesFunctionsEmpty2}{ExSeriesFunctionsPatch2}
\pastebutton{ExSeriesFunctionsEmpty2}{\showpaste}
\tab{5}\spadcommand{g := log(f)\free{f1 }\bound{g }}
\end{paste}\end{patch}

\begin{patch}{ExSeriesFunctionsPatch3}
\begin{paste}{ExSeriesFunctionsFull3}{ExSeriesFunctionsEmpty3}
\pastebutton{ExSeriesFunctionsFull3}{\hidepaste}
\tab{5}\spadcommand{exp(g)\free{g }}
\indentrel{3}\begin{verbatim}
   (3)
              2    3    4    5    6    7    8    9    10
     1 + x + x  + x  + x  + x  + x  + x  + x  + x  + x
   + 
        11
     O(x  )
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExSeriesFunctionsEmpty3}
\begin{paste}{ExSeriesFunctionsEmpty3}{ExSeriesFunctionsPatch3}
\pastebutton{ExSeriesFunctionsEmpty3}{\showpaste}
\tab{5}\spadcommand{exp(g)\free{g }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExSeriesSubstitution}{exseries.ht}
{Substituting Numerical Values in Power Series}
\begin{chunk}{exseries.ht}
\begin{page}{ExSeriesSubstitution}
{Substituting Numerical Values in Power Series}
\beginscroll
Here's a way to obtain numerical approximations of 
{\em e} from the Taylor series
expansion of {\em exp(x)}.
First you create the desired Taylor expansion:
\spadpaste{f := taylor(exp(x)) \bound{f2}}
Now you evaluate the series at the value {\em 1.0}:
% Warning: syntax for evaluating power series may change.
\spadpaste{eval(f,1.0) \free{f2}}
You get a sequence of partial sums.
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExSeriesSubstitutionPatch1}
\begin{paste}{ExSeriesSubstitutionFull1}{ExSeriesSubstitutionEmpty1}
\pastebutton{ExSeriesSubstitutionFull1}{\hidepaste}
\tab{5}\spadcommand{f := taylor(exp(x))\bound{f2 }}
\indentrel{3}\begin{verbatim}
   (1)
             1  2   1  3    1  4    1   5    1   6
     1 + x + Ä x  + Ä x  + ÄÄ x  + ÄÄÄ x  + ÄÄÄ x
             2      6      24      120      720
   + 
     1   7     1    8      1    9      1     10      11
   ÄÄÄÄ x  + ÄÄÄÄÄ x  + ÄÄÄÄÄÄ x  + ÄÄÄÄÄÄÄ x   + O(x  )
   5040      40320      362880      3628800
   Type: UnivariateTaylorSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExSeriesSubstitutionEmpty1}
\begin{paste}{ExSeriesSubstitutionEmpty1}{ExSeriesSubstitutionPatch1}
\pastebutton{ExSeriesSubstitutionEmpty1}{\showpaste}
\tab{5}\spadcommand{f := taylor(exp(x))\bound{f2 }}
\end{paste}\end{patch}

\begin{patch}{ExSeriesSubstitutionPatch2}
\begin{paste}{ExSeriesSubstitutionFull2}{ExSeriesSubstitutionEmpty2}
\pastebutton{ExSeriesSubstitutionFull2}{\hidepaste}
\tab{5}\spadcommand{eval(f,1.0)\free{f2 }}
\indentrel{3}\begin{verbatim}
   (2)
   [1.0, 2.0, 2.5, 2.6666666666 666666667,
    2.7083333333 333333333, 2.7166666666 666666667,
    2.7180555555 555555556, 2.7182539682 53968254,
    2.7182787698 412698413, 2.7182815255 731922399, ...]
                          Type: Stream Expression Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExSeriesSubstitutionEmpty2}
\begin{paste}{ExSeriesSubstitutionEmpty2}{ExSeriesSubstitutionPatch2}
\pastebutton{ExSeriesSubstitutionEmpty2}{\showpaste}
\tab{5}\spadcommand{eval(f,1.0)\free{f2 }}
\end{paste}\end{patch}

\end{chunk}
\section{exsum.ht}
\pagetitle{ExSumListEntriesI}{exsum.ht}{Summing the Entries of a List I}
\begin{chunk}{exsum.ht}
\begin{page}{ExSumListEntriesI}{Summing the Entries of a List I}
\beginscroll
In Axiom, you can create lists of consecutive integers by giving the
first and last entries of the list.
Here's how you create a list of the integers between {\em 1} and {\em 15}:
\spadpaste{[i for i in 1..15]}
To sum the entries of a list, simply put {\em +/} in front of the list.
For example, the following command will sum the integers from 1 to 15:
\spadpaste{reduce(+,[i for i in 1..15])}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExSumListEntriesIPatch1}
\begin{paste}{ExSumListEntriesIFull1}{ExSumListEntriesIEmpty1}
\pastebutton{ExSumListEntriesIFull1}{\hidepaste}
\tab{5}\spadcommand{[i for i in 1..15]}
\indentrel{3}\begin{verbatim}
   (1)  [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExSumListEntriesIEmpty1}
\begin{paste}{ExSumListEntriesIEmpty1}{ExSumListEntriesIPatch1}
\pastebutton{ExSumListEntriesIEmpty1}{\showpaste}
\tab{5}\spadcommand{[i for i in 1..15]}
\end{paste}\end{patch}

\begin{patch}{ExSumListEntriesIPatch2}
\begin{paste}{ExSumListEntriesIFull2}{ExSumListEntriesIEmpty2}
\pastebutton{ExSumListEntriesIFull2}{\hidepaste}
\tab{5}\spadcommand{reduce(+,[i for i in 1..15])}
\indentrel{3}\begin{verbatim}
   (2)  120
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExSumListEntriesIEmpty2}
\begin{paste}{ExSumListEntriesIEmpty2}{ExSumListEntriesIPatch2}
\pastebutton{ExSumListEntriesIEmpty2}{\showpaste}
\tab{5}\spadcommand{reduce(+,[i for i in 1..15])}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExSumListEntriesII}{exsum.ht}{Summing the Entries of a List II}
\begin{chunk}{exsum.ht}
\begin{page}{ExSumListEntriesII}{Summing the Entries of a List II}
\beginscroll
In Axiom, you can also create lists whose elements are some expression
{\em f(n)} as the parameter n ranges between two integers.
For example, the following command will create a list of the squares of
the integers between {\em 5} and {\em 20}:
\spadpaste{[n**2 for n in 5..20]}
You can also compute the sum of the entries of this list:
\spadpaste{reduce(+,[n**2 for n in 5..20])}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExSumListEntriesIIPatch1}
\begin{paste}{ExSumListEntriesIIFull1}{ExSumListEntriesIIEmpty1}
\pastebutton{ExSumListEntriesIIFull1}{\hidepaste}
\tab{5}\spadcommand{[n**2 for n in 5..20]}
\indentrel{3}\begin{verbatim}
   (1)
   [25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225,
    256, 289, 324, 361, 400]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExSumListEntriesIIEmpty1}
\begin{paste}{ExSumListEntriesIIEmpty1}{ExSumListEntriesIIPatch1}
\pastebutton{ExSumListEntriesIIEmpty1}{\showpaste}
\tab{5}\spadcommand{[n**2 for n in 5..20]}
\end{paste}\end{patch}

\begin{patch}{ExSumListEntriesIIPatch2}
\begin{paste}{ExSumListEntriesIIFull2}{ExSumListEntriesIIEmpty2}
\pastebutton{ExSumListEntriesIIFull2}{\hidepaste}
\tab{5}\spadcommand{reduce(+,[n**2 for n in 5..20])}
\indentrel{3}\begin{verbatim}
   (2)  2840
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExSumListEntriesIIEmpty2}
\begin{paste}{ExSumListEntriesIIEmpty2}{ExSumListEntriesIIPatch2}
\pastebutton{ExSumListEntriesIIEmpty2}{\showpaste}
\tab{5}\spadcommand{reduce(+,[n**2 for n in 5..20])}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExSumApproximateE}{exsum.ht}{Approximating $e$}
\begin{chunk}{exsum.ht}
\begin{page}{ExSumApproximateE}{Approximating e}
\beginscroll
You can obtain a numerical approximation of the number {\em e} by summing the
entries of the following list:
\spadpaste{reduce(+,[1.0/factorial(n) for n in 0..20])}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExSumApproximateEPatch1}
\begin{paste}{ExSumApproximateEFull1}{ExSumApproximateEEmpty1}
\pastebutton{ExSumApproximateEFull1}{\hidepaste}
\tab{5}\spadcommand{reduce(+,[1.0/factorial(n) for n in 0..20])}
\indentrel{3}\begin{verbatim}
   (1)  2.7182818284 590452354
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExSumApproximateEEmpty1}
\begin{paste}{ExSumApproximateEEmpty1}{ExSumApproximateEPatch1}
\pastebutton{ExSumApproximateEEmpty1}{\showpaste}
\tab{5}\spadcommand{reduce(+,[1.0/factorial(n) for n in 0..20])}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExSumClosedForm}{exsum.ht}{Closed Form Summations}
\begin{chunk}{exsum.ht}
\begin{page}{ExSumClosedForm}{Closed Form Summations}
\beginscroll
In a previous example, we found the sum of the squares of the integers
between {\em 5} and {\em 20}.
We can also use Axiom to find a formula for the sum of the squares of
the integers between {\em a} and {\em b}, where {\em a} and {\em b}
are integers which will remain
unspecified:
\spadpaste{s := sum(k**2,k = a..b) \bound{s}}
{\em sum(k**2,k = a..b)} returns the sum of {\em k**2} as the index {\em k}
runs from {\em a} to {\em b}.
Let's check our answer in one particular case by substituting specific values
for {\em a} and {\em b} in our formula:
% Warning: syntax for polynomial evaluation will probably change.
\spadpaste{eval(s,[a,b],[1,25]) \free{s}}
\spadpaste{reduce(+,[i**2 for i in 1..25])}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExSumClosedFormPatch1}
\begin{paste}{ExSumClosedFormFull1}{ExSumClosedFormEmpty1}
\pastebutton{ExSumClosedFormFull1}{\hidepaste}
\tab{5}\spadcommand{s := sum(k**2,k = a..b)\bound{s }}
\indentrel{3}\begin{verbatim}
          3     2         3     2
        2b  + 3b  + b - 2a  + 3a  - a
   (1)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                      6
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExSumClosedFormEmpty1}
\begin{paste}{ExSumClosedFormEmpty1}{ExSumClosedFormPatch1}
\pastebutton{ExSumClosedFormEmpty1}{\showpaste}
\tab{5}\spadcommand{s := sum(k**2,k = a..b)\bound{s }}
\end{paste}\end{patch}

\begin{patch}{ExSumClosedFormPatch2}
\begin{paste}{ExSumClosedFormFull2}{ExSumClosedFormEmpty2}
\pastebutton{ExSumClosedFormFull2}{\hidepaste}
\tab{5}\spadcommand{eval(s,[a,b],[1,25])\free{s }}
\indentrel{3}\begin{verbatim}
   (2)  5525
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExSumClosedFormEmpty2}
\begin{paste}{ExSumClosedFormEmpty2}{ExSumClosedFormPatch2}
\pastebutton{ExSumClosedFormEmpty2}{\showpaste}
\tab{5}\spadcommand{eval(s,[a,b],[1,25])\free{s }}
\end{paste}\end{patch}

\begin{patch}{ExSumClosedFormPatch3}
\begin{paste}{ExSumClosedFormFull3}{ExSumClosedFormEmpty3}
\pastebutton{ExSumClosedFormFull3}{\hidepaste}
\tab{5}\spadcommand{reduce(+,[i**2 for i in 1..25])}
\indentrel{3}\begin{verbatim}
   (3)  5525
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExSumClosedFormEmpty3}
\begin{paste}{ExSumClosedFormEmpty3}{ExSumClosedFormPatch3}
\pastebutton{ExSumClosedFormEmpty3}{\showpaste}
\tab{5}\spadcommand{reduce(+,[i**2 for i in 1..25])}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExSumCubes}{exsum.ht}{Sums of Cubes}
\begin{chunk}{exsum.ht}
\begin{page}{ExSumCubes}{Sums of Cubes}
\beginscroll
Here's a cute example.
First compute the sum of the cubes from {\em 1} to {\em n}:
\spadpaste{sum(k**3,k = 1..n)}
Then compute the square of the sum of the integers from {\em 1} to {\em n}:
\spadpaste{sum(k,k = 1..n) ** 2}
The answers are the same.
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExSumCubesPatch1}
\begin{paste}{ExSumCubesFull1}{ExSumCubesEmpty1}
\pastebutton{ExSumCubesFull1}{\hidepaste}
\tab{5}\spadcommand{sum(k**3,k = 1..n)}
\indentrel{3}\begin{verbatim}
         4     3    2
        n  + 2n  + n
   (1)  ÄÄÄÄÄÄÄÄÄÄÄÄÄ
              4
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExSumCubesEmpty1}
\begin{paste}{ExSumCubesEmpty1}{ExSumCubesPatch1}
\pastebutton{ExSumCubesEmpty1}{\showpaste}
\tab{5}\spadcommand{sum(k**3,k = 1..n)}
\end{paste}\end{patch}

\begin{patch}{ExSumCubesPatch2}
\begin{paste}{ExSumCubesFull2}{ExSumCubesEmpty2}
\pastebutton{ExSumCubesFull2}{\hidepaste}
\tab{5}\spadcommand{sum(k,k = 1..n) ** 2}
\indentrel{3}\begin{verbatim}
         4     3    2
        n  + 2n  + n
   (2)  ÄÄÄÄÄÄÄÄÄÄÄÄÄ
              4
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExSumCubesEmpty2}
\begin{paste}{ExSumCubesEmpty2}{ExSumCubesPatch2}
\pastebutton{ExSumCubesEmpty2}{\showpaste}
\tab{5}\spadcommand{sum(k,k = 1..n) ** 2}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExSumPolynomial}{exsum.ht}{Sums of Polynomials}
\begin{chunk}{exsum.ht}
\begin{page}{ExSumPolynomial}{Sums of Polynomials}
\beginscroll
Axiom can compute {\em sum(f,k = a..b)}
when {\em f} is any polynomial in {\em k}, even
one with parameters.
\spadpaste{sum(3*k**2/(c**2 + 1) + 12*k/d,k = (3*a)..(4*b))}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExSumPolynomialPatch1}
\begin{paste}{ExSumPolynomialFull1}{ExSumPolynomialEmpty1}
\pastebutton{ExSumPolynomialFull1}{\hidepaste}
\tab{5}\spadcommand{sum(3*k**2/(c**2 + 1) + 12*k/d,k = (3*a)..(4*b))}
\indentrel{3}\begin{verbatim}
   (1)
            3      2           3      2
       (128b  + 48b  + 4b - 54a  + 27a  - 3a)d
     + 
            2             2        2       2             2
       (192b  + 48b - 108a  + 36a)c  + 192b  + 48b - 108a
     + 
       36a
  /
        2
     (2c  + 2)d
           Type: Union(Fraction Polynomial Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExSumPolynomialEmpty1}
\begin{paste}{ExSumPolynomialEmpty1}{ExSumPolynomialPatch1}
\pastebutton{ExSumPolynomialEmpty1}{\showpaste}
\tab{5}\spadcommand{sum(3*k**2/(c**2 + 1) + 12*k/d,k = (3*a)..(4*b))}
\end{paste}\end{patch}

\end{chunk}
\begin{verbatim}
%\begin{page}{ExSumRationalFunction}{Sums of Rational Functions}
%\beginscroll
%Axiom can compute {\em sum(f,k = a..b)} for some rational functions (quotients
%of polynomials) in {\em k}.
%\spadpaste{sum(1/(k * (k + 2)),k = 1..n)}
%However, the method used (Gosper's method) does not guarantee an answer
%in every case.
%Here's an example of a sum that the method cannot compute:
%\spadpaste{sum(1/(k**2 + 1),k = 1..n)}
%\endscroll
%\autobuttons\end{page}
\end{verbatim}

\pagetitle{ExSumGeneralFunction}{exsum.ht}{Sums of General Functions}
\begin{chunk}{exsum.ht}
\begin{page}{ExSumGeneralFunction}{Sums of General Functions}
\beginscroll
Gosper's method can also be used to compute {\em sum(f,k = a..b)}
for some functions
f which are not rational functions in {\em k}.
Here's an example:
\spadpaste{sum(k * x**k,k = 1..n)}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExSumGeneralFunctionPatch1}
\begin{paste}{ExSumGeneralFunctionFull1}{ExSumGeneralFunctionEmpty1}
\pastebutton{ExSumGeneralFunctionFull1}{\hidepaste}
\tab{5}\spadcommand{sum(k * x**k,k = 1..n)}
\indentrel{3}\begin{verbatim}
            2               n
        (n x  + (- n - 1)x)x  + x
   (1)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                2
               x  - 2x + 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExSumGeneralFunctionEmpty1}
\begin{paste}{ExSumGeneralFunctionEmpty1}{ExSumGeneralFunctionPatch1}
\pastebutton{ExSumGeneralFunctionEmpty1}{\showpaste}
\tab{5}\spadcommand{sum(k * x**k,k = 1..n)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ExSumInfinite}{exsum.ht}{Infinite Sums}
Provide a package for infinite sums
\begin{chunk}{exsum.ht}
\begin{page}{ExSumInfinite}{Infinite Sums}
\beginscroll
In a few cases, we can compute infinite sums by taking limits of finite
sums.
For instance, you can compute the sum of {\em 1/(k * (k + 2))} as {\em k}
ranges from
{\em 1} to {\em infinity}.
Use {\em \%plusInfinity} to denote `plus infinity'.
\spadpaste{limit( sum(1/(k * (k + 2)),k = 1..n) ,n = \%plusInfinity)}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ExSumInfinitePatch1}
\begin{paste}{ExSumInfiniteFull1}{ExSumInfiniteEmpty1}
\pastebutton{ExSumInfiniteFull1}{\hidepaste}
\tab{5}\spadcommand{limit( sum(1/(k * (k + 2)),k = 1..n) ,n = \%plusInfinity)}
\indentrel{3}\begin{verbatim}
        3
   (1)  Ä
        4
Type: Union(OrderedCompletion Fraction Polynomial Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ExSumInfiniteEmpty1}
\begin{paste}{ExSumInfiniteEmpty1}{ExSumInfinitePatch1}
\pastebutton{ExSumInfiniteEmpty1}{\showpaste}
\tab{5}\spadcommand{limit( sum(1/(k * (k + 2)),k = 1..n) ,n = \%plusInfinity)}
\end{paste}\end{patch}

\end{chunk}
\section{farray.ht}
\pagetitle{FlexibleArrayXmpPage}{farray.ht}{FlexibleArray}
\pageto{notitle}{OneDimensionalArrayXmpPage}
\pageto{notitle}{VectorXmpPage}
\begin{chunk}{farray.ht}
\begin{page}{FlexibleArrayXmpPage}{FlexibleArray}
\beginscroll
The \spadtype{FlexibleArray} domain constructor creates
one-dimensional arrays of elements of the same type.
Flexible arrays are an attempt to provide a data type that has the
best features of both one-dimensional arrays (fast, random access
to elements) and lists (flexibility).
They are implemented by a fixed block of storage.
When necessary for expansion, a new, larger block of storage is
allocated and the elements from the old storage area are copied
into the new block.

Flexible arrays have available most of the operations provided by
\spadtype{OneDimensionalArray} 
(see \downlink{`OneDimensionalArray'}{OneDimensionalArrayXmpPage}
\ignore{OneDimensionalArray}
and \downlink{`Vector'}{VectorXmpPage}\ignore{Vector}).
Since flexible arrays are also of category
\spadtype{ExtensibleLinearAggregate}, they have operations
\spadfunX{concat}, \spadfunX{delete}, \spadfunX{insert},
\spadfunX{merge}, \spadfunX{remove}, \spadfunX{removeDuplicates},
and \spadfunX{select}.
In addition, the operations \spadfun{physicalLength} and
\spadfunX{physicalLength} provide user-control over expansion and
contraction.

\xtc{
A convenient way to create a flexible array is to apply
the operation \spadfun{flexibleArray} to a list of values.
}{
\spadpaste{flexibleArray [i for i in 1..6]}
}
\xtc{
Create a flexible array of six zeroes.
}{
\spadpaste{f : FARRAY INT := new(6,0)\bound{f}}
}
\xtc{
For \texht{$i=1\ldots 6$}{i = 1..6},
set the \eth{\smath{i}} element to \smath{i}.
Display \spad{f}.
}{
\spadpaste{for i in 1..6 repeat f.i := i; f\bound{f1}\free{f}}
}
\xtc{
Initially, the physical length is the same as the number of elements.
}{
\spadpaste{physicalLength f\free{f1}}
}
\xtc{
Add an element to the end of \spad{f}.
}{
\spadpaste{concat!(f,11)\bound{f2}\free{f1}}
}
\xtc{
See that its physical length has grown.
}{
\spadpaste{physicalLength f\free{f2}}
}
\xtc{
Make \spad{f} grow to have room for \spad{15} elements.
}{
\spadpaste{physicalLength!(f,15)\bound{f3}\free{f2}}
}
\xtc{
Concatenate the elements of \spad{f} to itself.
The physical length allows room for three more values at the end.
}{
\spadpaste{concat!(f,f)\bound{f4}\free{f3}}
}
\xtc{
Use \spadfunX{insert} to add an element to the front of
a flexible array.
}{
\spadpaste{insert!(22,f,1)\bound{f5}\free{f4}}
}
\xtc{
Create a second flexible array from \spad{f} consisting of the
elements from index 10 forward.
}{
\spadpaste{g := f(10..)\bound{g}\free{f5}}
}
\xtc{
Insert this array at the front of \spad{f}.
}{
\spadpaste{insert!(g,f,1)\bound{g1}\free{g f5}}
}
\xtc{
Merge the flexible array \spad{f} into \spad{g} after sorting each in place.
}{
\spadpaste{merge!(sort! f, sort! g)\bound{f6}\free{g f5}}
}
\xtc{
Remove duplicates in place.
}{
\spadpaste{removeDuplicates! f\bound{f7}\free{f6}}
}
\xtc{
Remove all odd integers.
}{
\spadpaste{select!(i +-> even? i,f)\bound{f8}\free{f7}}
}
\xtc{
All these operations have shrunk the physical length of \spad{f}.
}{
\spadpaste{physicalLength f\free{b8}}
}
\xtc{
To force Axiom not to shrink flexible arrays call the
\spadfun{shrinkable} operation with the argument \axiom{false}.
You must package call this operation.
The previous value is returned.
}{
\spadpaste{shrinkable(false)\$FlexibleArray(Integer)}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{FlexibleArrayXmpPagePatch1}
\begin{paste}{FlexibleArrayXmpPageFull1}{FlexibleArrayXmpPageEmpty1}
\pastebutton{FlexibleArrayXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{flexibleArray [i for i in 1..6]}
\indentrel{3}\begin{verbatim}
   (1)  [1,2,3,4,5,6]
                    Type: FlexibleArray PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPageEmpty1}
\begin{paste}{FlexibleArrayXmpPageEmpty1}{FlexibleArrayXmpPagePatch1}
\pastebutton{FlexibleArrayXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{flexibleArray [i for i in 1..6]}
\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPagePatch2}
\begin{paste}{FlexibleArrayXmpPageFull2}{FlexibleArrayXmpPageEmpty2}
\pastebutton{FlexibleArrayXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{f : FARRAY INT := new(6,0)\bound{f }}
\indentrel{3}\begin{verbatim}
   (2)  [0,0,0,0,0,0]
                            Type: FlexibleArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPageEmpty2}
\begin{paste}{FlexibleArrayXmpPageEmpty2}{FlexibleArrayXmpPagePatch2}
\pastebutton{FlexibleArrayXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{f : FARRAY INT := new(6,0)\bound{f }}
\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPagePatch3}
\begin{paste}{FlexibleArrayXmpPageFull3}{FlexibleArrayXmpPageEmpty3}
\pastebutton{FlexibleArrayXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{for i in 1..6 repeat f.i := i; f\bound{f1 }\free{f }}
\indentrel{3}\begin{verbatim}
   (3)  [1,2,3,4,5,6]
                            Type: FlexibleArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPageEmpty3}
\begin{paste}{FlexibleArrayXmpPageEmpty3}{FlexibleArrayXmpPagePatch3}
\pastebutton{FlexibleArrayXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{for i in 1..6 repeat f.i := i; f\bound{f1 }\free{f }}
\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPagePatch4}
\begin{paste}{FlexibleArrayXmpPageFull4}{FlexibleArrayXmpPageEmpty4}
\pastebutton{FlexibleArrayXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{physicalLength f\free{f1 }}
\indentrel{3}\begin{verbatim}
   (4)  6
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPageEmpty4}
\begin{paste}{FlexibleArrayXmpPageEmpty4}{FlexibleArrayXmpPagePatch4}
\pastebutton{FlexibleArrayXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{physicalLength f\free{f1 }}
\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPagePatch5}
\begin{paste}{FlexibleArrayXmpPageFull5}{FlexibleArrayXmpPageEmpty5}
\pastebutton{FlexibleArrayXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{concat!(f,11)\bound{f2 }\free{f1 }}
\indentrel{3}\begin{verbatim}
   (5)  [1,2,3,4,5,6,11]
                            Type: FlexibleArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPageEmpty5}
\begin{paste}{FlexibleArrayXmpPageEmpty5}{FlexibleArrayXmpPagePatch5}
\pastebutton{FlexibleArrayXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{concat!(f,11)\bound{f2 }\free{f1 }}
\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPagePatch6}
\begin{paste}{FlexibleArrayXmpPageFull6}{FlexibleArrayXmpPageEmpty6}
\pastebutton{FlexibleArrayXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{physicalLength f\free{f2 }}
\indentrel{3}\begin{verbatim}
   (6)  10
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPageEmpty6}
\begin{paste}{FlexibleArrayXmpPageEmpty6}{FlexibleArrayXmpPagePatch6}
\pastebutton{FlexibleArrayXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{physicalLength f\free{f2 }}
\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPagePatch7}
\begin{paste}{FlexibleArrayXmpPageFull7}{FlexibleArrayXmpPageEmpty7}
\pastebutton{FlexibleArrayXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{physicalLength!(f,15)\bound{f3 }\free{f2 }}
\indentrel{3}\begin{verbatim}
   (7)  [1,2,3,4,5,6,11]
                            Type: FlexibleArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPageEmpty7}
\begin{paste}{FlexibleArrayXmpPageEmpty7}{FlexibleArrayXmpPagePatch7}
\pastebutton{FlexibleArrayXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{physicalLength!(f,15)\bound{f3 }\free{f2 }}
\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPagePatch8}
\begin{paste}{FlexibleArrayXmpPageFull8}{FlexibleArrayXmpPageEmpty8}
\pastebutton{FlexibleArrayXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{concat!(f,f)\bound{f4 }\free{f3 }}
\indentrel{3}\begin{verbatim}
   (8)  [1,2,3,4,5,6,11,1,2,3,4,5,6,11]
                            Type: FlexibleArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPageEmpty8}
\begin{paste}{FlexibleArrayXmpPageEmpty8}{FlexibleArrayXmpPagePatch8}
\pastebutton{FlexibleArrayXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{concat!(f,f)\bound{f4 }\free{f3 }}
\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPagePatch9}
\begin{paste}{FlexibleArrayXmpPageFull9}{FlexibleArrayXmpPageEmpty9}
\pastebutton{FlexibleArrayXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{insert!(22,f,1)\bound{f5 }\free{f4 }}
\indentrel{3}\begin{verbatim}
   (9)  [22,1,2,3,4,5,6,11,1,2,3,4,5,6,11]
                            Type: FlexibleArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPageEmpty9}
\begin{paste}{FlexibleArrayXmpPageEmpty9}{FlexibleArrayXmpPagePatch9}
\pastebutton{FlexibleArrayXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{insert!(22,f,1)\bound{f5 }\free{f4 }}
\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPagePatch10}
\begin{paste}{FlexibleArrayXmpPageFull10}{FlexibleArrayXmpPageEmpty10}
\pastebutton{FlexibleArrayXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{g := f(10..)\bound{g }\free{f5 }}
\indentrel{3}\begin{verbatim}
   (10)  [2,3,4,5,6,11]
                            Type: FlexibleArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPageEmpty10}
\begin{paste}{FlexibleArrayXmpPageEmpty10}{FlexibleArrayXmpPagePatch10}
\pastebutton{FlexibleArrayXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{g := f(10..)\bound{g }\free{f5 }}
\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPagePatch11}
\begin{paste}{FlexibleArrayXmpPageFull11}{FlexibleArrayXmpPageEmpty11}
\pastebutton{FlexibleArrayXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{insert!(g,f,1)\bound{g1 }\free{g f5 }}
\indentrel{3}\begin{verbatim}
   (11)  [2,3,4,5,6,11,22,1,2,3,4,5,6,11,1,2,3,4,5,6,11]
                            Type: FlexibleArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPageEmpty11}
\begin{paste}{FlexibleArrayXmpPageEmpty11}{FlexibleArrayXmpPagePatch11}
\pastebutton{FlexibleArrayXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{insert!(g,f,1)\bound{g1 }\free{g f5 }}
\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPagePatch12}
\begin{paste}{FlexibleArrayXmpPageFull12}{FlexibleArrayXmpPageEmpty12}
\pastebutton{FlexibleArrayXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{merge!(sort! f, sort! g)\bound{f6 }\free{g f5 }}
\indentrel{3}\begin{verbatim}
   (12)
   [1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5,
    6, 6, 6, 6, 11, 11, 11, 11, 22]
                            Type: FlexibleArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPageEmpty12}
\begin{paste}{FlexibleArrayXmpPageEmpty12}{FlexibleArrayXmpPagePatch12}
\pastebutton{FlexibleArrayXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{merge!(sort! f, sort! g)\bound{f6 }\free{g f5 }}
\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPagePatch13}
\begin{paste}{FlexibleArrayXmpPageFull13}{FlexibleArrayXmpPageEmpty13}
\pastebutton{FlexibleArrayXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{removeDuplicates! f\bound{f7 }\free{f6 }}
\indentrel{3}\begin{verbatim}
   (13)  [1,2,3,4,5,6,11,22]
                            Type: FlexibleArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPageEmpty13}
\begin{paste}{FlexibleArrayXmpPageEmpty13}{FlexibleArrayXmpPagePatch13}
\pastebutton{FlexibleArrayXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{removeDuplicates! f\bound{f7 }\free{f6 }}
\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPagePatch14}
\begin{paste}{FlexibleArrayXmpPageFull14}{FlexibleArrayXmpPageEmpty14}
\pastebutton{FlexibleArrayXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{select!(i +-> even? i,f)\bound{f8 }\free{f7 }}
\indentrel{3}\begin{verbatim}
   (14)  [2,4,6,22]
                            Type: FlexibleArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPageEmpty14}
\begin{paste}{FlexibleArrayXmpPageEmpty14}{FlexibleArrayXmpPagePatch14}
\pastebutton{FlexibleArrayXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{select!(i +-> even? i,f)\bound{f8 }\free{f7 }}
\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPagePatch15}
\begin{paste}{FlexibleArrayXmpPageFull15}{FlexibleArrayXmpPageEmpty15}
\pastebutton{FlexibleArrayXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{physicalLength f\free{b8 }}
\indentrel{3}\begin{verbatim}
   (15)  8
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPageEmpty15}
\begin{paste}{FlexibleArrayXmpPageEmpty15}{FlexibleArrayXmpPagePatch15}
\pastebutton{FlexibleArrayXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{physicalLength f\free{b8 }}
\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPagePatch16}
\begin{paste}{FlexibleArrayXmpPageFull16}{FlexibleArrayXmpPageEmpty16}
\pastebutton{FlexibleArrayXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{shrinkable(false)$FlexibleArray(Integer)}
\indentrel{3}\begin{verbatim}
   (16)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FlexibleArrayXmpPageEmpty16}
\begin{paste}{FlexibleArrayXmpPageEmpty16}{FlexibleArrayXmpPagePatch16}
\pastebutton{FlexibleArrayXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{shrinkable(false)$FlexibleArray(Integer)}
\end{paste}\end{patch}

\end{chunk}
\section{file.ht}
\pagetitle{FileXmpPage}{file.ht}{File}
\pageto{notitle}{TextFileXmpPage}
\pageto{notitle}{KeyedAccessFileXmpPage}
\pageto{notitle}{LibraryXmpPage}
\pageto{notitle}{FileNameXmpPage}
\begin{chunk}{file.ht}
\begin{page}{FileXmpPage}{File}
\beginscroll

The \spadtype{File(S)} domain provides a basic interface to read and
write values of type \spad{S} in files.
\xtc{
Before working with a file, it must be made accessible to Axiom with
the \spadfunFrom{open}{File} operation.
}{
\spadpaste{ifile:File List Integer:=open("/tmp/jazz1","output")  
\bound{ifile}}
}
The \spadfunFrom{open}{File} function arguments are a \spadtype{FileName}
and a \spadtype{String} specifying the mode.
If a full pathname is not specified, the current default directory is
assumed.
The mode must be one of \spad{"input"} or \spad{"output"}.
If it is not specified, \spad{"input"} is assumed.
Once the file has been opened, you can read or write data.
\xtc{
The operations \spadfunFromX{read}{File} and \spadfunFromX{write}{File} 
are provided.
}{
\spadpaste{write!(ifile, [-1,2,3])        \free{ifile}\bound{ifile1}}
}
\xtc{
}{
\spadpaste{write!(ifile, [10,-10,0,111])  \free{ifile1}\bound{ifile2}}
}
\xtc{
}{
\spadpaste{write!(ifile, [7])             \free{ifile2}\bound{ifile3}}
}
\xtc{
You can change from writing to reading (or vice versa)
by reopening a file.
}{
\spadpaste{reopen!(ifile, "input")        \free{ifile3}\bound{ifile4}}
}
\xtc{
}{
\spadpaste{read! ifile                    \free{ifile4}\bound{ifile5}}
}
\xtc{
}{
\spadpaste{read! ifile                    \free{ifile5}\bound{ifile6}}
}
\xtc{
The \spadfunFromX{read}{File} operation can cause an error if one tries to
read more data than is in the file.
To guard against this possibility the \spadfunFromX{readIfCan}{File}
operation should be used.
}{
\spadpaste{readIfCan! ifile  \free{ifile6}\bound{ifile7}}
}
\xtc{
}{
\spadpaste{readIfCan! ifile  \free{ifile7}\bound{ifile8}}
}
\xtc{
You can find the current mode of the file, and the file's name.
}{
\spadpaste{iomode ifile           \free{ifile}}
}
\xtc{
}{
\spadpaste{name ifile             \free{ifile}}
}
\xtc{
When you are finished with a file, you should close it.
}{
\spadpaste{close! ifile           \free{ifile}\bound{ifileA}}
}
\noOutputXtc{
}{
\spadpaste{)system rm /tmp/jazz1  \free{ifileA}}
}
%\xtc{
%}{
%\spadcommand{)clear all  \free{}\bound{}}
%}

A limitation of the underlying LISP system is that not all values can be
represented in a file.
In particular, delayed values containing compiled functions cannot be
saved.

For more information on related topics, see
\downlink{`TextFile'}{TextFileXmpPage}\ignore{TextFile},
\downlink{`KeyedAccessFile'}{KeyedAccessFileXmpPage}
\ignore{KeyedAccessFile},
\downlink{`Library'}{LibraryXmpPage}\ignore{Library}, and
\downlink{`FileName'}{FileNameXmpPage}\ignore{FileName}.
\showBlurb{File}
\endscroll
\autobuttons
\end{page}

\begin{patch}{FileXmpPagePatch1}
\begin{paste}{FileXmpPageFull1}{FileXmpPageEmpty1}
\pastebutton{FileXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{ifile:File List Integer:=open("/tmp/jazz1","output")\bound{ifile }}
\indentrel{3}\begin{verbatim}
   (1)  "/tmp/jazz1"
                                Type: File List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileXmpPageEmpty1}
\begin{paste}{FileXmpPageEmpty1}{FileXmpPagePatch1}
\pastebutton{FileXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{ifile:File List Integer:=open("/tmp/jazz1","output")\bound{ifile }}
\end{paste}\end{patch}

\begin{patch}{FileXmpPagePatch2}
\begin{paste}{FileXmpPageFull2}{FileXmpPageEmpty2}
\pastebutton{FileXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{write!(ifile, [-1,2,3])\free{ifile }\bound{ifile1 }}
\indentrel{3}\begin{verbatim}
   (2)  [- 1,2,3]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileXmpPageEmpty2}
\begin{paste}{FileXmpPageEmpty2}{FileXmpPagePatch2}
\pastebutton{FileXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{write!(ifile, [-1,2,3])\free{ifile }\bound{ifile1 }}
\end{paste}\end{patch}

\begin{patch}{FileXmpPagePatch3}
\begin{paste}{FileXmpPageFull3}{FileXmpPageEmpty3}
\pastebutton{FileXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{write!(ifile, [10,-10,0,111])\free{ifile1 }\bound{ifile2 }}
\indentrel{3}\begin{verbatim}
   (3)  [10,- 10,0,111]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileXmpPageEmpty3}
\begin{paste}{FileXmpPageEmpty3}{FileXmpPagePatch3}
\pastebutton{FileXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{write!(ifile, [10,-10,0,111])\free{ifile1 }\bound{ifile2 }}
\end{paste}\end{patch}

\begin{patch}{FileXmpPagePatch4}
\begin{paste}{FileXmpPageFull4}{FileXmpPageEmpty4}
\pastebutton{FileXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{write!(ifile, [7])\free{ifile2 }\bound{ifile3 }}
\indentrel{3}\begin{verbatim}
   (4)  [7]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileXmpPageEmpty4}
\begin{paste}{FileXmpPageEmpty4}{FileXmpPagePatch4}
\pastebutton{FileXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{write!(ifile, [7])\free{ifile2 }\bound{ifile3 }}
\end{paste}\end{patch}

\begin{patch}{FileXmpPagePatch5}
\begin{paste}{FileXmpPageFull5}{FileXmpPageEmpty5}
\pastebutton{FileXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{reopen!(ifile, "input")\free{ifile3 }\bound{ifile4 }}
\indentrel{3}\begin{verbatim}
   (5)  "/tmp/jazz1"
                                Type: File List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileXmpPageEmpty5}
\begin{paste}{FileXmpPageEmpty5}{FileXmpPagePatch5}
\pastebutton{FileXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{reopen!(ifile, "input")\free{ifile3 }\bound{ifile4 }}
\end{paste}\end{patch}

\begin{patch}{FileXmpPagePatch6}
\begin{paste}{FileXmpPageFull6}{FileXmpPageEmpty6}
\pastebutton{FileXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{read! ifile\free{ifile4 }\bound{ifile5 }}
\indentrel{3}\begin{verbatim}
   (6)  [- 1,2,3]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileXmpPageEmpty6}
\begin{paste}{FileXmpPageEmpty6}{FileXmpPagePatch6}
\pastebutton{FileXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{read! ifile\free{ifile4 }\bound{ifile5 }}
\end{paste}\end{patch}

\begin{patch}{FileXmpPagePatch7}
\begin{paste}{FileXmpPageFull7}{FileXmpPageEmpty7}
\pastebutton{FileXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{read! ifile\free{ifile5 }\bound{ifile6 }}
\indentrel{3}\begin{verbatim}
   (7)  [10,- 10,0,111]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileXmpPageEmpty7}
\begin{paste}{FileXmpPageEmpty7}{FileXmpPagePatch7}
\pastebutton{FileXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{read! ifile\free{ifile5 }\bound{ifile6 }}
\end{paste}\end{patch}

\begin{patch}{FileXmpPagePatch8}
\begin{paste}{FileXmpPageFull8}{FileXmpPageEmpty8}
\pastebutton{FileXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{readIfCan! ifile\free{ifile6 }\bound{ifile7 }}
\indentrel{3}\begin{verbatim}
   (8)  [7]
                          Type: Union(List Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileXmpPageEmpty8}
\begin{paste}{FileXmpPageEmpty8}{FileXmpPagePatch8}
\pastebutton{FileXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{readIfCan! ifile\free{ifile6 }\bound{ifile7 }}
\end{paste}\end{patch}

\begin{patch}{FileXmpPagePatch9}
\begin{paste}{FileXmpPageFull9}{FileXmpPageEmpty9}
\pastebutton{FileXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{readIfCan! ifile\free{ifile7 }\bound{ifile8 }}
\indentrel{3}\begin{verbatim}
   (9)  "failed"
                              Type: Union("failed",...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileXmpPageEmpty9}
\begin{paste}{FileXmpPageEmpty9}{FileXmpPagePatch9}
\pastebutton{FileXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{readIfCan! ifile\free{ifile7 }\bound{ifile8 }}
\end{paste}\end{patch}

\begin{patch}{FileXmpPagePatch10}
\begin{paste}{FileXmpPageFull10}{FileXmpPageEmpty10}
\pastebutton{FileXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{iomode ifile\free{ifile }}
\indentrel{3}\begin{verbatim}
   (10)  "input"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileXmpPageEmpty10}
\begin{paste}{FileXmpPageEmpty10}{FileXmpPagePatch10}
\pastebutton{FileXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{iomode ifile\free{ifile }}
\end{paste}\end{patch}

\begin{patch}{FileXmpPagePatch11}
\begin{paste}{FileXmpPageFull11}{FileXmpPageEmpty11}
\pastebutton{FileXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{name ifile\free{ifile }}
\indentrel{3}\begin{verbatim}
   (11)  "/tmp/jazz1"
                                         Type: FileName
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileXmpPageEmpty11}
\begin{paste}{FileXmpPageEmpty11}{FileXmpPagePatch11}
\pastebutton{FileXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{name ifile\free{ifile }}
\end{paste}\end{patch}

\begin{patch}{FileXmpPagePatch12}
\begin{paste}{FileXmpPageFull12}{FileXmpPageEmpty12}
\pastebutton{FileXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{close! ifile\free{ifile }\bound{ifileA }}
\indentrel{3}\begin{verbatim}
   (12)  "/tmp/jazz1"
                                Type: File List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileXmpPageEmpty12}
\begin{paste}{FileXmpPageEmpty12}{FileXmpPagePatch12}
\pastebutton{FileXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{close! ifile\free{ifile }\bound{ifileA }}
\end{paste}\end{patch}

\begin{patch}{FileXmpPagePatch13}
\begin{paste}{FileXmpPageFull13}{FileXmpPageEmpty13}
\pastebutton{FileXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{)system rm /tmp/jazz1\free{ifileA }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileXmpPageEmpty13}
\begin{paste}{FileXmpPageEmpty13}{FileXmpPagePatch13}
\pastebutton{FileXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{)system rm /tmp/jazz1\free{ifileA }}
\end{paste}\end{patch}

\end{chunk}
\section{float.ht}
\pagetitle{FloatXmpPage}{float.ht}{Float}
\pagepic{ps/v71floatxmppage.eps}{FloatXmpPage}{0.50}
\pagefrom{Axiom Number Types}{NumberPage}
\pageto{Graphics}{ugGraphPage}
\pageto{Numeric Functions}{ugProblemNumericPage}
\pageto{DoubleFloat}{DoubleFloatXmpPage}
\pageto{Introduction to Float}{ugxFloatIntroPage}
\pageto{Conversion Functions}{ugxFloatConvertPage}
\pageto{Output Functions}{ugxFloatOutputPage}
\pageto{Determinant of a Hilbert Matrix}{ugxFloatHilbertPage}
\begin{chunk}{float.ht}
\begin{page}{FloatXmpPage}{Float}
\beginscroll
 Axiom provides two kinds of floating point numbers.
The domain \spadtype{Float} (abbreviation \spadtype{FLOAT})
implements a model of arbitrary
precision floating point numbers.
The domain \spadtype{DoubleFloat} (abbreviation \spadtype{DFLOAT})
is intended to make available
hardware floating point arithmetic in Axiom.
The actual model of floating point that \spadtype{DoubleFloat} provides is
system-dependent.
For example, on the IBM system 370 Axiom uses IBM double
precision which has fourteen hexadecimal digits of precision or roughly
sixteen decimal digits.
Arbitrary precision floats allow the user to specify the
precision at which arithmetic operations are computed.
Although this is an attractive facility, it comes at a cost.
Arbitrary-precision floating-point arithmetic typically takes
twenty to two hundred times more time than hardware floating point.

For more information about Axiom's numeric and graphic
facilities,  see
\downlink{``Graphics''}{ugGraphPage} in 
Section 7 \ignore{ugGraph},
\downlink{``Numeric Functions''}{ugProblemNumericPage} in 
Section 8.1\ignore{ugProblemNumeric}, and
\downlink{`DoubleFloat'}{DoubleFloatXmpPage}\ignore{DoubleFloat}.

\beginmenu
    \menudownlink{{9.27.1. Introduction to Float}}{ugxFloatIntroPage}
    \menudownlink{{9.27.2. Conversion Functions}}{ugxFloatConvertPage}
    \menudownlink{{9.27.3. Output Functions}}{ugxFloatOutputPage}
    \menudownlink{{9.27.4. An Example: Determinant of a Hilbert Matrix}}
{ugxFloatHilbertPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugxFloatIntroPage}{float.ht}{Introduction to Float}
\begin{chunk}{float.ht}
\begin{page}{ugxFloatIntroPage}{Introduction to Float}
\beginscroll

Scientific notation is supported for input and output
of floating point numbers.
A floating point number is written as a string of digits containing a
decimal point optionally followed by the letter ``{\tt E}'', and then
the exponent.
\xtc{
We begin by doing some calculations using arbitrary precision floats.
The default precision is twenty decimal digits.
}{
\spadpaste{1.234}
}
\xtc{
A decimal base for the exponent is assumed, so the number
\spad{1.234E2}  denotes
\texht{$1.234 \cdot  10^2$}{\spad{1.234 * 10**2}}.
}{
\spadpaste{1.234E2}
}
\xtc{
The normal arithmetic operations are available for floating point
numbers.
}{
\spadpaste{sqrt(1.2 + 2.3 / 3.4 ** 4.5)}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxFloatIntroPagePatch1}
\begin{paste}{ugxFloatIntroPageFull1}{ugxFloatIntroPageEmpty1}
\pastebutton{ugxFloatIntroPageFull1}{\hidepaste}
\tab{5}\spadcommand{1.234}
\indentrel{3}\begin{verbatim}
   (1)  1.234
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatIntroPageEmpty1}
\begin{paste}{ugxFloatIntroPageEmpty1}{ugxFloatIntroPagePatch1}
\pastebutton{ugxFloatIntroPageEmpty1}{\showpaste}
\tab{5}\spadcommand{1.234}
\end{paste}\end{patch}

\begin{patch}{ugxFloatIntroPagePatch2}
\begin{paste}{ugxFloatIntroPageFull2}{ugxFloatIntroPageEmpty2}
\pastebutton{ugxFloatIntroPageFull2}{\hidepaste}
\tab{5}\spadcommand{1.234E2}
\indentrel{3}\begin{verbatim}
   (2)  123.4
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatIntroPageEmpty2}
\begin{paste}{ugxFloatIntroPageEmpty2}{ugxFloatIntroPagePatch2}
\pastebutton{ugxFloatIntroPageEmpty2}{\showpaste}
\tab{5}\spadcommand{1.234E2}
\end{paste}\end{patch}

\begin{patch}{ugxFloatIntroPagePatch3}
\begin{paste}{ugxFloatIntroPageFull3}{ugxFloatIntroPageEmpty3}
\pastebutton{ugxFloatIntroPageFull3}{\hidepaste}
\tab{5}\spadcommand{sqrt(1.2 + 2.3 / 3.4 ** 4.5)}
\indentrel{3}\begin{verbatim}
   (3)  1.0996972790 671286226
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatIntroPageEmpty3}
\begin{paste}{ugxFloatIntroPageEmpty3}{ugxFloatIntroPagePatch3}
\pastebutton{ugxFloatIntroPageEmpty3}{\showpaste}
\tab{5}\spadcommand{sqrt(1.2 + 2.3 / 3.4 ** 4.5)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxFloatConvertPage}{float.ht}{Conversion Functions}
\pageto{notitle}{ugTypesConvertPage}
\begin{chunk}{float.ht}
\begin{page}{ugxFloatConvertPage}{Conversion Functions}
\beginscroll

\labelSpace{3pc}
\xtc{
You can use conversion
(\downlink{``Conversion''}{ugTypesConvertPage} 
in Section 2.7\ignore{ugTypesConvert})
to go back and forth between \spadtype{Integer}, 
\spadtype{Fraction Integer} and \spadtype{Float}, as appropriate.
}{
\spadpaste{i := 3 :: Float \bound{i}}
}
\xtc{
}{
\spadpaste{i :: Integer \free{i}}
}
\xtc{
}{
\spadpaste{i :: Fraction Integer \free{i}}
}
\xtc{
Since you are explicitly asking for a conversion, you must take
responsibility for any loss of exactness.
}{
\spadpaste{r := 3/7 :: Float \bound{r}}
}
\xtc{
}{
\spadpaste{r :: Fraction Integer \free{r}}
}
\xtc{
This conversion cannot be performed: use
\spadfunFrom{truncate}{Float} or \spadfunFrom{round}{Float} if that
is what you intend.
}{
\spadpaste{r :: Integer \free{r}}
}

\xtc{
The operations \spadfunFrom{truncate}{Float} and \spadfunFrom{round}{Float}
truncate  \ldots
}{
\spadpaste{truncate 3.6}
}
\xtc{
and round
to the nearest integral \spadtype{Float} respectively.
}{
\spadpaste{round 3.6}
}
\xtc{
}{
\spadpaste{truncate(-3.6)}
}
\xtc{
}{
\spadpaste{round(-3.6)}
}
\xtc{
The operation \spadfunFrom{fractionPart}{Float} computes the fractional part of
\spad{x}, that is, \spad{x - truncate x}.
}{
\spadpaste{fractionPart 3.6}
}
\xtc{
The operation \spadfunFrom{digits}{Float} allows the user to set the
precision.
It returns the previous value it was using.
}{
\spadpaste{digits 40 \bound{d40}}
}
\xtc{
}{
\spadpaste{sqrt 0.2}
}
\xtc{
}{
\spadpaste{pi()\$Float \free{d40}}
}
\xtc{
The precision is only limited by the computer memory available.
Calculations at 500 or more digits of precision are not difficult.
}{
\spadpaste{digits 500 \bound{d1000}}
}
\xtc{
}{
\spadpaste{pi()\$Float \free{d1000}}
}
\xtc{
Reset \spadfunFrom{digits}{Float} to its default value.
}{
\spadpaste{digits 20}
}
Numbers of type \spadtype{Float} are represented as a record of two
integers, namely, the mantissa and the exponent where the base of the
exponent is binary.
That is, the floating point number \spad{(m,e)} represents the number
\texht{$m \cdot 2^e$}{\spad{m * 2**e}}.
A consequence of using a binary base is that decimal numbers can not, in
general, be represented exactly.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxFloatConvertPagePatch1}
\begin{paste}{ugxFloatConvertPageFull1}{ugxFloatConvertPageEmpty1}
\pastebutton{ugxFloatConvertPageFull1}{\hidepaste}
\tab{5}\spadcommand{i := 3 :: Float\bound{i }}
\indentrel{3}\begin{verbatim}
   (1)  3.0
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPageEmpty1}
\begin{paste}{ugxFloatConvertPageEmpty1}{ugxFloatConvertPagePatch1}
\pastebutton{ugxFloatConvertPageEmpty1}{\showpaste}
\tab{5}\spadcommand{i := 3 :: Float\bound{i }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPagePatch2}
\begin{paste}{ugxFloatConvertPageFull2}{ugxFloatConvertPageEmpty2}
\pastebutton{ugxFloatConvertPageFull2}{\hidepaste}
\tab{5}\spadcommand{i :: Integer\free{i }}
\indentrel{3}\begin{verbatim}
   (2)  3
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPageEmpty2}
\begin{paste}{ugxFloatConvertPageEmpty2}{ugxFloatConvertPagePatch2}
\pastebutton{ugxFloatConvertPageEmpty2}{\showpaste}
\tab{5}\spadcommand{i :: Integer\free{i }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPagePatch3}
\begin{paste}{ugxFloatConvertPageFull3}{ugxFloatConvertPageEmpty3}
\pastebutton{ugxFloatConvertPageFull3}{\hidepaste}
\tab{5}\spadcommand{i :: Fraction Integer\free{i }}
\indentrel{3}\begin{verbatim}
   (3)  3
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPageEmpty3}
\begin{paste}{ugxFloatConvertPageEmpty3}{ugxFloatConvertPagePatch3}
\pastebutton{ugxFloatConvertPageEmpty3}{\showpaste}
\tab{5}\spadcommand{i :: Fraction Integer\free{i }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPagePatch4}
\begin{paste}{ugxFloatConvertPageFull4}{ugxFloatConvertPageEmpty4}
\pastebutton{ugxFloatConvertPageFull4}{\hidepaste}
\tab{5}\spadcommand{r := 3/7 :: Float\bound{r }}
\indentrel{3}\begin{verbatim}
   (4)  0.42857 14285 71428 57143
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPageEmpty4}
\begin{paste}{ugxFloatConvertPageEmpty4}{ugxFloatConvertPagePatch4}
\pastebutton{ugxFloatConvertPageEmpty4}{\showpaste}
\tab{5}\spadcommand{r := 3/7 :: Float\bound{r }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPagePatch5}
\begin{paste}{ugxFloatConvertPageFull5}{ugxFloatConvertPageEmpty5}
\pastebutton{ugxFloatConvertPageFull5}{\hidepaste}
\tab{5}\spadcommand{r :: Fraction Integer\free{r }}
\indentrel{3}\begin{verbatim}
        3
   (5)  Ä
        7
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPageEmpty5}
\begin{paste}{ugxFloatConvertPageEmpty5}{ugxFloatConvertPagePatch5}
\pastebutton{ugxFloatConvertPageEmpty5}{\showpaste}
\tab{5}\spadcommand{r :: Fraction Integer\free{r }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPagePatch6}
\begin{paste}{ugxFloatConvertPageFull6}{ugxFloatConvertPageEmpty6}
\pastebutton{ugxFloatConvertPageFull6}{\hidepaste}
\tab{5}\spadcommand{r :: Integer\free{r }}
\indentrel{3}\begin{verbatim}
   0.42857 14285 71428 57143
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPageEmpty6}
\begin{paste}{ugxFloatConvertPageEmpty6}{ugxFloatConvertPagePatch6}
\pastebutton{ugxFloatConvertPageEmpty6}{\showpaste}
\tab{5}\spadcommand{r :: Integer\free{r }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPagePatch7}
\begin{paste}{ugxFloatConvertPageFull7}{ugxFloatConvertPageEmpty7}
\pastebutton{ugxFloatConvertPageFull7}{\hidepaste}
\tab{5}\spadcommand{truncate 3.6}
\indentrel{3}\begin{verbatim}
   (6)  3.0
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPageEmpty7}
\begin{paste}{ugxFloatConvertPageEmpty7}{ugxFloatConvertPagePatch7}
\pastebutton{ugxFloatConvertPageEmpty7}{\showpaste}
\tab{5}\spadcommand{truncate 3.6}
\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPagePatch8}
\begin{paste}{ugxFloatConvertPageFull8}{ugxFloatConvertPageEmpty8}
\pastebutton{ugxFloatConvertPageFull8}{\hidepaste}
\tab{5}\spadcommand{round 3.6}
\indentrel{3}\begin{verbatim}
   (7)  4.0
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPageEmpty8}
\begin{paste}{ugxFloatConvertPageEmpty8}{ugxFloatConvertPagePatch8}
\pastebutton{ugxFloatConvertPageEmpty8}{\showpaste}
\tab{5}\spadcommand{round 3.6}
\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPagePatch9}
\begin{paste}{ugxFloatConvertPageFull9}{ugxFloatConvertPageEmpty9}
\pastebutton{ugxFloatConvertPageFull9}{\hidepaste}
\tab{5}\spadcommand{truncate(-3.6)}
\indentrel{3}\begin{verbatim}
   (8)  - 3.0
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPageEmpty9}
\begin{paste}{ugxFloatConvertPageEmpty9}{ugxFloatConvertPagePatch9}
\pastebutton{ugxFloatConvertPageEmpty9}{\showpaste}
\tab{5}\spadcommand{truncate(-3.6)}
\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPagePatch10}
\begin{paste}{ugxFloatConvertPageFull10}{ugxFloatConvertPageEmpty10}
\pastebutton{ugxFloatConvertPageFull10}{\hidepaste}
\tab{5}\spadcommand{round(-3.6)}
\indentrel{3}\begin{verbatim}
   (9)  - 4.0
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPageEmpty10}
\begin{paste}{ugxFloatConvertPageEmpty10}{ugxFloatConvertPagePatch10}
\pastebutton{ugxFloatConvertPageEmpty10}{\showpaste}
\tab{5}\spadcommand{round(-3.6)}
\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPagePatch11}
\begin{paste}{ugxFloatConvertPageFull11}{ugxFloatConvertPageEmpty11}
\pastebutton{ugxFloatConvertPageFull11}{\hidepaste}
\tab{5}\spadcommand{fractionPart 3.6}
\indentrel{3}\begin{verbatim}
   (10)  0.6
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPageEmpty11}
\begin{paste}{ugxFloatConvertPageEmpty11}{ugxFloatConvertPagePatch11}
\pastebutton{ugxFloatConvertPageEmpty11}{\showpaste}
\tab{5}\spadcommand{fractionPart 3.6}
\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPagePatch12}
\begin{paste}{ugxFloatConvertPageFull12}{ugxFloatConvertPageEmpty12}
\pastebutton{ugxFloatConvertPageFull12}{\hidepaste}
\tab{5}\spadcommand{digits 40\bound{d40 }}
\indentrel{3}\begin{verbatim}
   (11)  20
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPageEmpty12}
\begin{paste}{ugxFloatConvertPageEmpty12}{ugxFloatConvertPagePatch12}
\pastebutton{ugxFloatConvertPageEmpty12}{\showpaste}
\tab{5}\spadcommand{digits 40\bound{d40 }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPagePatch13}
\begin{paste}{ugxFloatConvertPageFull13}{ugxFloatConvertPageEmpty13}
\pastebutton{ugxFloatConvertPageFull13}{\hidepaste}
\tab{5}\spadcommand{sqrt 0.2}
\indentrel{3}\begin{verbatim}
   (12)
   0.44721 35954 99957 93928 18347 33746 25524 70881
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPageEmpty13}
\begin{paste}{ugxFloatConvertPageEmpty13}{ugxFloatConvertPagePatch13}
\pastebutton{ugxFloatConvertPageEmpty13}{\showpaste}
\tab{5}\spadcommand{sqrt 0.2}
\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPagePatch14}
\begin{paste}{ugxFloatConvertPageFull14}{ugxFloatConvertPageEmpty14}
\pastebutton{ugxFloatConvertPageFull14}{\hidepaste}
\tab{5}\spadcommand{pi()$Float\free{d40 }}
\indentrel{3}\begin{verbatim}
   (13)
   3.14159 26535 89793 23846 26433 83279 50288 4197
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPageEmpty14}
\begin{paste}{ugxFloatConvertPageEmpty14}{ugxFloatConvertPagePatch14}
\pastebutton{ugxFloatConvertPageEmpty14}{\showpaste}
\tab{5}\spadcommand{pi()$Float\free{d40 }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPagePatch15}
\begin{paste}{ugxFloatConvertPageFull15}{ugxFloatConvertPageEmpty15}
\pastebutton{ugxFloatConvertPageFull15}{\hidepaste}
\tab{5}\spadcommand{digits 500\bound{d1000 }}
\indentrel{3}\begin{verbatim}
   (14)  40
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPageEmpty15}
\begin{paste}{ugxFloatConvertPageEmpty15}{ugxFloatConvertPagePatch15}
\pastebutton{ugxFloatConvertPageEmpty15}{\showpaste}
\tab{5}\spadcommand{digits 500\bound{d1000 }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPagePatch16}
\begin{paste}{ugxFloatConvertPageFull16}{ugxFloatConvertPageEmpty16}
\pastebutton{ugxFloatConvertPageFull16}{\hidepaste}
\tab{5}\spadcommand{pi()$Float\free{d1000 }}
\indentrel{3}\begin{verbatim}
   (15)
  3.14159 26535 89793 23846 26433 83279 50288 41971 69399
   37510 58209 74944 59230 78164 06286 20899 86280 34825 
  34211 70679 82148 08651 32823 06647 09384 46095 50582 2
  3172 53594 08128 48111 74502 84102 70193 85211 05559 64
  462 29489 54930 38196 44288 10975 66593 34461 28475 648
  23 37867 83165 27120 19091 45648 56692 34603 48610 4543
  2 66482 13393 60726 02491 41273 72458 70066 06315 58817
   48815 20920 96282 92540 91715 36436 78925 90360 01133 
  05305 48820 46652 13841 46951 94151 16094 33057 27036 5
  7595 91953 09218 61173 81932 61179 31051 18548 07446 23
  799 62749 56735 18857 52724 89122 79381 83011 9491
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPageEmpty16}
\begin{paste}{ugxFloatConvertPageEmpty16}{ugxFloatConvertPagePatch16}
\pastebutton{ugxFloatConvertPageEmpty16}{\showpaste}
\tab{5}\spadcommand{pi()$Float\free{d1000 }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPagePatch17}
\begin{paste}{ugxFloatConvertPageFull17}{ugxFloatConvertPageEmpty17}
\pastebutton{ugxFloatConvertPageFull17}{\hidepaste}
\tab{5}\spadcommand{digits 20}
\indentrel{3}\begin{verbatim}
   (16)  500
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatConvertPageEmpty17}
\begin{paste}{ugxFloatConvertPageEmpty17}{ugxFloatConvertPagePatch17}
\pastebutton{ugxFloatConvertPageEmpty17}{\showpaste}
\tab{5}\spadcommand{digits 20}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxFloatOutputPage}{float.ht}{Output Functions}
\begin{chunk}{float.ht}
\begin{page}{ugxFloatOutputPage}{Output Functions}
\beginscroll

A number of operations exist for specifying how 
numbers of type \spadtype{Float} are to be
displayed.
By default, spaces are inserted every ten digits in the
output for readability.\footnote{Note that you cannot include spaces
in the input form of a floating point number, though you can use
underscores.}


\xtc{
Output spacing can be modified with the \spadfunFrom{outputSpacing}{Float}
operation.
This inserts no spaces and then displays the value of \spad{x}.
}{
\spadpaste{outputSpacing 0; x := sqrt 0.2 \bound{x}\bound{os0}}
}
\xtc{
Issue this to have the spaces inserted every \spad{5} digits.
}{
\spadpaste{outputSpacing 5; x \bound{os5}\free{x}}
}
\xtc{
By default, the system displays floats in either fixed format
or scientific format, depending on the magnitude of the number.
}{
\spadpaste{y := x/10**10 \bound{y}\free{x os5}}
}
\xtc{
A particular format may be requested with the operations
\spadfunFrom{outputFloating}{Float} and \spadfunFrom{outputFixed}{Float}.
}{
\spadpaste{outputFloating(); x \bound{of} \free{os5 x}}
}
\xtc{
}{
\spadpaste{outputFixed(); y \bound{ox} \free{os5 y}}
}
\xtc{
Additionally, you can ask for \spad{n} digits to be displayed after the
decimal point.
}{
\spadpaste{outputFloating 2; y \bound{of2} \free{os5 y}}
}
\xtc{
}{
\spadpaste{outputFixed 2; x \bound{ox2} \free{os5 x}}
}
\xtc{
This resets the output printing to the default behavior.
}{
\spadpaste{outputGeneral()}
}
%

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxFloatOutputPagePatch1}
\begin{paste}{ugxFloatOutputPageFull1}{ugxFloatOutputPageEmpty1}
\pastebutton{ugxFloatOutputPageFull1}{\hidepaste}
\tab{5}\spadcommand{outputSpacing 0; x := sqrt 0.2\bound{x }\bound{os0 }}
\indentrel{3}\begin{verbatim}
   (1)  0.44721359549995793928
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatOutputPageEmpty1}
\begin{paste}{ugxFloatOutputPageEmpty1}{ugxFloatOutputPagePatch1}
\pastebutton{ugxFloatOutputPageEmpty1}{\showpaste}
\tab{5}\spadcommand{outputSpacing 0; x := sqrt 0.2\bound{x }\bound{os0 }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatOutputPagePatch2}
\begin{paste}{ugxFloatOutputPageFull2}{ugxFloatOutputPageEmpty2}
\pastebutton{ugxFloatOutputPageFull2}{\hidepaste}
\tab{5}\spadcommand{outputSpacing 5; x\bound{os5 }\free{x }}
\indentrel{3}\begin{verbatim}
   (2)  0.44721 35954 99957 93928
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatOutputPageEmpty2}
\begin{paste}{ugxFloatOutputPageEmpty2}{ugxFloatOutputPagePatch2}
\pastebutton{ugxFloatOutputPageEmpty2}{\showpaste}
\tab{5}\spadcommand{outputSpacing 5; x\bound{os5 }\free{x }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatOutputPagePatch3}
\begin{paste}{ugxFloatOutputPageFull3}{ugxFloatOutputPageEmpty3}
\pastebutton{ugxFloatOutputPageFull3}{\hidepaste}
\tab{5}\spadcommand{y := x/10**10\bound{y }\free{x os5 }}
\indentrel{3}\begin{verbatim}
   (3)  0.44721 35954 99957 93928 E -10
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatOutputPageEmpty3}
\begin{paste}{ugxFloatOutputPageEmpty3}{ugxFloatOutputPagePatch3}
\pastebutton{ugxFloatOutputPageEmpty3}{\showpaste}
\tab{5}\spadcommand{y := x/10**10\bound{y }\free{x os5 }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatOutputPagePatch4}
\begin{paste}{ugxFloatOutputPageFull4}{ugxFloatOutputPageEmpty4}
\pastebutton{ugxFloatOutputPageFull4}{\hidepaste}
\tab{5}\spadcommand{outputFloating(); x\bound{of }\free{os5 x }}
\indentrel{3}\begin{verbatim}
   (4)  0.44721 35954 99957 93928 E 0
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatOutputPageEmpty4}
\begin{paste}{ugxFloatOutputPageEmpty4}{ugxFloatOutputPagePatch4}
\pastebutton{ugxFloatOutputPageEmpty4}{\showpaste}
\tab{5}\spadcommand{outputFloating(); x\bound{of }\free{os5 x }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatOutputPagePatch5}
\begin{paste}{ugxFloatOutputPageFull5}{ugxFloatOutputPageEmpty5}
\pastebutton{ugxFloatOutputPageFull5}{\hidepaste}
\tab{5}\spadcommand{outputFixed(); y\bound{ox }\free{os5 y }}
\indentrel{3}\begin{verbatim}
   (5)  0.00000 00000 44721 35954 99957 93928
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatOutputPageEmpty5}
\begin{paste}{ugxFloatOutputPageEmpty5}{ugxFloatOutputPagePatch5}
\pastebutton{ugxFloatOutputPageEmpty5}{\showpaste}
\tab{5}\spadcommand{outputFixed(); y\bound{ox }\free{os5 y }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatOutputPagePatch6}
\begin{paste}{ugxFloatOutputPageFull6}{ugxFloatOutputPageEmpty6}
\pastebutton{ugxFloatOutputPageFull6}{\hidepaste}
\tab{5}\spadcommand{outputFloating 2; y\bound{of2 }\free{os5 y }}
\indentrel{3}\begin{verbatim}
   (6)  0.45 E -10
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatOutputPageEmpty6}
\begin{paste}{ugxFloatOutputPageEmpty6}{ugxFloatOutputPagePatch6}
\pastebutton{ugxFloatOutputPageEmpty6}{\showpaste}
\tab{5}\spadcommand{outputFloating 2; y\bound{of2 }\free{os5 y }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatOutputPagePatch7}
\begin{paste}{ugxFloatOutputPageFull7}{ugxFloatOutputPageEmpty7}
\pastebutton{ugxFloatOutputPageFull7}{\hidepaste}
\tab{5}\spadcommand{outputFixed 2; x\bound{ox2 }\free{os5 x }}
\indentrel{3}\begin{verbatim}
   (7)  0.45
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatOutputPageEmpty7}
\begin{paste}{ugxFloatOutputPageEmpty7}{ugxFloatOutputPagePatch7}
\pastebutton{ugxFloatOutputPageEmpty7}{\showpaste}
\tab{5}\spadcommand{outputFixed 2; x\bound{ox2 }\free{os5 x }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatOutputPagePatch8}
\begin{paste}{ugxFloatOutputPageFull8}{ugxFloatOutputPageEmpty8}
\pastebutton{ugxFloatOutputPageFull8}{\hidepaste}
\tab{5}\spadcommand{outputGeneral()}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatOutputPageEmpty8}
\begin{paste}{ugxFloatOutputPageEmpty8}{ugxFloatOutputPagePatch8}
\pastebutton{ugxFloatOutputPageEmpty8}{\showpaste}
\tab{5}\spadcommand{outputGeneral()}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxFloatHilbertPage}{float.ht}
{An Example: Determinant of a Hilbert Matrix}
\begin{chunk}{float.ht}
\begin{page}{ugxFloatHilbertPage}
{An Example: Determinant of a Hilbert Matrix}
\beginscroll

Consider the problem of computing the determinant of a \spad{10} by \spad{10}
Hilbert matrix.
The \eth{\spad{(i,j)}} entry of a Hilbert matrix is given by
\spad{1/(i+j+1)}.

\labelSpace{2pc}
\xtc{
First do the computation using rational numbers to obtain the
exact result.
}{
\spadpaste{a: Matrix Fraction Integer := 
matrix [[1/(i+j+1) for j in 0..9] for i in 0..9] \bound{a}}
}
\xtc{
This version of \spadfunFrom{determinant}{Matrix} uses Gaussian
elimination.
}{
\spadpaste{d:= determinant a \free{a}\bound{d}}
}
\xtc{
}{
\spadpaste{d :: Float \free{d}}
}
\xtc{
Now use hardware floats. Note that a semicolon (;) is used
to prevent the display of the matrix.
}{
\spadpaste{b: Matrix DoubleFloat := 
matrix [[1/(i+j+1\$DoubleFloat) for j in 0..9] for i in 0..9]; \bound{b}}
}
\xtc{
The result given by hardware floats is correct only to four significant
digits of precision.
In the jargon of numerical analysis, the Hilbert matrix is said to be
``ill-conditioned.''
}{
\spadpaste{determinant b \free{b}}
}
\xtc{
Now repeat the computation at a higher precision using \spadtype{Float}.
}{
\spadpaste{digits 40 \bound{d40}}
}
\xtc{
}{
\spadpaste{c: Matrix Float := 
matrix [[1/(i+j+1\$Float) for j in 0..9] for i in 0..9]; 
\free{d40} \bound{c}}
}
\xtc{
}{
\spadpaste{determinant c \free{c}}
}
\xtc{
Reset \spadfunFrom{digits}{Float} to its default value.
}{
\spadpaste{digits 20}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxFloatHilbertPagePatch1}
\begin{paste}{ugxFloatHilbertPageFull1}{ugxFloatHilbertPageEmpty1}
\pastebutton{ugxFloatHilbertPageFull1}{\hidepaste}
\tab{5}\spadcommand{a: Matrix Fraction Integer := matrix [[1/(i+j+1) for j in 0..9] for i in 0..9]\bound{a }}
\indentrel{3}\begin{verbatim}
        Ú    1   1   1   1   1   1   1   1    1¿
        ³1   Ä   Ä   Ä   Ä   Ä   Ä   Ä   Ä   ÄÄ³
        ³    2   3   4   5   6   7   8   9   10³
        ³                                      ³
        ³1   1   1   1   1   1   1   1    1   1³
        ³Ä   Ä   Ä   Ä   Ä   Ä   Ä   Ä   ÄÄ  ÄÄ³
        ³2   3   4   5   6   7   8   9   10  11³
        ³                                      ³
        ³1   1   1   1   1   1   1    1   1   1³
        ³Ä   Ä   Ä   Ä   Ä   Ä   Ä   ÄÄ  ÄÄ  ÄÄ³
        ³3   4   5   6   7   8   9   10  11  12³
        ³                                      ³
        ³1   1   1   1   1   1    1   1   1   1³
        ³Ä   Ä   Ä   Ä   Ä   Ä   ÄÄ  ÄÄ  ÄÄ  ÄÄ³
        ³4   5   6   7   8   9   10  11  12  13³
        ³                                      ³
        ³1   1   1   1   1    1   1   1   1   1³
        ³Ä   Ä   Ä   Ä   Ä   ÄÄ  ÄÄ  ÄÄ  ÄÄ  ÄÄ³
        ³5   6   7   8   9   10  11  12  13  14³
   (1)  ³                                      ³
        ³1   1   1   1    1   1   1   1   1   1³
        ³Ä   Ä   Ä   Ä   ÄÄ  ÄÄ  ÄÄ  ÄÄ  ÄÄ  ÄÄ³
        ³6   7   8   9   10  11  12  13  14  15³
        ³                                      ³
        ³1   1   1    1   1   1   1   1   1   1³
        ³Ä   Ä   Ä   ÄÄ  ÄÄ  ÄÄ  ÄÄ  ÄÄ  ÄÄ  ÄÄ³
        ³7   8   9   10  11  12  13  14  15  16³
        ³                                      ³
        ³1   1    1   1   1   1   1   1   1   1³
        ³Ä   Ä   ÄÄ  ÄÄ  ÄÄ  ÄÄ  ÄÄ  ÄÄ  ÄÄ  ÄÄ³
        ³8   9   10  11  12  13  14  15  16  17³
        ³                                      ³
        ³1    1   1   1   1   1   1   1   1   1³
        ³Ä   ÄÄ  ÄÄ  ÄÄ  ÄÄ  ÄÄ  ÄÄ  ÄÄ  ÄÄ  ÄÄ³
        ³9   10  11  12  13  14  15  16  17  18³
        ³                                      ³
        ³ 1   1   1   1   1   1   1   1   1   1³
        ³ÄÄ  ÄÄ  ÄÄ  ÄÄ  ÄÄ  ÄÄ  ÄÄ  ÄÄ  ÄÄ  ÄÄ³
        À10  11  12  13  14  15  16  17  18  19Ù
                          Type: Matrix Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatHilbertPageEmpty1}
\begin{paste}{ugxFloatHilbertPageEmpty1}{ugxFloatHilbertPagePatch1}
\pastebutton{ugxFloatHilbertPageEmpty1}{\showpaste}
\tab{5}\spadcommand{a: Matrix Fraction Integer := matrix [[1/(i+j+1) for j in 0..9] for i in 0..9]\bound{a }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatHilbertPagePatch2}
\begin{paste}{ugxFloatHilbertPageFull2}{ugxFloatHilbertPageEmpty2}
\pastebutton{ugxFloatHilbertPageFull2}{\hidepaste}
\tab{5}\spadcommand{d:= determinant a\free{a }\bound{d }}
\indentrel{3}\begin{verbatim}
   (2)
                             1
   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
   46206893947914691316295628839036278726983680000000000
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatHilbertPageEmpty2}
\begin{paste}{ugxFloatHilbertPageEmpty2}{ugxFloatHilbertPagePatch2}
\pastebutton{ugxFloatHilbertPageEmpty2}{\showpaste}
\tab{5}\spadcommand{d:= determinant a\free{a }\bound{d }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatHilbertPagePatch3}
\begin{paste}{ugxFloatHilbertPageFull3}{ugxFloatHilbertPageEmpty3}
\pastebutton{ugxFloatHilbertPageFull3}{\hidepaste}
\tab{5}\spadcommand{d :: Float\free{d }}
\indentrel{3}\begin{verbatim}
   (3)  0.21641 79226 43149 18691 E -52
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatHilbertPageEmpty3}
\begin{paste}{ugxFloatHilbertPageEmpty3}{ugxFloatHilbertPagePatch3}
\pastebutton{ugxFloatHilbertPageEmpty3}{\showpaste}
\tab{5}\spadcommand{d :: Float\free{d }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatHilbertPagePatch4}
\begin{paste}{ugxFloatHilbertPageFull4}{ugxFloatHilbertPageEmpty4}
\pastebutton{ugxFloatHilbertPageFull4}{\hidepaste}
\tab{5}\spadcommand{b: Matrix DoubleFloat := matrix [[1/(i+j+1$DoubleFloat) for j in 0..9] for i in 0..9];\bound{b }}
\indentrel{3}\begin{verbatim}
                               Type: Matrix DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatHilbertPageEmpty4}
\begin{paste}{ugxFloatHilbertPageEmpty4}{ugxFloatHilbertPagePatch4}
\pastebutton{ugxFloatHilbertPageEmpty4}{\showpaste}
\tab{5}\spadcommand{b: Matrix DoubleFloat := matrix [[1/(i+j+1$DoubleFloat) for j in 0..9] for i in 0..9];\bound{b }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatHilbertPagePatch5}
\begin{paste}{ugxFloatHilbertPageFull5}{ugxFloatHilbertPageEmpty5}
\pastebutton{ugxFloatHilbertPageFull5}{\hidepaste}
\tab{5}\spadcommand{determinant b\free{b }}
\indentrel{3}\begin{verbatim}
   (5)  2.1643677945721411e-53
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatHilbertPageEmpty5}
\begin{paste}{ugxFloatHilbertPageEmpty5}{ugxFloatHilbertPagePatch5}
\pastebutton{ugxFloatHilbertPageEmpty5}{\showpaste}
\tab{5}\spadcommand{determinant b\free{b }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatHilbertPagePatch6}
\begin{paste}{ugxFloatHilbertPageFull6}{ugxFloatHilbertPageEmpty6}
\pastebutton{ugxFloatHilbertPageFull6}{\hidepaste}
\tab{5}\spadcommand{digits 40\bound{d40 }}
\indentrel{3}\begin{verbatim}
   (6)  20
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatHilbertPageEmpty6}
\begin{paste}{ugxFloatHilbertPageEmpty6}{ugxFloatHilbertPagePatch6}
\pastebutton{ugxFloatHilbertPageEmpty6}{\showpaste}
\tab{5}\spadcommand{digits 40\bound{d40 }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatHilbertPagePatch7}
\begin{paste}{ugxFloatHilbertPageFull7}{ugxFloatHilbertPageEmpty7}
\pastebutton{ugxFloatHilbertPageFull7}{\hidepaste}
\tab{5}\spadcommand{c: Matrix Float := matrix [[1/(i+j+1$Float) for j in 0..9] for i in 0..9];\free{d40 }\bound{c }}
\indentrel{3}\begin{verbatim}
                                     Type: Matrix Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatHilbertPageEmpty7}
\begin{paste}{ugxFloatHilbertPageEmpty7}{ugxFloatHilbertPagePatch7}
\pastebutton{ugxFloatHilbertPageEmpty7}{\showpaste}
\tab{5}\spadcommand{c: Matrix Float := matrix [[1/(i+j+1$Float) for j in 0..9] for i in 0..9];\free{d40 }\bound{c }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatHilbertPagePatch8}
\begin{paste}{ugxFloatHilbertPageFull8}{ugxFloatHilbertPageEmpty8}
\pastebutton{ugxFloatHilbertPageFull8}{\hidepaste}
\tab{5}\spadcommand{determinant c\free{c }}
\indentrel{3}\begin{verbatim}
   (8)
   0.21641 79226 43149 18690 60594 98362 26174 36159 E -52
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatHilbertPageEmpty8}
\begin{paste}{ugxFloatHilbertPageEmpty8}{ugxFloatHilbertPagePatch8}
\pastebutton{ugxFloatHilbertPageEmpty8}{\showpaste}
\tab{5}\spadcommand{determinant c\free{c }}
\end{paste}\end{patch}

\begin{patch}{ugxFloatHilbertPagePatch9}
\begin{paste}{ugxFloatHilbertPageFull9}{ugxFloatHilbertPageEmpty9}
\pastebutton{ugxFloatHilbertPageFull9}{\hidepaste}
\tab{5}\spadcommand{digits 20}
\indentrel{3}\begin{verbatim}
   (9)  40
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFloatHilbertPageEmpty9}
\begin{paste}{ugxFloatHilbertPageEmpty9}{ugxFloatHilbertPagePatch9}
\pastebutton{ugxFloatHilbertPageEmpty9}{\showpaste}
\tab{5}\spadcommand{digits 20}
\end{paste}\end{patch}

\end{chunk}
\section{fname.ht}
\pagetitle{FileNameXmpPage}{fname.ht}{FileName}
\begin{chunk}{fname.ht}
\begin{page}{FileNameXmpPage}{FileName}
\beginscroll
 
The \spadtype{FileName} domain provides an interface to the computer's
file system.
Functions are provided to manipulate file names and to test properties of
files.
 
The simplest way to use file names in the Axiom interpreter is to
rely on conversion to and from strings.
The syntax of these strings depends on the operating system.
\xtc{
}{
\spadpaste{fn: FileName \bound{fndecl}}
}
\xtc{
On AIX, this is a proper file syntax:
}{
\spadpaste{fn := "/spad/src/input/fname.input" \free{fndecl}\bound{fn}}
}
 
Although it is very convenient to be able to use string notation
for file names in the interpreter, it is desirable to have a portable
way of creating and manipulating file names from within programs.
\xtc{
A measure of portability is obtained by considering a file name
to consist of three parts: the {\it directory}, the {\it name},
and the {\it extension}.
}{
\spadpaste{directory fn \free{fn}}
}
\xtc{
}{
\spadpaste{name fn \free{fn}}
}
\xtc{
}{
\spadpaste{extension fn \free{fn}}
}
The meaning of these three parts depends on the operating system.
For example, on CMS the file \spad{"SPADPROF INPUT M"}
would have directory \spad{"M"}, name \spad{"SPADPROF"} and
extension \spad{"INPUT"}.
 
\xtc{
It is possible to create a filename from its parts.
}{
\spadpaste{fn := filename("/u/smwatt/work", "fname", "input") 
\free{fndecl}\bound{fn1}}
}
\xtc{
When writing programs, it is helpful to refer to directories via
variables.
}{
\spadpaste{objdir := "/tmp" \bound{objdir}}
}
\xtc{
}{
\spadpaste{fn := filename(objdir, "table", "spad") 
\free{fndecl,objdir}\bound{fn2}}
}
\xtc{
If the directory or the extension is given as an empty string, then
a default is used.  On AIX, the defaults are the current directory
and no extension.
}{
\spadpaste{fn := filename("", "letter", "") \free{fndecl}\bound{fn3}}
}
 
Three tests provide information about names in the file system.
\xtc{
The \spadfunFrom{exists?}{FileName} operation tests whether 
the named file exists.
}{
\spadpaste{exists? "/etc/passwd"}
}
\xtc{
The operation \spadfunFrom{readable?}{FileName} tells whether the named 
file can be read.  If the file does not exist, then it cannot be read.
}{
\spadpaste{readable? "/etc/passwd"}
}
\xtc{
}{
\spadpaste{readable? "/etc/security/passwd"}
}
\xtc{
}{
\spadpaste{readable? "/ect/passwd"}
}
\xtc{
Likewise, the operation \spadfunFrom{writable?}{FileName} 
tells whether the named file
can be written.
If the file does not exist, the test is determined
by the properties of the directory.
}{
\spadpaste{writable? "/etc/passwd"}
}
\xtc{
}{
\spadpaste{writable? "/dev/null"}
}
\xtc{
}{
\spadpaste{writable? "/etc/DoesNotExist"}
}
\xtc{
}{
\spadpaste{writable? "/tmp/DoesNotExist"}
}
 
The \spadfunFrom{new}{FileName} operation constructs the name of a new
writable file.
The argument sequence is the same as for \spadfunFrom{filename}{FileName},
except that the name part is actually a prefix for a constructed
unique name.
\xtc{
The resulting file is in the specified directory
with the given extension, and the same defaults are used.
}{
\spadpaste{fn := new(objdir, "xxx", "yy") \free{objdir,fndecl}\bound{fn4}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{FileNameXmpPagePatch1}
\begin{paste}{FileNameXmpPageFull1}{FileNameXmpPageEmpty1}
\pastebutton{FileNameXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{fn: FileName\bound{fndecl }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileNameXmpPageEmpty1}
\begin{paste}{FileNameXmpPageEmpty1}{FileNameXmpPagePatch1}
\pastebutton{FileNameXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{fn: FileName\bound{fndecl }}
\end{paste}\end{patch}

\begin{patch}{FileNameXmpPagePatch2}
\begin{paste}{FileNameXmpPageFull2}{FileNameXmpPageEmpty2}
\pastebutton{FileNameXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{fn := "/spad/src/input/fname.input"\free{fndecl }\bound{fn }}
\indentrel{3}\begin{verbatim}
   (2)  "/spad/src/input/fname.input"
                                         Type: FileName
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileNameXmpPageEmpty2}
\begin{paste}{FileNameXmpPageEmpty2}{FileNameXmpPagePatch2}
\pastebutton{FileNameXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{fn := "/spad/src/input/fname.input"\free{fndecl }\bound{fn }}
\end{paste}\end{patch}

\begin{patch}{FileNameXmpPagePatch3}
\begin{paste}{FileNameXmpPageFull3}{FileNameXmpPageEmpty3}
\pastebutton{FileNameXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{directory fn\free{fn }}
\indentrel{3}\begin{verbatim}
   (3)  "/spad/src/input"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileNameXmpPageEmpty3}
\begin{paste}{FileNameXmpPageEmpty3}{FileNameXmpPagePatch3}
\pastebutton{FileNameXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{directory fn\free{fn }}
\end{paste}\end{patch}

\begin{patch}{FileNameXmpPagePatch4}
\begin{paste}{FileNameXmpPageFull4}{FileNameXmpPageEmpty4}
\pastebutton{FileNameXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{name fn\free{fn }}
\indentrel{3}\begin{verbatim}
   (4)  "fname"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileNameXmpPageEmpty4}
\begin{paste}{FileNameXmpPageEmpty4}{FileNameXmpPagePatch4}
\pastebutton{FileNameXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{name fn\free{fn }}
\end{paste}\end{patch}

\begin{patch}{FileNameXmpPagePatch5}
\begin{paste}{FileNameXmpPageFull5}{FileNameXmpPageEmpty5}
\pastebutton{FileNameXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{extension fn\free{fn }}
\indentrel{3}\begin{verbatim}
   (5)  "input"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileNameXmpPageEmpty5}
\begin{paste}{FileNameXmpPageEmpty5}{FileNameXmpPagePatch5}
\pastebutton{FileNameXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{extension fn\free{fn }}
\end{paste}\end{patch}

\begin{patch}{FileNameXmpPagePatch6}
\begin{paste}{FileNameXmpPageFull6}{FileNameXmpPageEmpty6}
\pastebutton{FileNameXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{fn := filename("/u/smwatt/work", "fname", "input")\free{fndecl }\bound{fn1 }}
\indentrel{3}\begin{verbatim}
   (6)  "/u/smwatt/work/fname.input"
                                         Type: FileName
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileNameXmpPageEmpty6}
\begin{paste}{FileNameXmpPageEmpty6}{FileNameXmpPagePatch6}
\pastebutton{FileNameXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{fn := filename("/u/smwatt/work", "fname", "input")\free{fndecl }\bound{fn1 }}
\end{paste}\end{patch}

\begin{patch}{FileNameXmpPagePatch7}
\begin{paste}{FileNameXmpPageFull7}{FileNameXmpPageEmpty7}
\pastebutton{FileNameXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{objdir := "/tmp"\bound{objdir }}
\indentrel{3}\begin{verbatim}
   (7)  "/tmp"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileNameXmpPageEmpty7}
\begin{paste}{FileNameXmpPageEmpty7}{FileNameXmpPagePatch7}
\pastebutton{FileNameXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{objdir := "/tmp"\bound{objdir }}
\end{paste}\end{patch}

\begin{patch}{FileNameXmpPagePatch8}
\begin{paste}{FileNameXmpPageFull8}{FileNameXmpPageEmpty8}
\pastebutton{FileNameXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{fn := filename(objdir, "table", "spad")\free{fndecl objdir }\bound{fn2 }}
\indentrel{3}\begin{verbatim}
   (8)  "/tmp/table.spad"
                                         Type: FileName
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileNameXmpPageEmpty8}
\begin{paste}{FileNameXmpPageEmpty8}{FileNameXmpPagePatch8}
\pastebutton{FileNameXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{fn := filename(objdir, "table", "spad")\free{fndecl objdir }\bound{fn2 }}
\end{paste}\end{patch}

\begin{patch}{FileNameXmpPagePatch9}
\begin{paste}{FileNameXmpPageFull9}{FileNameXmpPageEmpty9}
\pastebutton{FileNameXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{fn := filename("", "letter", "")\free{fndecl }\bound{fn3 }}
\indentrel{3}\begin{verbatim}
   (9)  "letter"
                                         Type: FileName
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileNameXmpPageEmpty9}
\begin{paste}{FileNameXmpPageEmpty9}{FileNameXmpPagePatch9}
\pastebutton{FileNameXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{fn := filename("", "letter", "")\free{fndecl }\bound{fn3 }}
\end{paste}\end{patch}

\begin{patch}{FileNameXmpPagePatch10}
\begin{paste}{FileNameXmpPageFull10}{FileNameXmpPageEmpty10}
\pastebutton{FileNameXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{exists? "/etc/passwd"}
\indentrel{3}\begin{verbatim}
   (10)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileNameXmpPageEmpty10}
\begin{paste}{FileNameXmpPageEmpty10}{FileNameXmpPagePatch10}
\pastebutton{FileNameXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{exists? "/etc/passwd"}
\end{paste}\end{patch}

\begin{patch}{FileNameXmpPagePatch11}
\begin{paste}{FileNameXmpPageFull11}{FileNameXmpPageEmpty11}
\pastebutton{FileNameXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{readable? "/etc/passwd"}
\indentrel{3}\begin{verbatim}
   (11)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileNameXmpPageEmpty11}
\begin{paste}{FileNameXmpPageEmpty11}{FileNameXmpPagePatch11}
\pastebutton{FileNameXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{readable? "/etc/passwd"}
\end{paste}\end{patch}

\begin{patch}{FileNameXmpPagePatch12}
\begin{paste}{FileNameXmpPageFull12}{FileNameXmpPageEmpty12}
\pastebutton{FileNameXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{readable? "/etc/security/passwd"}
\indentrel{3}\begin{verbatim}
   (12)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileNameXmpPageEmpty12}
\begin{paste}{FileNameXmpPageEmpty12}{FileNameXmpPagePatch12}
\pastebutton{FileNameXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{readable? "/etc/security/passwd"}
\end{paste}\end{patch}

\begin{patch}{FileNameXmpPagePatch13}
\begin{paste}{FileNameXmpPageFull13}{FileNameXmpPageEmpty13}
\pastebutton{FileNameXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{readable? "/ect/passwd"}
\indentrel{3}\begin{verbatim}
   (13)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileNameXmpPageEmpty13}
\begin{paste}{FileNameXmpPageEmpty13}{FileNameXmpPagePatch13}
\pastebutton{FileNameXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{readable? "/ect/passwd"}
\end{paste}\end{patch}

\begin{patch}{FileNameXmpPagePatch14}
\begin{paste}{FileNameXmpPageFull14}{FileNameXmpPageEmpty14}
\pastebutton{FileNameXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{writable? "/etc/passwd"}
\indentrel{3}\begin{verbatim}
   (14)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileNameXmpPageEmpty14}
\begin{paste}{FileNameXmpPageEmpty14}{FileNameXmpPagePatch14}
\pastebutton{FileNameXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{writable? "/etc/passwd"}
\end{paste}\end{patch}

\begin{patch}{FileNameXmpPagePatch15}
\begin{paste}{FileNameXmpPageFull15}{FileNameXmpPageEmpty15}
\pastebutton{FileNameXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{writable? "/dev/null"}
\indentrel{3}\begin{verbatim}
   (15)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileNameXmpPageEmpty15}
\begin{paste}{FileNameXmpPageEmpty15}{FileNameXmpPagePatch15}
\pastebutton{FileNameXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{writable? "/dev/null"}
\end{paste}\end{patch}

\begin{patch}{FileNameXmpPagePatch16}
\begin{paste}{FileNameXmpPageFull16}{FileNameXmpPageEmpty16}
\pastebutton{FileNameXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{writable? "/etc/DoesNotExist"}
\indentrel{3}\begin{verbatim}
   (16)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileNameXmpPageEmpty16}
\begin{paste}{FileNameXmpPageEmpty16}{FileNameXmpPagePatch16}
\pastebutton{FileNameXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{writable? "/etc/DoesNotExist"}
\end{paste}\end{patch}

\begin{patch}{FileNameXmpPagePatch17}
\begin{paste}{FileNameXmpPageFull17}{FileNameXmpPageEmpty17}
\pastebutton{FileNameXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{writable? "/tmp/DoesNotExist"}
\indentrel{3}\begin{verbatim}
   (17)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileNameXmpPageEmpty17}
\begin{paste}{FileNameXmpPageEmpty17}{FileNameXmpPagePatch17}
\pastebutton{FileNameXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{writable? "/tmp/DoesNotExist"}
\end{paste}\end{patch}

\begin{patch}{FileNameXmpPagePatch18}
\begin{paste}{FileNameXmpPageFull18}{FileNameXmpPageEmpty18}
\pastebutton{FileNameXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{fn := new(objdir, "xxx", "yy")\free{objdir fndecl }\bound{fn4 }}
\indentrel{3}\begin{verbatim}
   (18)  "/tmp/xxx82222.yy"
                                         Type: FileName
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FileNameXmpPageEmpty18}
\begin{paste}{FileNameXmpPageEmpty18}{FileNameXmpPagePatch18}
\pastebutton{FileNameXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{fn := new(objdir, "xxx", "yy")\free{objdir fndecl }\bound{fn4 }}
\end{paste}\end{patch}

\end{chunk}
\section{fr.ht}
\pagetitle{FactoredXmpPage}{fr.ht}{Factored}
\pagepic{ps/v71factoredxmppage.eps}{FactoredXmpPage}{0.50}
\pagefrom{Primes and Factorization}{ugxIntegerPrimesPage}
\pagefrom{Computation of Galois Groups}{ugProblemGaloisPage}
\pagefrom{FactoredFunctions2}{FactoredFnsTwoXmpPage}
\pagefrom{Some Examples of Domains and Packages}{ExamplesExposedPage}
\pageto{Decomposing Factored Objects}{ugxFactoredDecompPage}
\pageto{Expanding Factored Objects}{ugxFactoredExpandPage}
\pageto{Arithmetic with Factored Objects}{ugxFactoredArithPage}
\pageto{Creating New Factored Objects}{ugxFactoredNewPage}
\pageto{Factored Objects with Variables}{ugxFactoredVarPage}
\begin{chunk}{fr.ht}
\begin{page}{FactoredXmpPage}{Factored}
\beginscroll

\spadtype{Factored} creates a domain whose objects are kept in factored
form as long as possible.
Thus certain operations like \spadopFrom{*}{Factored}
(multiplication) and \spadfunFrom{gcd}{Factored} are relatively
easy to do.
Others, such as addition, require somewhat more work, and
the result may not be completely factored
unless the argument domain \spad{R} provides a
\spadfunFrom{factor}{Factored} operation.
Each object consists of a unit and a list of factors, where each
factor consists of a member of \spad{R} (the {\em base}), an
exponent, and a flag indicating what is known about the base.
A flag may be one of \spad{"nil"}, \spad{"sqfr"}, \spad{"irred"}
or \spad{"prime"}, which mean that nothing is known about the
base, it is square-free, it is irreducible, or it is prime,
respectively.
The current restriction to factored objects of integral domains
allows simplification to be performed without worrying about
multiplication order.

\beginmenu
    \menudownlink{{9.22.1. Decomposing Factored Objects}}
{ugxFactoredDecompPage}
    \menudownlink{{9.22.2. Expanding Factored Objects}}
{ugxFactoredExpandPage}
    \menudownlink{{9.22.3. Arithmetic with Factored Objects}}
{ugxFactoredArithPage}
    \menudownlink{{9.22.4. Creating New Factored Objects}}
{ugxFactoredNewPage}
    \menudownlink{{9.22.5. Factored Objects with Variables}}
{ugxFactoredVarPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugxFactoredDecompPage}{fr.ht}{Decomposing Factored Objects}
\pagepic{ps/v71ugxfactoreddecomppage.eps}{ugxFactoredDecompPage}{0.50}
\pagefrom{Factored}{FactoredXmpPage}
\begin{chunk}{fr.ht}
\begin{page}{ugxFactoredDecompPage}{Decomposing Factored Objects}
\beginscroll

\labelSpace{4pc}
\xtc{
In this section we will work with a factored integer.
}{
\spadpaste{g := factor(4312) \bound{g}}
}
\xtc{
Let's begin by decomposing \spad{g} into pieces.
The only possible units for integers are \spad{1} and \spad{-1}.
}{
\spadpaste{unit(g) \free{g}}
}
\xtc{
There are three factors.
}{
\spadpaste{numberOfFactors(g) \free{g}}
}
\xtc{
We can make a list of the bases, \ldots
}{
\spadpaste{[nthFactor(g,i) for i in 1..numberOfFactors(g)] \free{g}}
}
\xtc{
and the exponents, \ldots
}{
\spadpaste{[nthExponent(g,i) for i in 1..numberOfFactors(g)] \free{g}}
}
\xtc{
and the flags.
You can see that all the bases (factors) are prime.
}{
\spadpaste{[nthFlag(g,i) for i in 1..numberOfFactors(g)] \free{g}}
}
\xtc{
A useful operation for pulling apart a factored object into a list
of records of the components is \spadfunFrom{factorList}{Factored}.
}{
\spadpaste{factorList(g) \free{g}}
}
\xtc{
If you don't care about the flags, use \spadfunFrom{factors}{Factored}.
}{
\spadpaste{factors(g) \free{g}\bound{prev1}}
}
\xtc{
Neither of these operations returns the unit.
}{
\spadpaste{first(\%).factor \free{prev1}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxFactoredDecompPagePatch1}
\begin{paste}{ugxFactoredDecompPageFull1}{ugxFactoredDecompPageEmpty1}
\pastebutton{ugxFactoredDecompPageFull1}{\hidepaste}
\tab{5}\spadcommand{g := factor(4312)\bound{g }}
\indentrel{3}\begin{verbatim}
         3 2
   (1)  2 7 11
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredDecompPageEmpty1}
\begin{paste}{ugxFactoredDecompPageEmpty1}{ugxFactoredDecompPagePatch1}
\pastebutton{ugxFactoredDecompPageEmpty1}{\showpaste}
\tab{5}\spadcommand{g := factor(4312)\bound{g }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredDecompPagePatch2}
\begin{paste}{ugxFactoredDecompPageFull2}{ugxFactoredDecompPageEmpty2}
\pastebutton{ugxFactoredDecompPageFull2}{\hidepaste}
\tab{5}\spadcommand{unit(g)\free{g }}
\indentrel{3}\begin{verbatim}
   (2)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredDecompPageEmpty2}
\begin{paste}{ugxFactoredDecompPageEmpty2}{ugxFactoredDecompPagePatch2}
\pastebutton{ugxFactoredDecompPageEmpty2}{\showpaste}
\tab{5}\spadcommand{unit(g)\free{g }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredDecompPagePatch3}
\begin{paste}{ugxFactoredDecompPageFull3}{ugxFactoredDecompPageEmpty3}
\pastebutton{ugxFactoredDecompPageFull3}{\hidepaste}
\tab{5}\spadcommand{numberOfFactors(g)\free{g }}
\indentrel{3}\begin{verbatim}
   (3)  3
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredDecompPageEmpty3}
\begin{paste}{ugxFactoredDecompPageEmpty3}{ugxFactoredDecompPagePatch3}
\pastebutton{ugxFactoredDecompPageEmpty3}{\showpaste}
\tab{5}\spadcommand{numberOfFactors(g)\free{g }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredDecompPagePatch4}
\begin{paste}{ugxFactoredDecompPageFull4}{ugxFactoredDecompPageEmpty4}
\pastebutton{ugxFactoredDecompPageFull4}{\hidepaste}
\tab{5}\spadcommand{[nthFactor(g,i) for i in 1..numberOfFactors(g)]\free{g }}
\indentrel{3}\begin{verbatim}
   (4)  [2,7,11]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredDecompPageEmpty4}
\begin{paste}{ugxFactoredDecompPageEmpty4}{ugxFactoredDecompPagePatch4}
\pastebutton{ugxFactoredDecompPageEmpty4}{\showpaste}
\tab{5}\spadcommand{[nthFactor(g,i) for i in 1..numberOfFactors(g)]\free{g }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredDecompPagePatch5}
\begin{paste}{ugxFactoredDecompPageFull5}{ugxFactoredDecompPageEmpty5}
\pastebutton{ugxFactoredDecompPageFull5}{\hidepaste}
\tab{5}\spadcommand{[nthExponent(g,i) for i in 1..numberOfFactors(g)]\free{g }}
\indentrel{3}\begin{verbatim}
   (5)  [3,2,1]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredDecompPageEmpty5}
\begin{paste}{ugxFactoredDecompPageEmpty5}{ugxFactoredDecompPagePatch5}
\pastebutton{ugxFactoredDecompPageEmpty5}{\showpaste}
\tab{5}\spadcommand{[nthExponent(g,i) for i in 1..numberOfFactors(g)]\free{g }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredDecompPagePatch6}
\begin{paste}{ugxFactoredDecompPageFull6}{ugxFactoredDecompPageEmpty6}
\pastebutton{ugxFactoredDecompPageFull6}{\hidepaste}
\tab{5}\spadcommand{[nthFlag(g,i) for i in 1..numberOfFactors(g)]\free{g }}
\indentrel{3}\begin{verbatim}
   (6)  ["prime","prime","prime"]
         Type: List Union("nil","sqfr","irred","prime")
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredDecompPageEmpty6}
\begin{paste}{ugxFactoredDecompPageEmpty6}{ugxFactoredDecompPagePatch6}
\pastebutton{ugxFactoredDecompPageEmpty6}{\showpaste}
\tab{5}\spadcommand{[nthFlag(g,i) for i in 1..numberOfFactors(g)]\free{g }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredDecompPagePatch7}
\begin{paste}{ugxFactoredDecompPageFull7}{ugxFactoredDecompPageEmpty7}
\pastebutton{ugxFactoredDecompPageFull7}{\hidepaste}
\tab{5}\spadcommand{factorList(g)\free{g }}
\indentrel{3}\begin{verbatim}
   (7)
   [[flg= "prime",fctr= 2,xpnt= 3],
    [flg= "prime",fctr= 7,xpnt= 2],
    [flg= "prime",fctr= 11,xpnt= 1]]
Type: List Record(flg: Union("nil","sqfr","irred","prime"),fctr: Integer,xpnt: Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredDecompPageEmpty7}
\begin{paste}{ugxFactoredDecompPageEmpty7}{ugxFactoredDecompPagePatch7}
\pastebutton{ugxFactoredDecompPageEmpty7}{\showpaste}
\tab{5}\spadcommand{factorList(g)\free{g }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredDecompPagePatch8}
\begin{paste}{ugxFactoredDecompPageFull8}{ugxFactoredDecompPageEmpty8}
\pastebutton{ugxFactoredDecompPageFull8}{\hidepaste}
\tab{5}\spadcommand{factors(g)\free{g }\bound{prev1 }}
\indentrel{3}\begin{verbatim}
   (8)
   [[factor= 2,exponent= 3], [factor= 7,exponent= 2],
    [factor= 11,exponent= 1]]
   Type: List Record(factor: Integer,exponent: Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredDecompPageEmpty8}
\begin{paste}{ugxFactoredDecompPageEmpty8}{ugxFactoredDecompPagePatch8}
\pastebutton{ugxFactoredDecompPageEmpty8}{\showpaste}
\tab{5}\spadcommand{factors(g)\free{g }\bound{prev1 }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredDecompPagePatch9}
\begin{paste}{ugxFactoredDecompPageFull9}{ugxFactoredDecompPageEmpty9}
\pastebutton{ugxFactoredDecompPageFull9}{\hidepaste}
\tab{5}\spadcommand{first(\%).factor\free{prev1 }}
\indentrel{3}\begin{verbatim}
   (9)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredDecompPageEmpty9}
\begin{paste}{ugxFactoredDecompPageEmpty9}{ugxFactoredDecompPagePatch9}
\pastebutton{ugxFactoredDecompPageEmpty9}{\showpaste}
\tab{5}\spadcommand{first(\%).factor\free{prev1 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxFactoredExpandPage}{fr.ht}{Expanding Factored Objects}
\pagepic{ps/v71ugxfactoredexpandpage.eps}{ugxFactoredExpandPage}{0.50}
\pagefrom{Factored}{FactoredXmpPage}
\begin{chunk}{fr.ht}
\begin{page}{ugxFactoredExpandPage}{Expanding Factored Objects}
\beginscroll

\labelSpace{4pc}
\xtc{
Recall that we are working with this factored integer.
}{
\spadpaste{g := factor(4312) \bound{g}}
}
\xtc{
To multiply out the factors with their multiplicities, use
\spadfunFrom{expand}{Factored}.
}{
\spadpaste{expand(g) \free{g}}
}
\xtc{
If you would like, say, the distinct factors multiplied together
but with multiplicity one, you could do it this way.
}{
\spadpaste{reduce(*,[t.factor for t in factors(g)]) \free{g}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxFactoredExpandPagePatch1}
\begin{paste}{ugxFactoredExpandPageFull1}{ugxFactoredExpandPageEmpty1}
\pastebutton{ugxFactoredExpandPageFull1}{\hidepaste}
\tab{5}\spadcommand{g := factor(4312)\bound{g }}
\indentrel{3}\begin{verbatim}
         3 2
   (1)  2 7 11
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredExpandPageEmpty1}
\begin{paste}{ugxFactoredExpandPageEmpty1}{ugxFactoredExpandPagePatch1}
\pastebutton{ugxFactoredExpandPageEmpty1}{\showpaste}
\tab{5}\spadcommand{g := factor(4312)\bound{g }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredExpandPagePatch2}
\begin{paste}{ugxFactoredExpandPageFull2}{ugxFactoredExpandPageEmpty2}
\pastebutton{ugxFactoredExpandPageFull2}{\hidepaste}
\tab{5}\spadcommand{expand(g)\free{g }}
\indentrel{3}\begin{verbatim}
   (2)  4312
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredExpandPageEmpty2}
\begin{paste}{ugxFactoredExpandPageEmpty2}{ugxFactoredExpandPagePatch2}
\pastebutton{ugxFactoredExpandPageEmpty2}{\showpaste}
\tab{5}\spadcommand{expand(g)\free{g }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredExpandPagePatch3}
\begin{paste}{ugxFactoredExpandPageFull3}{ugxFactoredExpandPageEmpty3}
\pastebutton{ugxFactoredExpandPageFull3}{\hidepaste}
\tab{5}\spadcommand{reduce(*,[t.factor for t in factors(g)])\free{g }}
\indentrel{3}\begin{verbatim}
   (3)  154
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredExpandPageEmpty3}
\begin{paste}{ugxFactoredExpandPageEmpty3}{ugxFactoredExpandPagePatch3}
\pastebutton{ugxFactoredExpandPageEmpty3}{\showpaste}
\tab{5}\spadcommand{reduce(*,[t.factor for t in factors(g)])\free{g }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxFactoredArithPage}{fr.ht}{Arithmetic with Factored Objects}
\pagepic{ps/v71ugxfactoredarithpage.eps}{ugxFactoredArithPage}{0.50}
\pagefrom{Factored}{FactoredXmpPage}
\begin{chunk}{fr.ht}
\begin{page}{ugxFactoredArithPage}{Arithmetic with Factored Objects}
\beginscroll

\labelSpace{4pc}
\xtc{
We're still working with this factored integer.
}{
\spadpaste{g := factor(4312) \bound{g}}
}
\xtc{
We'll also define this factored integer.
}{
\spadpaste{f := factor(246960) \bound{f}}
}
\xtc{
Operations involving multiplication and division are particularly
easy with factored objects.
}{
\spadpaste{f * g \free{f g}}
}
\xtc{
}{
\spadpaste{f**500 \free{f}}
}
\xtc{
}{
\spadpaste{gcd(f,g) \free{f g}}
}
\xtc{
}{
\spadpaste{lcm(f,g) \free{f g}}
}
\xtc{
If we use addition and subtraction things can slow down because
we may need to compute greatest common divisors.
}{
\spadpaste{f + g \free{f g}}
}
\xtc{
}{
\spadpaste{f - g \free{f g}}
}
\xtc{
Test for equality with \spad{0} and \spad{1} by using
\spadfunFrom{zero?}{Factored} and \spadfunFrom{one?}{Factored},
respectively.
}{
\spadpaste{zero?(factor(0))}
}
\xtc{
}{
\spadpaste{zero?(g) \free{g}}
}
\xtc{
}{
\spadpaste{one?(factor(1))}
}
\xtc{
}{
\spadpaste{one?(f) \free{f}}
}
\xtc{
Another way to get the zero and one factored objects is to use
package calling 
(see \downlink{``Package Calling and Target Types''}
{ugTypesPkgCallPage} in Section 2.9\ignore{ugTypesPkgCall}).
}{
\spadpaste{0\$Factored(Integer)}
}
\xtc{
}{
\spadpaste{1\$Factored(Integer)}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxFactoredArithPagePatch1}
\begin{paste}{ugxFactoredArithPageFull1}{ugxFactoredArithPageEmpty1}
\pastebutton{ugxFactoredArithPageFull1}{\hidepaste}
\tab{5}\spadcommand{g := factor(4312)\bound{g }}
\indentrel{3}\begin{verbatim}
         3 2
   (1)  2 7 11
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPageEmpty1}
\begin{paste}{ugxFactoredArithPageEmpty1}{ugxFactoredArithPagePatch1}
\pastebutton{ugxFactoredArithPageEmpty1}{\showpaste}
\tab{5}\spadcommand{g := factor(4312)\bound{g }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPagePatch2}
\begin{paste}{ugxFactoredArithPageFull2}{ugxFactoredArithPageEmpty2}
\pastebutton{ugxFactoredArithPageFull2}{\hidepaste}
\tab{5}\spadcommand{f := factor(246960)\bound{f }}
\indentrel{3}\begin{verbatim}
         4 2   3
   (2)  2 3 5 7
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPageEmpty2}
\begin{paste}{ugxFactoredArithPageEmpty2}{ugxFactoredArithPagePatch2}
\pastebutton{ugxFactoredArithPageEmpty2}{\showpaste}
\tab{5}\spadcommand{f := factor(246960)\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPagePatch3}
\begin{paste}{ugxFactoredArithPageFull3}{ugxFactoredArithPageEmpty3}
\pastebutton{ugxFactoredArithPageFull3}{\hidepaste}
\tab{5}\spadcommand{f * g\free{f g }}
\indentrel{3}\begin{verbatim}
         7 2   5
   (3)  2 3 5 7 11
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPageEmpty3}
\begin{paste}{ugxFactoredArithPageEmpty3}{ugxFactoredArithPagePatch3}
\pastebutton{ugxFactoredArithPageEmpty3}{\showpaste}
\tab{5}\spadcommand{f * g\free{f g }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPagePatch4}
\begin{paste}{ugxFactoredArithPageFull4}{ugxFactoredArithPageEmpty4}
\pastebutton{ugxFactoredArithPageFull4}{\hidepaste}
\tab{5}\spadcommand{f**500\free{f }}
\indentrel{3}\begin{verbatim}
         2000 1000 500 1500
   (4)  2    3    5   7
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPageEmpty4}
\begin{paste}{ugxFactoredArithPageEmpty4}{ugxFactoredArithPagePatch4}
\pastebutton{ugxFactoredArithPageEmpty4}{\showpaste}
\tab{5}\spadcommand{f**500\free{f }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPagePatch5}
\begin{paste}{ugxFactoredArithPageFull5}{ugxFactoredArithPageEmpty5}
\pastebutton{ugxFactoredArithPageFull5}{\hidepaste}
\tab{5}\spadcommand{gcd(f,g)\free{f g }}
\indentrel{3}\begin{verbatim}
         3 2
   (5)  2 7
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPageEmpty5}
\begin{paste}{ugxFactoredArithPageEmpty5}{ugxFactoredArithPagePatch5}
\pastebutton{ugxFactoredArithPageEmpty5}{\showpaste}
\tab{5}\spadcommand{gcd(f,g)\free{f g }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPagePatch6}
\begin{paste}{ugxFactoredArithPageFull6}{ugxFactoredArithPageEmpty6}
\pastebutton{ugxFactoredArithPageFull6}{\hidepaste}
\tab{5}\spadcommand{lcm(f,g)\free{f g }}
\indentrel{3}\begin{verbatim}
         4 2   3
   (6)  2 3 5 7 11
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPageEmpty6}
\begin{paste}{ugxFactoredArithPageEmpty6}{ugxFactoredArithPagePatch6}
\pastebutton{ugxFactoredArithPageEmpty6}{\showpaste}
\tab{5}\spadcommand{lcm(f,g)\free{f g }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPagePatch7}
\begin{paste}{ugxFactoredArithPageFull7}{ugxFactoredArithPageEmpty7}
\pastebutton{ugxFactoredArithPageFull7}{\hidepaste}
\tab{5}\spadcommand{f + g\free{f g }}
\indentrel{3}\begin{verbatim}
         3 2
   (7)  2 7 641
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPageEmpty7}
\begin{paste}{ugxFactoredArithPageEmpty7}{ugxFactoredArithPagePatch7}
\pastebutton{ugxFactoredArithPageEmpty7}{\showpaste}
\tab{5}\spadcommand{f + g\free{f g }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPagePatch8}
\begin{paste}{ugxFactoredArithPageFull8}{ugxFactoredArithPageEmpty8}
\pastebutton{ugxFactoredArithPageFull8}{\hidepaste}
\tab{5}\spadcommand{f - g\free{f g }}
\indentrel{3}\begin{verbatim}
         3 2
   (8)  2 7 619
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPageEmpty8}
\begin{paste}{ugxFactoredArithPageEmpty8}{ugxFactoredArithPagePatch8}
\pastebutton{ugxFactoredArithPageEmpty8}{\showpaste}
\tab{5}\spadcommand{f - g\free{f g }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPagePatch9}
\begin{paste}{ugxFactoredArithPageFull9}{ugxFactoredArithPageEmpty9}
\pastebutton{ugxFactoredArithPageFull9}{\hidepaste}
\tab{5}\spadcommand{zero?(factor(0))}
\indentrel{3}\begin{verbatim}
   (9)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPageEmpty9}
\begin{paste}{ugxFactoredArithPageEmpty9}{ugxFactoredArithPagePatch9}
\pastebutton{ugxFactoredArithPageEmpty9}{\showpaste}
\tab{5}\spadcommand{zero?(factor(0))}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPagePatch10}
\begin{paste}{ugxFactoredArithPageFull10}{ugxFactoredArithPageEmpty10}
\pastebutton{ugxFactoredArithPageFull10}{\hidepaste}
\tab{5}\spadcommand{zero?(g)\free{g }}
\indentrel{3}\begin{verbatim}
   (10)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPageEmpty10}
\begin{paste}{ugxFactoredArithPageEmpty10}{ugxFactoredArithPagePatch10}
\pastebutton{ugxFactoredArithPageEmpty10}{\showpaste}
\tab{5}\spadcommand{zero?(g)\free{g }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPagePatch11}
\begin{paste}{ugxFactoredArithPageFull11}{ugxFactoredArithPageEmpty11}
\pastebutton{ugxFactoredArithPageFull11}{\hidepaste}
\tab{5}\spadcommand{one?(factor(1))}
\indentrel{3}\begin{verbatim}
   (11)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPageEmpty11}
\begin{paste}{ugxFactoredArithPageEmpty11}{ugxFactoredArithPagePatch11}
\pastebutton{ugxFactoredArithPageEmpty11}{\showpaste}
\tab{5}\spadcommand{one?(factor(1))}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPagePatch12}
\begin{paste}{ugxFactoredArithPageFull12}{ugxFactoredArithPageEmpty12}
\pastebutton{ugxFactoredArithPageFull12}{\hidepaste}
\tab{5}\spadcommand{one?(f)\free{f }}
\indentrel{3}\begin{verbatim}
   (12)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPageEmpty12}
\begin{paste}{ugxFactoredArithPageEmpty12}{ugxFactoredArithPagePatch12}
\pastebutton{ugxFactoredArithPageEmpty12}{\showpaste}
\tab{5}\spadcommand{one?(f)\free{f }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPagePatch13}
\begin{paste}{ugxFactoredArithPageFull13}{ugxFactoredArithPageEmpty13}
\pastebutton{ugxFactoredArithPageFull13}{\hidepaste}
\tab{5}\spadcommand{0$Factored(Integer)}
\indentrel{3}\begin{verbatim}
   (13)  0
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPageEmpty13}
\begin{paste}{ugxFactoredArithPageEmpty13}{ugxFactoredArithPagePatch13}
\pastebutton{ugxFactoredArithPageEmpty13}{\showpaste}
\tab{5}\spadcommand{0$Factored(Integer)}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPagePatch14}
\begin{paste}{ugxFactoredArithPageFull14}{ugxFactoredArithPageEmpty14}
\pastebutton{ugxFactoredArithPageFull14}{\hidepaste}
\tab{5}\spadcommand{1$Factored(Integer)}
\indentrel{3}\begin{verbatim}
   (14)  1
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredArithPageEmpty14}
\begin{paste}{ugxFactoredArithPageEmpty14}{ugxFactoredArithPagePatch14}
\pastebutton{ugxFactoredArithPageEmpty14}{\showpaste}
\tab{5}\spadcommand{1$Factored(Integer)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxFactoredNewPage}{fr.ht}{Creating New Factored Objects}
\pagepic{ps/v71ugxfactorednewpage.eps}{ugxFactoredNewPage}{0.50}
\pagefrom{Factored}{FactoredXmpPage}
\pageto{FactoredFunctions2}{FactoredFnsTwoXmpPage}
\begin{chunk}{fr.ht}
\begin{page}{ugxFactoredNewPage}{Creating New Factored Objects}
\beginscroll

The \spadfunFrom{map}{Factored} operation is used to iterate across the
unit and bases of a factored object.
See \downlink{`FactoredFunctions2'}{FactoredFnsTwoXmpPage}
\ignore{FactoredFunctions2} for a discussion of
\spadfunFrom{map}{Factored}.

\labelSpace{1pc}
\xtc{
The following four operations take a base and an exponent and create
a factored object.
They differ in handling the flag component.
}{
\spadpaste{nilFactor(24,2) \bound{prev2}}
}
\xtc{
This factor has no associated information.
}{
\spadpaste{nthFlag(\%,1) \free{prev2}}
}
\xtc{
This factor is asserted to be square-free.
}{
\spadpaste{sqfrFactor(30,2) \bound{prev3}}
}
\xtc{
This factor is asserted to be irreducible.
}{
\spadpaste{irreducibleFactor(13,10) \bound{prev4}}
}
\xtc{
This factor is asserted to be prime.
}{
\spadpaste{primeFactor(11,5) \bound{prev5}}
}

\xtc{
A partial inverse to \spadfunFrom{factorList}{Factored} is
\spadfunFrom{makeFR}{Factored}.
}{
\spadpaste{h := factor(-720) \bound{h}}
}
\xtc{
The first argument is the unit and the second is a list of records as
returned by \spadfunFrom{factorList}{Factored}.
}{
\spadpaste{h - makeFR(unit(h),factorList(h)) \free{h}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxFactoredNewPagePatch1}
\begin{paste}{ugxFactoredNewPageFull1}{ugxFactoredNewPageEmpty1}
\pastebutton{ugxFactoredNewPageFull1}{\hidepaste}
\tab{5}\spadcommand{nilFactor(24,2)\bound{prev2 }}
\indentrel{3}\begin{verbatim}
          2
   (1)  24
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredNewPageEmpty1}
\begin{paste}{ugxFactoredNewPageEmpty1}{ugxFactoredNewPagePatch1}
\pastebutton{ugxFactoredNewPageEmpty1}{\showpaste}
\tab{5}\spadcommand{nilFactor(24,2)\bound{prev2 }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredNewPagePatch2}
\begin{paste}{ugxFactoredNewPageFull2}{ugxFactoredNewPageEmpty2}
\pastebutton{ugxFactoredNewPageFull2}{\hidepaste}
\tab{5}\spadcommand{nthFlag(\%,1)\free{prev2 }}
\indentrel{3}\begin{verbatim}
   (2)  "nil"
                                 Type: Union("nil",...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredNewPageEmpty2}
\begin{paste}{ugxFactoredNewPageEmpty2}{ugxFactoredNewPagePatch2}
\pastebutton{ugxFactoredNewPageEmpty2}{\showpaste}
\tab{5}\spadcommand{nthFlag(\%,1)\free{prev2 }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredNewPagePatch3}
\begin{paste}{ugxFactoredNewPageFull3}{ugxFactoredNewPageEmpty3}
\pastebutton{ugxFactoredNewPageFull3}{\hidepaste}
\tab{5}\spadcommand{sqfrFactor(30,2)\bound{prev3 }}
\indentrel{3}\begin{verbatim}
          2
   (3)  30
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredNewPageEmpty3}
\begin{paste}{ugxFactoredNewPageEmpty3}{ugxFactoredNewPagePatch3}
\pastebutton{ugxFactoredNewPageEmpty3}{\showpaste}
\tab{5}\spadcommand{sqfrFactor(30,2)\bound{prev3 }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredNewPagePatch4}
\begin{paste}{ugxFactoredNewPageFull4}{ugxFactoredNewPageEmpty4}
\pastebutton{ugxFactoredNewPageFull4}{\hidepaste}
\tab{5}\spadcommand{irreducibleFactor(13,10)\bound{prev4 }}
\indentrel{3}\begin{verbatim}
          10
   (4)  13
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredNewPageEmpty4}
\begin{paste}{ugxFactoredNewPageEmpty4}{ugxFactoredNewPagePatch4}
\pastebutton{ugxFactoredNewPageEmpty4}{\showpaste}
\tab{5}\spadcommand{irreducibleFactor(13,10)\bound{prev4 }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredNewPagePatch5}
\begin{paste}{ugxFactoredNewPageFull5}{ugxFactoredNewPageEmpty5}
\pastebutton{ugxFactoredNewPageFull5}{\hidepaste}
\tab{5}\spadcommand{primeFactor(11,5)\bound{prev5 }}
\indentrel{3}\begin{verbatim}
          5
   (5)  11
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredNewPageEmpty5}
\begin{paste}{ugxFactoredNewPageEmpty5}{ugxFactoredNewPagePatch5}
\pastebutton{ugxFactoredNewPageEmpty5}{\showpaste}
\tab{5}\spadcommand{primeFactor(11,5)\bound{prev5 }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredNewPagePatch6}
\begin{paste}{ugxFactoredNewPageFull6}{ugxFactoredNewPageEmpty6}
\pastebutton{ugxFactoredNewPageFull6}{\hidepaste}
\tab{5}\spadcommand{h := factor(-720)\bound{h }}
\indentrel{3}\begin{verbatim}
           4 2
   (6)  - 2 3 5
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredNewPageEmpty6}
\begin{paste}{ugxFactoredNewPageEmpty6}{ugxFactoredNewPagePatch6}
\pastebutton{ugxFactoredNewPageEmpty6}{\showpaste}
\tab{5}\spadcommand{h := factor(-720)\bound{h }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredNewPagePatch7}
\begin{paste}{ugxFactoredNewPageFull7}{ugxFactoredNewPageEmpty7}
\pastebutton{ugxFactoredNewPageFull7}{\hidepaste}
\tab{5}\spadcommand{h - makeFR(unit(h),factorList(h))\free{h }}
\indentrel{3}\begin{verbatim}
   (7)  0
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredNewPageEmpty7}
\begin{paste}{ugxFactoredNewPageEmpty7}{ugxFactoredNewPagePatch7}
\pastebutton{ugxFactoredNewPageEmpty7}{\showpaste}
\tab{5}\spadcommand{h - makeFR(unit(h),factorList(h))\free{h }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxFactoredVarPage}{fr.ht}{Factored Objects with Variables}
\pagepic{ps/v71ugxfactoredvarpage.eps}{ugxFactoredVarPage}{0.50}
\pagefrom{Factored}{FactoredXmpPage}
\begin{chunk}{fr.ht}
\begin{page}{ugxFactoredVarPage}{Factored Objects with Variables}
\beginscroll

\labelSpace{4pc}
\xtc{
Some of the operations available for polynomials are also available
for factored polynomials.
}{
\spadpaste{p := (4*x*x-12*x+9)*y*y + (4*x*x-12*x+9)*y + 28*x*x - 84*x + 63 
\bound{p}}
}
\xtc{
}{
\spadpaste{fp := factor(p) \free{p}\bound{fp}}
}
\xtc{
You can differentiate with respect to a variable.
}{
\spadpaste{D(p,x) \free{p}}
}
\xtc{
}{
\spadpaste{D(fp,x) \free{fp}\bound{prev1}}
}
\xtc{
}{
\spadpaste{numberOfFactors(\%) \free{prev1}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxFactoredVarPagePatch1}
\begin{paste}{ugxFactoredVarPageFull1}{ugxFactoredVarPageEmpty1}
\pastebutton{ugxFactoredVarPageFull1}{\hidepaste}
\tab{5}\spadcommand{p := (4*x*x-12*x+9)*y*y + (4*x*x-12*x+9)*y + 28*x*x - 84*x + 63\bound{p }}
\indentrel{3}\begin{verbatim}
   (1)
      2            2      2                  2
   (4x  - 12x + 9)y  + (4x  - 12x + 9)y + 28x  - 84x + 63
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredVarPageEmpty1}
\begin{paste}{ugxFactoredVarPageEmpty1}{ugxFactoredVarPagePatch1}
\pastebutton{ugxFactoredVarPageEmpty1}{\showpaste}
\tab{5}\spadcommand{p := (4*x*x-12*x+9)*y*y + (4*x*x-12*x+9)*y + 28*x*x - 84*x + 63\bound{p }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredVarPagePatch2}
\begin{paste}{ugxFactoredVarPageFull2}{ugxFactoredVarPageEmpty2}
\pastebutton{ugxFactoredVarPageFull2}{\hidepaste}
\tab{5}\spadcommand{fp := factor(p)\free{p }\bound{fp }}
\indentrel{3}\begin{verbatim}
                2  2
   (2)  (2x - 3) (y  + y + 7)
                      Type: Factored Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredVarPageEmpty2}
\begin{paste}{ugxFactoredVarPageEmpty2}{ugxFactoredVarPagePatch2}
\pastebutton{ugxFactoredVarPageEmpty2}{\showpaste}
\tab{5}\spadcommand{fp := factor(p)\free{p }\bound{fp }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredVarPagePatch3}
\begin{paste}{ugxFactoredVarPageFull3}{ugxFactoredVarPageEmpty3}
\pastebutton{ugxFactoredVarPageFull3}{\hidepaste}
\tab{5}\spadcommand{D(p,x)\free{p }}
\indentrel{3}\begin{verbatim}
                  2
   (3)  (8x - 12)y  + (8x - 12)y + 56x - 84
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredVarPageEmpty3}
\begin{paste}{ugxFactoredVarPageEmpty3}{ugxFactoredVarPagePatch3}
\pastebutton{ugxFactoredVarPageEmpty3}{\showpaste}
\tab{5}\spadcommand{D(p,x)\free{p }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredVarPagePatch4}
\begin{paste}{ugxFactoredVarPageFull4}{ugxFactoredVarPageEmpty4}
\pastebutton{ugxFactoredVarPageFull4}{\hidepaste}
\tab{5}\spadcommand{D(fp,x)\free{fp }\bound{prev1 }}
\indentrel{3}\begin{verbatim}
                   2
   (4)  4(2x - 3)(y  + y + 7)
                      Type: Factored Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredVarPageEmpty4}
\begin{paste}{ugxFactoredVarPageEmpty4}{ugxFactoredVarPagePatch4}
\pastebutton{ugxFactoredVarPageEmpty4}{\showpaste}
\tab{5}\spadcommand{D(fp,x)\free{fp }\bound{prev1 }}
\end{paste}\end{patch}

\begin{patch}{ugxFactoredVarPagePatch5}
\begin{paste}{ugxFactoredVarPageFull5}{ugxFactoredVarPageEmpty5}
\pastebutton{ugxFactoredVarPageFull5}{\hidepaste}
\tab{5}\spadcommand{numberOfFactors(\%)\free{prev1 }}
\indentrel{3}\begin{verbatim}
   (5)  3
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxFactoredVarPageEmpty5}
\begin{paste}{ugxFactoredVarPageEmpty5}{ugxFactoredVarPagePatch5}
\pastebutton{ugxFactoredVarPageEmpty5}{\showpaste}
\tab{5}\spadcommand{numberOfFactors(\%)\free{prev1 }}
\end{paste}\end{patch}

\end{chunk}
\section{fr2.ht}
\pagetitle{FactoredFnsTwoXmpPage}{fr2.ht}{FactoredFunctions2}
\pagepic{ps/v71factoredfnstwoxmppage.eps}{FactoredFnsTwoXmpPage}{0.50}
\pagefrom{Creating New Factored Objects}{ugxFactoredNewPage}
\pageto{Factored}{FactoredXmpPage}
\pageto{Computation of Galois Groups}{ugProblemGaloisPage}
\begin{chunk}{fr2.ht}
\begin{page}{FactoredFnsTwoXmpPage}{FactoredFunctions2}
\beginscroll

The \spadtype{FactoredFunctions2} package implements one operation,
\spadfunFrom{map}{FactoredFunctions2}, for applying an operation to every
base in a factored object and to the unit.
\xtc{
}{
\spadpaste{double(x) == x + x \bound{double}}
}
\xtc{
}{
\spadpaste{f := factor(720) \bound{f}}
}
\xtc{
Actually, the \spadfunFrom{map}{FactoredFunctions2} operation used
in this example comes from \spadtype{Factored} itself, since
\userfun{double} takes an integer argument and returns an integer
result.
}{
\spadpaste{map(double,f) \free{f}\free{double}}
}
\xtc{
If we want to use an operation that returns an object that has a type
different from the operation's argument,
the \spadfunFrom{map}{FactoredFunctions2} in \spadtype{Factored}
cannot be used and we use the one in \spadtype{FactoredFunctions2}.
}{
\spadpaste{makePoly(b) == x + b \bound{makePoly}}
}
\xtc{
In fact, the ``2'' in the name of the package means that we might
be using factored objects of two different types.
}{
\spadpaste{g := map(makePoly,f) \free{f}\free{makePoly}\bound{g}}
}
It is important to note that both versions of 
\spadfunFrom{map}{FactoredFunctions2}
destroy any information known about the bases (the fact that 
they are prime, for instance).
\xtc{
The flags for each base are set to ``nil'' in the object returned
by \spadfunFrom{map}{FactoredFunctions2}.
}{
\spadpaste{nthFlag(g,1) \free{g}}
}

For more information about factored objects and their use, see
\downlink{`Factored'}{FactoredXmpPage}\ignore{Factored} and
\downlink{``Computation of Galois Groups''}{ugProblemGaloisPage} in 
Section 8.13\ignore{ugProblemGalois}.
\endscroll
\autobuttons
\end{page}

\begin{patch}{FactoredFnsTwoXmpPagePatch1}
\begin{paste}{FactoredFnsTwoXmpPageFull1}{FactoredFnsTwoXmpPageEmpty1}
\pastebutton{FactoredFnsTwoXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{double(x) == x + x\bound{double }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FactoredFnsTwoXmpPageEmpty1}
\begin{paste}{FactoredFnsTwoXmpPageEmpty1}{FactoredFnsTwoXmpPagePatch1}
\pastebutton{FactoredFnsTwoXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{double(x) == x + x\bound{double }}
\end{paste}\end{patch}

\begin{patch}{FactoredFnsTwoXmpPagePatch2}
\begin{paste}{FactoredFnsTwoXmpPageFull2}{FactoredFnsTwoXmpPageEmpty2}
\pastebutton{FactoredFnsTwoXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{f := factor(720)\bound{f }}
\indentrel{3}\begin{verbatim}
         4 2
   (2)  2 3 5
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FactoredFnsTwoXmpPageEmpty2}
\begin{paste}{FactoredFnsTwoXmpPageEmpty2}{FactoredFnsTwoXmpPagePatch2}
\pastebutton{FactoredFnsTwoXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{f := factor(720)\bound{f }}
\end{paste}\end{patch}

\begin{patch}{FactoredFnsTwoXmpPagePatch3}
\begin{paste}{FactoredFnsTwoXmpPageFull3}{FactoredFnsTwoXmpPageEmpty3}
\pastebutton{FactoredFnsTwoXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{map(double,f)\free{f }\free{double }}
\indentrel{3}\begin{verbatim}
           4 2
   (3)  2 4 6 10
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FactoredFnsTwoXmpPageEmpty3}
\begin{paste}{FactoredFnsTwoXmpPageEmpty3}{FactoredFnsTwoXmpPagePatch3}
\pastebutton{FactoredFnsTwoXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{map(double,f)\free{f }\free{double }}
\end{paste}\end{patch}

\begin{patch}{FactoredFnsTwoXmpPagePatch4}
\begin{paste}{FactoredFnsTwoXmpPageFull4}{FactoredFnsTwoXmpPageEmpty4}
\pastebutton{FactoredFnsTwoXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{makePoly(b) == x + b\bound{makePoly }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FactoredFnsTwoXmpPageEmpty4}
\begin{paste}{FactoredFnsTwoXmpPageEmpty4}{FactoredFnsTwoXmpPagePatch4}
\pastebutton{FactoredFnsTwoXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{makePoly(b) == x + b\bound{makePoly }}
\end{paste}\end{patch}

\begin{patch}{FactoredFnsTwoXmpPagePatch5}
\begin{paste}{FactoredFnsTwoXmpPageFull5}{FactoredFnsTwoXmpPageEmpty5}
\pastebutton{FactoredFnsTwoXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{g := map(makePoly,f)\free{f }\free{makePoly }\bound{g }}
\indentrel{3}\begin{verbatim}
                      4       2
   (5)  (x + 1)(x + 2) (x + 3) (x + 5)
                      Type: Factored Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FactoredFnsTwoXmpPageEmpty5}
\begin{paste}{FactoredFnsTwoXmpPageEmpty5}{FactoredFnsTwoXmpPagePatch5}
\pastebutton{FactoredFnsTwoXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{g := map(makePoly,f)\free{f }\free{makePoly }\bound{g }}
\end{paste}\end{patch}

\begin{patch}{FactoredFnsTwoXmpPagePatch6}
\begin{paste}{FactoredFnsTwoXmpPageFull6}{FactoredFnsTwoXmpPageEmpty6}
\pastebutton{FactoredFnsTwoXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{nthFlag(g,1)\free{g }}
\indentrel{3}\begin{verbatim}
   (6)  "nil"
                                 Type: Union("nil",...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FactoredFnsTwoXmpPageEmpty6}
\begin{paste}{FactoredFnsTwoXmpPageEmpty6}{FactoredFnsTwoXmpPagePatch6}
\pastebutton{FactoredFnsTwoXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{nthFlag(g,1)\free{g }}
\end{paste}\end{patch}

\end{chunk}
\section{frac.ht}
\pagetitle{FractionXmpPage}{frac.ht}{Fraction}
\pageto{Integer}{IntegerXmpPage}
\pageto{notitle}{ContinuedFractionXmpPage}
\pageto{notitle}{PartialFractionXmpPage}
\begin{chunk}{frac.ht}
\begin{page}{FractionXmpPage}{Fraction}
\beginscroll

The \spadtype{Fraction} domain implements quotients.
The elements must belong to a domain of category \spadtype{IntegralDomain}:
multiplication must be commutative and the product of two non-zero
elements must not be zero.
This allows you to make fractions of most things you would think of,
but don't expect to create a fraction of two matrices!
The abbreviation for \spadtype{Fraction} is \spadtype{FRAC}.

\xtc{
Use \spadopFrom{/}{Fraction} to create a fraction.
}{
\spadpaste{a := 11/12 \bound{a}}
}
\xtc{
}{
\spadpaste{b := 23/24 \bound{b}}
}
\xtc{
The standard arithmetic operations are available.
}{
\spadpaste{3 - a*b**2 + a + b/a \free{a}\free{b}}
}
\xtc{
Extract the numerator and denominator by using
\spadfunFrom{numer}{Fraction} and \spadfunFrom{denom}{Fraction},
respectively.
}{
\spadpaste{numer(a) \free{a}}
}
\xtc{
}{
\spadpaste{denom(b) \free{b}}
}
Operations like \spadfunFrom{max}{Fraction}, \spadfunFrom{min}{Fraction},
\spadfunFrom{negative?}{Fraction}, \spadfunFrom{positive?}{Fraction} and
\spadfunFrom{zero?}{Fraction} are all available if they are provided for
the numerators and denominators.
See \downlink{`Integer'}{IntegerXmpPage}\ignore{Integer} for examples.

Don't expect a useful answer from \spadfunFrom{factor}{Fraction},
\spadfunFrom{gcd}{Fraction} or \spadfunFrom{lcm}{Fraction} if you apply
them to fractions.
\xtc{
}{
\spadpaste{r := (x**2 + 2*x + 1)/(x**2 - 2*x + 1) \bound{r}}
}
\xtc{
Since all non-zero fractions are invertible, these operations have trivial
definitions.
}{
\spadpaste{factor(r) \free{r}}
}
\xtc{
Use \spadfunFrom{map}{Fraction} to apply \spadfunFrom{factor}{Fraction} to
the numerator and denominator, which is probably what you mean.
}{
\spadpaste{map(factor,r) \free{r}}
}

\xtc{
Other forms of fractions are available.
Use \spadfun{continuedFraction} to create a continued fraction.
}{
\spadpaste{continuedFraction(7/12)}
}
\xtc{
Use \spadfun{partialFraction} to create a partial fraction.
See \downlink{`ContinuedFraction'}{ContinuedFractionXmpPage}
\ignore{ContinuedFraction} and 
\downlink{`PartialFraction'}{PartialFractionXmpPage}
\ignore{PartialFraction} for
additional information and examples.
}{
\spadpaste{partialFraction(7,12)}
}

\xtc{
Use conversion to create alternative views of fractions with objects
moved in and out of the numerator and denominator.
}{
\spadpaste{g := 2/3 + 4/5*\%i \bound{g}}
}
\xtc{
Conversion is discussed in detail in 
\downlink{``Conversion''}{ugTypesConvertPage} 
in Section 2.7\ignore{ugTypesConvert}.
}{
\spadpaste{g :: FRAC COMPLEX INT \free{g}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{FractionXmpPagePatch1}
\begin{paste}{FractionXmpPageFull1}{FractionXmpPageEmpty1}
\pastebutton{FractionXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{a := 11/12\bound{a }}
\indentrel{3}\begin{verbatim}
        11
   (1)  ÄÄ
        12
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FractionXmpPageEmpty1}
\begin{paste}{FractionXmpPageEmpty1}{FractionXmpPagePatch1}
\pastebutton{FractionXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{a := 11/12\bound{a }}
\end{paste}\end{patch}

\begin{patch}{FractionXmpPagePatch2}
\begin{paste}{FractionXmpPageFull2}{FractionXmpPageEmpty2}
\pastebutton{FractionXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{b := 23/24\bound{b }}
\indentrel{3}\begin{verbatim}
        23
   (2)  ÄÄ
        24
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FractionXmpPageEmpty2}
\begin{paste}{FractionXmpPageEmpty2}{FractionXmpPagePatch2}
\pastebutton{FractionXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{b := 23/24\bound{b }}
\end{paste}\end{patch}

\begin{patch}{FractionXmpPagePatch3}
\begin{paste}{FractionXmpPageFull3}{FractionXmpPageEmpty3}
\pastebutton{FractionXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{3 - a*b**2 + a + b/a\free{a }\free{b }}
\indentrel{3}\begin{verbatim}
        313271
   (3)  ÄÄÄÄÄÄ
         76032
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FractionXmpPageEmpty3}
\begin{paste}{FractionXmpPageEmpty3}{FractionXmpPagePatch3}
\pastebutton{FractionXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{3 - a*b**2 + a + b/a\free{a }\free{b }}
\end{paste}\end{patch}

\begin{patch}{FractionXmpPagePatch4}
\begin{paste}{FractionXmpPageFull4}{FractionXmpPageEmpty4}
\pastebutton{FractionXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{numer(a)\free{a }}
\indentrel{3}\begin{verbatim}
   (4)  11
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FractionXmpPageEmpty4}
\begin{paste}{FractionXmpPageEmpty4}{FractionXmpPagePatch4}
\pastebutton{FractionXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{numer(a)\free{a }}
\end{paste}\end{patch}

\begin{patch}{FractionXmpPagePatch5}
\begin{paste}{FractionXmpPageFull5}{FractionXmpPageEmpty5}
\pastebutton{FractionXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{denom(b)\free{b }}
\indentrel{3}\begin{verbatim}
   (5)  24
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FractionXmpPageEmpty5}
\begin{paste}{FractionXmpPageEmpty5}{FractionXmpPagePatch5}
\pastebutton{FractionXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{denom(b)\free{b }}
\end{paste}\end{patch}

\begin{patch}{FractionXmpPagePatch6}
\begin{paste}{FractionXmpPageFull6}{FractionXmpPageEmpty6}
\pastebutton{FractionXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{r := (x**2 + 2*x + 1)/(x**2 - 2*x + 1)\bound{r }}
\indentrel{3}\begin{verbatim}
         2
        x  + 2x + 1
   (6)  ÄÄÄÄÄÄÄÄÄÄÄ
         2
        x  - 2x + 1
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FractionXmpPageEmpty6}
\begin{paste}{FractionXmpPageEmpty6}{FractionXmpPagePatch6}
\pastebutton{FractionXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{r := (x**2 + 2*x + 1)/(x**2 - 2*x + 1)\bound{r }}
\end{paste}\end{patch}

\begin{patch}{FractionXmpPagePatch7}
\begin{paste}{FractionXmpPageFull7}{FractionXmpPageEmpty7}
\pastebutton{FractionXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{factor(r)\free{r }}
\indentrel{3}\begin{verbatim}
         2
        x  + 2x + 1
   (7)  ÄÄÄÄÄÄÄÄÄÄÄ
         2
        x  - 2x + 1
             Type: Factored Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FractionXmpPageEmpty7}
\begin{paste}{FractionXmpPageEmpty7}{FractionXmpPagePatch7}
\pastebutton{FractionXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{factor(r)\free{r }}
\end{paste}\end{patch}

\begin{patch}{FractionXmpPagePatch8}
\begin{paste}{FractionXmpPageFull8}{FractionXmpPageEmpty8}
\pastebutton{FractionXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{map(factor,r)\free{r }}
\indentrel{3}\begin{verbatim}
               2
        (x + 1)
   (8)  ÄÄÄÄÄÄÄÄ
               2
        (x - 1)
             Type: Fraction Factored Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FractionXmpPageEmpty8}
\begin{paste}{FractionXmpPageEmpty8}{FractionXmpPagePatch8}
\pastebutton{FractionXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{map(factor,r)\free{r }}
\end{paste}\end{patch}

\begin{patch}{FractionXmpPagePatch9}
\begin{paste}{FractionXmpPageFull9}{FractionXmpPageEmpty9}
\pastebutton{FractionXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{continuedFraction(7/12)}
\indentrel{3}\begin{verbatim}
          1 ³     1 ³     1 ³     1 ³
   (9)  ÚÄÄÄÙ + ÚÄÄÄÙ + ÚÄÄÄÙ + ÚÄÄÄÙ
        ³ 1     ³ 1     ³ 2     ³ 2
                        Type: ContinuedFraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FractionXmpPageEmpty9}
\begin{paste}{FractionXmpPageEmpty9}{FractionXmpPagePatch9}
\pastebutton{FractionXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{continuedFraction(7/12)}
\end{paste}\end{patch}

\begin{patch}{FractionXmpPagePatch10}
\begin{paste}{FractionXmpPageFull10}{FractionXmpPageEmpty10}
\pastebutton{FractionXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{partialFraction(7,12)}
\indentrel{3}\begin{verbatim}
              3   1
   (10)  1 - ÄÄ + Ä
              2   3
             2
                          Type: PartialFraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FractionXmpPageEmpty10}
\begin{paste}{FractionXmpPageEmpty10}{FractionXmpPagePatch10}
\pastebutton{FractionXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{partialFraction(7,12)}
\end{paste}\end{patch}

\begin{patch}{FractionXmpPagePatch11}
\begin{paste}{FractionXmpPageFull11}{FractionXmpPageEmpty11}
\pastebutton{FractionXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{g := 2/3 + 4/5*\%i\bound{g }}
\indentrel{3}\begin{verbatim}
         2   4
   (11)  Ä + Ä %i
         3   5
                         Type: Complex Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FractionXmpPageEmpty11}
\begin{paste}{FractionXmpPageEmpty11}{FractionXmpPagePatch11}
\pastebutton{FractionXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{g := 2/3 + 4/5*\%i\bound{g }}
\end{paste}\end{patch}

\begin{patch}{FractionXmpPagePatch12}
\begin{paste}{FractionXmpPageFull12}{FractionXmpPageEmpty12}
\pastebutton{FractionXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{g :: FRAC COMPLEX INT\free{g }}
\indentrel{3}\begin{verbatim}
         10 + 12%i
   (12)  ÄÄÄÄÄÄÄÄÄ
             15
                         Type: Fraction Complex Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FractionXmpPageEmpty12}
\begin{paste}{FractionXmpPageEmpty12}{FractionXmpPagePatch12}
\pastebutton{FractionXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{g :: FRAC COMPLEX INT\free{g }}
\end{paste}\end{patch}

\end{chunk}
\section{fparfrac.ht}
\pagetitle{FullPartialFracExpansionXmpPage}{fparfrac.ht}
{FullPartialFracExpansion}
\pageto{notitle}{PartialFractionXmpPage}
\begin{chunk}{fparfrac.ht}
\begin{page}{FullPartialFracExpansionXmpPage}{FullPartialFracExpansion}
\beginscroll

The domain \spadtype{FullPartialFracExpansion} implements
factor-free conversion of quotients to full partial fractions.

\xtc{
Our examples will all involve quotients of univariate polynomials
with rational number coefficients.
}{
\spadpaste{Fx := FRAC UP(x, FRAC INT) \bound{Fx}}
}
\xtc{
Here is a simple-looking rational function.
}{
\spadpaste{f : Fx := 36 / (x**5-2*x**4-2*x**3+4*x**2+x-2) \bound{f}\free{Fx}}
}
\xtc{
We use \spadfunFrom{fullPartialFraction}{FullPartialFracExpansion}
to convert it to an object of type
\spadtype{FullPartialFracExpansion}.
}{
\spadpaste{g := fullPartialFraction f \bound{g}\free{f}}
}
\xtc{
Use a coercion to change it back into a quotient.
}{
\spadpaste{g :: Fx \free{g}}
}
\xtc{
Full partial fractions differentiate faster than rational
functions.
}{
\spadpaste{g5 := D(g, 5) \free{g}\bound{g5}}
}
\xtc{
}{
\spadpaste{f5 := D(f, 5) \free{f}\bound{f5}}
}
\xtc{
We can check that the two forms represent the same function.
}{
\spadpaste{g5::Fx - f5 \free{Fx g5 f5}}
}
\xtc{
Here are some examples that are more complicated.
}{
\spadpaste{f : Fx := (x**5 * (x-1)) / ((x**2 + x + 1)**2 * (x-2)**3) 
\free{Fx}\bound{f2}}
}
\xtc{
}{
\spadpaste{g := fullPartialFraction f \free{f2}\bound{g2}}
}
\xtc{
}{
\spadpaste{g :: Fx - f \free{f2 g2 Fx}}
}
\xtc{
}{
\spadpaste{f : Fx := (2*x**7-7*x**5+26*x**3+8*x) / 
(x**8-5*x**6+6*x**4+4*x**2-8) \free{Fx}\bound{f3}}
}
\xtc{
}{
\spadpaste{g := fullPartialFraction f \free{f3}\bound{g3}}
}
\xtc{
}{
\spadpaste{g :: Fx - f \free{f3 g3 Fx}}
}
\xtc{
}{
\spadpaste{f:Fx := x**3 / 
(x**21 + 2*x**20 + 4*x**19 + 7*x**18 + 10*x**17 + 17*x**16 + 
22*x**15 + 30*x**14 + 36*x**13 + 40*x**12 + 47*x**11 + 46*x**10 + 
49*x**9 + 43*x**8 + 38*x**7 + 32*x**6 + 23*x**5 + 19*x**4 + 
10*x**3 + 7*x**2 + 2*x + 1)\free{Fx}\bound{f4}}
}
\xtc{
}{
\spadpaste{g := fullPartialFraction f \free{f4}\bound{g4}}
}
\xtc{
This verification takes much longer than the conversion to
partial fractions.
}{
\spadpaste{g :: Fx - f \free{f4 g4 Fx}}
}

For more information, see the paper:
Bronstein, M and Salvy, B.
``Full Partial Fraction Decomposition of Rational Functions,''
{\it Proceedings of ISSAC'93, Kiev}, ACM Press.
All see \downlink{`PartialFraction'}{PartialFractionXmpPage}
\ignore{PartialFraction} for standard partial fraction
decompositions.
\endscroll
\autobuttons
\end{page}

\begin{patch}{FullPartialFractionExpansionXmpPagePatch1}
\begin{paste}{FullPartialFractionExpansionXmpPageFull1}{FullPartialFractionExpansionXmpPageEmpty1}
\pastebutton{FullPartialFractionExpansionXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{Fx := FRAC UP(x, FRAC INT)\bound{Fx }}
\indentrel{3}\begin{verbatim}
   (1)
   Fraction UnivariatePolynomial(x,Fraction Integer)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPageEmpty1}
\begin{paste}{FullPartialFractionExpansionXmpPageEmpty1}{FullPartialFractionExpansionXmpPagePatch1}
\pastebutton{FullPartialFractionExpansionXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{Fx := FRAC UP(x, FRAC INT)\bound{Fx }}
\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPagePatch2}
\begin{paste}{FullPartialFractionExpansionXmpPageFull2}{FullPartialFractionExpansionXmpPageEmpty2}
\pastebutton{FullPartialFractionExpansionXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{f : Fx := 36 / (x**5-2*x**4-2*x**3+4*x**2+x-2)\bound{f }\free{Fx }}
\indentrel{3}\begin{verbatim}
                     36
   (2)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
         5     4     3     2
        x  - 2x  - 2x  + 4x  + x - 2
Type: Fraction UnivariatePolynomial(x,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPageEmpty2}
\begin{paste}{FullPartialFractionExpansionXmpPageEmpty2}{FullPartialFractionExpansionXmpPagePatch2}
\pastebutton{FullPartialFractionExpansionXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{f : Fx := 36 / (x**5-2*x**4-2*x**3+4*x**2+x-2)\bound{f }\free{Fx }}
\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPagePatch3}
\begin{paste}{FullPartialFractionExpansionXmpPageFull3}{FullPartialFractionExpansionXmpPageEmpty3}
\pastebutton{FullPartialFractionExpansionXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{g := fullPartialFraction f\bound{g }\free{f }}
\indentrel{3}\begin{verbatim}
          4       4        ÄÄ¿      - 3%A - 6
   (3)  ÄÄÄÄÄ - ÄÄÄÄÄ +    >        ÄÄÄÄÄÄÄÄÄ
        x - 2   x + 1      ÄÄÙ              2
                          2         (x - %A)
                        %A  - 1= 0
Type: FullPartialFractionExpansion(Fraction Integer,UnivariatePolynomial(x,Fraction Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPageEmpty3}
\begin{paste}{FullPartialFractionExpansionXmpPageEmpty3}{FullPartialFractionExpansionXmpPagePatch3}
\pastebutton{FullPartialFractionExpansionXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{g := fullPartialFraction f\bound{g }\free{f }}
\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPagePatch4}
\begin{paste}{FullPartialFractionExpansionXmpPageFull4}{FullPartialFractionExpansionXmpPageEmpty4}
\pastebutton{FullPartialFractionExpansionXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{g :: Fx\free{g }}
\indentrel{3}\begin{verbatim}
                     36
   (4)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
         5     4     3     2
        x  - 2x  - 2x  + 4x  + x - 2
Type: Fraction UnivariatePolynomial(x,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPageEmpty4}
\begin{paste}{FullPartialFractionExpansionXmpPageEmpty4}{FullPartialFractionExpansionXmpPagePatch4}
\pastebutton{FullPartialFractionExpansionXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{g :: Fx\free{g }}
\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPagePatch5}
\begin{paste}{FullPartialFractionExpansionXmpPageFull5}{FullPartialFractionExpansionXmpPageEmpty5}
\pastebutton{FullPartialFractionExpansionXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{g5 := D(g, 5)\free{g }\bound{g5 }}
\indentrel{3}\begin{verbatim}
   (5)
        480        480        ÄÄ¿      2160%A + 4320
   - ÄÄÄÄÄÄÄÄ + ÄÄÄÄÄÄÄÄ +    >        ÄÄÄÄÄÄÄÄÄÄÄÄÄ
            6          6      ÄÄÙ                7
     (x - 2)    (x + 1)      2           (x - %A)
                           %A  - 1= 0
Type: FullPartialFractionExpansion(Fraction Integer,UnivariatePolynomial(x,Fraction Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPageEmpty5}
\begin{paste}{FullPartialFractionExpansionXmpPageEmpty5}{FullPartialFractionExpansionXmpPagePatch5}
\pastebutton{FullPartialFractionExpansionXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{g5 := D(g, 5)\free{g }\bound{g5 }}
\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPagePatch6}
\begin{paste}{FullPartialFractionExpansionXmpPageFull6}{FullPartialFractionExpansionXmpPageEmpty6}
\pastebutton{FullPartialFractionExpansionXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{f5 := D(f, 5)\free{f }\bound{f5 }}
\indentrel{3}\begin{verbatim}
   (6)
                10           9            8            7
       - 544320x   + 4354560x  - 14696640x  + 28615680x
     + 
                  6            5            4            3
       - 40085280x  + 46656000x  - 39411360x  + 18247680x
     + 
                 2
       - 5870880x  + 3317760x + 246240
  /
        20      19      18      17       16       15
       x   - 12x   + 53x   - 76x   - 159x   + 676x
     + 
             14        13        12        11        10
       - 391x   - 1596x   + 2527x   + 1148x   - 4977x
     + 
            9        8        7        6        5       4
       1372x  + 4907x  - 3444x  - 2381x  + 2924x  + 276x
     + 
              3       2
       - 1184x  + 208x  + 192x - 64
Type: Fraction UnivariatePolynomial(x,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPageEmpty6}
\begin{paste}{FullPartialFractionExpansionXmpPageEmpty6}{FullPartialFractionExpansionXmpPagePatch6}
\pastebutton{FullPartialFractionExpansionXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{f5 := D(f, 5)\free{f }\bound{f5 }}
\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPagePatch7}
\begin{paste}{FullPartialFractionExpansionXmpPageFull7}{FullPartialFractionExpansionXmpPageEmpty7}
\pastebutton{FullPartialFractionExpansionXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{g5::Fx - f5\free{Fx g5 f5 }}
\indentrel{3}\begin{verbatim}
   (7)  0
Type: Fraction UnivariatePolynomial(x,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPageEmpty7}
\begin{paste}{FullPartialFractionExpansionXmpPageEmpty7}{FullPartialFractionExpansionXmpPagePatch7}
\pastebutton{FullPartialFractionExpansionXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{g5::Fx - f5\free{Fx g5 f5 }}
\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPagePatch8}
\begin{paste}{FullPartialFractionExpansionXmpPageFull8}{FullPartialFractionExpansionXmpPageEmpty8}
\pastebutton{FullPartialFractionExpansionXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{f : Fx := (x**5 * (x-1)) / ((x**2 + x + 1)**2 * (x-2)**3)\free{Fx }\bound{f2 }}
\indentrel{3}\begin{verbatim}
                       6    5
                      x  - x
   (8)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
         7     6     5     3     2
        x  - 4x  + 3x  + 9x  - 6x  - 4x - 8
Type: Fraction UnivariatePolynomial(x,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPageEmpty8}
\begin{paste}{FullPartialFractionExpansionXmpPageEmpty8}{FullPartialFractionExpansionXmpPagePatch8}
\pastebutton{FullPartialFractionExpansionXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{f : Fx := (x**5 * (x-1)) / ((x**2 + x + 1)**2 * (x-2)**3)\free{Fx }\bound{f2 }}
\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPagePatch9}
\begin{paste}{FullPartialFractionExpansionXmpPageFull9}{FullPartialFractionExpansionXmpPageEmpty9}
\pastebutton{FullPartialFractionExpansionXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{g := fullPartialFraction f\free{f2 }\bound{g2 }}
\indentrel{3}\begin{verbatim}
   (9)
      1952       464        32
      ÄÄÄÄ       ÄÄÄ        ÄÄ
      2401       343        49
     ÄÄÄÄÄÄ + ÄÄÄÄÄÄÄÄ + ÄÄÄÄÄÄÄÄ
      x - 2          2          3
              (x - 2)    (x - 2)
   + 
                         179       135
                      - ÄÄÄÄ %A + ÄÄÄÄ
           ÄÄ¿          2401      2401
           >          ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
           ÄÄÙ             x - %A
       2
     %A  + %A + 1= 0
   + 
                       37        20
                      ÄÄÄÄ %A + ÄÄÄÄ
           ÄÄ¿        1029      1029
           >          ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
           ÄÄÙ                   2
       2                 (x - %A)
     %A  + %A + 1= 0
Type: FullPartialFractionExpansion(Fraction Integer,UnivariatePolynomial(x,Fraction Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPageEmpty9}
\begin{paste}{FullPartialFractionExpansionXmpPageEmpty9}{FullPartialFractionExpansionXmpPagePatch9}
\pastebutton{FullPartialFractionExpansionXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{g := fullPartialFraction f\free{f2 }\bound{g2 }}
\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPagePatch10}
\begin{paste}{FullPartialFractionExpansionXmpPageFull10}{FullPartialFractionExpansionXmpPageEmpty10}
\pastebutton{FullPartialFractionExpansionXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{g :: Fx - f\free{f2 g2 Fx }}
\indentrel{3}\begin{verbatim}
   (10)  0
Type: Fraction UnivariatePolynomial(x,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPageEmpty10}
\begin{paste}{FullPartialFractionExpansionXmpPageEmpty10}{FullPartialFractionExpansionXmpPagePatch10}
\pastebutton{FullPartialFractionExpansionXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{g :: Fx - f\free{f2 g2 Fx }}
\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPagePatch11}
\begin{paste}{FullPartialFractionExpansionXmpPageFull11}{FullPartialFractionExpansionXmpPageEmpty11}
\pastebutton{FullPartialFractionExpansionXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{f : Fx := (2*x**7-7*x**5+26*x**3+8*x) / (x**8-5*x**6+6*x**4+4*x**2-8)\free{Fx }\bound{f3 }}
\indentrel{3}\begin{verbatim}
             7     5      3
           2x  - 7x  + 26x  + 8x
   (11)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
          8     6     4     2
         x  - 5x  + 6x  + 4x  - 8
Type: Fraction UnivariatePolynomial(x,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPageEmpty11}
\begin{paste}{FullPartialFractionExpansionXmpPageEmpty11}{FullPartialFractionExpansionXmpPagePatch11}
\pastebutton{FullPartialFractionExpansionXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{f : Fx := (2*x**7-7*x**5+26*x**3+8*x) / (x**8-5*x**6+6*x**4+4*x**2-8)\free{Fx }\bound{f3 }}
\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPagePatch12}
\begin{paste}{FullPartialFractionExpansionXmpPageFull12}{FullPartialFractionExpansionXmpPageEmpty12}
\pastebutton{FullPartialFractionExpansionXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{g := fullPartialFraction f\free{f3 }\bound{g3 }}
\indentrel{3}\begin{verbatim}
   (12)
                    1
                    Ä
        ÄÄ¿         2        ÄÄ¿          1
        >        ÄÄÄÄÄÄ +    >        ÄÄÄÄÄÄÄÄÄ
        ÄÄÙ      x - %A      ÄÄÙ              3
       2                    2         (x - %A)
     %A  - 2= 0           %A  - 2= 0
   + 
                    1
                    Ä
        ÄÄ¿         2
        >        ÄÄÄÄÄÄ
        ÄÄÙ      x - %A
       2
     %A  + 1= 0
Type: FullPartialFractionExpansion(Fraction Integer,UnivariatePolynomial(x,Fraction Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPageEmpty12}
\begin{paste}{FullPartialFractionExpansionXmpPageEmpty12}{FullPartialFractionExpansionXmpPagePatch12}
\pastebutton{FullPartialFractionExpansionXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{g := fullPartialFraction f\free{f3 }\bound{g3 }}
\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPagePatch13}
\begin{paste}{FullPartialFractionExpansionXmpPageFull13}{FullPartialFractionExpansionXmpPageEmpty13}
\pastebutton{FullPartialFractionExpansionXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{g :: Fx - f\free{f3 g3 Fx }}
\indentrel{3}\begin{verbatim}
   (13)  0
Type: Fraction UnivariatePolynomial(x,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPageEmpty13}
\begin{paste}{FullPartialFractionExpansionXmpPageEmpty13}{FullPartialFractionExpansionXmpPagePatch13}
\pastebutton{FullPartialFractionExpansionXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{g :: Fx - f\free{f3 g3 Fx }}
\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPagePatch14}
\begin{paste}{FullPartialFractionExpansionXmpPageFull14}{FullPartialFractionExpansionXmpPageEmpty14}
\pastebutton{FullPartialFractionExpansionXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{f:Fx := x**3 / (x**21 + 2*x**20 + 4*x**19 + 7*x**18 + 10*x**17 + 17*x**16 + 22*x**15 + 30*x**14 + 36*x**13 + 40*x**12 + 47*x**11 + 46*x**10 + 49*x**9 + 43*x**8 + 38*x**7 + 32*x**6 + 23*x**5 + 19*x**4 + 10*x**3 + 7*x**2 + 2*x + 1)\free{Fx }\bound{f4 }}
\indentrel{3}\begin{verbatim}
   (14)
      3
     x
  /
        21     20     19     18      17      16      15
       x   + 2x   + 4x   + 7x   + 10x   + 17x   + 22x
     + 
          14      13      12      11      10      9      8
       30x   + 36x   + 40x   + 47x   + 46x   + 49x  + 43x
     + 
          7      6      5      4      3     2
       38x  + 32x  + 23x  + 19x  + 10x  + 7x  + 2x + 1
Type: Fraction UnivariatePolynomial(x,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPageEmpty14}
\begin{paste}{FullPartialFractionExpansionXmpPageEmpty14}{FullPartialFractionExpansionXmpPagePatch14}
\pastebutton{FullPartialFractionExpansionXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{f:Fx := x**3 / (x**21 + 2*x**20 + 4*x**19 + 7*x**18 + 10*x**17 + 17*x**16 + 22*x**15 + 30*x**14 + 36*x**13 + 40*x**12 + 47*x**11 + 46*x**10 + 49*x**9 + 43*x**8 + 38*x**7 + 32*x**6 + 23*x**5 + 19*x**4 + 10*x**3 + 7*x**2 + 2*x + 1)\free{Fx }\bound{f4 }}
\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPagePatch15}
\begin{paste}{FullPartialFractionExpansionXmpPageFull15}{FullPartialFractionExpansionXmpPageEmpty15}
\pastebutton{FullPartialFractionExpansionXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{g := fullPartialFraction f\free{f4 }\bound{g4 }}
\indentrel{3}\begin{verbatim}
   (15)
                  1                        1      19
                  Ä %A                     Ä %A - ÄÄ
        ÄÄ¿       2             ÄÄ¿        9      27
        >        ÄÄÄÄÄÄ +       >          ÄÄÄÄÄÄÄÄÄ
        ÄÄÙ      x - %A         ÄÄÙ          x - %A
       2                    2
     %A  + 1= 0           %A  + %A + 1= 0
   + 
                       1       1
                      ÄÄ %A - ÄÄ
           ÄÄ¿        27      27
           >          ÄÄÄÄÄÄÄÄÄÄ
           ÄÄÙ                 2
       2               (x - %A)
     %A  + %A + 1= 0
   + 
     SIGMA
          5     2
        %A  + %A  + 1= 0
    ,
               96556567040   4   420961732891   3
            - ÄÄÄÄÄÄÄÄÄÄÄÄ %A  + ÄÄÄÄÄÄÄÄÄÄÄÄ %A
              912390759099       912390759099
          + 
               59101056149   2   373545875923
            - ÄÄÄÄÄÄÄÄÄÄÄÄ %A  - ÄÄÄÄÄÄÄÄÄÄÄÄ %A
              912390759099       912390759099
          + 
            529673492498
            ÄÄÄÄÄÄÄÄÄÄÄÄ
            912390759099
       /
          x - %A
   + 
     SIGMA
          5     2
        %A  + %A  + 1= 0
    ,
               5580868   4    2024443   3    4321919   2
            - ÄÄÄÄÄÄÄÄ %A  - ÄÄÄÄÄÄÄÄ %A  + ÄÄÄÄÄÄÄÄ %A
              94070601       94070601       94070601
          + 
               84614        5070620
            - ÄÄÄÄÄÄÄ %A - ÄÄÄÄÄÄÄÄ
              1542141      94070601
       /
                  2
          (x - %A)
   + 
     SIGMA
          5     2
        %A  + %A  + 1= 0
    ,
             1610957   4    2763014   3    2016775   2
            ÄÄÄÄÄÄÄÄ %A  + ÄÄÄÄÄÄÄÄ %A  - ÄÄÄÄÄÄÄÄ %A
            94070601       94070601       94070601
          + 
             266953        4529359
            ÄÄÄÄÄÄÄÄ %A + ÄÄÄÄÄÄÄÄ
            94070601      94070601
       /
                  3
          (x - %A)
Type: FullPartialFractionExpansion(Fraction Integer,UnivariatePolynomial(x,Fraction Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPageEmpty15}
\begin{paste}{FullPartialFractionExpansionXmpPageEmpty15}{FullPartialFractionExpansionXmpPagePatch15}
\pastebutton{FullPartialFractionExpansionXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{g := fullPartialFraction f\free{f4 }\bound{g4 }}
\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPagePatch16}
\begin{paste}{FullPartialFractionExpansionXmpPageFull16}{FullPartialFractionExpansionXmpPageEmpty16}
\pastebutton{FullPartialFractionExpansionXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{g :: Fx - f\free{f4 g4 Fx }}
\indentrel{3}\begin{verbatim}
   (16)  0
Type: Fraction UnivariatePolynomial(x,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FullPartialFractionExpansionXmpPageEmpty16}
\begin{paste}{FullPartialFractionExpansionXmpPageEmpty16}{FullPartialFractionExpansionXmpPagePatch16}
\pastebutton{FullPartialFractionExpansionXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{g :: Fx - f\free{f4 g4 Fx }}
\end{paste}\end{patch}

\end{chunk}
\section{function.ht}
\pagetitle{FunctionPage}{function.ht}{Functions in Axiom}
\pagepic{ps/v71functionpage.eps}{functionpage}{0.50}
\pagefrom{Topics}{TopicPage}
\pageto{Rational Functions}{RationalFunctionPage}
\pageto{Algebraic Functions}{AlgebraicFunctionPage}
\pageto{Elementary Functions}{ElementaryFunctionPage}
\pageto{Simplification}{FunctionSimplificationPage}
\pageto{Pattern Matching}{ugUserRulesPage}
\pageto{Operator Algebra}{OperatorXmpPage}
\begin{chunk}{function.ht}
\begin{page}{FunctionPage}{Functions in Axiom}
%
In Axiom, a function is an expression in one or more variables.
(Think of it as a function of those variables).
You can also define a function by rules or use a built-in function
Axiom lets you convert expressions to compiled functions.
\beginscroll
\beginmenu
\menulink{Rational Functions}{RationalFunctionPage} \tab{22}
Quotients of polynomials.

\menulink{Algebraic Functions}{AlgebraicFunctionPage} \tab{22}
Those defined by polynomial equations.

\menulink{Elementary Functions}{ElementaryFunctionPage} \tab{22}
The elementary functions of calculus.

\menulink{Simplification}{FunctionSimplificationPage} \tab{22}
How to simplify expressions.

\menulink{Pattern Matching}{ugUserRulesPage} \tab{22}
How to use the pattern matcher.
\endmenu
\endscroll
\newline
Additional Topics:
\beginmenu

\menulink{Operator Algebra}{OperatorXmpPage}\tab{22}
The operator algebra facility.

\endmenu
\autobuttons \end{page}

\end{chunk}
\pagetitle{RationalFunctionPage}{function.ht}{Rational Functions}
\begin{chunk}{function.ht}
\begin{page}{RationalFunctionPage}{Rational Functions}
\beginscroll
To create a rational function, just compute the
quotient of two polynomials:
\spadpaste{f := (x - y) / (x + y)\bound{f}}
Use the functions \spadfun{numer} and \spadfun{denom}:
to recover the numerator and denominator of a fraction:
%
\spadpaste{numer f\free{f}}
\spadpaste{denom f\free{f}}
%
Since these are polynomials, you can apply all the
\downlink{polynomial operations}{PolynomialPage}
to them.
You can substitute values or
other rational functions for the variables using
the function \spadfun{eval}. The syntax for \spadfun{eval} is
similar to the one for polynomials:
\spadpaste{eval(f, x = 1/x)\free{f}}
\spadpaste{eval(f, [x = y, y = x])\free{f}}
\endscroll
\autobuttons
\end{page}

\begin{patch}{RationatFunctionPagePatch1}
\begin{paste}{RationatFunctionPageFull1}{RationatFunctionPageEmpty1}
\pastebutton{RationatFunctionPageFull1}{\hidepaste}
\tab{5}\spadcommand{f := (x - y) / (x + y)\bound{f }}
\indentrel{3}\begin{verbatim}
        - y + x
   (1)  ÄÄÄÄÄÄÄ
         y + x
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RationatFunctionPageEmpty1}
\begin{paste}{RationatFunctionPageEmpty1}{RationatFunctionPagePatch1}
\pastebutton{RationatFunctionPageEmpty1}{\showpaste}
\tab{5}\spadcommand{f := (x - y) / (x + y)\bound{f }}
\end{paste}\end{patch}

\begin{patch}{RationatFunctionPagePatch2}
\begin{paste}{RationatFunctionPageFull2}{RationatFunctionPageEmpty2}
\pastebutton{RationatFunctionPageFull2}{\hidepaste}
\tab{5}\spadcommand{numer f\free{f }}
\indentrel{3}\begin{verbatim}
   (2)  - y + x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RationatFunctionPageEmpty2}
\begin{paste}{RationatFunctionPageEmpty2}{RationatFunctionPagePatch2}
\pastebutton{RationatFunctionPageEmpty2}{\showpaste}
\tab{5}\spadcommand{numer f\free{f }}
\end{paste}\end{patch}

\begin{patch}{RationatFunctionPagePatch3}
\begin{paste}{RationatFunctionPageFull3}{RationatFunctionPageEmpty3}
\pastebutton{RationatFunctionPageFull3}{\hidepaste}
\tab{5}\spadcommand{denom f\free{f }}
\indentrel{3}\begin{verbatim}
   (3)  y + x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RationatFunctionPageEmpty3}
\begin{paste}{RationatFunctionPageEmpty3}{RationatFunctionPagePatch3}
\pastebutton{RationatFunctionPageEmpty3}{\showpaste}
\tab{5}\spadcommand{denom f\free{f }}
\end{paste}\end{patch}

\begin{patch}{RationatFunctionPagePatch4}
\begin{paste}{RationatFunctionPageFull4}{RationatFunctionPageEmpty4}
\pastebutton{RationatFunctionPageFull4}{\hidepaste}
\tab{5}\spadcommand{eval(f, x = 1/x)\free{f }}
\indentrel{3}\begin{verbatim}
        - x y + 1
   (4)  ÄÄÄÄÄÄÄÄÄ
         x y + 1
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RationatFunctionPageEmpty4}
\begin{paste}{RationatFunctionPageEmpty4}{RationatFunctionPagePatch4}
\pastebutton{RationatFunctionPageEmpty4}{\showpaste}
\tab{5}\spadcommand{eval(f, x = 1/x)\free{f }}
\end{paste}\end{patch}

\begin{patch}{RationatFunctionPagePatch5}
\begin{paste}{RationatFunctionPageFull5}{RationatFunctionPageEmpty5}
\pastebutton{RationatFunctionPageFull5}{\hidepaste}
\tab{5}\spadcommand{eval(f, [x = y, y = x])\free{f }}
\indentrel{3}\begin{verbatim}
        y - x
   (5)  ÄÄÄÄÄ
        y + x
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RationatFunctionPageEmpty5}
\begin{paste}{RationatFunctionPageEmpty5}{RationatFunctionPagePatch5}
\pastebutton{RationatFunctionPageEmpty5}{\showpaste}
\tab{5}\spadcommand{eval(f, [x = y, y = x])\free{f }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{AlgebraicFunctionPage}{function.ht}{Algebraic Functions}
\begin{chunk}{function.ht}
\begin{page}{AlgebraicFunctionPage}{Algebraic Functions}
\beginscroll
Algebraic functions are functions defined by algebraic equations. There
are two ways of constructing them: using rational powers, or implicitly.
For rational powers, use \spadopFrom{**}{RadicalCategory}
(or the system functions \spadfun{sqrt} and
\spadfun{nthRoot} for square and nth roots):
\spadpaste{f := sqrt(1 + x ** (1/3))\bound{f}}
To define an algebraic function implicitly
use \spadfun{rootOf}. The following
line defines a function \spad{y} of \spad{x} satisfying the equation
\spad{y**3 = x*y - y**2 - x**3 + 1}:
\spadpaste{y := rootOf(y**3 + y**2 - x*y + x**3 - 1, y)\bound{y}}
You can manipulate, differentiate or integrate an implicitly defined
algebraic function like any other Axiom function:
\spadpaste{differentiate(y, x)\free{y}}
Higher powers of algebraic functions are automatically reduced during
calculations:
\spadpaste{(y + 1) ** 3\free{y}}
But denominators, are not automatically rationalized:
\spadpaste{g := inv f\bound{g}\free{y}}
Use \spadfun{ratDenom} to remove the algebraic quantities 
from the denominator:
\spadpaste{ratDenom g\free{g}}
\endscroll
\autobuttons 
\end{page}

\begin{patch}{AlgebraicFunctionPagePatch1}
\begin{paste}{AlgebraicFunctionPageFull1}{AlgebraicFunctionPageEmpty1}
\pastebutton{AlgebraicFunctionPageFull1}{\hidepaste}
\tab{5}\spadcommand{f := sqrt(1 + x ** (1/3))\bound{f }}
\indentrel{3}\begin{verbatim}
         ÚÄÄÄÄÄÄÄÄ¿
         ³3ÚÄ¿
   (1)  \³\³x  + 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{AlgebraicFunctionPageEmpty1}
\begin{paste}{AlgebraicFunctionPageEmpty1}{AlgebraicFunctionPagePatch1}
\pastebutton{AlgebraicFunctionPageEmpty1}{\showpaste}
\tab{5}\spadcommand{f := sqrt(1 + x ** (1/3))\bound{f }}
\end{paste}\end{patch}

\begin{patch}{AlgebraicFunctionPagePatch2}
\begin{paste}{AlgebraicFunctionPageFull2}{AlgebraicFunctionPageEmpty2}
\pastebutton{AlgebraicFunctionPageFull2}{\hidepaste}
\tab{5}\spadcommand{y := rootOf(y**3 + y**2 - x*y + x**3 - 1, y)\bound{y }}
\indentrel{3}\begin{verbatim}
   (2)  y
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{AlgebraicFunctionPageEmpty2}
\begin{paste}{AlgebraicFunctionPageEmpty2}{AlgebraicFunctionPagePatch2}
\pastebutton{AlgebraicFunctionPageEmpty2}{\showpaste}
\tab{5}\spadcommand{y := rootOf(y**3 + y**2 - x*y + x**3 - 1, y)\bound{y }}
\end{paste}\end{patch}

\begin{patch}{AlgebraicFunctionPagePatch3}
\begin{paste}{AlgebraicFunctionPageFull3}{AlgebraicFunctionPageEmpty3}
\pastebutton{AlgebraicFunctionPageFull3}{\hidepaste}
\tab{5}\spadcommand{differentiate(y, x)\free{y }}
\indentrel{3}\begin{verbatim}
                 2
           y - 3x
   (3)  ÄÄÄÄÄÄÄÄÄÄÄÄ
          2
        3y  + 2y - x
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{AlgebraicFunctionPageEmpty3}
\begin{paste}{AlgebraicFunctionPageEmpty3}{AlgebraicFunctionPagePatch3}
\pastebutton{AlgebraicFunctionPageEmpty3}{\showpaste}
\tab{5}\spadcommand{differentiate(y, x)\free{y }}
\end{paste}\end{patch}

\begin{patch}{AlgebraicFunctionPagePatch4}
\begin{paste}{AlgebraicFunctionPageFull4}{AlgebraicFunctionPageEmpty4}
\pastebutton{AlgebraicFunctionPageFull4}{\hidepaste}
\tab{5}\spadcommand{(y + 1) ** 3\free{y }}
\indentrel{3}\begin{verbatim}
          2               3
   (4)  2y  + (x + 3)y - x  + 2
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{AlgebraicFunctionPageEmpty4}
\begin{paste}{AlgebraicFunctionPageEmpty4}{AlgebraicFunctionPagePatch4}
\pastebutton{AlgebraicFunctionPageEmpty4}{\showpaste}
\tab{5}\spadcommand{(y + 1) ** 3\free{y }}
\end{paste}\end{patch}

\begin{patch}{AlgebraicFunctionPagePatch5}
\begin{paste}{AlgebraicFunctionPageFull5}{AlgebraicFunctionPageEmpty5}
\pastebutton{AlgebraicFunctionPageFull5}{\hidepaste}
\tab{5}\spadcommand{g := inv f\bound{g }\free{y }}
\indentrel{3}\begin{verbatim}
             1
   (5)  ÄÄÄÄÄÄÄÄÄÄÄ
         ÚÄÄÄÄÄÄÄÄ¿
         ³3ÚÄ¿
        \³\³x  + 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{AlgebraicFunctionPageEmpty5}
\begin{paste}{AlgebraicFunctionPageEmpty5}{AlgebraicFunctionPagePatch5}
\pastebutton{AlgebraicFunctionPageEmpty5}{\showpaste}
\tab{5}\spadcommand{g := inv f\bound{g }\free{y }}
\end{paste}\end{patch}

\begin{patch}{AlgebraicFunctionPagePatch6}
\begin{paste}{AlgebraicFunctionPageFull6}{AlgebraicFunctionPageEmpty6}
\pastebutton{AlgebraicFunctionPageFull6}{\hidepaste}
\tab{5}\spadcommand{ratDenom g\free{g }}
\indentrel{3}\begin{verbatim}
                           ÚÄÄÄÄÄÄÄÄ¿
         3ÚÄ¿2   3ÚÄ¿      ³3ÚÄ¿
        (\³x   - \³x  + 1)\³\³x  + 1
   (6)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                    x + 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{AlgebraicFunctionPageEmpty6}
\begin{paste}{AlgebraicFunctionPageEmpty6}{AlgebraicFunctionPagePatch6}
\pastebutton{AlgebraicFunctionPageEmpty6}{\showpaste}
\tab{5}\spadcommand{ratDenom g\free{g }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ElementaryFunctionPage}{function.ht}{Elementary Functions}
\begin{chunk}{function.ht}
\begin{page}{ElementaryFunctionPage}{Elementary Functions}
\beginscroll
Axiom has most of the usual functions from calculus built-in:
\spadpaste{f := x * log y * sin(1/(x+y))\bound{f}}
You can substitute values or another elementary functions for 
the variables with the function \spadfun{eval}:
\spadpaste{eval(f, [x = y, y = x])\free{f}}
As you can see, the substitutions are made 'in parallel' as in the 
case of polynomials. It's also possible to substitute expressions 
for kernels instead of variables:
\spadpaste{eval(f, log y = acosh(x + sqrt y))\free{f}}
\endscroll
\autobuttons 
\end{page}

\begin{patch}{ElementaryFunctionPagePatch1}
\begin{paste}{ElementaryFunctionPageFull1}{ElementaryFunctionPageEmpty1}
\pastebutton{ElementaryFunctionPageFull1}{\hidepaste}
\tab{5}\spadcommand{f := x * log y * sin(1/(x+y))\bound{f }}
\indentrel{3}\begin{verbatim}
                      1
   (1)  x log(y)sin(ÄÄÄÄÄ)
                    y + x
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ElementaryFunctionPageEmpty1}
\begin{paste}{ElementaryFunctionPageEmpty1}{ElementaryFunctionPagePatch1}
\pastebutton{ElementaryFunctionPageEmpty1}{\showpaste}
\tab{5}\spadcommand{f := x * log y * sin(1/(x+y))\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ElementaryFunctionPagePatch2}
\begin{paste}{ElementaryFunctionPageFull2}{ElementaryFunctionPageEmpty2}
\pastebutton{ElementaryFunctionPageFull2}{\hidepaste}
\tab{5}\spadcommand{eval(f, [x = y, y = x])\free{f }}
\indentrel{3}\begin{verbatim}
                      1
   (2)  y log(x)sin(ÄÄÄÄÄ)
                    y + x
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ElementaryFunctionPageEmpty2}
\begin{paste}{ElementaryFunctionPageEmpty2}{ElementaryFunctionPagePatch2}
\pastebutton{ElementaryFunctionPageEmpty2}{\showpaste}
\tab{5}\spadcommand{eval(f, [x = y, y = x])\free{f }}
\end{paste}\end{patch}

\begin{patch}{ElementaryFunctionPagePatch3}
\begin{paste}{ElementaryFunctionPageFull3}{ElementaryFunctionPageEmpty3}
\pastebutton{ElementaryFunctionPageFull3}{\hidepaste}
\tab{5}\spadcommand{eval(f, log y = acosh(x + sqrt y))\free{f }}
\indentrel{3}\begin{verbatim}
                1          ÚÄ¿
   (3)  x sin(ÄÄÄÄÄ)acosh(\³y  + x)
              y + x
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ElementaryFunctionPageEmpty3}
\begin{paste}{ElementaryFunctionPageEmpty3}{ElementaryFunctionPagePatch3}
\pastebutton{ElementaryFunctionPageEmpty3}{\showpaste}
\tab{5}\spadcommand{eval(f, log y = acosh(x + sqrt y))\free{f }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{FunctionSimplificationPage}{function.ht}{Simplification}
\pageto{notitle}{ugUserRulesPage}
\begin{chunk}{function.ht}
\begin{page}{FunctionSimplificationPage}{Simplification}
\beginscroll
Simplifying an expression often means different things at
different times, so Axiom offers a large number of
`simplification' functions.
The most common one, which performs the usual trigonometric
simplifications is \spadfun{simplify}:
\spadpaste{f := cos(x)/sec(x) * log(sin(x)**2/(cos(x)**2+sin(x)**2)) 
\bound{f}}
\spadpaste{g := simplify f\bound{g}\free{f}}
If the result of \spadfun{simplify} is not satisfactory, specific
transformations are available.
For example, to rewrite \spad{g} in terms of secants and
cosecants instead of sines and cosines, issue:
%
\spadpaste{h := sin2csc cos2sec g\bound{h}\free{g}}
%
To apply the logarithm simplification rules to \spad{h}, issue:
\spadpaste{expandLog h\free{h}}
Since the square root of \spad{x**2} is the absolute value of
\spad{x} and not \spad{x} itself, algebraic radicals are not
automatically simplified, but you can specifically request it by
calling \spadfun{rootSimp}:
%
\spadpaste{f1 := sqrt((x+1)**3)\bound{f1}}
\spadpaste{rootSimp f1\free{f1}}
%
There are other transformations which are sometimes useful.
Use the functions \spadfun{complexElementary} and \spadfun{trigs}
to go back and forth between the complex exponential and
trigonometric forms of an elementary function:
%
\spadpaste{g1 := sin(x + cos x)\bound{g1}}
\spadpaste{g2 := complexElementary g1\bound{g2}\free{g1}}
\spadpaste{trigs g2\free{g2}}
%
Similarly, the functions \spadfun{realElementary} and
\spadfun{htrigs} convert hyperbolic functions in and out of their
exponential form:
%
\spadpaste{h1 := sinh(x + cosh x)\bound{h1}}
\spadpaste{h2 := realElementary h1\bound{h2}\free{h1}}
\spadpaste{htrigs h2\free{h2}}
%
Axiom has other transformations, most of which
are in the packages
\spadtype{ElementaryFunctionStructurePackage},
\spadtype{TrigonometricManipulations},
\spadtype{AlgebraicManipulations},
and \spadtype{TranscendentalManipulations}.
If you need to apply a simplification rule not built into the
system, you can use Axiom's \downlink{pattern
matcher}{ugUserRulesPage}.
\endscroll
\autobuttons
\end{page}

\begin{patch}{FunctionSimplificationPagePatch1}
\begin{paste}{FunctionSimplificationPageFull1}{FunctionSimplificationPageEmpty1}
\pastebutton{FunctionSimplificationPageFull1}{\hidepaste}
\tab{5}\spadcommand{f := cos(x)/sec(x) * log(sin(x)**2/(cos(x)**2+sin(x)**2))\bound{f }}
\indentrel{3}\begin{verbatim}
                             2
                       sin(x)
        cos(x)log(ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ)
                        2         2
                  sin(x)  + cos(x)
   (1)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                   sec(x)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPageEmpty1}
\begin{paste}{FunctionSimplificationPageEmpty1}{FunctionSimplificationPagePatch1}
\pastebutton{FunctionSimplificationPageEmpty1}{\showpaste}
\tab{5}\spadcommand{f := cos(x)/sec(x) * log(sin(x)**2/(cos(x)**2+sin(x)**2))\bound{f }}
\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPagePatch2}
\begin{paste}{FunctionSimplificationPageFull2}{FunctionSimplificationPageEmpty2}
\pastebutton{FunctionSimplificationPageFull2}{\hidepaste}
\tab{5}\spadcommand{g := simplify f\bound{g }\free{f }}
\indentrel{3}\begin{verbatim}
              2            2
   (2)  cos(x) log(- cos(x)  + 1)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPageEmpty2}
\begin{paste}{FunctionSimplificationPageEmpty2}{FunctionSimplificationPagePatch2}
\pastebutton{FunctionSimplificationPageEmpty2}{\showpaste}
\tab{5}\spadcommand{g := simplify f\bound{g }\free{f }}
\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPagePatch3}
\begin{paste}{FunctionSimplificationPageFull3}{FunctionSimplificationPageEmpty3}
\pastebutton{FunctionSimplificationPageFull3}{\hidepaste}
\tab{5}\spadcommand{h := sin2csc cos2sec g\bound{h }\free{g }}
\indentrel{3}\begin{verbatim}
                  2
            sec(x)  - 1
        log(ÄÄÄÄÄÄÄÄÄÄÄ)
                    2
              sec(x)
   (3)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                   2
             sec(x)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPageEmpty3}
\begin{paste}{FunctionSimplificationPageEmpty3}{FunctionSimplificationPagePatch3}
\pastebutton{FunctionSimplificationPageEmpty3}{\showpaste}
\tab{5}\spadcommand{h := sin2csc cos2sec g\bound{h }\free{g }}
\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPagePatch4}
\begin{paste}{FunctionSimplificationPageFull4}{FunctionSimplificationPageEmpty4}
\pastebutton{FunctionSimplificationPageFull4}{\hidepaste}
\tab{5}\spadcommand{expandLog h\free{h }}
\indentrel{3}\begin{verbatim}
                  2
        log(sec(x)  - 1) - 2log(sec(x))
   (4)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                          2
                    sec(x)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPageEmpty4}
\begin{paste}{FunctionSimplificationPageEmpty4}{FunctionSimplificationPagePatch4}
\pastebutton{FunctionSimplificationPageEmpty4}{\showpaste}
\tab{5}\spadcommand{expandLog h\free{h }}
\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPagePatch5}
\begin{paste}{FunctionSimplificationPageFull5}{FunctionSimplificationPageEmpty5}
\pastebutton{FunctionSimplificationPageFull5}{\hidepaste}
\tab{5}\spadcommand{f1 := sqrt((x+1)**3)\bound{f1 }}
\indentrel{3}\begin{verbatim}
         ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
         ³ 3     2
   (5)  \³x  + 3x  + 3x + 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPageEmpty5}
\begin{paste}{FunctionSimplificationPageEmpty5}{FunctionSimplificationPagePatch5}
\pastebutton{FunctionSimplificationPageEmpty5}{\showpaste}
\tab{5}\spadcommand{f1 := sqrt((x+1)**3)\bound{f1 }}
\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPagePatch6}
\begin{paste}{FunctionSimplificationPageFull6}{FunctionSimplificationPageEmpty6}
\pastebutton{FunctionSimplificationPageFull6}{\hidepaste}
\tab{5}\spadcommand{rootSimp f1\free{f1 }}
\indentrel{3}\begin{verbatim}
                ÚÄÄÄÄÄ¿
   (6)  (x + 1)\³x + 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPageEmpty6}
\begin{paste}{FunctionSimplificationPageEmpty6}{FunctionSimplificationPagePatch6}
\pastebutton{FunctionSimplificationPageEmpty6}{\showpaste}
\tab{5}\spadcommand{rootSimp f1\free{f1 }}
\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPagePatch7}
\begin{paste}{FunctionSimplificationPageFull7}{FunctionSimplificationPageEmpty7}
\pastebutton{FunctionSimplificationPageFull7}{\hidepaste}
\tab{5}\spadcommand{g1 := sin(x + cos x)\bound{g1 }}
\indentrel{3}\begin{verbatim}
   (7)  sin(cos(x) + x)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPageEmpty7}
\begin{paste}{FunctionSimplificationPageEmpty7}{FunctionSimplificationPagePatch7}
\pastebutton{FunctionSimplificationPageEmpty7}{\showpaste}
\tab{5}\spadcommand{g1 := sin(x + cos x)\bound{g1 }}
\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPagePatch8}
\begin{paste}{FunctionSimplificationPageFull8}{FunctionSimplificationPageEmpty8}
\pastebutton{FunctionSimplificationPageFull8}{\hidepaste}
\tab{5}\spadcommand{g2 := complexElementary g1\bound{g2 }\free{g1 }}
\indentrel{3}\begin{verbatim}
   (8)
       -
             ÚÄÄÄ¿
            \³- 1
         *
                %e
             **
                               ÚÄÄÄ¿ 2               ÚÄÄÄ¿
                     ÚÄÄÄ¿   x\³- 1         ÚÄÄÄ¿  x\³- 1
                    \³- 1 (%e       )  + 2x\³- 1 %e
                  + 
                     ÚÄÄÄ¿
                    \³- 1
               /
                       ÚÄÄÄ¿
                     x\³- 1
                  2%e
           **
              2
     + 
        ÚÄÄÄ¿
       \³- 1
  /
                   ÚÄÄÄ¿ 2               ÚÄÄÄ¿
         ÚÄÄÄ¿   x\³- 1         ÚÄÄÄ¿  x\³- 1     ÚÄÄÄ¿
        \³- 1 (%e       )  + 2x\³- 1 %e        + \³- 1
        ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                                ÚÄÄÄ¿
                              x\³- 1
                           2%e
     2%e
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPageEmpty8}
\begin{paste}{FunctionSimplificationPageEmpty8}{FunctionSimplificationPagePatch8}
\pastebutton{FunctionSimplificationPageEmpty8}{\showpaste}
\tab{5}\spadcommand{g2 := complexElementary g1\bound{g2 }\free{g1 }}
\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPagePatch9}
\begin{paste}{FunctionSimplificationPageFull9}{FunctionSimplificationPageEmpty9}
\pastebutton{FunctionSimplificationPageFull9}{\hidepaste}
\tab{5}\spadcommand{trigs g2\free{g2 }}
\indentrel{3}\begin{verbatim}
   (9)  sin(cos(x) + x)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPageEmpty9}
\begin{paste}{FunctionSimplificationPageEmpty9}{FunctionSimplificationPagePatch9}
\pastebutton{FunctionSimplificationPageEmpty9}{\showpaste}
\tab{5}\spadcommand{trigs g2\free{g2 }}
\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPagePatch10}
\begin{paste}{FunctionSimplificationPageFull10}{FunctionSimplificationPageEmpty10}
\pastebutton{FunctionSimplificationPageFull10}{\hidepaste}
\tab{5}\spadcommand{h1 := sinh(x + cosh x)\bound{h1 }}
\indentrel{3}\begin{verbatim}
   (10)  sinh(cosh(x) + x)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPageEmpty10}
\begin{paste}{FunctionSimplificationPageEmpty10}{FunctionSimplificationPagePatch10}
\pastebutton{FunctionSimplificationPageEmpty10}{\showpaste}
\tab{5}\spadcommand{h1 := sinh(x + cosh x)\bound{h1 }}
\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPagePatch11}
\begin{paste}{FunctionSimplificationPageFull11}{FunctionSimplificationPageEmpty11}
\pastebutton{FunctionSimplificationPageFull11}{\hidepaste}
\tab{5}\spadcommand{h2 := realElementary h1\bound{h2 }\free{h1 }}
\indentrel{3}\begin{verbatim}
               x 2        x     2
            (%e )  + 2x %e  + 1
            ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                       x
                    2%e
         (%e                   )  - 1
   (11)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                  x 2        x
               (%e )  + 2x %e  + 1
               ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                          x
                       2%e
            2%e
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPageEmpty11}
\begin{paste}{FunctionSimplificationPageEmpty11}{FunctionSimplificationPagePatch11}
\pastebutton{FunctionSimplificationPageEmpty11}{\showpaste}
\tab{5}\spadcommand{h2 := realElementary h1\bound{h2 }\free{h1 }}
\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPagePatch12}
\begin{paste}{FunctionSimplificationPageFull12}{FunctionSimplificationPageEmpty12}
\pastebutton{FunctionSimplificationPageFull12}{\hidepaste}
\tab{5}\spadcommand{htrigs h2\free{h2 }}
\indentrel{3}\begin{verbatim}
   (12)  sinh(cosh(x) + x)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FunctionSimplificationPageEmpty12}
\begin{paste}{FunctionSimplificationPageEmpty12}{FunctionSimplificationPagePatch12}
\pastebutton{FunctionSimplificationPageEmpty12}{\showpaste}
\tab{5}\spadcommand{htrigs h2\free{h2 }}
\end{paste}
\end{patch}

\end{chunk}
\section{gbf.ht}
\pagetitle{GroebnerFactorizationPkgXmpPage}{gbf.ht}
{GroebnerFactorizationPkg}
\begin{chunk}{gbf.ht}
\begin{page}{GroebnerFactorizationPkgXmpPage}
{GroebnerFactorizationPkg}
\beginscroll
%%  J. Grabmeier 26 04 91
Solving systems of polynomial equations with the
\texht{Gr\"{o}bner}{Groebner}
basis algorithm can often be very time consuming because, in general,
the algorithm has exponential run-time.
These systems, which often come from concrete applications,
frequently have symmetries which are not taken advantage of by the
algorithm.
However, it often happens in this case
that the polynomials which occur during the
\texht{Gr\"{o}bner}{Groebner} calculations are reducible.
Since Axiom has an excellent polynomial factorization algorithm, it is
very natural to combine the
\texht{Gr\"{o}bner}{Groebner} and factorization algorithms.

\spadtype{GroebnerFactorizationPkg} exports the
\axiomFunFrom{groebnerFactorize}{GroebnerFactorizationPkg}
operation which implements a modified
\texht{Gr\"{o}bner}{Groebner} basis algorithm.
In this algorithm, each polynomial that is to be put into the
partial list of the basis is first factored.
The remaining calculation is split into as many parts as there are
irreducible factors.
Call these factors \texht{$p_1, \ldots,p_n.$}{\spad{p1, ..., pn.}}
In the branches corresponding to \texht{$p_2,
\ldots,p_n,$}{\spad{p2, ..., pn,}} the factor
\texht{$p_1$}{\spad{p1}} can be divided out, and so on.
This package also contains operations that allow you to specify the
polynomials that are not zero on the common roots of the final
\texht{Gr\"{o}bner}{Groebner} basis.

Here is an example from chemistry.
In a theoretical model of the cyclohexan 
\texht{${\rm C}_6{\rm H}_{12}$}{C6H12},
the six carbon atoms each sit in the center of gravity of a
tetrahedron that has two hydrogen atoms and two carbon atoms at its
corners.
We first normalize and set the length of each edge to 1.
Hence, the distances of one fixed carbon atom to each of its
immediate neighbours is 1.
We will denote the distances to the other three carbon atoms by
\smath{x}, \smath{y} and \smath{z}.

%% reference?
\texht{A.~Dress}{A. Dress} developed a theory to decide whether a set 
of points and distances between them can be realized in an 
\smath{n}-dimensional space. Here, of course, we have \smath{n = 3}.
\xtc{
}{
\spadpaste{mfzn : SQMATRIX(6,DMP([x,y,z],Fraction INT)) := 
[[0,1,1,1,1,1], [1,0,1,8/3,x,8/3], [1,1,0,1,8/3,y], [1,8/3,1,0,1,8/3], 
[1,x,8/3,1,0,1], [1,8/3,y,8/3,1,0]] \bound{mfzn}}
}
\xtc{
For the cyclohexan, the distances have to satisfy this equation.
}{
\spadpaste{eq := determinant mfzn \free{mfzn}\bound{eq}}
}
\xtc{
They also must satisfy the equations
given by cyclic shifts of the indeterminates.
}{
\spadpaste{groebnerFactorize [eq, eval(eq, [x,y,z], [y,z,x]), 
eval(eq, [x,y,z], [z,x,y])] \free{eq}}
}

The union of the solutions of this list is the
solution of our original problem.
If we impose positivity conditions, we get two relevant ideals.
One ideal is
zero-dimensional, namely \smath{x = y = z = 11/3}, and this
determines the ``boat'' form of the cyclohexan.
The other ideal is one-dimensional,
which means that we have a solution space given by one parameter.
This gives the ``chair'' form of the cyclohexan.
The parameter describes the angle of the ``back of the chair.''

\axiomFunFrom{groebnerFactorize}{GroebnerFactorizationPkg}
has an optional \axiomType{Boolean}-valued second argument.
When it is \spad{true} partial results are displayed, 
since it may happen that the
calculation does not terminate in a reasonable time.
See the source code for \spadtype{GroebnerFactorizationPkg}
in {\bf groebf\spadFileExt{}} for more details about the algorithms
used.
\endscroll
\autobuttons
\end{page}

\begin{patch}{GroebnerFactorizationPackageXmpPagePatch1}
\begin{paste}{GroebnerFactorizationPackageXmpPageFull1}{GroebnerFactorizationPackageXmpPageEmpty1}
\pastebutton{GroebnerFactorizationPackageXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{mfzn : SQMATRIX(6,DMP([x,y,z],Fraction INT)) := [[0,1,1,1,1,1], [1,0,1,8/3,x,8/3], [1,1,0,1,8/3,y], [1,8/3,1,0,1,8/3], [1,x,8/3,1,0,1], [1,8/3,y,8/3,1,0]]\bound{mfzn }}
\indentrel{3}\begin{verbatim}
        Ú0  1  1  1  1  1¿
        ³                ³
        ³         8     8³
        ³1  0  1  Ä  x  Ä³
        ³         3     3³
        ³                ³
        ³            8   ³
        ³1  1  0  1  Ä  y³
        ³            3   ³
        ³                ³
   (1)  ³   8           8³
        ³1  Ä  1  0  1  Ä³
        ³   3           3³
        ³                ³
        ³      8         ³
        ³1  x  Ä  1  0  1³
        ³      3         ³
        ³                ³
        ³   8     8      ³
        ³1  Ä  y  Ä  1  0³
        À   3     3      Ù
Type: SquareMatrix(6,DistributedMultivariatePolynomial([x,y,z],Fraction Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{GroebnerFactorizationPackageXmpPageEmpty1}
\begin{paste}{GroebnerFactorizationPackageXmpPageEmpty1}{GroebnerFactorizationPackageXmpPagePatch1}
\pastebutton{GroebnerFactorizationPackageXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{mfzn : SQMATRIX(6,DMP([x,y,z],Fraction INT)) := [[0,1,1,1,1,1], [1,0,1,8/3,x,8/3], [1,1,0,1,8/3,y], [1,8/3,1,0,1,8/3], [1,x,8/3,1,0,1], [1,8/3,y,8/3,1,0]]\bound{mfzn }}
\end{paste}\end{patch}

\begin{patch}{GroebnerFactorizationPackageXmpPagePatch2}
\begin{paste}{GroebnerFactorizationPackageXmpPageFull2}{GroebnerFactorizationPackageXmpPageEmpty2}
\pastebutton{GroebnerFactorizationPackageXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{eq := determinant mfzn\free{mfzn }\bound{eq }}
\indentrel{3}\begin{verbatim}
   (2)
        2 2   22  2    25  2   22    2   388       250
     - x y  + ÄÄ x y - ÄÄ x  + ÄÄ x y  - ÄÄÄ x y - ÄÄÄ x
               3        9       3         9         27
   + 
       25  2   250     14575
     - ÄÄ y  - ÄÄÄ y + ÄÄÄÄÄ
        9       27       81
Type: DistributedMultivariatePolynomial([x,y,z],Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{GroebnerFactorizationPackageXmpPageEmpty2}
\begin{paste}{GroebnerFactorizationPackageXmpPageEmpty2}{GroebnerFactorizationPackageXmpPagePatch2}
\pastebutton{GroebnerFactorizationPackageXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{eq := determinant mfzn\free{mfzn }\bound{eq }}
\end{paste}\end{patch}

\begin{patch}{GroebnerFactorizationPackageXmpPagePatch3}
\begin{paste}{GroebnerFactorizationPackageXmpPageFull3}{GroebnerFactorizationPackageXmpPageEmpty3}
\pastebutton{GroebnerFactorizationPackageXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{groebnerFactorize [eq, eval(eq, [x,y,z], [y,z,x]), eval(eq, [x,y,z], [z,x,y])]\free{eq }}
\indentrel{3}\begin{verbatim}
   (3)
   [
                  22           22     22     121
     [x y + x z - ÄÄ x + y z - ÄÄ y - ÄÄ z + ÄÄÄ,
                   3            3      3      3

            2   22       25        2   22       25
         x z  - ÄÄ x z + ÄÄ x + y z  - ÄÄ y z + ÄÄ y
                 3        9             3        9
       + 
           22  2   388     250
         - ÄÄ z  + ÄÄÄ z + ÄÄÄ
            3       9       27
       ,

          2 2   22  2    25  2   22    2   388       250
         y z  - ÄÄ y z + ÄÄ y  - ÄÄ y z  + ÄÄÄ y z + ÄÄÄ y
                 3        9       3         9         27
       + 
         25  2   250     14575
         ÄÄ z  + ÄÄÄ z - ÄÄÄÄÄ
          9       27       81
       ]
     ,
             21994  2   21994     4427     463
    [x + y - ÄÄÄÄÄ,y  - ÄÄÄÄÄ y + ÄÄÄÄ,z - ÄÄÄ],
              5625       5625      675      87
      2   1       11     5     265        2   38     265
    [x  - Ä x z - ÄÄ x - Ä z + ÄÄÄ,y - z,z  - ÄÄ z + ÄÄÄ],
          2        2     6      18             3      9
         25     11     11        11     11     11
    [x - ÄÄ,y - ÄÄ,z - ÄÄ], [x - ÄÄ,y - ÄÄ,z - ÄÄ],
          9      3      3         3      3      3
         5     5     5        19     5     5
    [x + Ä,y + Ä,z + Ä], [x - ÄÄ,y + Ä,z + Ä]]
         3     3     3         3     3     3
Type: List List DistributedMultivariatePolynomial([x,y,z],Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{GroebnerFactorizationPackageXmpPageEmpty3}
\begin{paste}{GroebnerFactorizationPackageXmpPageEmpty3}{GroebnerFactorizationPackageXmpPagePatch3}
\pastebutton{GroebnerFactorizationPackageXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{groebnerFactorize [eq, eval(eq, [x,y,z], [y,z,x]), eval(eq, [x,y,z], [z,x,y])]\free{eq }}
\end{paste}\end{patch}

\end{chunk}
\section{gloss.ht}
\pagetitle{GlossaryPage}{gloss.ht}{Glossary}
\pagepic{ps/v71glossary.eps}{glossary}{0.50}
\pagefrom{Reference}{TopReferencePage}
\pageto{Search}{LispFunctions}
\begin{chunk}{gloss.ht}
\begin{page}{GlossaryPage}{G l o s s a r y}
\beginscroll\beginmenu\item\newline{\em \menuitemstyle{}}{\em !}\space{}
{\em (syntax)} Suffix character for \spadgloss{destructive operations}.
\item\newline{\em \menuitemstyle{}}{\em ,}\space{}
{\em (syntax)} a separator for items in a \spadgloss{tuple},{} 
\spadignore{e.g.} to separate arguments of a function \spad{f(x,{}y)}.
\item\newline{\em \menuitemstyle{}}{\em =>}\space{}
{\em (syntax)} the expression \spad{a => b} is equivalent to 
\spad{if a then} \spadgloss{exit} \spad{b}.
\item\newline{\em \menuitemstyle{}}{\em ?}\space{}
1. {\em (syntax)} a suffix character for Boolean-valued \spadfun{function} 
names,{} \spadignore{e.g.} \spadfun{odd?}. 2. Suffix character for pattern 
variables. 3. The special type \spad{?} means {\em don't care}. For 
example,{} the declaration \newline\center{\spad{x : Polynomial ?}}\newline,
{} means that values assigned to \spad{x} must be polynomials over an 
arbitrary \spadgloss{underlying domain}.
\item\newline{\em \menuitemstyle{}}{\em abstract datatype}\space{}
a programming language principle used in Axiom where a datatype 
is defined in two parts: (1) a {\em public} part describing a set of 
\spadgloss{exports},{} principally operations that apply to objects of 
that type,{} and (2) a {\em private} part describing the implementation 
of the datatype usually in terms of a \spadgloss{representation} for 
objects of the type. Programs which create and otherwise manipulate 
objects of the type may only do so through its exports. The representation 
and other implementation information is specifically hidden.
\item\newline{\em \menuitemstyle{}}{\em abstraction}\space{}
described functionally or conceptually without regard to implementation
\item\newline{\em \menuitemstyle{}}{\em accuracy}\space{}
the degree of exactness of an approximation or measurement. In computer 
algebra systems,{} computations are typically carried out with complete 
accuracy using integers or rational numbers of indefinite size. Domain 
\spadtype{Float} provides a function \spadfunFrom{precision}{Float} to 
change the precision for floating point computations. Computations using 
\spadtype{DoubleFloat} have a fixed precision but uncertain accuracy.
\item\newline{\em \menuitemstyle{}}{\em add-chain}\space{}
a hierarchy formed by \spadgloss{domain extensions}. If domain \spad{A} 
extends domain \spad{B} and domain \spad{B} extends domain \spad{C},{} 
then \spad{A} has {\em add-chain} \spad{B}-\spad{C}.
\item\newline{\em \menuitemstyle{}}{\em aggregate}\space{}
a data structure designed to hold multiple values. Examples of aggregates 
are \spadtype{List},{} \spadtype{Set},{} \spadtype{Matrix} and \spadtype{Bits}.
\item\newline{\em \menuitemstyle{}}{\em AKCL}\space{}
Austin Kyoto Common LISP,{} a version of \spadgloss{\spad{KCL}} produced 
by William Schelter,{} Austin,{} Texas.
\item\newline{\em \menuitemstyle{}}{\em algorithm}\space{}
a step-by-step procedure for a solution of a problem; a program
\item\newline{\em \menuitemstyle{}}{\em ancestor}\space{}
(of a domain) a category which is a \spadgloss{parent} of the domain,{} 
or a \spadgloss{parent} of a \spadgloss{parent},{} and so on.
\item\newline{\em \menuitemstyle{}}{\em application}\space{}
{\em (syntax)} an expression denoting "application" of a function to a set 
of \spadgloss{argument} parameters. Applications are written as a 
\spadgloss{parameterized form}. For example,{} the form \spad{f(x,{}y)} 
indicates the "application of the function \spad{f} to the tuple of 
arguments \spad{x} and \spad{y}". See also \spadgloss{evaluation} and 
\spadgloss{invocation}.
\item\newline{\em \menuitemstyle{}}{\em apply}\space{}
See \spadgloss{application}.
\item\newline{\em \menuitemstyle{}}{\em argument}\space{}
1. (actual argument) a value passed to a function at the time of a 
\spadglossSee{function call}{application}; also called an {\em actual 
parameter}. 2. (formal argument) a variable used in the definition of 
a function to denote the actual argument passed when the function is called.
\item\newline{\em \menuitemstyle{}}{\em arity}\space{}
1. (function) the number of arguments. 2. (operator or operation) 
corresponds to the arity of a function implementing the operator or operation.
\item\newline{\em \menuitemstyle{}}{\em assignment}\space{}
{\em (syntax)} an expression of the form \spad{x := e},{} meaning 
"assign the value of \spad{e} to \spad{x"}. After \spadgloss{evaluation},{} 
the \spadgloss{variable} \spad{x} \spadglossSee{points}{pointer} to an 
object obtained by evaluating the expression \spad{e}. If \spad{x} has 
a \spadgloss{type} as a result of a previous \spadgloss{declaration},{} 
the object assigned to \spad{x} must have that type. An interpreter must 
often \spadglossSee{coerce}{coercion} the value of \spad{e} to make that 
happen. For example,{} in the interpreter,{} \center{\spad{x : Float := 11}} 
first \spadglossSee{declares}{declaration} \spad{x} to be a float. This 
declaration causes the interpreter to coerce 11 to 11.0 in order to assign 
a floating point value to \spad{x}.
\item\newline{\em \menuitemstyle{}}{\em attribute}\space{}
a name or functional form denoting {\em any} useful computational property. 
For example,{} \spadatt{commutative(\spad{"*"})} asserts that "\spadfun{*} 
is commutative". Also,{} \spadatt{finiteAggregate} is used to assert that 
an aggregate has a finite number of immediate components.
\item\newline{\em \menuitemstyle{}}{\em basis}\space{}
{\em (algebra)} \spad{S} is a basis of a module \spad{M} over a 
\spadgloss{ring} if \spad{S} generates \spad{M},{} and \spad{S} is 
linearly independent
\item\newline{\em \menuitemstyle{}}{\em benefactor}\space{}
(of a given domain) a domain or package that the given domain explicitly 
references (for example,{} calls functions from) in its implementation
\item\newline{\em \menuitemstyle{}}{\em binary}\space{}
operation or function with \spadgloss{arity} 2
\item\newline{\em \menuitemstyle{}}{\em binding}\space{}
the association of a variable with properties such as \spadgloss{value} 
and \spadgloss{type}. The top-level \spadgloss{environment} in the 
interpreter consists of bindings for all user variables and functions. 
Every \spadgloss{function} has an associated set of bindings,{} one for 
each formal \spadgloss{argument} and \spadgloss{local variable}.
\item\newline{\em \menuitemstyle{}}{\em block}\space{}
{\em (syntax)} a control structure where expressions are sequentially 
\spadglossSee{evaluated}{evaluation}.
\item\newline{\em \menuitemstyle{}}{\em body}\space{}
a \spadgloss{function body} or \spadgloss{loop body}.
\item\newline{\em \menuitemstyle{}}{\em boolean}\space{}
objects denoted by the \spadgloss{literals} \spad{true} and \spad{false}; 
elements of domain \spadtype{Boolean}. See also \spadtype{Bits}.
\item\newline{\em \menuitemstyle{}}{\em built-in function}\space{}
a \spadgloss{function} in the standard Axiom library. Contrast 
\spadgloss{user function}.
\item\newline{\em \menuitemstyle{}}{\em cache}\space{}
1. (noun) a mechanism for immediate retrieval of previously computed data. 
For example,{} a function which does a lengthy computation might store its 
values in a \spadgloss{hash table} using argument as a key. The hash table 
then serves as a cache for the function (see also \spadsyscom{)set function 
cache}). Also,{} when \spadgloss{recurrence relations} which depend upon 
\spad{n} previous values are compiled,{} the previous \spad{n} values are 
normally cached (use \spadsyscom{)set functions recurrence} to change this). 
2. (verb) to save values in a cache.
\item\newline{\em \menuitemstyle{}}{\em capsule}\space{}
the part of the \spadglossSee{body}{function body} of a 
\spadgloss{domain constructor} that defines the functions implemented by 
the constructor.
\item\newline{\em \menuitemstyle{}}{\em case}\space{}
{\em (syntax)} an operator used to conditionally evaluate code based on 
the branch of a \spadgloss{Union}. For example,{} if value \spad{u} is 
\spad{Union(Integer,{}"failed")},{} the conditional expression \spad{if u 
case Integer then A else B} evaluate \spad{A} if \spad{u} is an integer 
and \spad{B} otherwise.
\item\newline{\em \menuitemstyle{}}{\em Category}\space{}
the distinguished object denoting the type of a category; the class of 
all categories.
\item\newline{\em \menuitemstyle{}}{\em category}\space{}
{\em (basic concept)} second-order types which serve to define useful 
"classification worlds" for domains,{} such as algebraic constructs 
(\spadignore{e.g.} groups,{} rings,{} fields),{} and data structures 
(\spadignore{e.g.} homogeneous aggregates,{} collections,{} dictionaries). 
Examples of categories are \spadtype{Ring} ("the class of all rings") and 
\spadtype{Aggregate} ("the class of all aggregates"). The categories of a 
given world are arranged in a hierarchy (formally,{} a directed acyclic 
graph). Each category inherits the properties of all its ancestors. Thus,{} 
for example,{} the category of ordered rings (\spadtype{OrderedRing}) 
inherits the properties of the category of rings (\spadtype{Ring}) and 
those of the ordered sets (\spadtype{OrderedSet}). Categories provide a 
database of algebraic knowledge and ensure mathematical correctness,{} 
\spadignore{e.g.} that "matrices of polynomials" is correct but "polynomials 
of hash tables" is not,{} that the multiply operation for "polynomials of 
continued fractions" is commutative,{} but that for "matrices of power 
series" is not. optionally provide "default definitions" for operations 
they export. Categories are defined in Axiom by functions called 
\spadgloss{category constructors}. Technically,{} a category designates 
a class of domains with common \spadgloss{operations} and 
\spadgloss{attributes} but usually with different \spadgloss{functions} 
and \spadgloss{representations} for its constituent \spadgloss{objects}. 
Categories are always defined using the Axiom library language 
(see also \spadgloss{category extension}). See also file {\em catdef.spad} 
for definitions of basic algebraic categories in Axiom.
\item\newline{\em \menuitemstyle{}}{\em category constructor}\space{}
a function that creates categories,{} described by an abstract datatype in 
the Axiom programming language. For example,{} the category 
constructor \spadtype{Module} is a function which takes a domain parameter 
\spad{R} and creates the category "modules over \spad{R}".
\item\newline{\em \menuitemstyle{}}{\em category extension}\space{}
created by a category definition,{} an expression usually of the form 
\spad{A == B with ...}. In English,{} this means "category A is a \spad{B} 
with the new operations and attributes as given by ... . See,{} for 
example,{} file {\em catdef.spad} for a definitions of the algebra 
categories in Axiom,{} {\em aggcat.spad} for data structure categories.
\item\newline{\em \menuitemstyle{}}{\em category hierarchy}\space{}
hierarchy formed by category extensions. The root category is 
\spadtype{Object}. A category can be defined as a \spadgloss{Join} of two 
or more categories so as to have multiple \spadgloss{parents}. Categories 
may also have parameterized so as to allow conditional inheritance.
\item\newline{\em \menuitemstyle{}}{\em character}\space{}
1. an element of a character set,{} as represented by a keyboard key. 2. 
a component of a string. For example,{} the 0th element of the string 
\spad{"hello there"} is the character {\em h}.
\item\newline{\em \menuitemstyle{}}{\em client}\space{}
(of a given domain) any domain or package that explicitly calls functions 
from the given domain
\item\newline{\em \menuitemstyle{}}{\em coercion}\space{}
an automatic transformation of an object of one \spadgloss{type} to an 
object of a similar or desired target type. In the interpreter,{} coercions 
and \spadgloss{retractions} are done automatically by the interpreter when 
a type mismatch occurs. Compare \spadgloss{conversion}.
\item\newline{\em \menuitemstyle{}}{\em comment}\space{}
textual remarks imbedded in code. Comments are preceded by a double dash 
({\em --}). For Axiom library code,{} stylized comments for on-line 
documentation are preceded by a two plus signs ({\em ++}).
\item\newline{\em \menuitemstyle{}}{\em Common LISP}\space{}
A version of \spadgloss{LISP} adopted as an informal standard by major 
users and suppliers of LISP
\item\newline{\em \menuitemstyle{}}{\em compile-time}\space{}
the time when category or domain constructors are compiled. Contrast 
\spadgloss{run-time}.
\item\newline{\em \menuitemstyle{}}{\em compiler}\space{}
a program that generates low-level code from a higher-level source 
language. Axiom has three compilers. A {\em graphics compiler} 
converts graphical formulas to a compiled subroutine so that points can 
be rapidly produced for graphics commands. An {\em interpreter compiler} 
optionally compiles \spadgloss{user functions} when first 
\spadglossSee{invoked}{invocation} (use \spadsyscom{)set functions compile} 
to turn this feature on). A {\em library compiler} compiles all constructors 
(not available in Release 1)
\item\newline{\em \menuitemstyle{}}{\em computational object}\space{}
In Axiom,{} domains are objects. This term is used to distinquish 
the objects which are members of domains rather than domains themselves.
\item\newline{\em \menuitemstyle{}}{\em conditional}\space{}
a \spadgloss{control structure} of the form \spad{if A then B else C}; 
The \spadgloss{evaluation} of \spad{A} produces \spad{true} or \spad{false}. 
If \spad{true},{} \spad{B} evaluates to produce a value; otherwise \spad{C} 
evaluates to produce a value. When the value is not used,{} \spad{else C} 
part can be omitted.
\item\newline{\em \menuitemstyle{}}{\em constant}\space{}
{\em (syntax)} a reserved word used in \spadgloss{signatures} in Axiom 
programming language to signify that mark an operation always returns the 
same value. For example,{} the signature \spad{0: constant -> \$} in the 
source code of \spadtype{AbelianMonoid} tells the Axiom compiler that 
\spad{0} is a constant so that suitable optimizations might be performed.
\item\newline{\em \menuitemstyle{}}{\em constructor}\space{}
a \spadgloss{function} which creates a \spadgloss{category},{} 
\spadgloss{domain},{} or \spadgloss{package}.
\item\newline{\em \menuitemstyle{}}{\em continuation}\space{}
when a line of a program is so long that it must be broken into several 
lines,{} then all but the first line are called {\em continuation lines}. 
If such a line is given interactively,{} then each incomplete line must 
end with an underscore.
\item\newline{\em \menuitemstyle{}}{\em control structure}\space{}
program structures which can specify a departure from normal sequential 
execution. Axiom has four kinds of control structures: 
\spadgloss{blocks},{} \spadgloss{case} statements,{} 
\spadgloss{conditionals},{} and \spadgloss{loops}.
\item\newline{\em \menuitemstyle{}}{\em conversion}\space{}
the transformation of an object on one \spadgloss{type} to one of another 
type. Conversions performed automatically are called \spadgloss{coercions}. 
These happen when the interpreter has a type mismatch and a similar or 
declared target type is needed. In general,{} the user must use the 
infix operation \spadSyntax{\spad{::}} to cause this transformation.
\item\newline{\em \menuitemstyle{}}{\em copying semantics}\space{}
the programming language semantics used in Pascal but {\em not} in 
Axiom. See also \spadgloss{pointer semantics} for details.
\item\newline{\em \menuitemstyle{}}{\em data structure}\space{}
a structure for storing data in the computer. Examples are 
\spadgloss{lists} and \spadgloss{hash tables}.
\item\newline{\em \menuitemstyle{}}{\em datatype}\space{}
equivalent to \spadgloss{domain} in Axiom.
\item\newline{\em \menuitemstyle{}}{\em declaration}\space{}
{\em (syntax)} an expression of the form \spad{x : T} where \spad{T} is 
some \spad{type}. A declaration forces all values 
\spadglossSee{assigned}{assignment} to \spad{T} to be of that type. If a 
value is of a different type,{} the interpreter will try to 
\spadglossSee{coerce}{coercion} the value to type \spad{T}. Declarations 
are necessary in case of ambiguity or when a user wants to introduce an 
an \spadglossSee{unexposed}{expose} domain.
\item\newline{\em \menuitemstyle{}}{\em default definition}\space{}
a function defined by a \spadgloss{category}. Such definitions appear 
category definitions of the form \spad{C: Category == T add I} in an 
optional implmentation part \spad{I} to the right of the keyword \spad{add}.
\item\newline{\em \menuitemstyle{}}{\em default package}\space{}
a optional \spadgloss{package} of \spadgloss{functions} associated with 
a category. Such functions are necessarily defined in terms over other 
functions exported by the category.
\item\newline{\em \menuitemstyle{}}{\em definition}\space{}
{\em (syntax)} 1. An expression of the form \spad{f(a) == b} defining 
function \spad{f} with \spadgloss{formal arguments} \spad{a} and 
\spadgloss{body} \spad{b}; equivalent to the statement 
\spad{f == (a) +-> b}. 2. An expression of the form \spad{a == b} 
where \spad{a} is a \spadgloss{symbol},{} equivalent to \spad{a() == b}. 
See also \spadgloss{macro} where a similar substitution is done at 
\spadgloss{parse} time.
\item\newline{\em \menuitemstyle{}}{\em delimiter}\space{}
a \spadgloss{character} which marks the beginning or end of some 
syntactically correct unit in the language,{} \spadignore{e.g.} 
\spadSyntax{"} for strings,{} blanks for identifiers.
\item\newline{\em \menuitemstyle{}}{\em destructive operation}\space{}
An operation which changes a component or structure of a value. In 
Axiom,{} all destructive operations have names which end with an 
exclamation mark ({\em !}). For example,{} domain \spadtype{List} has 
two operations to reverse the elements of a list,{} one named 
\spadfunFrom{reverse}{List} which returns a copy of the original list with 
the elements reversed,{} another named \spadfunFrom{reverse!}{List} which 
reverses the elements {\em in place} thus destructively changing the 
original list.
\item\newline{\em \menuitemstyle{}}{\em documentation}\space{}
1. on-line or hard copy descriptions of Axiom; 2. text in library 
code preceded by {\em ++} comments as opposed to general comments 
preceded by {\em --}.
\item\newline{\em \menuitemstyle{}}{\em domain}\space{}
{\em (basic concept)} a domain corresponds to the usual notion of 
abstract datatypes: that of a set of values and a set of "exported 
operations" for the creation and manipulation of these values. Datatypes 
are parameterized,{} dynamically constructed,{} and can combine with others 
in any meaningful way,{} \spadignore{e.g.} "lists of floats" 
(\spadtype{List Float}),{} "fractions of polynomials with integer 
coefficients" (\spadtype{Fraction Polynomial Integer}),{} "matrices 
of infinite \spadgloss{streams} of cardinal numbers" 
(\spadtype{Matrix Stream CardinalNumber}). The term {\em domain} is 
actually abbreviates {\em domain of computation}. Technically,{} a 
domain denotes a class of objects,{} a class of \spadgloss{operations} 
for creating and other manipulating these objects,{} and a class of 
\spadgloss{attributes} describing computationally useful properties. 
Domains also provide \spadgloss{functions} for each operation often in 
terms of some \spadgloss{representation} for the objects. A domain 
itself is an \spadgloss{object} created by a \spadgloss{function} 
called a \spadgloss{domain constructor}.
\item\newline{\em \menuitemstyle{}}{\em domain constructor}\space{}
a function that creates domains,{} described by an abstract datatype 
in the Axiom programming language. Simple domains like 
\spadtype{Integer} and \spadtype{Boolean} are created by domain 
constructors with no arguments. Most domain constructors take one or 
more parameters,{} one usually denoting an \spadgloss{underlying domain}. 
For example,{} the domain \spadtype{Matrix(R)} denotes "matrices over 
\spad{R"}. Domains {\em Mapping},{} {\em Record},{} and {\em Union} are 
primitive domains. All other domains are written in the Axiom 
programming language and can be modified by users with access to the 
library source code.
\item\newline{\em \menuitemstyle{}}{\em domain extension}\space{}
a domain constructor \spad{A} is said to {\em extend} a domain 
constructor \spad{B} if \spad{A}\spad{'s} definition has the form 
\spad{A == B add ...}. This intuitively means "functions not defined 
by \spad{A} are assumed to come from \spad{B}". Successive domain 
extensions form \spadgloss{add-chains} affecting the the 
\spadglossSee{search order}{lineage} for functions not implemented 
directly by the domain during \spadgloss{dynamic lookup}.
\item\newline{\em \menuitemstyle{}}{\em dot notation}\space{}
using an infix dot ({\em .}) for function application. If \spad{u} is 
the list \spad{[7,{}4,{}-11]} then both \spad{u(2)} and \spad{u.2} return 
4. Dot notation nests to left. Thus \spad{f . g . h} is equivalent to 
\spad{(f . g) . h}.
\item\newline{\em \menuitemstyle{}}{\em dynamic}\space{}
that which is done at \spadgloss{run-time} as opposed to 
\spadgloss{compile-time}. For example,{} the interpreter will build the 
domain "matrices over integers" dynamically in response to user input. 
However,{} the compilation of all functions for matrices and integers is 
done during \spadgloss{compile-time}. Constrast \spadgloss{static}.
\item\newline{\em \menuitemstyle{}}{\em dynamic lookup}\space{}
In Axiom,{} a \spadgloss{domain} may or may not explicitly provide 
\spadgloss{function} definitions for all of its exported 
\spadgloss{operations}. These definitions may instead come from domains 
in the \spadgloss{add-chain} or from \spadgloss{default packages}. When 
a \spadglossSee{function call}{application} is made for an operation in 
the domain,{} up to five steps are carried out.\begin{items} \item (1) 
If the domain itself implements a function for the operation,{} that 
function is returned. \item (2) Each of the domains in the 
\spadgloss{add-chain} are searched for one which implements the function; 
if found,{} the function is returned. \item (3) Each of the 
\spadgloss{default packages} for the domain are searched in order of 
the \spadgloss{lineage}. If any of the default packages implements the 
function,{} the first one found is returned. \item (4) Each of the 
\spadgloss{default packages} for each of the domains in the 
\spadgloss{add-chain} are searched in the order of their 
\spadgloss{lineage}. If any of the default packages implements the 
function,{} the first one found is returned. \item (5) If all of the 
above steps fail,{} an error message is reported. \end{items}
\item\newline{\em \menuitemstyle{}}{\em empty}\space{}
the unique value of objects with type \spadtype{Void}.
\item\newline{\em \menuitemstyle{}}{\em environment}\space{}
a set of \spadgloss{bindings}.
\item\newline{\em \menuitemstyle{}}{\em evaluation}\space{}
a systematic process which transforms an \spadgloss{expression} into an 
object called the \spadgloss{value} of the expression. Evaluation may 
produce \spadgloss{side effects}.
\item\newline{\em \menuitemstyle{}}{\em exit}\space{}
{\em (reserved word)} an \spadgloss{operator} which forces an exit from 
the current block. For example,{} the \spadgloss{block} \spad{(a := 1; 
if i > 0 then exit a; a := 2)} will prematurely exit at the second 
statement with value 1 if the value of \spad{i} is greater than 0. 
See \spadgloss{\spad{=>}} for an alternate syntax.
\item\newline{\em \menuitemstyle{}}{\em explicit export}\space{}
1. (of a domain \spad{D}) any \spadgloss{attribute},{} 
\spadgloss{operation},{} or \spadgloss{category} explicitly mentioned 
in the \spadgloss{type} specification part \spad{T} for the domain 
constructor definition \spad{D: T == I} 2. (of a category \spad{C}) 
any \spadgloss{attribute},{} \spadgloss{operation},{} or 
\spadgloss{category} explicitly mentioned in the \spadgloss{type} 
specification part \spad{T} for the domain constructor definition 
\spad{C: \spadgloss{Category} == T}
\item\newline{\em \menuitemstyle{}}{\em export}\space{}
\spadgloss{explicit export} or \spadgloss{implicit export} of a domain 
or category
\item\newline{\em \menuitemstyle{}}{\em expose}\space{}
some constructors are {\em exposed},{} others {\em unexposed}. Exposed 
domains and packages are recognized by the interpreter. Use \spadsys{)set 
expose} to control change what is exposed. To see both exposed and 
unexposed constructors,{} use \Browse{} with give the system command 
\spadsyscom{)set hyperdoc browse exposure on}. Unexposed constructors 
will now appear prefixed by star(\spad{*}).
\item\newline{\em \menuitemstyle{}}{\em expression}\space{}
1. any syntactically correct program fragment. 2. an element of domain 
\spadtype{Expression}
\item\newline{\em \menuitemstyle{}}{\em extend}\space{}
see \spadgloss{category extension} or \spadgloss{domain extension}
\item\newline{\em \menuitemstyle{}}{\em field}\space{}
{\em (algebra)} a \spadgloss{domain} which is \spadgloss{ring} where 
every non-zero element is invertible and where \spad{xy=yx}; a member 
of category \spadtype{Field}. For a complete list of fields,{} click 
on {\em Domains} under {\em Cross Reference} for \spadtype{Field}.
\item\newline{\em \menuitemstyle{}}{\em file}\space{}
a program or collection of data stored on disk,{} tape or other medium.
\item\newline{\em \menuitemstyle{}}{\em float}\space{}
a floating-point number with user-specified precision; an element of 
domain \spadtype{Float}. Floats are \spadgloss{literals} which are written 
two ways: without an exponent (\spadignore{e.g.} \spad{3.1416}),{} or with 
an exponent (\spadignore{e.g.} \spad{3.12E-12}). Use function 
\spadgloss{precision} to change the precision of the mantissage 
(20 digits by default). See also \spadgloss{small float}.
\item\newline{\em \menuitemstyle{}}{\em formal parameter}\space{}
(of a function) an identifier \spadglossSee{bound}{binding} to the value 
of an actual \spadgloss{argument} on \spadgloss{invocation}. In the 
function definition \spad{f(x,{}y) == u},{} for example,{} \spad{x} 
and \spad{y} are the formal parameter.
\item\newline{\em \menuitemstyle{}}{\em frame}\space{}
the basic unit of an interactive session; each frame has its own 
\spadgloss{step number},{} \spadgloss{environment},{} and 
\spadgloss{history}. In one interactive session,{} users can create 
and drop frames,{} and have several active frames simultaneously.
\item\newline{\em \menuitemstyle{}}{\em free}\space{}
{\em (syntax)} A keyword used in user-defined functions to declare 
that a variable is a \spadgloss{free variable} of that function. For 
example,{} the statement \spad{free x} declares the variable \spad{x} 
within the body of a function \spad{f} to be a free variable in \spad{f}. 
Without such a declaration,{} any variable \spad{x} which appears on the 
left hand side of an assignment is regarded as a \spadgloss{local variable} 
of that function. If the intention of the assignment is to give an value 
to a \spadgloss{global variable} \spad{x},{} the body of that function 
must contain the statement \spad{free x}.
\item\newline{\em \menuitemstyle{}}{\em free variable}\space{}
(of a function) a variable which appears in a body of a function but is 
not \spadglossSee{bound}{binding} by that function. See \spadgloss{local 
variable} by default.
\item\newline{\em \menuitemstyle{}}{\em function}\space{}
implementation of \spadgloss{operation}; it takes zero or more 
\spadgloss{argument} parameters and produces zero or more values. 
Functions are objects which can be passed as parameters to functions 
and can be returned as values of functions. Functions can also create 
other functions (see also \spadtype{InputForm}). See also 
\spadgloss{application} and \spadgloss{invocation}. The terms 
{\em operation} and {\em function} are distinct notions in Axiom. 
An operation is an abstraction of a function,{} described by declaring a 
\spadgloss{signature}. A function is created by providing an implementation 
of that operation by some piece of Axiom code. Consider the example 
of defining a user-function \spad{fact} to compute the \spadfun{factorial} 
of a nonnegative integer. The Axiom statement 
\spad{fact: Integer -> Integer} describes the operation,{} whereas the 
statement \spad{fact(n) = reduce(*,{}[1..n])} defines the functions. See 
also \spadgloss{generic function}.
\item\newline{\em \menuitemstyle{}}{\em function body}\space{}
the part of a \spadgloss{function}\spad{'s} definition which is evaluated 
when the function is called at \spadgloss{run-time}; the part of the 
function definition to the right of the \spadSyntax{\spad{==}}.
\item\newline{\em \menuitemstyle{}}{\em garbage collection}\space{}
a system function that automatically recycles memory cells from the 
\spadgloss{heap}. Axiom is built upon \spadgloss{Common LISP} 
which provides this facility.
\item\newline{\em \menuitemstyle{}}{\em garbage collector}\space{}
a mechanism for reclaiming storage in the \spadgloss{heap}.
\item\newline{\em \menuitemstyle{}}{\em Gaussian}\space{}
a complex-valued expression,{} \spadignore{e.g.} one with both a real 
and imaginary part; a member of a \spadtype{Complex} domain.
\item\newline{\em \menuitemstyle{}}{\em generic function}\space{}
the use of one function to operate on objects of different types; One 
might regard Axiom as supporting generic \spadgloss{operations} 
but not generic functions. One operation \spad{+: (D,{}D) -> D} exists 
for adding elements in a ring; each ring however provides its own 
type-specific function for implementing this operation.
\item\newline{\em \menuitemstyle{}}{\em global variable}\space{}
A variable which can be referenced freely by functions. In Axiom,{} 
all top-level user-defined variables defined during an interactive user 
session are global variables. Axiom does not allow {\em fluid 
variables},{} that is,{} variables \spadglossSee{bound}{binding} by 
functions which can be referenced by functions those functions call.
\item\newline{\em \menuitemstyle{}}{\em Groebner basis}\space{}
{\em (algebra)} a special basis for a polynomial ideal that allows a 
simple test for membership. It is useful in solving systems of polynomial 
equations.
\item\newline{\em \menuitemstyle{}}{\em group}\space{}
{\em (algebra)} a monoid where every element has a multiplicative inverse.
\item\newline{\em \menuitemstyle{}}{\em hash table}\space{}
A data structure that efficiency maps a given object to another. A hash 
table consists of a set of {\em entries},{} each of which associates a 
{\em key} with a {\em value}. Finding the object stored under a key can 
be very fast even if there are a large number of entries since keys are 
{\em hashed} into numerical codes for fast lookup.
\item\newline{\em \menuitemstyle{}}{\em heap}\space{}
an area of storage used by data in programs. For example,{} Axiom will 
use the heap to hold the partial results of symbolic computations. When 
cancellations occur,{} these results remain in the heap until 
\spadglossSee{garbage collected}{garbage collector}.
\item\newline{\em \menuitemstyle{}}{\em history}\space{}
a mechanism which records the results for an interactive computation. 
Using the history facility,{} users can save computations,{} review 
previous steps of a computation,{} and restore a previous interactive 
session at some later time. For details,{} issue the system command 
{\em )history ?} to the interpreter. See also \spadgloss{frame}.
\item\newline{\em \menuitemstyle{}}{\em ideal}\space{}
{\em (algebra)} a subset of a ring that is closed under addition and 
multiplication by arbitrary ring elements,{} \spadignore{i.e.} 
it\spad{'s} a module over the ring.
\item\newline{\em \menuitemstyle{}}{\em identifier}\space{}
{\em (syntax)} an Axiom name; a \spadgloss{literal} of type 
\spadtype{Symbol}. An identifier begins with an alphabetical character or 
\% and may be followed by alphabetic characters,{} digits,{} ? or !.
Certain distinquished \spadgloss{reserved words} are not allowed as 
identifiers but have special meaning in the Axiom.
\item\newline{\em \menuitemstyle{}}{\em immutable}\space{}
an object is immutable if it cannot be changed by an \spadgloss{operation}; 
not a \spadglossSee{mutable object}{mutable}. Algebraic objects generally 
immutable: changing an algebraic expression involves copying parts of the 
original object. One exception is a matrix object of type \spadtype{Matrix}. 
Examples of mutable objects are data structures such as those of type 
\spadtype{List}. See also \spadgloss{pointer semantics}.
\item\newline{\em \menuitemstyle{}}{\em implicit export}\space{}
(of a domain or category) any \spadgloss{attribute} or 
\spadgloss{operation} which is either an explicit export or else an 
explicit export of some category which an explicit category export 
\spadglossSee{extends}{category extension}.
\item\newline{\em \menuitemstyle{}}{\em index}\space{}
1. a variable that counts the number of times a \spadgloss{loop} is 
repeated. 2. the "address" of an element in a data structure (see also 
category \spadtype{LinearAggregate}).
\item\newline{\em \menuitemstyle{}}{\em infix}\space{}
{\em (syntax)} an \spadgloss{operator} placed between two 
\spadgloss{operands}; also called a {\em binary operator},{} 
\spadignore{e.g.} \spad{a + b}. An infix operator may also be used as a 
\spadgloss{prefix},{} \spadignore{e.g.} \spad{+(a,{}b)} is also permissable 
in the Axiom language. Infix operators have a relative 
\spadgloss{precedence}.
\item\newline{\em \menuitemstyle{}}{\em input area}\space{}
a rectangular area on a Hyperdoc screen into which users can enter text.
\item\newline{\em \menuitemstyle{}}{\em instantiate}\space{}
to build a \spadgloss{category},{} \spadgloss{domain},{} or 
\spadgloss{package} at run-time
\item\newline{\em \menuitemstyle{}}{\em integer}\space{}
a \spadgloss{literal} object of domain \spadtype{Integer},{} the class 
of integers with an unbounded number of digits. Integer literals consist 
of one or more consecutive digits (0-9) with no embedded blanks. 
Underscores can be used to separate digits in long integers if desirable.
\item\newline{\em \menuitemstyle{}}{\em interactive}\space{}
a system where the user interacts with the computer step-by-step
\item\newline{\em \menuitemstyle{}}{\em interpreter}\space{}
the subsysystem of Axiom responsible for handling user input during 
an interactive session. The following somewhat simplified description of 
the typical action of the interpreter. The interpreter parsers the 
user\spad{'s} input expression to create an expression tree then does a 
bottom-up traversal of the tree. Each subtree encountered which is not a 
value consists of a root node denoting an operation name and one or more 
leaf nodes denoting \spadgloss{operands}. The interpreter resolves type 
mismatches and uses type-inferencing and a library database to determine 
appropriate types of the operands and the result,{} and an operation to 
be performed. The interpreter then builds a domain to perform the 
indicated operation,{} then invokes a function from the domain to compute 
a value. The subtree is then replaced by that value and the process 
continues. Once the entire tree has been processed,{} the value replacing 
the top node of the tree is displayed back to the user as the value of the 
expression.
\item\newline{\em \menuitemstyle{}}{\em invocation}\space{}
(of a function) the run-time process involved in 
\spadglossSee{evaluating}{evaluation} a a \spadgloss{function} 
\spadgloss{application}. This process has two steps. First,{} a 
local \spadgloss{environment} is created where \spadgloss{formal arguments} 
are locally \spadglossSee{bound}{binding} by \spadgloss{assignment} to 
their respective actual \spadgloss{argument}. Second,{} the 
\spadgloss{function body} is evaluated in that local environment. 
The evaluation of a function is terminated either by completely 
evaluating the function body or by the evaluation of a 
\spadSyntax{return} expression.
\item\newline{\em \menuitemstyle{}}{\em iteration}\space{}
repeated evaluation of an expression or a sequence of expressions. 
Iterations use the reserved words \spadSyntax{for},{} 
\spadSyntax{while},{} and \spadSyntax{repeat}.
\item\newline{\em \menuitemstyle{}}{\em Join}\space{}
a primitive Axiom function taking two or more categories as 
arguments and producing a category containing all of the operations 
and attributes from the respective categories.
\item\newline{\em \menuitemstyle{}}{\em KCL}\space{}
Kyoto Common LISP,{} a version of \spadgloss{Common LISP} which 
features compilation of the compilation of LISP into the \spad{C} 
Programming Language
\item\newline{\em \menuitemstyle{}}{\em library}\space{}
In Axiom,{} a collection of compiled modules respresenting 
the \spadgloss{category} or \spadgloss{domain} constructor.
\item\newline{\em \menuitemstyle{}}{\em lineage}\space{}
the sequence of \spadgloss{default packages} for a given domain to be 
searched during \spadgloss{dynamic lookup}. This sequence is computed 
first by ordering the category \spadgloss{ancestors} of the domain 
according to their {\em level number},{} an integer equal to to the 
minimum distance of the domain from the category. Parents have level 
1,{} parents of parents have level 2,{} and so on. Among categories 
with equal level numbers,{} ones which appear in the left-most branches 
of {\em Join}\spad{s} in the source code come first. See also 
\spadgloss{dynamic lookup}.
\item\newline{\em \menuitemstyle{}}{\em LISP}\space{}
acronymn for List Processing Language,{} a language designed for the 
manipulation of nonnumerical data. The Axiom library is 
translated into LISP then compiled into machine code by an underlying LISP.
\item\newline{\em \menuitemstyle{}}{\em list}\space{}
an object of a \spadtype{List} domain.
\item\newline{\em \menuitemstyle{}}{\em literal}\space{}
an object with a special syntax in the language. In Axiom,{} 
there are five types of literals: \spadgloss{booleans},{} 
\spadgloss{integers},{} \spadgloss{floats},{} \spadgloss{strings},{} 
and \spadgloss{symbols}.
\item\newline{\em \menuitemstyle{}}{\em local}\space{}
{\em (syntax)} A keyword used in user-defined functions to declare that 
a variable is a \spadgloss{local variable} of that function. Because of 
default assumptions on variables,{} such a declaration is not necessary 
but is available to the user for clarity when appropriate.
\item\newline{\em \menuitemstyle{}}{\em local variable}\space{}
(of a function) a variable \spadglossSee{bound}{binding} by that function 
and such that its binding is invisible to any function that function calls. 
Also called a {\em lexical} variable. By default in the 
interpreter:\begin{items} \item 1. any variable \spad{x} which appears 
on the left hand side of an assignment is regarded a local variable of 
that function. If the intention of an assignment is to change the value 
of a \spadgloss{global variable} \spad{x},{} the body of the function 
must then contain the statement \spad{free x}. \item 2. any other variable 
is regarded as a \spadgloss{free variable}. \end{items} An optional 
declaration \spad{local x} is available to explicitly declare a variable 
to be a local variable. All \spadgloss{formal parameters} to the function 
can be regarded as local variables to the function.
\item\newline{\em \menuitemstyle{}}{\em loop}\space{}
1. an expression containing a \spadSyntax{repeat} 2. a collection expression 
having a \spadSyntax{for} or a \spadSyntax{while},{} \spadignore{e.g.} 
\spad{[f(i) for i in S]}.
\item\newline{\em \menuitemstyle{}}{\em loop body}\space{}
the part of a loop following the \spadSyntax{repeat} that tells what to 
do each iteration. For example,{} the body of the loop \spad{for x in S 
repeat B} is \spad{B}. For a collection expression,{} the body of the loop 
precedes the initial \spadSyntax{for} or \spadSyntax{while}.
\item\newline{\em \menuitemstyle{}}{\em macro}\space{}
{\em (syntax)} 1. An expression of the form \spad{macro a == b} where 
\spad{a} is a \spadgloss{symbol} causes \spad{a} to be textually replaced 
by the expression \spad{b} at \spadgloss{parse} time. 2. An expression of 
the form \spad{macro f(a) == b} defines a parameterized macro expansion for 
a parameterized form \spad{f} This macro causes a form \spad{f}(\spad{x}) 
to be textually replaced by the expression \spad{c} at parse time,{} where 
\spad{c} is the expression obtained by replacing \spad{a} by \spad{x} 
everywhere in \spad{b}. See also \spadgloss{definition} where a similar 
substitution is done during \spadgloss{evaluation}.
\item\newline{\em \menuitemstyle{}}{\em mode}\space{}
a type expression containing a question-mark ({\em ?}). For example,{} 
the mode {\em P ?} designates {\em the class of all polynomials over an 
arbitrary ring}.
\item\newline{\em \menuitemstyle{}}{\em mutable}\space{}
objects which contain \spadgloss{pointers} to other objects and which 
have operations defined on them which alter these pointers. Contrast 
\spadgloss{immutable}. Axiom uses \spadgloss{pointer semantics} 
as does \spadgloss{LISP} in contrast with many other languages such as 
Pascal which use \spadgloss{copying semantics}. See \spadgloss{pointer 
semantics} for details.
\item\newline{\em \menuitemstyle{}}{\em name}\space{}
1. a \spadgloss{symbol} denoting a \spadgloss{variable},{} 
\spadignore{i.e.} the variable \spad{x}. 2. a \spadgloss{symbol} 
denoting an \spadgloss{operation},{} \spadignore{i.e.} the operation 
\spad{divide: (Integer,{}Integer) -> Integer}.
\item\newline{\em \menuitemstyle{}}{\em nullary}\space{}
a function with no arguments,{} \spadignore{e.g.} \spadfun{characteristic}.
\item\newline{\em \menuitemstyle{}}{\em nullary}\space{}
operation or function with \spadgloss{arity} 0
\item\newline{\em \menuitemstyle{}}{\em Object}\space{}
a category with no operations or attributes,{} from which most categories 
in Axiom are \spadglossSee{extensions}{category extension}.
\item\newline{\em \menuitemstyle{}}{\em object}\space{}
a data entity created or manipulated by programs. Elements of domains,{} 
functions,{} and domains themselves are objects. Whereas categories are 
created by functions,{} they cannot be dynamically manipulated in the 
current system and are thus not considered as objects. The most basic 
objects are \spadgloss{literals}; all other objects must be created 
\spadgloss{functions}. Objects can refer to other objects using 
\spadgloss{pointers}. Axiom language uses 
\spadgloss{pointer semantics} when dealing with \spadgloss{mutable} objects.
\item\newline{\em \menuitemstyle{}}{\em object code}\space{}
code which can be directly executed by hardware; also known as 
{\em machine language}.
\item\newline{\em \menuitemstyle{}}{\em operand}\space{}
an argument of an \spadgloss{operator} (regarding an operator as a 
\spadgloss{function}).
\item\newline{\em \menuitemstyle{}}{\em operation}\space{}
an abstraction of a \spadgloss{function},{} described by a 
\spadgloss{signature}. For example,{} 
\center{\spad{fact: NonNegativeInteger -> NonNegativeInteger}} describes 
an operation for "the factorial of a (non-negative) integer".
\item\newline{\em \menuitemstyle{}}{\em operator}\space{}
special reserved words in the language such as \spadop{+} and \spadop{*}; 
operators can be either \spadgloss{prefix} or \spadgloss{infix} and have a
relative \spadgloss{precedence}.
\item\newline{\em \menuitemstyle{}}{\em overloading}\space{}
the use of the same name to denote distinct functions; a function is 
identified by a \spadgloss{signature} identifying its name,{} the number 
and types of its arguments,{} and its return types. If two functions can 
have identical signatures,{} a \spadgloss{package call} must be made to 
distinquish the two.
\item\newline{\em \menuitemstyle{}}{\em package}\space{}
a domain whose exported operations depend solely on the parameters and 
other explicit domains,{} \spadignore{e.g.} a package for solving systems 
of equations of polynomials over any field,{} \spadignore{e.g.} floats,{} 
rational numbers,{} complex rational functions,{} or power series. 
Facilities for integration,{} differential equations,{} solution of 
linear or polynomial equations,{} and group theory are provided by 
"packages". Technically,{} a package is a domain which has no 
\spadgloss{signature} containing the symbol \$. While domains intuitively 
provide computational objects you can compute with,{} packages intuitively 
provide functions (\spadgloss{polymorphic} functions) which will work over 
a variety of datatypes.
\item\newline{\em \menuitemstyle{}}{\em package call}\space{}
{\em (syntax)} an expression of the form \spad{e \$ D} where \spad{e} is 
an \spadgloss{application} and \spad{D} denotes some \spadgloss{package} 
(or \spadgloss{domain}).
\item\newline{\em \menuitemstyle{}}{\em package call}\space{}
{\em (syntax)} an expression of the form \spad{f(x,{}y)\$D} used to identify 
that the function \spad{f} is to be one from \spad{D}.
\item\newline{\em \menuitemstyle{}}{\em package constructor}\space{}
same as \spadgloss{domain constructor}.
\item\newline{\em \menuitemstyle{}}{\em parameter}\space{}
see \spadgloss{argument}
\item\newline{\em \menuitemstyle{}}{\em parameterized datatype}\space{}
a domain that is built on another,{} for example,{} polynomials with integer 
coefficients.
\item\newline{\em \menuitemstyle{}}{\em parameterized form}\space{}
a expression of the form \spad{f(x,{}y)},{} an \spadgloss{application} of a 
function.
\item\newline{\em \menuitemstyle{}}{\em parent}\space{}
(of a domain) a category which is explicitly declared in the source code 
definition for the domain to be an \spadgloss{export} of the domain.
\item\newline{\em \menuitemstyle{}}{\em parse}\space{}
1. (verb) to produce an internal representation of a user input string; 
the resultant internal representation is then "interpreted" by Axiom 
to perform some indicated action.
\item\newline{\em \menuitemstyle{}}{\em parse}\space{}
the transformation of a user input string representing a valid Axiom 
expression into an internal representation as a tree-structure.
\item\newline{\em \menuitemstyle{}}{\em partially ordered set}\space{}
a set with a reflexive,{} transitive and antisymetric \spadgloss{binary} 
operation.
\item\newline{\em \menuitemstyle{}}{\em pattern match}\space{}
1. (on expressions) Given a expression called a "subject" \spad{u},{} the 
attempt to rewrite \spad{u} using a set of "rewrite rules". Each rule has 
the form \spad{A == B} where \spad{A} indicates a expression called a 
"pattern" and \spad{B} denotes a "replacement". The meaning of this rule 
is "replace \spad{A} by \spad{B"}. If a given pattern \spad{A} matches a 
subexpression of \spad{u},{} that subexpression is replaced by \spad{B}. 
Once rewritten,{} pattern matching continues until no further changes occur. 
2. (on strings) the attempt to match a string indicating a "pattern" to 
another string called a "subject",{} for example,{} for the purpose of 
identifying a list of names. In \Browse{},{} users may enter 
\spadgloss{search strings} for the purpose of identifying constructors,{} 
operations,{} and attributes.
\item\newline{\em \menuitemstyle{}}{\em pile}\space{}
alternate syntax for a block,{} using indentation and column alignment 
(see also \spadgloss{block}).
\item\newline{\em \menuitemstyle{}}{\em pointer}\space{}
a reference implemented by a link directed from one object to another in 
the computer memory. An object is said to {\em refer} to another if it 
has a pointer to that other object. Objects can also refer to themselves 
(cyclic references are legal). Also more than one object can refer to the 
same object. See also \spadgloss{pointer semantics}.
\item\newline{\em \menuitemstyle{}}{\em pointer semantics}\space{}
the programming language semantics used in languages such as LISP which 
allow objects to be \spadgloss{mutable}. Consider the following sequence 
of Axiom statements:\begin{items} \item \spad{x : Vector Integer := 
[1,{}4,{}7]} \item \spad{y := x} \item \spad{swap!(x,{}2,{}3)} \end{items} 
The function \spadfunFrom{swap!}{Vector} is used to interchange the 2nd and 
3rd value in the list \spad{x} producing the value \spad{[1,{}7,{}4]}. 
What value does \spad{y} have after evaluation of the third statement? 
The answer is different in Axiom than it is in a language with 
\spadgloss{copying semantics}. In Axiom,{} first the vector 
[1,{}2,{}3] is created and the variable \spad{x} set to 
\spadglossSee{point}{pointer} to this object. Let\spad{'s} call this 
object \spad{V}. Now \spad{V} refers to its \spadgloss{immutable} 
components 1,{}2,{} and 3. Next,{} the variable \spad{y} is made to 
point to \spad{V} just as \spad{x} does. Now the third statement 
interchanges the last 2 elements of \spad{V} (the {\em !} at the end 
of the name \spadfunFrom{swap!}{Vector} tells you that this operation 
is destructive,{} that is,{} it changes the elements {\em in place}). 
Both \spad{x} and \spad{y} perceive this change to \spad{V}. Thus both 
\spad{x} and \spad{y} then have the value \spad{[1,{}7,{}4]}. In Pascal,{} 
the second statement causes a copy of \spad{V} to be stored under \spad{y}. 
Thus the change to \spad{V} made by the third statement does not affect 
\spad{y}.
\item\newline{\em \menuitemstyle{}}{\em polymorphic}\space{}
a \spadgloss{function} parameterized by one or more \spadgloss{domains}; 
a \spadgloss{algorithm} defined \spadglossSee{categorically}{category}. 
Every function defined in a domain or package constructor with a 
domain-valued parameter is polymorphic. For example,{} the same matrix 
\spadSyntax{*} function is used to multiply "matrices over integers" as 
"matrices over matrices over integers" Likewise,{} various 
\ignore{\spad{???}} in \ignore{\spad{???}} solves polynomial equations 
over any \spadgloss{field}.
\item\newline{\em \menuitemstyle{}}{\em postfix}\space{}
an \spadgloss{operator} that follows its single \spadgloss{operand}. 
Postfix operators are not available in Axiom.
\item\newline{\em \menuitemstyle{}}{\em precedence}\space{}
{\em (syntax)} refers to the so-called {\em binding power} of an operator. 
For example,{} \spad{*} has higher binding power than \spad{+} so that the 
expression \spad{a + b * c} is equivalent to \spad{a + (b * c)}.
\item\newline{\em \menuitemstyle{}}{\em precision}\space{}
the number of digits in the specification of a number,{} \spadignore{e.g.} 
as set by \spadfunFrom{precision}{Float}.
\item\newline{\em \menuitemstyle{}}{\em predicate}\space{}
1. a Boolean valued function,{} \spadignore{e.g.} 
\spad{odd: Integer -> Boolean}. 2. an Boolean valued expression
\item\newline{\em \menuitemstyle{}}{\em prefix}\space{}
{\em (syntax)} an \spadgloss{operator} such as \spad{-} and \spad{not} 
that is written {\em before} its single \spadgloss{operand}. Every 
function of one argument can be used as a prefix operator. For example,{} 
all of the following have equivalent meaning in Axiom: \spad{f(x)},{} 
\spad{f x},{} and \spad{f.x}. See also \spadgloss{dot notation}.
\item\newline{\em \menuitemstyle{}}{\em quote}\space{}
the prefix \spadgloss{operator} \spadSyntax{'} meaning {\em do not evaluate}.
\item\newline{\em \menuitemstyle{}}{\em Record}\space{}
(basic domain constructor) a domain constructor used to create a 
inhomogeneous aggregate composed of pairs of "selectors" and 
\spadgloss{values}. A Record domain is written in the form 
\spad{Record(a1:D1,{}...,{}an:Dn)} (\spad{n} > 0) where 
\spad{a1},{}...,{}\spad{an} are identifiers called the 
{\em selectors} of the record,{} and \spad{D1},{}...,{}\spad{Dn} 
are domains indicating the type of the component stored under selector 
\spad{an}.
\item\newline{\em \menuitemstyle{}}{\em recurrence relation}\space{}
A relation which can be expressed as a function \spad{f} with some 
argument \spad{n} which depends on the value of \spad{f} at \spad{k} 
previous values. In many cases,{} Axiom will rewrite a recurrence 
relation on compilation so as to \spadgloss{cache} its previous \spad{k} 
values and therefore make the computation significantly more efficient.
\item\newline{\em \menuitemstyle{}}{\em recursion}\space{}
use of a self-reference within the body of a function. Indirect recursion 
is when a function uses a function below it in the call chain.
\item\newline{\em \menuitemstyle{}}{\em recursive}\space{}
1. A function that calls itself,{} either directly or indirectly through 
another function. 2. self-referential. See also \spadgloss{recursive}.
\item\newline{\em \menuitemstyle{}}{\em reference}\space{}
see \spadgloss{pointer}
\item\newline{\em \menuitemstyle{}}{\em Rep}\space{}
a special identifier used as \spadgloss{local variable} of a domain 
constructor body to denote the representation domain for objects of a domain.
\item\newline{\em \menuitemstyle{}}{\em representation}\space{}
a \spadgloss{domain} providing a data structure for elements of a 
domain; generally denoted by the special identifier \spadgloss{Rep} 
in the Axiom programming language. As domains are 
\spadgloss{abstract datatypes},{} this representation is not available 
to users of the domain,{} only to functions defined in the 
\spadgloss{function body} for a domain constructor. Any domain can be used 
as a representation.
\item\newline{\em \menuitemstyle{}}{\em reserved word}\space{}
a special sequence of non-blank characters with special meaning in the 
Axiom language. Examples of reserved words are names such as 
\spadSyntax{for},{} \spadSyntax{if},{} and \spadSyntax{free},{} operator 
names such as \spadSyntax{+} and \spad{mod},{} special character strings 
such as spadSyntax{\spad{==}} and spadSyntax{\spad{:=}}.
\item\newline{\em \menuitemstyle{}}{\em retraction}\space{}
to move an object in a parameterized domain back to the underlying 
domain,{} for example to move the object \spad{7} from a "fraction of 
integers" (domain \spadtype{Fraction Integer}) to "the integers" 
(domain \spadtype{Integer}).
\item\newline{\em \menuitemstyle{}}{\em return}\space{}
when leaving a function,{} the value of the expression following 
\spadSyntax{return} becomes the value of the function.
\item\newline{\em \menuitemstyle{}}{\em ring}\space{}
a set with a commutative addition,{} associative multiplication,{} 
a unit element,{} and multiplication distributes over addition and 
subtraction.
\item\newline{\em \menuitemstyle{}}{\em rule}\space{}
{\em (syntax)} 1. An expression of the form \spad{rule A == B} 
indicating a "rewrite rule". 2. An expression of the form 
\spad{rule (R1;...;Rn)} indicating a set of "rewrite rules" 
\spad{R1},{}...,{}\spad{Rn}. See \spadgloss{pattern matching} for details.
\item\newline{\em \menuitemstyle{}}{\em run-time}\space{}
the time of doing a computation. Contrast \spadgloss{compile-time}.
 rather than prior to it; \spadgloss{dynamic} as opposed to 
\spadgloss{static}. For example,{} the decision of the intepreter 
to build a structure such as "matrices with power series entries" 
in response to user input is made at run-time.
\item\newline{\em \menuitemstyle{}}{\em run-time check}\space{}
an error-checking which can be done only when the program receives 
user input; for example,{} confirming that a value is in the proper 
range for a computation.
\item\newline{\em \menuitemstyle{}}{\em search string}\space{}
a string entered into an \spadgloss{input area} on a Hyperdoc screen
\item\newline{\em \menuitemstyle{}}{\em selector}\space{}
an identifier used to address a component value of a gloss{Record} datatype.
\item\newline{\em \menuitemstyle{}}{\em semantics}\space{}
the relationships between symbols and their meanings. The rules for 
obtaining the {\em meaning} of any syntactically valid expression.
\item\newline{\em \menuitemstyle{}}{\em semigroup}\space{}
{\em (algebra)} a \spadgloss{monoid} which need not have an identity; 
it is closed and associative.
\item\newline{\em \menuitemstyle{}}{\em side effect}\space{}
action which changes a component or structure of a value. See 
\spadgloss{destructive operation} for details.
\item\newline{\em \menuitemstyle{}}{\em signature}\space{}
{\em (syntax)} an expression describing an \spadgloss{operation}. 
A signature has the form as \spad{name : source -> target},{} where 
\spad{source} gives the type of the arguments of the operation,{} and 
\spad{target} gives the type of the result.
\item\newline{\em \menuitemstyle{}}{\em small float}\space{}
the domain for hardware floating point arithmetic as provided by the 
computer hardware.
\item\newline{\em \menuitemstyle{}}{\em small integer}\space{}
the domain for hardware integer arithmetic. as provided by the computer 
hardware.
\item\newline{\em \menuitemstyle{}}{\em source}\space{}
the \spadgloss{type} of the argument of a \spadgloss{function}; the type 
expression before the \spad{->} in a \spadgloss{signature}. For example,{} 
the source of \spad{f : (Integer,{}Integer) -> Integer} is 
\spad{(Integer,{}Integer)}.
\item\newline{\em \menuitemstyle{}}{\em sparse}\space{}
data structure whose elements are mostly identical (a sparse matrix is 
one filled with mostly zeroes).
\item\newline{\em \menuitemstyle{}}{\em static}\space{}
that computation done before run-time,{} such as compilation. Contrast 
\spadgloss{dynamic}.
\item\newline{\em \menuitemstyle{}}{\em step number}\space{}
the number which precedes user input lines in an interactive session; 
the output of user results is also labeled by this number.
\item\newline{\em \menuitemstyle{}}{\em stream}\space{}
an object of \spadtype{Stream(R)},{} a generalization of a 
\spadgloss{list} to allow an infinite number of elements. Elements of 
a stream are computed "on demand". Strings are used to implement various 
forms of power series (\ignore{\spad{???}}).
\item\newline{\em \menuitemstyle{}}{\em string}\space{}
an object of domain \spadtype{String}. Strings are \spadgloss{literals} 
consisting of an arbitrary sequence of \spadgloss{characters} surrounded 
by double-quotes (\spadSyntax{"}),{} \spadignore{e.g.} \spad{"Look here!"}.
\item\newline{\em \menuitemstyle{}}{\em subdomain}\space{}
{\em (basic concept)} a \spadgloss{domain} together with a 
\spadgloss{predicate} characterizing which members of the domain belong 
to the subdomain. The exports of a subdomain are usually distinct from the 
domain itself. A fundamental assumption however is that values in the 
subdomain are automatically \spadglossSee{coerceable}{coercion} to values 
in the domain. For example,{} if \spad{n} and \spad{m} are declared to be 
members of a subdomain of the integers,{} then {\em any} \spadgloss{binary} 
operation from \spadtype{Integer} is available on \spad{n} and \spad{m}. 
On the other hand,{} if the result of that operation is to be assigned 
to,{} say,{} \spad{k},{} also declared to be of that subdomain,{} a 
\spadgloss{run-time} check is generally necessary to ensure that the 
result belongs to the subdomain.
\item\newline{\em \menuitemstyle{}}{\em such that clause}\space{}
the use of \spadSyntax{|} followed by an expression to filter an iteration.
\item\newline{\em \menuitemstyle{}}{\em suffix}\space{}
{\em (syntax)} an \spadgloss{operator} which placed after its operand. 
Suffix operators are not allowed in the Axiom language.
\item\newline{\em \menuitemstyle{}}{\em symbol}\space{}
objects denoted by \spadgloss{identifier} \spadgloss{literals}; an 
element of domain \spadtype{Symbol}. The interpreter defaultly converts 
a symbol \spad{x} into \spadtype{Variable(x)}.
\item\newline{\em \menuitemstyle{}}{\em syntax}\space{}
rules of grammar,{} punctuation etc. for forming correct expressions.
\item\newline{\em \menuitemstyle{}}{\em system commands}\space{}
top-level Axiom statements that begin with {\em )}. System 
commands allow users to query the database,{} read files,{} trace 
functions,{} and so on.
\item\newline{\em \menuitemstyle{}}{\em tag}\space{}
an identifier used to discriminate a branch of a \spadgloss{Union} type.
\item\newline{\em \menuitemstyle{}}{\em target}\space{}
the \spadgloss{type} of the result of a \spadgloss{function}; the 
type expression following the \spad{->} in a \spadgloss{signature}.
\item\newline{\em \menuitemstyle{}}{\em top-level}\space{}
refers to direct user interactions with the Axiom interpreter.
\item\newline{\em \menuitemstyle{}}{\em totally ordered set}\space{}
{\em (algebra)} a partially ordered set where any two elements are 
comparable.
\item\newline{\em \menuitemstyle{}}{\em trace}\space{}
use of system function \spadsys{)trace} to track the arguments passed 
to a function and the values returned.
\item\newline{\em \menuitemstyle{}}{\em tuple}\space{}
an expression of two or more other expressions separated by commas,{} 
\spadignore{e.g.} \spad{4,{}7,{}11}. Tuples are also used for multiple 
arguments both for \spadgloss{applications} (\spadignore{e.g.} 
\spad{f(x,{}y)}) and in \spadgloss{signatures} (\spadignore{e.g.} 
\spad{(Integer,{}Integer) -> Integer}). A tuple is not a data structure,{} 
rather a syntax mechanism for grouping expressions.
\item\newline{\em \menuitemstyle{}}{\em type}\space{}
The type of any \spadgloss{subdomain} is the unique symbol {\em Category}. 
The type of a \spadgloss{domain} is any \spadgloss{category} that domain 
belongs to. The type of any other object is either the (unique) domain 
that object belongs to or any \spadgloss{subdomain} of that domain. The 
type of objects is in general not unique.
\item\newline{\em \menuitemstyle{}}{\em type checking}\space{}
a system function which determines whether the datatype of an object is 
appropriate for a given operation.
\item\newline{\em \menuitemstyle{}}{\em type constructor}\space{}
a \spadgloss{domain constructor} or \spadgloss{category constructor}.
\item\newline{\em \menuitemstyle{}}{\em type inference}\space{}
when the interpreter chooses the type for an object based on context. 
For example,{} if the user interactively issues the definition 
\center{\spad{f(x) == (x + \%i)**2}} then issues \spad{f(2)},{} 
the interpreter will infer the type of \spad{f} to be 
\spad{Integer -> Complex Integer}.
\item\newline{\em \menuitemstyle{}}{\em unary}\space{}
operation or function with \spadgloss{arity} 1
\item\newline{\em \menuitemstyle{}}{\em underlying domain}\space{}
for a \spadgloss{domain} that has a single domain-valued parameter,{} 
the {\em underlying domain} refers to that parameter. For example,{} 
the domain "matrices of integers" (\spadtype{Matrix Integer}) has 
underlying domain \spadtype{Integer}.
\item\newline{\em \menuitemstyle{}}{\em Union}\space{}
(basic domain constructor) a domain constructor used to combine any 
set of domains into a single domain. A Union domain is written in the 
form \spad{Union(a1:D1,{}...,{}an:Dn)} (\spad{n} > 0) where 
\spad{a1},{}...,{}\spad{an} are identifiers called the {\em tags} of 
the union,{} and \spad{D1},{}...,{}\spad{Dn} are domains called the 
{\em branches} of the union. The tags \spad{\spad{ai}} are optional,{} 
but required when two of the \spad{\spad{Di}} are equal,{} 
\spadignore{e.g.} \spad{Union(inches:Integer,{}centimeters:Integer)}. 
In the interpreter,{} values of union domains are automatically coerced 
to values in the branches and vice-versa as appropriate. See also 
\spadgloss{case}.
\item\newline{\em \menuitemstyle{}}{\em unit}\space{}
{\em (algebra)} an invertible element.
\item\newline{\em \menuitemstyle{}}{\em user function}\space{}
a function defined by a user during an interactive session. Contrast 
\spadgloss{built-in function}.
\item\newline{\em \menuitemstyle{}}{\em user variable}\space{}
a variable created by the user at top-level during an interactive session
\item\newline{\em \menuitemstyle{}}{\em value}\space{}
1. the result of \spadglossSee{evaluating}{evaluation} an expression. 
2. a property associated with a \spadgloss{variable} in a \spadgloss{binding} 
in an \spadgloss{environment}.
\item\newline{\em \menuitemstyle{}}{\em variable}\space{}
a means of referring to an object but itself {\spad{\bf} not} an object. A 
variable has a name and an associated \spadgloss{binding} created by 
\spadgloss{evaluation} of Axiom expressions such as 
\spadgloss{declarations},{} \spadgloss{assignments},{} and 
\spadgloss{definitions}. In the top-level \spadgloss{environment} of the 
interpreter,{} variables are \spadgloss{global variables}. Such variables 
can be freely referenced in user-defined functions although a 
\spadgloss{free} declaration is needed to assign values to them. 
See \spadgloss{local variable} for details.
\item\newline{\em \menuitemstyle{}}{\em Void}\space{}
the type given when the \spadgloss{value} and \spadgloss{type} of an 
expression are not needed. Also used when there is no guarantee at 
run-time that a value and predictable mode will result.
\item\newline{\em \menuitemstyle{}}{\em wild card}\space{}
a symbol which matches any substring including the empty string; for 
example,{} the search string {\em *an*} matches an word containing the 
consecutive letters {\em a} and {\em n}
\item\newline{\em \menuitemstyle{}}{\em workspace}\space{}
an interactive record of the user input and output held in an interactive 
history file. Each user input and corresponding output expression in the 
workspace has a corresponding \spadgloss{step number}. The current output 
expression in the workspace is referred to as \spad{\%}. The output 
expression associated with step number \spad{n} is referred to by 
\spad{\%\%(n)}. The \spad{k}-th previous output expression relative 
to the current step number \spad{n} is referred to by \spad{\%\%(- k)}. 
Each interactive \spadgloss{frame} has its own workspace.
\endmenu\endscroll\lispdownlink{Search}{(|htGloss| "\stringvalue{pattern}")} 
for glossary entry matching \inputstring{pattern}{24}{*}\end{page}

\end{chunk}
\section{graphics.ht}
\pagetitle{GraphicsPage}{graphics.ht}{Graphics}
\pagepic{ps/v71graphicspage.eps}{graphicspage}{0.50}
\pagefrom{Topics}{TopicPage}
\pageto{Examples}{GraphicsExamplePage}
\pageto{2D Graphics}{TwoDimensionalGraphicsPage}
\pageto{3D Graphics}{ThreeDimensionalGraphicsPage}
\pageto{Viewports}{ViewportPage}
\begin{chunk}{graphics.ht}
\begin{page}{GraphicsPage}{Graphics}
Axiom can plot curves and surfaces of
various types, as well as lists of points in the plane.
% sequences, and complex functions.
\beginscroll
\beginmenu
\menulink{Examples}{GraphicsExamplePage} \tab{13}
See examples of Axiom graphics
\menulink{2D Graphics}{TwoDimensionalGraphicsPage} \tab{13}
Graphics in the real and complex plane
\menulink{3D Graphics}{ThreeDimensionalGraphicsPage} \tab{13}
Plot surfaces, curves, or tubes around curves
\menulink{Viewports}{ViewportPage} \tab{13}
Customize graphics using Viewports
\endmenu
\endscroll
\autobuttons \end{page}

\end{chunk}
\pagetitle{GraphicsExamplePage}{graphics.ht}{Graphics Examples}
\pageto{notitle}{AssortedGraphicsExamplePage}
\pageto{notitle}{ThreeDimensionalGraphicsExamplePage}
\pageto{notitle}{OneVariableGraphicsExamplePage}
\pageto{notitle}{PolarGraphicsExamplePage}
\pageto{notitle}{ParametricCurveGraphicsExamplePage}
\pageto{notitle}{ImplicitCurveGraphicsExamplePage}
\pageto{notitle}{ListPointsGraphicsExamplePage}
\begin{chunk}{graphics.ht}
\begin{page}{GraphicsExamplePage}{Graphics Examples}
\beginscroll
Here are some examples of Axiom graphics.
Choose a specific type of graph or choose Assorted Examples.
\beginmenu
\menulink{Assorted Examples}{AssortedGraphicsExamplePage} \newline
Examples of each type of Axiom graphics.
\menulink{Three Dimensional Graphics}
{ThreeDimensionalGraphicsExamplePage} \newline
Plot parametrically defined surfaces of three functions.
\menulink{Functions of One Variable}{OneVariableGraphicsExamplePage} 
\newline
Plot curves defined by an equation y = f(x).
\menulink{Parametric Curves}{ParametricCurveGraphicsExamplePage} \newline
Plot curves defined by parametric equations x = f(t), y = g(t).
\menulink{Polar Coordinates}{PolarGraphicsExamplePage} \newline
Plot curves given in polar form by an equation r = f(theta).
\menulink{Implicit Curves}{ImplicitCurveGraphicsExamplePage} \newline
Plot non-singular curves defined by a polynomial equation
\menulink{Lists of Points}{ListPointsGraphicsExamplePage} \newline
Plot lists of points in the (x,y)-plane.
% \menulink{Sequences}{SequenceGraphicsExamplePage}
% Plot a sequence a1, a2, a3,...
% \menulink{Complex Functions}{ComplexFunctionGraphicsExamplePage}
% Plot complex functions of a complex variable by means of grid plots.
\endmenu
\endscroll
\autobuttons \end{page}

\end{chunk}
\pagetitle{AssortedGraphicsExamplePage}{graphics.ht}{Assorted Graphics Examples}
\begin{chunk}{graphics.ht}
\begin{page}{AssortedGraphicsExamplePage}{Assorted Graphics Examples}
\beginscroll
Pick a specific example or choose 'All' to see all the examples.\newline
Function of two variables: z = f(x,y).
\graphpaste{draw(sin(x * y), x = -2.5..2.5, y = -2.5..2.5) \bound{example1}}
Function of one variable: y = f(x).
\graphpaste{draw(sin tan x - tan sin x,x = 0..6) \bound{example2} }
Plane parametric curve: x = f(t), y = g(t).
\graphpaste{draw(curve(sin(t)*sin(2*t), sin(3*t)*sin(4*t)), t = 0..2*\%pi) 
\bound{example3}}
Space parametric curve: x = f(t), y = g(t), z = h(t).
\graphpaste{draw(curve(sin(t)*sin(2*t), sin(3*t)*sin(4*t), 
sin(5*t)*sin(6*t)), t = 0..2*\%pi) \bound{example4}}
Polar coordinates: r = f(theta).
\graphpaste{draw(sin(17*t), t = 0..2*\%pi, coordinates == polar) 
\bound{example5}}
Implicit curves: p(x,y) = 0.
\graphpaste{draw(y**2 + y = x**3 - x, x, y,range == \[-2..2,-2..1\]) 
\bound{example6}}
Run all examples.
\spadpaste{All \free{example1 example2 example3 example4 example5 example6}}
\endscroll
\autobuttons 
\end{page}

\begin{patch}{AssortedGraphicsExamplePagePatch1}
\begin{paste}{AssortedGraphicsExamplePageFull1}{AssortedGraphicsExamplePageEmpty1}
\pastebutton{AssortedGraphicsExamplePageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(sin(x * y), x = -2.5..2.5, y = -2.5..2.5)\bound{example1 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/assortedgraphicsexamplepage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/assortedgraphicsexamplepage1}}
\end{paste}\end{patch}

\begin{patch}{AssortedGraphicsExamplePageEmpty1}
\begin{paste}{AssortedGraphicsExamplePageEmpty1}{AssortedGraphicsExamplePagePatch1}
\pastebutton{AssortedGraphicsExamplePageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(sin(x * y), x = -2.5..2.5, y = -2.5..2.5)\bound{example1 }}
\end{paste}\end{patch}

\begin{patch}{AssortedGraphicsExamplePagePatch2}
\begin{paste}{AssortedGraphicsExamplePageFull2}{AssortedGraphicsExamplePageEmpty2}
\pastebutton{AssortedGraphicsExamplePageFull2}{\hidepaste}
\tab{5}\spadgraph{draw(sin tan x - tan sin x,x = 0..6)\bound{example2 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/assortedgraphicsexamplepage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/assortedgraphicsexamplepage2}}
\end{paste}\end{patch}

\begin{patch}{AssortedGraphicsExamplePageEmpty2}
\begin{paste}{AssortedGraphicsExamplePageEmpty2}{AssortedGraphicsExamplePagePatch2}
\pastebutton{AssortedGraphicsExamplePageEmpty2}{\showpaste}
\tab{5}\spadgraph{draw(sin tan x - tan sin x,x = 0..6)\bound{example2 }}
\end{paste}\end{patch}

\begin{patch}{AssortedGraphicsExamplePagePatch3}
\begin{paste}{AssortedGraphicsExamplePageFull3}{AssortedGraphicsExamplePageEmpty3}
\pastebutton{AssortedGraphicsExamplePageFull3}{\hidepaste}
\tab{5}\spadgraph{draw(curve(sin(t)*sin(2*t), sin(3*t)*sin(4*t)), t = 0..2*\%pi)\bound{example3 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/assortedgraphicsexamplepage3.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/assortedgraphicsexamplepage3}}
\end{paste}\end{patch}

\begin{patch}{AssortedGraphicsExamplePageEmpty3}
\begin{paste}{AssortedGraphicsExamplePageEmpty3}{AssortedGraphicsExamplePagePatch3}
\pastebutton{AssortedGraphicsExamplePageEmpty3}{\showpaste}
\tab{5}\spadgraph{draw(curve(sin(t)*sin(2*t), sin(3*t)*sin(4*t)), t = 0..2*\%pi)\bound{example3 }}
\end{paste}\end{patch}

\begin{patch}{AssortedGraphicsExamplePagePatch4}
\begin{paste}{AssortedGraphicsExamplePageFull4}{AssortedGraphicsExamplePageEmpty4}
\pastebutton{AssortedGraphicsExamplePageFull4}{\hidepaste}
\tab{5}\spadgraph{draw(curve(sin(t)*sin(2*t), sin(3*t)*sin(4*t), sin(5*t)*sin(6*t)), t = 0..2*\%pi)\bound{example4 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/assortedgraphicsexamplepage4.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/assortedgraphicsexamplepage4}}
\end{paste}\end{patch}

\begin{patch}{AssortedGraphicsExamplePageEmpty4}
\begin{paste}{AssortedGraphicsExamplePageEmpty4}{AssortedGraphicsExamplePagePatch4}
\pastebutton{AssortedGraphicsExamplePageEmpty4}{\showpaste}
\tab{5}\spadgraph{draw(curve(sin(t)*sin(2*t), sin(3*t)*sin(4*t), sin(5*t)*sin(6*t)), t = 0..2*\%pi)\bound{example4 }}
\end{paste}\end{patch}

\begin{patch}{AssortedGraphicsExamplePagePatch5}
\begin{paste}{AssortedGraphicsExamplePageFull5}{AssortedGraphicsExamplePageEmpty5}
\pastebutton{AssortedGraphicsExamplePageFull5}{\hidepaste}
\tab{5}\spadgraph{draw(sin(17*t), t = 0..2*\%pi, coordinates == polar)\bound{example5 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/assortedgraphicsexamplepage5.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/assortedgraphicsexamplepage5}}
\end{paste}\end{patch}

\begin{patch}{AssortedGraphicsExamplePageEmpty5}
\begin{paste}{AssortedGraphicsExamplePageEmpty5}{AssortedGraphicsExamplePagePatch5}
\pastebutton{AssortedGraphicsExamplePageEmpty5}{\showpaste}
\tab{5}\spadgraph{draw(sin(17*t), t = 0..2*\%pi, coordinates == polar)\bound{example5 }}
\end{paste}\end{patch}

\begin{patch}{AssortedGraphicsExamplePagePatch6}
\begin{paste}{AssortedGraphicsExamplePageFull6}{AssortedGraphicsExamplePageEmpty6}
\pastebutton{AssortedGraphicsExamplePageFull6}{\hidepaste}
\tab{5}\spadgraph{draw(y**2 + y = x**3 - x, x, y,range == [-2..2,-2..1])\bound{example6 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/assortedgraphicsexamplepage6.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/assortedgraphicsexamplepage6}}
\end{paste}\end{patch}

\begin{patch}{AssortedGraphicsExamplePageEmpty6}
\begin{paste}{AssortedGraphicsExamplePageEmpty6}{AssortedGraphicsExamplePagePatch6}
\pastebutton{AssortedGraphicsExamplePageEmpty6}{\showpaste}
\tab{5}\spadgraph{draw(y**2 + y = x**3 - x, x, y,range == [-2..2,-2..1])\bound{example6 }}
\end{paste}\end{patch}

\begin{patch}{AssortedGraphicsExamplePagePatch7}
\begin{paste}{AssortedGraphicsExamplePageFull7}{AssortedGraphicsExamplePageEmpty7}
\pastebutton{AssortedGraphicsExamplePageFull7}{\hidepaste}
\tab{5}\spadcommand{All\free{example1 example2 example3 example4 example5 example6 }}
\indentrel{3}\begin{verbatim}
   (7)  All
                                     Type: Variable All
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{AssortedGraphicsExamplePageEmpty7}
\begin{paste}{AssortedGraphicsExamplePageEmpty7}{AssortedGraphicsExamplePagePatch7}
\pastebutton{AssortedGraphicsExamplePageEmpty7}{\showpaste}
\tab{5}\spadcommand{All\free{example1 example2 example3 example4 example5 example6 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ThreeDimensionalGraphicsExamplePage}{graphics.ht}
{Three Dimensional Graphics}
\begin{chunk}{graphics.ht}
\begin{page}{ThreeDimensionalGraphicsExamplePage}
{Three Dimensional Graphics}
Plots of parametric surfaces defined by functions f(u,v), g(u,v), 
and h(u,v). Choose a particular example or choose 'All' to see 
all the examples.
\beginscroll
Pear Surface.
\graphpaste{draw(surface((1+exp(-100*u*u))*sin(\%pi*u)*sin(\%pi*v), 
(1+exp(-100*u*u))*sin(\%pi*u)*cos(\%pi*v), 
(1+exp(-100*u*u))*cos(\%pi*u)), u=0..1, v=0..2, title=="Pear") 
\bound{example1}}
Trigonometric Screw.
\graphpaste{draw(surface(x*cos(y),x*sin(y),y*cos(x)), 
x=-4..4, y=0..2*\%pi, var1Steps==40, var2Steps==40, 
title=="Trig Screw") \bound{example2}}
Etruscan Venus. \newline
(click on the draw button to execute this example)
\spadpaste{a := 1.3 * cos(2*x) * cos(y) + sin(y) * cos(x)\bound{a}} 
\newline
\spadpaste{b := 1.3 * sin(2*x) * cos(y) - sin(y) * sin(x)\bound{b}} 
\newline
\spadpaste{c := 2.5 * cos(y) \bound{c}} 
\newline
\graphpaste{draw(surface(a,b,c), x=0..\%pi, y=-\%pi..\%pi, 
var1Steps==40, var2Steps==40, title=="Etruscan Venus") 
\free{a b c} \bound{example3}}
Banchoff Klein Bottle. \newline
(click on the draw button to execute this example)
\spadpaste{f:=cos(x)*(cos(x/2)*(sqrt(2) + cos(y))+
(sin(x/2)*sin(y)*cos(y)))\bound{f}} 
\newline
\spadpaste{g:=sin(x)*(cos(x/2)*(sqrt(2) + cos(y))+
(sin(x/2)*sin(y)*cos(y)))\bound{g}} 
\newline
\spadpaste{h:=-sin(x/2)*(sqrt(2)+cos(y)) + 
cos(x/2)*sin(y)*cos(y) \bound{h}}
\newline
\graphpaste{draw(surface(f,g,h), x=0..4*\%pi, 
y=0..2*\%pi, var1Steps==50, var2Steps==50, 
title=="Banchoff Klein Bottle") \free{f g h} \bound{example4}}
\newline
\spadpaste{All \free{example1 example2 example3 example4}}
\endscroll
\autobuttons 
\end{page}

\begin{patch}{ThreeDimensionalGraphicsExamplePagePatch1}
\begin{paste}{ThreeDimensionalGraphicsExamplePageFull1}{ThreeDimensionalGraphicsExamplePageEmpty1}
\pastebutton{ThreeDimensionalGraphicsExamplePageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(surface((1+exp(-100*u*u))*sin(\%pi*u)*sin(\%pi*v), (1+exp(-100*u*u))*sin(\%pi*u)*cos(\%pi*v), (1+exp(-100*u*u))*cos(\%pi*u)), u=0..1, v=0..2, title=="Pear")\bound{example1 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/threedimensionalgraphicsexamplepage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/threedimensionalgraphicsexamplepage1}}
\end{paste}\end{patch}

\begin{patch}{ThreeDimensionalGraphicsExamplePageEmpty1}
\begin{paste}{ThreeDimensionalGraphicsExamplePageEmpty1}{ThreeDimensionalGraphicsExamplePagePatch1}
\pastebutton{ThreeDimensionalGraphicsExamplePageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(surface((1+exp(-100*u*u))*sin(\%pi*u)*sin(\%pi*v), (1+exp(-100*u*u))*sin(\%pi*u)*cos(\%pi*v), (1+exp(-100*u*u))*cos(\%pi*u)), u=0..1, v=0..2, title=="Pear")\bound{example1 }}
\end{paste}\end{patch}

\begin{patch}{ThreeDimensionalGraphicsExamplePagePatch2}
\begin{paste}{ThreeDimensionalGraphicsExamplePageFull2}{ThreeDimensionalGraphicsExamplePageEmpty2}
\pastebutton{ThreeDimensionalGraphicsExamplePageFull2}{\hidepaste}
\tab{5}\spadgraph{draw(surface(x*cos(y),x*sin(y),y*cos(x)), x=-4..4, y=0..2*\%pi, var1Steps==40, var2Steps==40, title=="Trig Screw")\bound{example2 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/threedimensionalgraphicsexamplepage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/threedimensionalgraphicsexamplepage2}}
\end{paste}\end{patch}

\begin{patch}{ThreeDimensionalGraphicsExamplePageEmpty2}
\begin{paste}{ThreeDimensionalGraphicsExamplePageEmpty2}{ThreeDimensionalGraphicsExamplePagePatch2}
\pastebutton{ThreeDimensionalGraphicsExamplePageEmpty2}{\showpaste}
\tab{5}\spadgraph{draw(surface(x*cos(y),x*sin(y),y*cos(x)), x=-4..4, y=0..2*\%pi, var1Steps==40, var2Steps==40, title=="Trig Screw")\bound{example2 }}
\end{paste}\end{patch}

\begin{patch}{ThreeDimensionalGraphicsExamplePagePatch3}
\begin{paste}{ThreeDimensionalGraphicsExamplePageFull3}{ThreeDimensionalGraphicsExamplePageEmpty3}
\pastebutton{ThreeDimensionalGraphicsExamplePageFull3}{\hidepaste}
\tab{5}\spadcommand{a := 1.3 * cos(2*x) * cos(y) + sin(y) * cos(x)\bound{a }}
\indentrel{3}\begin{verbatim}
   (3)  cos(x)sin(y) + 1.3 cos(2.0 x)cos(y)
                                 Type: Expression Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ThreeDimensionalGraphicsExamplePageEmpty3}
\begin{paste}{ThreeDimensionalGraphicsExamplePageEmpty3}{ThreeDimensionalGraphicsExamplePagePatch3}
\pastebutton{ThreeDimensionalGraphicsExamplePageEmpty3}{\showpaste}
\tab{5}\spadcommand{a := 1.3 * cos(2*x) * cos(y) + sin(y) * cos(x)\bound{a }}
\end{paste}\end{patch}

\begin{patch}{ThreeDimensionalGraphicsExamplePagePatch4}
\begin{paste}{ThreeDimensionalGraphicsExamplePageFull4}{ThreeDimensionalGraphicsExamplePageEmpty4}
\pastebutton{ThreeDimensionalGraphicsExamplePageFull4}{\hidepaste}
\tab{5}\spadcommand{b := 1.3 * sin(2*x) * cos(y) - sin(y) * sin(x)\bound{b }}
\indentrel{3}\begin{verbatim}
   (4)  - 1.0 sin(x)sin(y) + 1.3 cos(y)sin(2.0 x)
                                 Type: Expression Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ThreeDimensionalGraphicsExamplePageEmpty4}
\begin{paste}{ThreeDimensionalGraphicsExamplePageEmpty4}{ThreeDimensionalGraphicsExamplePagePatch4}
\pastebutton{ThreeDimensionalGraphicsExamplePageEmpty4}{\showpaste}
\tab{5}\spadcommand{b := 1.3 * sin(2*x) * cos(y) - sin(y) * sin(x)\bound{b }}
\end{paste}\end{patch}

\begin{patch}{ThreeDimensionalGraphicsExamplePagePatch5}
\begin{paste}{ThreeDimensionalGraphicsExamplePageFull5}{ThreeDimensionalGraphicsExamplePageEmpty5}
\pastebutton{ThreeDimensionalGraphicsExamplePageFull5}{\hidepaste}
\tab{5}\spadcommand{c := 2.5 * cos(y)\bound{c }}
\indentrel{3}\begin{verbatim}
   (5)  2.5 cos(y)
                                 Type: Expression Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ThreeDimensionalGraphicsExamplePageEmpty5}
\begin{paste}{ThreeDimensionalGraphicsExamplePageEmpty5}{ThreeDimensionalGraphicsExamplePagePatch5}
\pastebutton{ThreeDimensionalGraphicsExamplePageEmpty5}{\showpaste}
\tab{5}\spadcommand{c := 2.5 * cos(y)\bound{c }}
\end{paste}\end{patch}

\begin{patch}{ThreeDimensionalGraphicsExamplePagePatch6}
\begin{paste}{ThreeDimensionalGraphicsExamplePageFull6}{ThreeDimensionalGraphicsExamplePageEmpty6}
\pastebutton{ThreeDimensionalGraphicsExamplePageFull6}{\hidepaste}
\tab{5}\spadgraph{draw(surface(a,b,c), x=0..\%pi, y=-\%pi..\%pi, var1Steps==40, var2Steps==40, title=="Etruscan Venus")\free{a b c }\bound{example3 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/threedimensionalgraphicsexamplepage6.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/threedimensionalgraphicsexamplepage6}}
\end{paste}\end{patch}

\begin{patch}{ThreeDimensionalGraphicsExamplePageEmpty6}
\begin{paste}{ThreeDimensionalGraphicsExamplePageEmpty6}{ThreeDimensionalGraphicsExamplePagePatch6}
\pastebutton{ThreeDimensionalGraphicsExamplePageEmpty6}{\showpaste}
\tab{5}\spadgraph{draw(surface(a,b,c), x=0..\%pi, y=-\%pi..\%pi, var1Steps==40, var2Steps==40, title=="Etruscan Venus")\free{a b c }\bound{example3 }}
\end{paste}\end{patch}

\begin{patch}{ThreeDimensionalGraphicsExamplePagePatch7}
\begin{paste}{ThreeDimensionalGraphicsExamplePageFull7}{ThreeDimensionalGraphicsExamplePageEmpty7}
\pastebutton{ThreeDimensionalGraphicsExamplePageFull7}{\hidepaste}
\tab{5}\spadcommand{f:=cos(x)*(cos(x/2)*(sqrt(2) + cos(y))+(sin(x/2)*sin(y)*cos(y)))\bound{f }}
\indentrel{3}\begin{verbatim}
   (7)
                     x              x
     cos(x)cos(y)sin(Ä)sin(y) + cos(Ä)cos(x)cos(y)
                     2              2
   + 
      ÚÄ¿    x
     \³2 cos(Ä)cos(x)
             2
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ThreeDimensionalGraphicsExamplePageEmpty7}
\begin{paste}{ThreeDimensionalGraphicsExamplePageEmpty7}{ThreeDimensionalGraphicsExamplePagePatch7}
\pastebutton{ThreeDimensionalGraphicsExamplePageEmpty7}{\showpaste}
\tab{5}\spadcommand{f:=cos(x)*(cos(x/2)*(sqrt(2) + cos(y))+(sin(x/2)*sin(y)*cos(y)))\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ThreeDimensionalGraphicsExamplePagePatch8}
\begin{paste}{ThreeDimensionalGraphicsExamplePageFull8}{ThreeDimensionalGraphicsExamplePageEmpty8}
\pastebutton{ThreeDimensionalGraphicsExamplePageFull8}{\hidepaste}
\tab{5}\spadcommand{g:=sin(x)*(cos(x/2)*(sqrt(2) + cos(y))+(sin(x/2)*sin(y)*cos(y)))\bound{g }}
\indentrel{3}\begin{verbatim}
   (8)
               x
     cos(y)sin(Ä)sin(x)sin(y)
               2
   + 
          x           ÚÄ¿    x
     (cos(Ä)cos(y) + \³2 cos(Ä))sin(x)
          2                  2
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ThreeDimensionalGraphicsExamplePageEmpty8}
\begin{paste}{ThreeDimensionalGraphicsExamplePageEmpty8}{ThreeDimensionalGraphicsExamplePagePatch8}
\pastebutton{ThreeDimensionalGraphicsExamplePageEmpty8}{\showpaste}
\tab{5}\spadcommand{g:=sin(x)*(cos(x/2)*(sqrt(2) + cos(y))+(sin(x/2)*sin(y)*cos(y)))\bound{g }}
\end{paste}\end{patch}

\begin{patch}{ThreeDimensionalGraphicsExamplePagePatch9}
\begin{paste}{ThreeDimensionalGraphicsExamplePageFull9}{ThreeDimensionalGraphicsExamplePageEmpty9}
\pastebutton{ThreeDimensionalGraphicsExamplePageFull9}{\hidepaste}
\tab{5}\spadcommand{h:=-sin(x/2)*(sqrt(2)+cos(y)) + cos(x/2)*sin(y)*cos(y)\bound{h }}
\indentrel{3}\begin{verbatim}
            x                             ÚÄ¿     x
   (9)  cos(Ä)cos(y)sin(y) + (- cos(y) - \³2 )sin(Ä)
            2                                     2
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ThreeDimensionalGraphicsExamplePageEmpty9}
\begin{paste}{ThreeDimensionalGraphicsExamplePageEmpty9}{ThreeDimensionalGraphicsExamplePagePatch9}
\pastebutton{ThreeDimensionalGraphicsExamplePageEmpty9}{\showpaste}
\tab{5}\spadcommand{h:=-sin(x/2)*(sqrt(2)+cos(y)) + cos(x/2)*sin(y)*cos(y)\bound{h }}
\end{paste}\end{patch}

\begin{patch}{ThreeDimensionalGraphicsExamplePagePatch10}
\begin{paste}{ThreeDimensionalGraphicsExamplePageFull10}{ThreeDimensionalGraphicsExamplePageEmpty10}
\pastebutton{ThreeDimensionalGraphicsExamplePageFull10}{\hidepaste}
\tab{5}\spadgraph{draw(surface(f,g,h), x=0..4*\%pi, y=0..2*\%pi, var1Steps==50, var2Steps==50, title=="Banchoff Klein Bottle")\free{f g h }\bound{example4 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/threedimensionalgraphicsexamplepage10.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/threedimensionalgraphicsexamplepage10}}
\end{paste}\end{patch}

\begin{patch}{ThreeDimensionalGraphicsExamplePageEmpty10}
\begin{paste}{ThreeDimensionalGraphicsExamplePageEmpty10}{ThreeDimensionalGraphicsExamplePagePatch10}
\pastebutton{ThreeDimensionalGraphicsExamplePageEmpty10}{\showpaste}
\tab{5}\spadgraph{draw(surface(f,g,h), x=0..4*\%pi, y=0..2*\%pi, var1Steps==50, var2Steps==50, title=="Banchoff Klein Bottle")\free{f g h }\bound{example4 }}
\end{paste}\end{patch}

\begin{patch}{ThreeDimensionalGraphicsExamplePagePatch11}
\begin{paste}{ThreeDimensionalGraphicsExamplePageFull11}{ThreeDimensionalGraphicsExamplePageEmpty11}
\pastebutton{ThreeDimensionalGraphicsExamplePageFull11}{\hidepaste}
\tab{5}\spadcommand{All\free{example1 example2 example3 example4 }}
\indentrel{3}\begin{verbatim}
   (11)  All
                                     Type: Variable All
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ThreeDimensionalGraphicsExamplePageEmpty11}
\begin{paste}{ThreeDimensionalGraphicsExamplePageEmpty11}{ThreeDimensionalGraphicsExamplePagePatch11}
\pastebutton{ThreeDimensionalGraphicsExamplePageEmpty11}{\showpaste}
\tab{5}\spadcommand{All\free{example1 example2 example3 example4 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{OneVariableGraphicsExamplePage}{graphics.ht}
{Functions of One Variable}
\begin{chunk}{graphics.ht}
\begin{page}{OneVariableGraphicsExamplePage}{Functions of One Variable}
\beginscroll
Plots of functions y = f(x).
Choose a particular example or choose 'All' to see all the examples.
\graphpaste{draw(sin tan x - tan sin x, x = 0..6) \bound{example1}}
\newline
\graphpaste{draw(sin x + cos x, x = 0..2*\%pi) \bound{example2}}
\newline
\graphpaste{draw(sin(1/x), x = -1..1) \bound{example3}}
\newline
\graphpaste{draw(x * sin(1/x), x = -1..1) \bound{example4}}
\newline
\spadpaste{All \free{example1 example2 example3 example4}}
\endscroll
\autobuttons 
\end{page}

\begin{patch}{OneVariableGraphicsExamplePagePatch1}
\begin{paste}{OneVariableGraphicsExamplePageFull1}{OneVariableGraphicsExamplePageEmpty1}
\pastebutton{OneVariableGraphicsExamplePageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(sin tan x - tan sin x, x = 0..6)\bound{example1 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/onevariablegraphicsexamplepage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/onevariablegraphicsexamplepage1}}
\end{paste}\end{patch}

\begin{patch}{OneVariableGraphicsExamplePageEmpty1}
\begin{paste}{OneVariableGraphicsExamplePageEmpty1}{OneVariableGraphicsExamplePagePatch1}
\pastebutton{OneVariableGraphicsExamplePageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(sin tan x - tan sin x, x = 0..6)\bound{example1 }}
\end{paste}\end{patch}

\begin{patch}{OneVariableGraphicsExamplePagePatch2}
\begin{paste}{OneVariableGraphicsExamplePageFull2}{OneVariableGraphicsExamplePageEmpty2}
\pastebutton{OneVariableGraphicsExamplePageFull2}{\hidepaste}
\tab{5}\spadgraph{draw(sin x + cos x, x = 0..2*\%pi)\bound{example2 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/onevariablegraphicsexamplepage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/onevariablegraphicsexamplepage2}}
\end{paste}\end{patch}

\begin{patch}{OneVariableGraphicsExamplePageEmpty2}
\begin{paste}{OneVariableGraphicsExamplePageEmpty2}{OneVariableGraphicsExamplePagePatch2}
\pastebutton{OneVariableGraphicsExamplePageEmpty2}{\showpaste}
\tab{5}\spadgraph{draw(sin x + cos x, x = 0..2*\%pi)\bound{example2 }}
\end{paste}\end{patch}

\begin{patch}{OneVariableGraphicsExamplePagePatch3}
\begin{paste}{OneVariableGraphicsExamplePageFull3}{OneVariableGraphicsExamplePageEmpty3}
\pastebutton{OneVariableGraphicsExamplePageFull3}{\hidepaste}
\tab{5}\spadgraph{draw(sin(1/x), x = -1..1)\bound{example3 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/onevariablegraphicsexamplepage3.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/onevariablegraphicsexamplepage3}}
\end{paste}\end{patch}

\begin{patch}{OneVariableGraphicsExamplePageEmpty3}
\begin{paste}{OneVariableGraphicsExamplePageEmpty3}{OneVariableGraphicsExamplePagePatch3}
\pastebutton{OneVariableGraphicsExamplePageEmpty3}{\showpaste}
\tab{5}\spadgraph{draw(sin(1/x), x = -1..1)\bound{example3 }}
\end{paste}\end{patch}

\begin{patch}{OneVariableGraphicsExamplePagePatch4}
\begin{paste}{OneVariableGraphicsExamplePageFull4}{OneVariableGraphicsExamplePageEmpty4}
\pastebutton{OneVariableGraphicsExamplePageFull4}{\hidepaste}
\tab{5}\spadgraph{draw(x * sin(1/x), x = -1..1)\bound{example4 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/onevariablegraphicsexamplepage4.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/onevariablegraphicsexamplepage4}}
\end{paste}\end{patch}

\begin{patch}{OneVariableGraphicsExamplePageEmpty4}
\begin{paste}{OneVariableGraphicsExamplePageEmpty4}{OneVariableGraphicsExamplePagePatch4}
\pastebutton{OneVariableGraphicsExamplePageEmpty4}{\showpaste}
\tab{5}\spadgraph{draw(x * sin(1/x), x = -1..1)\bound{example4 }}
\end{paste}\end{patch}

\begin{patch}{OneVariableGraphicsExamplePagePatch5}
\begin{paste}{OneVariableGraphicsExamplePageFull5}{OneVariableGraphicsExamplePageEmpty5}
\pastebutton{OneVariableGraphicsExamplePageFull5}{\hidepaste}
\tab{5}\spadcommand{All\free{example1 example2 example3 example4 }}
\indentrel{3}\begin{verbatim}
   (5)  All
                                     Type: Variable All
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OneVariableGraphicsExamplePageEmpty5}
\begin{paste}{OneVariableGraphicsExamplePageEmpty5}{OneVariableGraphicsExamplePagePatch5}
\pastebutton{OneVariableGraphicsExamplePageEmpty5}{\showpaste}
\tab{5}\spadcommand{All\free{example1 example2 example3 example4 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ParametricCurveGraphicsExamplePage}{graphics.ht}
{Parametric Curves}
\begin{chunk}{graphics.ht}
\begin{page}{ParametricCurveGraphicsExamplePage}{Parametric Curves}
Plots of parametric curves x = f(t), y = g(t).
Pick a particular example or choose 'All' to see all the examples.
\beginscroll
The Lemniscate of Bernoulli.
\graphpaste{draw(curve(cos(t/(1+sin(t)**2)), 
sin(t)*cos(t)/(1+sin(t)**2)), t = -\%pi..\%pi) \bound{example1}}
Lissajous curve.
\graphpaste{draw(curve(9*sin(3*t/4), 8*sin(t)), 
t = -4*\%pi..4*\%pi) \bound{example2}}
A gnarly closed curve.
\graphpaste{draw(curve(sin(t)*sin(2*t)*sin(3*t), 
sin(4*t)*sin(5*t)*sin(6*t)),t = 0..2*\%pi)
             \bound{example3}}
Another closed curve.
\graphpaste{draw(curve(cos(4*t)*cos(7*t), cos(4*t)*sin(7*t)), 
t = 0..2*\%pi) \bound{example4}}
Run all examples on this page.
\spadpaste{All \free{example1 example2 example3 example4}}
\endscroll
\autobuttons 
\end{page}

\begin{patch}{ParametricCurveGraphicsExamplePagePatch1}
\begin{paste}{ParametricCurveGraphicsExamplePageFull1}{ParametricCurveGraphicsExamplePageEmpty1}
\pastebutton{ParametricCurveGraphicsExamplePageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(curve(cos(t/(1+sin(t)**2)), sin(t)*cos(t)/(1+sin(t)**2)), t = -\%pi..\%pi)\bound{example1 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/parametriccurvegraphicsexamplepage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/parametriccurvegraphicsexamplepage1}}
\end{paste}\end{patch}

\begin{patch}{ParametricCurveGraphicsExamplePageEmpty1}
\begin{paste}{ParametricCurveGraphicsExamplePageEmpty1}{ParametricCurveGraphicsExamplePagePatch1}
\pastebutton{ParametricCurveGraphicsExamplePageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(curve(cos(t/(1+sin(t)**2)), sin(t)*cos(t)/(1+sin(t)**2)), t = -\%pi..\%pi)\bound{example1 }}
\end{paste}\end{patch}

\begin{patch}{ParametricCurveGraphicsExamplePagePatch2}
\begin{paste}{ParametricCurveGraphicsExamplePageFull2}{ParametricCurveGraphicsExamplePageEmpty2}
\pastebutton{ParametricCurveGraphicsExamplePageFull2}{\hidepaste}
\tab{5}\spadgraph{draw(curve(9*sin(3*t/4), 8*sin(t)), t = -4*\%pi..4*\%pi)\bound{example2 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/parametriccurvegraphicsexamplepage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/parametriccurvegraphicsexamplepage2}}
\end{paste}\end{patch}

\begin{patch}{ParametricCurveGraphicsExamplePageEmpty2}
\begin{paste}{ParametricCurveGraphicsExamplePageEmpty2}{ParametricCurveGraphicsExamplePagePatch2}
\pastebutton{ParametricCurveGraphicsExamplePageEmpty2}{\showpaste}
\tab{5}\spadgraph{draw(curve(9*sin(3*t/4), 8*sin(t)), t = -4*\%pi..4*\%pi)\bound{example2 }}
\end{paste}\end{patch}

\begin{patch}{ParametricCurveGraphicsExamplePagePatch3}
\begin{paste}{ParametricCurveGraphicsExamplePageFull3}{ParametricCurveGraphicsExamplePageEmpty3}
\pastebutton{ParametricCurveGraphicsExamplePageFull3}{\hidepaste}
\tab{5}\spadgraph{draw(curve(sin(t)*sin(2*t)*sin(3*t), sin(4*t)*sin(5*t)*sin(6*t)),t = 0..2*\%pi)\bound{example3 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/parametriccurvegraphicsexamplepage3.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/parametriccurvegraphicsexamplepage3}}
\end{paste}\end{patch}

\begin{patch}{ParametricCurveGraphicsExamplePageEmpty3}
\begin{paste}{ParametricCurveGraphicsExamplePageEmpty3}{ParametricCurveGraphicsExamplePagePatch3}
\pastebutton{ParametricCurveGraphicsExamplePageEmpty3}{\showpaste}
\tab{5}\spadgraph{draw(curve(sin(t)*sin(2*t)*sin(3*t), sin(4*t)*sin(5*t)*sin(6*t)),t = 0..2*\%pi)\bound{example3 }}
\end{paste}\end{patch}

\begin{patch}{ParametricCurveGraphicsExamplePagePatch4}
\begin{paste}{ParametricCurveGraphicsExamplePageFull4}{ParametricCurveGraphicsExamplePageEmpty4}
\pastebutton{ParametricCurveGraphicsExamplePageFull4}{\hidepaste}
\tab{5}\spadgraph{draw(curve(cos(4*t)*cos(7*t), cos(4*t)*sin(7*t)), t = 0..2*\%pi)\bound{example4 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/parametriccurvegraphicsexamplepage4.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/parametriccurvegraphicsexamplepage4}}
\end{paste}\end{patch}

\begin{patch}{ParametricCurveGraphicsExamplePageEmpty4}
\begin{paste}{ParametricCurveGraphicsExamplePageEmpty4}{ParametricCurveGraphicsExamplePagePatch4}
\pastebutton{ParametricCurveGraphicsExamplePageEmpty4}{\showpaste}
\tab{5}\spadgraph{draw(curve(cos(4*t)*cos(7*t), cos(4*t)*sin(7*t)), t = 0..2*\%pi)\bound{example4 }}
\end{paste}\end{patch}

\begin{patch}{ParametricCurveGraphicsExamplePagePatch5}
\begin{paste}{ParametricCurveGraphicsExamplePageFull5}{ParametricCurveGraphicsExamplePageEmpty5}
\pastebutton{ParametricCurveGraphicsExamplePageFull5}{\hidepaste}
\tab{5}\spadcommand{All\free{example1 example2 example3 example4 }}
\indentrel{3}\begin{verbatim}
   (5)  All
                                     Type: Variable All
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ParametricCurveGraphicsExamplePageEmpty5}
\begin{paste}{ParametricCurveGraphicsExamplePageEmpty5}{ParametricCurveGraphicsExamplePagePatch5}
\pastebutton{ParametricCurveGraphicsExamplePageEmpty5}{\showpaste}
\tab{5}\spadcommand{All\free{example1 example2 example3 example4 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{PolarGraphicsExamplePage}{graphics.ht}{Polar Coordinates}
\begin{chunk}{graphics.ht}
\begin{page}{PolarGraphicsExamplePage}{Polar Coordinates}
Plots of curves given by an equation in polar coordinates, r = f(theta).
Pick a particular example or choose 'All' to see all the examples.
\beginscroll
A Circle.
\graphpaste{draw(1,t = 0..2*\%pi, coordinates == polar) \bound{example1} }
A Spiral.
\graphpaste{draw(t,t = 0..100, coordinates == polar) \bound{example2} }
A Petal Curve.
\graphpaste{draw(sin(4*t), t = 0..2*\%pi, coordinates == polar) 
\bound{example3} }
A Limacon.
\graphpaste{draw(2 + 3 * sin t, t = 0..2*\%pi, coordinates == polar) 
\bound{example4} }
Run all examples on this page.
\spadpaste{All \free{
%example1
example2 example3 example4}}
\endscroll
\autobuttons 
\end{page}

\begin{patch}{PolarGraphicsExamplePagePatch1}
\begin{paste}{PolarGraphicsExamplePageFull1}{PolarGraphicsExamplePageEmpty1}
\pastebutton{PolarGraphicsExamplePageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(1,t = 0..2*\%pi, coordinates == polar)\bound{example1 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/polargraphicsexamplepage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/polargraphicsexamplepage1}}
\end{paste}\end{patch}

\begin{patch}{PolarGraphicsExamplePageEmpty1}
\begin{paste}{PolarGraphicsExamplePageEmpty1}{PolarGraphicsExamplePagePatch1}
\pastebutton{PolarGraphicsExamplePageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(1,t = 0..2*\%pi, coordinates == polar)\bound{example1 }}
\end{paste}\end{patch}

\begin{patch}{PolarGraphicsExamplePagePatch2}
\begin{paste}{PolarGraphicsExamplePageFull2}{PolarGraphicsExamplePageEmpty2}
\pastebutton{PolarGraphicsExamplePageFull2}{\hidepaste}
\tab{5}\spadgraph{draw(t,t = 0..100, coordinates == polar)\bound{example2 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/polargraphicsexamplepage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/polargraphicsexamplepage2}}
\end{paste}\end{patch}

\begin{patch}{PolarGraphicsExamplePageEmpty2}
\begin{paste}{PolarGraphicsExamplePageEmpty2}{PolarGraphicsExamplePagePatch2}
\pastebutton{PolarGraphicsExamplePageEmpty2}{\showpaste}
\tab{5}\spadgraph{draw(t,t = 0..100, coordinates == polar)\bound{example2 }}
\end{paste}\end{patch}

\begin{patch}{PolarGraphicsExamplePagePatch3}
\begin{paste}{PolarGraphicsExamplePageFull3}{PolarGraphicsExamplePageEmpty3}
\pastebutton{PolarGraphicsExamplePageFull3}{\hidepaste}
\tab{5}\spadgraph{draw(sin(4*t), t = 0..2*\%pi, coordinates == polar)\bound{example3 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/polargraphicsexamplepage3.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/polargraphicsexamplepage3}}
\end{paste}\end{patch}

\begin{patch}{PolarGraphicsExamplePageEmpty3}
\begin{paste}{PolarGraphicsExamplePageEmpty3}{PolarGraphicsExamplePagePatch3}
\pastebutton{PolarGraphicsExamplePageEmpty3}{\showpaste}
\tab{5}\spadgraph{draw(sin(4*t), t = 0..2*\%pi, coordinates == polar)\bound{example3 }}
\end{paste}\end{patch}

\begin{patch}{PolarGraphicsExamplePagePatch4}
\begin{paste}{PolarGraphicsExamplePageFull4}{PolarGraphicsExamplePageEmpty4}
\pastebutton{PolarGraphicsExamplePageFull4}{\hidepaste}
\tab{5}\spadgraph{draw(2 + 3 * sin t, t = 0..2*\%pi, coordinates == polar)\bound{example4 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/polargraphicsexamplepage4.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/polargraphicsexamplepage4}}
\end{paste}\end{patch}

\begin{patch}{PolarGraphicsExamplePageEmpty4}
\begin{paste}{PolarGraphicsExamplePageEmpty4}{PolarGraphicsExamplePagePatch4}
\pastebutton{PolarGraphicsExamplePageEmpty4}{\showpaste}
\tab{5}\spadgraph{draw(2 + 3 * sin t, t = 0..2*\%pi, coordinates == polar)\bound{example4 }}
\end{paste}\end{patch}

\begin{patch}{PolarGraphicsExamplePagePatch5}
\begin{paste}{PolarGraphicsExamplePageFull5}{PolarGraphicsExamplePageEmpty5}
\pastebutton{PolarGraphicsExamplePageFull5}{\hidepaste}
\tab{5}\spadcommand{All\free{example2 example3 example4 }}
\indentrel{3}\begin{verbatim}
   (5)  All
                                     Type: Variable All
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolarGraphicsExamplePageEmpty5}
\begin{paste}{PolarGraphicsExamplePageEmpty5}{PolarGraphicsExamplePagePatch5}
\pastebutton{PolarGraphicsExamplePageEmpty5}{\showpaste}
\tab{5}\spadcommand{All\free{example2 example3 example4 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ImplicitCurveGraphicsExamplePage}{graphics.ht}{Implicit Curves}
\begin{chunk}{graphics.ht}
\begin{page}{ImplicitCurveGraphicsExamplePage}{Implicit Curves}
Non-singular curves defined by a polynomial equation p(x,y) = 0
in a rectangular region in the plane.
Pick a particular example or choose 'All' to see all the examples.
\beginscroll
A Conic Section (Hyperbola).
\graphpaste{draw(x * y = 1, x, y, range == \[-3..3, -3..3\]) 
\bound{example1} }
An Elliptic Curve.
\graphpaste{draw(y**2 + y = x**3 - x, x, y, 
range == \[-2..2, -2..1\]) \bound{example2} }
Cartesian Ovals.
\spadpaste{p := ((x**2 + y**2 + 1) - 8*x)**2 - 
(8*(x**2 + y**2 + 1) - 4*x - 1) \bound{p} }
\graphpaste{draw(p = 0, x, y, range == \[-1..11, -7..7\], 
title == "Cartesian Ovals") \free{p} \bound{example3} }
Cassinian Ovals: two loops.
\spadpaste{q := (x**2 + y**2 + 7**2)**2 - (6**4 + 4*7**2*x**2) 
\bound{q} }
\graphpaste{draw(q = 0, x, y, range == \[-10..10, -4..4\], 
title == "Cassinian oval with two loops") \free{q} \bound{example4} }
Run all examples on this page.
\spadpaste{All \free{example1 example2 example3 example4}}
\endscroll
\autobuttons 
\end{page}

\begin{patch}{ImplicitCurveGraphicsExamplePagePatch1}
\begin{paste}{ImplicitCurveGraphicsExamplePageFull1}{ImplicitCurveGraphicsExamplePageEmpty1}
\pastebutton{ImplicitCurveGraphicsExamplePageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(x * y = 1, x, y, range == [-3..3, -3..3])\bound{example1 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/implicitcurvegraphicsexamplepage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/implicitcurvegraphicsexamplepage1}}
\end{paste}\end{patch}

\begin{patch}{ImplicitCurveGraphicsExamplePageEmpty1}
\begin{paste}{ImplicitCurveGraphicsExamplePageEmpty1}{ImplicitCurveGraphicsExamplePagePatch1}
\pastebutton{ImplicitCurveGraphicsExamplePageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(x * y = 1, x, y, range == [-3..3, -3..3])\bound{example1 }}
\end{paste}\end{patch}

\begin{patch}{ImplicitCurveGraphicsExamplePagePatch2}
\begin{paste}{ImplicitCurveGraphicsExamplePageFull2}{ImplicitCurveGraphicsExamplePageEmpty2}
\pastebutton{ImplicitCurveGraphicsExamplePageFull2}{\hidepaste}
\tab{5}\spadgraph{draw(y**2 + y = x**3 - x, x, y, range == [-2..2, -2..1])\bound{example2 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/implicitcurvegraphicsexamplepage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/implicitcurvegraphicsexamplepage2}}
\end{paste}\end{patch}

\begin{patch}{ImplicitCurveGraphicsExamplePageEmpty2}
\begin{paste}{ImplicitCurveGraphicsExamplePageEmpty2}{ImplicitCurveGraphicsExamplePagePatch2}
\pastebutton{ImplicitCurveGraphicsExamplePageEmpty2}{\showpaste}
\tab{5}\spadgraph{draw(y**2 + y = x**3 - x, x, y, range == [-2..2, -2..1])\bound{example2 }}
\end{paste}\end{patch}

\begin{patch}{ImplicitCurveGraphicsExamplePagePatch3}
\begin{paste}{ImplicitCurveGraphicsExamplePageFull3}{ImplicitCurveGraphicsExamplePageEmpty3}
\pastebutton{ImplicitCurveGraphicsExamplePageFull3}{\hidepaste}
\tab{5}\spadcommand{p := ((x**2 + y**2 + 1) - 8*x)**2 - (8*(x**2 + y**2 + 1) - 4*x - 1)\bound{p }}
\indentrel{3}\begin{verbatim}
   (3)
    4      2            2    4      3      2
   y  + (2x  - 16x - 6)y  + x  - 16x  + 58x  - 12x - 6
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ImplicitCurveGraphicsExamplePageEmpty3}
\begin{paste}{ImplicitCurveGraphicsExamplePageEmpty3}{ImplicitCurveGraphicsExamplePagePatch3}
\pastebutton{ImplicitCurveGraphicsExamplePageEmpty3}{\showpaste}
\tab{5}\spadcommand{p := ((x**2 + y**2 + 1) - 8*x)**2 - (8*(x**2 + y**2 + 1) - 4*x - 1)\bound{p }}
\end{paste}\end{patch}

\begin{patch}{ImplicitCurveGraphicsExamplePagePatch4}
\begin{paste}{ImplicitCurveGraphicsExamplePageFull4}{ImplicitCurveGraphicsExamplePageEmpty4}
\pastebutton{ImplicitCurveGraphicsExamplePageFull4}{\hidepaste}
\tab{5}\spadgraph{draw(p = 0, x, y, range == [-1..11, -7..7], title == "Cartesian Ovals")\free{p }\bound{example3 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/implicitcurvegraphicsexamplepage4.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/implicitcurvegraphicsexamplepage4}}
\end{paste}\end{patch}

\begin{patch}{ImplicitCurveGraphicsExamplePageEmpty4}
\begin{paste}{ImplicitCurveGraphicsExamplePageEmpty4}{ImplicitCurveGraphicsExamplePagePatch4}
\pastebutton{ImplicitCurveGraphicsExamplePageEmpty4}{\showpaste}
\tab{5}\spadgraph{draw(p = 0, x, y, range == [-1..11, -7..7], title == "Cartesian Ovals")\free{p }\bound{example3 }}
\end{paste}\end{patch}

\begin{patch}{ImplicitCurveGraphicsExamplePagePatch5}
\begin{paste}{ImplicitCurveGraphicsExamplePageFull5}{ImplicitCurveGraphicsExamplePageEmpty5}
\pastebutton{ImplicitCurveGraphicsExamplePageFull5}{\hidepaste}
\tab{5}\spadcommand{q := (x**2 + y**2 + 7**2)**2 - (6**4 + 4*7**2*x**2)\bound{q }}
\indentrel{3}\begin{verbatim}
         4      2       2    4      2
   (5)  y  + (2x  + 98)y  + x  - 98x  + 1105
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ImplicitCurveGraphicsExamplePageEmpty5}
\begin{paste}{ImplicitCurveGraphicsExamplePageEmpty5}{ImplicitCurveGraphicsExamplePagePatch5}
\pastebutton{ImplicitCurveGraphicsExamplePageEmpty5}{\showpaste}
\tab{5}\spadcommand{q := (x**2 + y**2 + 7**2)**2 - (6**4 + 4*7**2*x**2)\bound{q }}
\end{paste}\end{patch}

\begin{patch}{ImplicitCurveGraphicsExamplePagePatch6}
\begin{paste}{ImplicitCurveGraphicsExamplePageFull6}{ImplicitCurveGraphicsExamplePageEmpty6}
\pastebutton{ImplicitCurveGraphicsExamplePageFull6}{\hidepaste}
\tab{5}\spadgraph{draw(q = 0, x, y, range == [-10..10, -4..4], title == "Cassinian oval with two loops")\free{q }\bound{example4 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/implicitcurvegraphicsexamplepage6.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/implicitcurvegraphicsexamplepage6}}
\end{paste}\end{patch}

\begin{patch}{ImplicitCurveGraphicsExamplePageEmpty6}
\begin{paste}{ImplicitCurveGraphicsExamplePageEmpty6}{ImplicitCurveGraphicsExamplePagePatch6}
\pastebutton{ImplicitCurveGraphicsExamplePageEmpty6}{\showpaste}
\tab{5}\spadgraph{draw(q = 0, x, y, range == [-10..10, -4..4], title == "Cassinian oval with two loops")\free{q }\bound{example4 }}
\end{paste}\end{patch}

\begin{patch}{ImplicitCurveGraphicsExamplePagePatch7}
\begin{paste}{ImplicitCurveGraphicsExamplePageFull7}{ImplicitCurveGraphicsExamplePageEmpty7}
\pastebutton{ImplicitCurveGraphicsExamplePageFull7}{\hidepaste}
\tab{5}\spadcommand{All\free{example1 example2 example3 example4 }}
\indentrel{3}\begin{verbatim}
   (7)  All
                                     Type: Variable All
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ImplicitCurveGraphicsExamplePageEmpty7}
\begin{paste}{ImplicitCurveGraphicsExamplePageEmpty7}{ImplicitCurveGraphicsExamplePagePatch7}
\pastebutton{ImplicitCurveGraphicsExamplePageEmpty7}{\showpaste}
\tab{5}\spadcommand{All\free{example1 example2 example3 example4 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ListPointsGraphicsExamplePage}{graphics.ht}{Lists of Points}
\begin{chunk}{graphics.ht}
\begin{page}{ListPointsGraphicsExamplePage}{Lists of Points}
Axiom has the ability to create lists of points in a two dimensional
graphics viewport.  This is done by utilizing the \spadtype{GraphImage} 
and \spadtype{TwoDimensionalViewport} domain facilities.
\beginscroll
\indent{5}\newline
{\em NOTE:  It is only necessary to click on the makeViewport2D 
command button to plot this curve example}.
\indent{0}\newline
\spadpaste{p1 := point [1::SF,1::SF]\$(Point SF) \bound{p1}} 
\newline
\spadpaste{p2 := point [0::SF,1::SF]\$(Point SF) \bound{p2}} 
\newline
\spadpaste{p3 := point [0::SF,0::SF]\$(Point SF) \bound{p3}} 
\newline
\spadpaste{p4 := point [1::SF,0::SF]\$(Point SF) \bound{p4}} 
\newline
\spadpaste{p5 := point [1::SF,.5::SF]\$(Point SF) \bound{p5}} 
\newline
\spadpaste{p6 := point [.5::SF,0::SF]\$(Point SF) \bound{p6}} 
\newline
\spadpaste{p7 := point [0::SF,0.5::SF]\$(Point SF) \bound{p7}} 
\newline
\spadpaste{p8 := point [.5::SF,1::SF]\$(Point SF) \bound{p8}} 
\newline
\spadpaste{p9 := point [.25::SF,.25::SF]\$(Point SF) \bound{p9}} 
\newline
\spadpaste{p10 := point [.25::SF,.75::SF]\$(Point SF) \bound{p10}} 
\newline
\spadpaste{p11 := point [.75::SF,.75::SF]\$(Point SF) \bound{p11}} 
\newline
\spadpaste{p12 := point [.75::SF,.25::SF]\$(Point SF) \bound{p12}} 
\newline
\spadpaste{llp := [[p1,p2],[p2,p3],[p3,p4],[p4,p1],[p5,p6],[p6,p7],
[p7,p8],[p8,p5],[p9,p10],[p10,p11],[p11,p12],[p12,p9]] \bound{llp} 
\free{p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12}} 
\newline
\spadpaste{size1 := 6::PositiveInteger \bound{size1}} 
\newline
\spadpaste{size2 := 8::PositiveInteger \bound{size2}} 
\newline
\spadpaste{size3 := 10::PositiveInteger \bound{size3}} 
\newline
\spadpaste{lsize := [size1, size1, size1, size1, size2, size2, 
size2, size2, size3, size3, size3, size3] \bound{lsize} 
\free{size1 size2 size3}} 
\newline
\spadpaste{pc1 := pastel red() \bound{pc1}} 
\newline
\spadpaste{pc2 := dim green() \bound{pc2}} 
\newline
\spadpaste{pc3 := pastel yellow() \bound{pc3}} 
\newline
\spadpaste{lpc := [pc1, pc1, pc1, pc1, pc2, pc2, pc2, pc2, pc3, 
pc3, pc3, pc3] \bound{lpc} \free{pc1 pc2 pc3}} 
\newline
\spadpaste{lc := [pastel blue(), light yellow(), dim green(), 
bright red(), light green(), dim yellow(), bright blue(), 
dark red(), pastel red(), light blue(), dim green(), 
light yellow()] \bound{lc}} 
\newline
\spadpaste{g := makeGraphImage(llp,lpc,lc,lsize)\$GRIMAGE 
\bound{g} \free{llp lpc lc lsize}} 
\newline
\graphpaste{makeViewport2D(g,[title("Lines")])\$VIEW2D \free{g}}
The \spadfun{makeViewport2D} command takes a list of options 
as a parameter in this example.  The string "Lines" is designated 
as the viewport's title.
\endscroll
\autobuttons 
\end{page}

\begin{patch}{ListPointsGraphicsExamplePagePatch1}
\begin{paste}{ListPointsGraphicsExamplePageFull1}{ListPointsGraphicsExamplePageEmpty1}
\pastebutton{ListPointsGraphicsExamplePageFull1}{\hidepaste}
\tab{5}\spadcommand{p1 := point [1::SF,1::SF]$(Point SF)\bound{p1 }}
\indentrel{3}\begin{verbatim}
   (1)  [1.0,1.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty1}
\begin{paste}{ListPointsGraphicsExamplePageEmpty1}{ListPointsGraphicsExamplePagePatch1}
\pastebutton{ListPointsGraphicsExamplePageEmpty1}{\showpaste}
\tab{5}\spadcommand{p1 := point [1::SF,1::SF]$(Point SF)\bound{p1 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch2}
\begin{paste}{ListPointsGraphicsExamplePageFull2}{ListPointsGraphicsExamplePageEmpty2}
\pastebutton{ListPointsGraphicsExamplePageFull2}{\hidepaste}
\tab{5}\spadcommand{p2 := point [0::SF,1::SF]$(Point SF)\bound{p2 }}
\indentrel{3}\begin{verbatim}
   (2)  [0.0,1.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty2}
\begin{paste}{ListPointsGraphicsExamplePageEmpty2}{ListPointsGraphicsExamplePagePatch2}
\pastebutton{ListPointsGraphicsExamplePageEmpty2}{\showpaste}
\tab{5}\spadcommand{p2 := point [0::SF,1::SF]$(Point SF)\bound{p2 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch3}
\begin{paste}{ListPointsGraphicsExamplePageFull3}{ListPointsGraphicsExamplePageEmpty3}
\pastebutton{ListPointsGraphicsExamplePageFull3}{\hidepaste}
\tab{5}\spadcommand{p3 := point [0::SF,0::SF]$(Point SF)\bound{p3 }}
\indentrel{3}\begin{verbatim}
   (3)  [0.0,0.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty3}
\begin{paste}{ListPointsGraphicsExamplePageEmpty3}{ListPointsGraphicsExamplePagePatch3}
\pastebutton{ListPointsGraphicsExamplePageEmpty3}{\showpaste}
\tab{5}\spadcommand{p3 := point [0::SF,0::SF]$(Point SF)\bound{p3 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch4}
\begin{paste}{ListPointsGraphicsExamplePageFull4}{ListPointsGraphicsExamplePageEmpty4}
\pastebutton{ListPointsGraphicsExamplePageFull4}{\hidepaste}
\tab{5}\spadcommand{p4 := point [1::SF,0::SF]$(Point SF)\bound{p4 }}
\indentrel{3}\begin{verbatim}
   (4)  [1.0,0.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty4}
\begin{paste}{ListPointsGraphicsExamplePageEmpty4}{ListPointsGraphicsExamplePagePatch4}
\pastebutton{ListPointsGraphicsExamplePageEmpty4}{\showpaste}
\tab{5}\spadcommand{p4 := point [1::SF,0::SF]$(Point SF)\bound{p4 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch5}
\begin{paste}{ListPointsGraphicsExamplePageFull5}{ListPointsGraphicsExamplePageEmpty5}
\pastebutton{ListPointsGraphicsExamplePageFull5}{\hidepaste}
\tab{5}\spadcommand{p5 := point [1::SF,.5::SF]$(Point SF)\bound{p5 }}
\indentrel{3}\begin{verbatim}
   (5)  [1.0,0.5]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty5}
\begin{paste}{ListPointsGraphicsExamplePageEmpty5}{ListPointsGraphicsExamplePagePatch5}
\pastebutton{ListPointsGraphicsExamplePageEmpty5}{\showpaste}
\tab{5}\spadcommand{p5 := point [1::SF,.5::SF]$(Point SF)\bound{p5 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch6}
\begin{paste}{ListPointsGraphicsExamplePageFull6}{ListPointsGraphicsExamplePageEmpty6}
\pastebutton{ListPointsGraphicsExamplePageFull6}{\hidepaste}
\tab{5}\spadcommand{p6 := point [.5::SF,0::SF]$(Point SF)\bound{p6 }}
\indentrel{3}\begin{verbatim}
   (6)  [0.5,0.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty6}
\begin{paste}{ListPointsGraphicsExamplePageEmpty6}{ListPointsGraphicsExamplePagePatch6}
\pastebutton{ListPointsGraphicsExamplePageEmpty6}{\showpaste}
\tab{5}\spadcommand{p6 := point [.5::SF,0::SF]$(Point SF)\bound{p6 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch7}
\begin{paste}{ListPointsGraphicsExamplePageFull7}{ListPointsGraphicsExamplePageEmpty7}
\pastebutton{ListPointsGraphicsExamplePageFull7}{\hidepaste}
\tab{5}\spadcommand{p7 := point [0::SF,0.5::SF]$(Point SF)\bound{p7 }}
\indentrel{3}\begin{verbatim}
   (7)  [0.0,0.5]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty7}
\begin{paste}{ListPointsGraphicsExamplePageEmpty7}{ListPointsGraphicsExamplePagePatch7}
\pastebutton{ListPointsGraphicsExamplePageEmpty7}{\showpaste}
\tab{5}\spadcommand{p7 := point [0::SF,0.5::SF]$(Point SF)\bound{p7 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch8}
\begin{paste}{ListPointsGraphicsExamplePageFull8}{ListPointsGraphicsExamplePageEmpty8}
\pastebutton{ListPointsGraphicsExamplePageFull8}{\hidepaste}
\tab{5}\spadcommand{p8 := point [.5::SF,1::SF]$(Point SF)\bound{p8 }}
\indentrel{3}\begin{verbatim}
   (8)  [0.5,1.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty8}
\begin{paste}{ListPointsGraphicsExamplePageEmpty8}{ListPointsGraphicsExamplePagePatch8}
\pastebutton{ListPointsGraphicsExamplePageEmpty8}{\showpaste}
\tab{5}\spadcommand{p8 := point [.5::SF,1::SF]$(Point SF)\bound{p8 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch9}
\begin{paste}{ListPointsGraphicsExamplePageFull9}{ListPointsGraphicsExamplePageEmpty9}
\pastebutton{ListPointsGraphicsExamplePageFull9}{\hidepaste}
\tab{5}\spadcommand{p9 := point [.25::SF,.25::SF]$(Point SF)\bound{p9 }}
\indentrel{3}\begin{verbatim}
   (9)  [0.25,0.25]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty9}
\begin{paste}{ListPointsGraphicsExamplePageEmpty9}{ListPointsGraphicsExamplePagePatch9}
\pastebutton{ListPointsGraphicsExamplePageEmpty9}{\showpaste}
\tab{5}\spadcommand{p9 := point [.25::SF,.25::SF]$(Point SF)\bound{p9 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch10}
\begin{paste}{ListPointsGraphicsExamplePageFull10}{ListPointsGraphicsExamplePageEmpty10}
\pastebutton{ListPointsGraphicsExamplePageFull10}{\hidepaste}
\tab{5}\spadcommand{p10 := point [.25::SF,.75::SF]$(Point SF)\bound{p10 }}
\indentrel{3}\begin{verbatim}
   (10)  [0.25,0.75]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty10}
\begin{paste}{ListPointsGraphicsExamplePageEmpty10}{ListPointsGraphicsExamplePagePatch10}
\pastebutton{ListPointsGraphicsExamplePageEmpty10}{\showpaste}
\tab{5}\spadcommand{p10 := point [.25::SF,.75::SF]$(Point SF)\bound{p10 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch11}
\begin{paste}{ListPointsGraphicsExamplePageFull11}{ListPointsGraphicsExamplePageEmpty11}
\pastebutton{ListPointsGraphicsExamplePageFull11}{\hidepaste}
\tab{5}\spadcommand{p11 := point [.75::SF,.75::SF]$(Point SF)\bound{p11 }}
\indentrel{3}\begin{verbatim}
   (11)  [0.75,0.75]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty11}
\begin{paste}{ListPointsGraphicsExamplePageEmpty11}{ListPointsGraphicsExamplePagePatch11}
\pastebutton{ListPointsGraphicsExamplePageEmpty11}{\showpaste}
\tab{5}\spadcommand{p11 := point [.75::SF,.75::SF]$(Point SF)\bound{p11 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch12}
\begin{paste}{ListPointsGraphicsExamplePageFull12}{ListPointsGraphicsExamplePageEmpty12}
\pastebutton{ListPointsGraphicsExamplePageFull12}{\hidepaste}
\tab{5}\spadcommand{p12 := point [.75::SF,.25::SF]$(Point SF)\bound{p12 }}
\indentrel{3}\begin{verbatim}
   (12)  [0.75,0.25]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty12}
\begin{paste}{ListPointsGraphicsExamplePageEmpty12}{ListPointsGraphicsExamplePagePatch12}
\pastebutton{ListPointsGraphicsExamplePageEmpty12}{\showpaste}
\tab{5}\spadcommand{p12 := point [.75::SF,.25::SF]$(Point SF)\bound{p12 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch13}
\begin{paste}{ListPointsGraphicsExamplePageFull13}{ListPointsGraphicsExamplePageEmpty13}
\pastebutton{ListPointsGraphicsExamplePageFull13}{\hidepaste}
\tab{5}\spadcommand{llp := [[p1,p2],[p2,p3],[p3,p4],[p4,p1],[p5,p6],[p6,p7],[p7,p8],[p8,p5],[p9,p10],[p10,p11],[p11,p12],[p12,p9]]\bound{llp }\free{p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 }}
\indentrel{3}\begin{verbatim}
   (13)
   [[[1.0,1.0],[0.0,1.0]], [[0.0,1.0],[0.0,0.0]],
    [[0.0,0.0],[1.0,0.0]], [[1.0,0.0],[1.0,1.0]],
    [[1.0,0.5],[0.5,0.0]], [[0.5,0.0],[0.0,0.5]],
    [[0.0,0.5],[0.5,1.0]], [[0.5,1.0],[1.0,0.5]],
    [[0.25,0.25],[0.25,0.75]], [[0.25,0.75],[0.75,0.75]],
    [[0.75,0.75],[0.75,0.25]], [[0.75,0.25],[0.25,0.25]]]
                      Type: List List Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty13}
\begin{paste}{ListPointsGraphicsExamplePageEmpty13}{ListPointsGraphicsExamplePagePatch13}
\pastebutton{ListPointsGraphicsExamplePageEmpty13}{\showpaste}
\tab{5}\spadcommand{llp := [[p1,p2],[p2,p3],[p3,p4],[p4,p1],[p5,p6],[p6,p7],[p7,p8],[p8,p5],[p9,p10],[p10,p11],[p11,p12],[p12,p9]]\bound{llp }\free{p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch14}
\begin{paste}{ListPointsGraphicsExamplePageFull14}{ListPointsGraphicsExamplePageEmpty14}
\pastebutton{ListPointsGraphicsExamplePageFull14}{\hidepaste}
\tab{5}\spadcommand{size1 := 6::PositiveInteger\bound{size1 }}
\indentrel{3}\begin{verbatim}
   (14)  6
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty14}
\begin{paste}{ListPointsGraphicsExamplePageEmpty14}{ListPointsGraphicsExamplePagePatch14}
\pastebutton{ListPointsGraphicsExamplePageEmpty14}{\showpaste}
\tab{5}\spadcommand{size1 := 6::PositiveInteger\bound{size1 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch15}
\begin{paste}{ListPointsGraphicsExamplePageFull15}{ListPointsGraphicsExamplePageEmpty15}
\pastebutton{ListPointsGraphicsExamplePageFull15}{\hidepaste}
\tab{5}\spadcommand{size2 := 8::PositiveInteger\bound{size2 }}
\indentrel{3}\begin{verbatim}
   (15)  8
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty15}
\begin{paste}{ListPointsGraphicsExamplePageEmpty15}{ListPointsGraphicsExamplePagePatch15}
\pastebutton{ListPointsGraphicsExamplePageEmpty15}{\showpaste}
\tab{5}\spadcommand{size2 := 8::PositiveInteger\bound{size2 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch16}
\begin{paste}{ListPointsGraphicsExamplePageFull16}{ListPointsGraphicsExamplePageEmpty16}
\pastebutton{ListPointsGraphicsExamplePageFull16}{\hidepaste}
\tab{5}\spadcommand{size3 := 10::PositiveInteger\bound{size3 }}
\indentrel{3}\begin{verbatim}
   (16)  10
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty16}
\begin{paste}{ListPointsGraphicsExamplePageEmpty16}{ListPointsGraphicsExamplePagePatch16}
\pastebutton{ListPointsGraphicsExamplePageEmpty16}{\showpaste}
\tab{5}\spadcommand{size3 := 10::PositiveInteger\bound{size3 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch17}
\begin{paste}{ListPointsGraphicsExamplePageFull17}{ListPointsGraphicsExamplePageEmpty17}
\pastebutton{ListPointsGraphicsExamplePageFull17}{\hidepaste}
\tab{5}\spadcommand{lsize := [size1, size1, size1, size1, size2, size2, size2, size2, size3, size3, size3, size3]\bound{lsize }\free{size1 size2 size3 }}
\indentrel{3}\begin{verbatim}
   (17)  [6,6,6,6,8,8,8,8,10,10,10,10]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty17}
\begin{paste}{ListPointsGraphicsExamplePageEmpty17}{ListPointsGraphicsExamplePagePatch17}
\pastebutton{ListPointsGraphicsExamplePageEmpty17}{\showpaste}
\tab{5}\spadcommand{lsize := [size1, size1, size1, size1, size2, size2, size2, size2, size3, size3, size3, size3]\bound{lsize }\free{size1 size2 size3 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch18}
\begin{paste}{ListPointsGraphicsExamplePageFull18}{ListPointsGraphicsExamplePageEmpty18}
\pastebutton{ListPointsGraphicsExamplePageFull18}{\hidepaste}
\tab{5}\spadcommand{pc1 := pastel red()\bound{pc1 }}
\indentrel{3}\begin{verbatim}
   (18)  [Hue: 1  Weight: 1.0] from the Pastel palette
                                          Type: Palette
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty18}
\begin{paste}{ListPointsGraphicsExamplePageEmpty18}{ListPointsGraphicsExamplePagePatch18}
\pastebutton{ListPointsGraphicsExamplePageEmpty18}{\showpaste}
\tab{5}\spadcommand{pc1 := pastel red()\bound{pc1 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch19}
\begin{paste}{ListPointsGraphicsExamplePageFull19}{ListPointsGraphicsExamplePageEmpty19}
\pastebutton{ListPointsGraphicsExamplePageFull19}{\hidepaste}
\tab{5}\spadcommand{pc2 := dim green()\bound{pc2 }}
\indentrel{3}\begin{verbatim}
   (19)  [Hue: 14  Weight: 1.0] from the Dim palette
                                          Type: Palette
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty19}
\begin{paste}{ListPointsGraphicsExamplePageEmpty19}{ListPointsGraphicsExamplePagePatch19}
\pastebutton{ListPointsGraphicsExamplePageEmpty19}{\showpaste}
\tab{5}\spadcommand{pc2 := dim green()\bound{pc2 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch20}
\begin{paste}{ListPointsGraphicsExamplePageFull20}{ListPointsGraphicsExamplePageEmpty20}
\pastebutton{ListPointsGraphicsExamplePageFull20}{\hidepaste}
\tab{5}\spadcommand{pc3 := pastel yellow()\bound{pc3 }}
\indentrel{3}\begin{verbatim}
   (20)  [Hue: 11  Weight: 1.0] from the Pastel palette
                                          Type: Palette
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty20}
\begin{paste}{ListPointsGraphicsExamplePageEmpty20}{ListPointsGraphicsExamplePagePatch20}
\pastebutton{ListPointsGraphicsExamplePageEmpty20}{\showpaste}
\tab{5}\spadcommand{pc3 := pastel yellow()\bound{pc3 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch21}
\begin{paste}{ListPointsGraphicsExamplePageFull21}{ListPointsGraphicsExamplePageEmpty21}
\pastebutton{ListPointsGraphicsExamplePageFull21}{\hidepaste}
\tab{5}\spadcommand{lpc := [pc1, pc1, pc1, pc1, pc2, pc2, pc2, pc2, pc3, pc3, pc3, pc3]\bound{lpc }\free{pc1 pc2 pc3 }}
\indentrel{3}\begin{verbatim}
   (21)
   [[Hue: 1  Weight: 1.0] from the Pastel palette,
    [Hue: 1  Weight: 1.0] from the Pastel palette,
    [Hue: 1  Weight: 1.0] from the Pastel palette,
    [Hue: 1  Weight: 1.0] from the Pastel palette,
    [Hue: 14  Weight: 1.0] from the Dim palette,
    [Hue: 14  Weight: 1.0] from the Dim palette,
    [Hue: 14  Weight: 1.0] from the Dim palette,
    [Hue: 14  Weight: 1.0] from the Dim palette,
    [Hue: 11  Weight: 1.0] from the Pastel palette,
    [Hue: 11  Weight: 1.0] from the Pastel palette,
    [Hue: 11  Weight: 1.0] from the Pastel palette,
    [Hue: 11  Weight: 1.0] from the Pastel palette]
                                     Type: List Palette
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty21}
\begin{paste}{ListPointsGraphicsExamplePageEmpty21}{ListPointsGraphicsExamplePagePatch21}
\pastebutton{ListPointsGraphicsExamplePageEmpty21}{\showpaste}
\tab{5}\spadcommand{lpc := [pc1, pc1, pc1, pc1, pc2, pc2, pc2, pc2, pc3, pc3, pc3, pc3]\bound{lpc }\free{pc1 pc2 pc3 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch22}
\begin{paste}{ListPointsGraphicsExamplePageFull22}{ListPointsGraphicsExamplePageEmpty22}
\pastebutton{ListPointsGraphicsExamplePageFull22}{\hidepaste}
\tab{5}\spadcommand{lc := [pastel blue(), light yellow(), dim green(), bright red(), light green(), dim yellow(), bright blue(), dark red(), pastel red(), light blue(), dim green(), light yellow()]\bound{lc }}
\indentrel{3}\begin{verbatim}
   (22)
   [[Hue: 22  Weight: 1.0] from the Pastel palette,
    [Hue: 11  Weight: 1.0] from the Light palette,
    [Hue: 14  Weight: 1.0] from the Dim palette,
    [Hue: 1  Weight: 1.0] from the Bright palette,
    [Hue: 14  Weight: 1.0] from the Light palette,
    [Hue: 11  Weight: 1.0] from the Dim palette,
    [Hue: 22  Weight: 1.0] from the Bright palette,
    [Hue: 1  Weight: 1.0] from the Dark palette,
    [Hue: 1  Weight: 1.0] from the Pastel palette,
    [Hue: 22  Weight: 1.0] from the Light palette,
    [Hue: 14  Weight: 1.0] from the Dim palette,
    [Hue: 11  Weight: 1.0] from the Light palette]
                                     Type: List Palette
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty22}
\begin{paste}{ListPointsGraphicsExamplePageEmpty22}{ListPointsGraphicsExamplePagePatch22}
\pastebutton{ListPointsGraphicsExamplePageEmpty22}{\showpaste}
\tab{5}\spadcommand{lc := [pastel blue(), light yellow(), dim green(), bright red(), light green(), dim yellow(), bright blue(), dark red(), pastel red(), light blue(), dim green(), light yellow()]\bound{lc }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch23}
\begin{paste}{ListPointsGraphicsExamplePageFull23}{ListPointsGraphicsExamplePageEmpty23}
\pastebutton{ListPointsGraphicsExamplePageFull23}{\hidepaste}
\tab{5}\spadcommand{g := makeGraphImage(llp,lpc,lc,lsize)$GRIMAGE\bound{g }\free{llp lpc lc lsize }}
\indentrel{3}\begin{verbatim}
   (23)  Graph with 12 point lists
                                       Type: GraphImage
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty23}
\begin{paste}{ListPointsGraphicsExamplePageEmpty23}{ListPointsGraphicsExamplePagePatch23}
\pastebutton{ListPointsGraphicsExamplePageEmpty23}{\showpaste}
\tab{5}\spadcommand{g := makeGraphImage(llp,lpc,lc,lsize)$GRIMAGE\bound{g }\free{llp lpc lc lsize }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePagePatch24}
\begin{paste}{ListPointsGraphicsExamplePageFull24}{ListPointsGraphicsExamplePageEmpty24}
\pastebutton{ListPointsGraphicsExamplePageFull24}{\hidepaste}
\tab{5}\spadgraph{makeViewport2D(g,[title("Lines")])$VIEW2D\free{g }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/listpointsgraphicsexamplepage24.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/listpointsgraphicsexamplepage24}}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsExamplePageEmpty24}
\begin{paste}{ListPointsGraphicsExamplePageEmpty24}{ListPointsGraphicsExamplePagePatch24}
\pastebutton{ListPointsGraphicsExamplePageEmpty24}{\showpaste}
\tab{5}\spadgraph{makeViewport2D(g,[title("Lines")])$VIEW2D\free{g }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ThreeDimensionalGraphicsPage}{graphics.ht}
{Three Dimensional Graphing}
\pageto{notitle}{TwoVariableGraphicsPage}
\pageto{notitle}{SpaceCurveGraphicsPage}
\pageto{notitle}{ParametricTubeGraphicsPage}
\pageto{notitle}{ParametricSurfaceGraphicsPage}
\pageto{notitle}{ugGraphThreeDBuildPage}
\begin{chunk}{graphics.ht}
\begin{page}{ThreeDimensionalGraphicsPage}{Three Dimensional Graphing}
\beginscroll
\beginmenu
\menulink{Functions of Two Variables}{TwoVariableGraphicsPage} \newline
Plot surfaces defined by an equation z = f(x,y).
\menulink{Parametric Curves}{SpaceCurveGraphicsPage} \newline
Plot curves defined by equations x = f(t), y = g(t), z = g(t).
\menulink{Parametric Tube Plots}{ParametricTubeGraphicsPage} \newline
Plot a tube around a parametric space curve.
\menulink{Parametric Surfaces}{ParametricSurfaceGraphicsPage} \newline
Plot surfaces defined by x = f(u,v), y = g(u,v), z = h(u,v).
\menulink{Building Objects}{ugGraphThreeDBuildPage} \newline
Create objects constructed from geometric primitives.
\endmenu
\endscroll
\autobuttons \end{page}

\end{chunk}
\pagetitle{TwoVariableGraphicsPage}{graphics.ht}{Functions of Two Variables}
\begin{chunk}{graphics.ht}
\begin{page}{TwoVariableGraphicsPage}{Functions of Two Variables}
\beginscroll

This page describes the plotting of surfaces defined by an equation of
two variables, z = f(x,y), for which the ranges of x and y are
explicitly defined.  The basic draw command for this function utilizes
either the uncompiled function or compiled function format.  The
general format for an uncompiled function is:
\indent{5}\newline
{\em draw(f(x,y), x = a..b, y = c..d)}
\indent{0}\newline
where a..b and c..d are segments defining the intervals [a,b] and
[c,d] over which the variables x and y span.  In this case the
function is not compiled until the draw command is executed.  Here is
an example:
\graphpaste{draw(cos(x*y),x=-3..3,y=-3..3)}
In the case of a compiled function, the function is named and compiled
independently.  This is useful if you intend to use a function often,
or if the function is long and complex.  The following line shows a
function whose parameters are of the type Small Float. The function is
compiled and stored by Axiom when it is entered.
\indent{5}\newline
{\em NOTE:  It is only necessary to click on the draw command button to 
plot this example}.
\indent{0}\newline
\spadpaste{f(x:SF,y:SF):SF == sin(x)*cos(y) \bound{f}}
\newline
Once the function is compiled the draw command only needs the name 
of the function to execute.  Here is a compiled function example:
\graphpaste{draw(f,-\%pi..\%pi,-\%pi..\%pi) \free{f}}
Note that the parameter ranges do not take the variable names as in the
case of uncompiled functions.  The variables are entered in the order in
which they are defined in the function specification.  In this case the
first range specifies the x-variable and the second range specifies the
y-variable.
\endscroll
\autobuttons 
\end{page}

\begin{patch}{TwoVariableGraphicsPagePatch1}
\begin{paste}{TwoVariableGraphicsPageFull1}{TwoVariableGraphicsPageEmpty1}
\pastebutton{TwoVariableGraphicsPageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(cos(x*y),x=-3..3,y=-3..3)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/twovariablegraphicspage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/twovariablegraphicspage1}}
\end{paste}\end{patch}

\begin{patch}{TwoVariableGraphicsPageEmpty1}
\begin{paste}{TwoVariableGraphicsPageEmpty1}{TwoVariableGraphicsPagePatch1}
\pastebutton{TwoVariableGraphicsPageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(cos(x*y),x=-3..3,y=-3..3)}
\end{paste}\end{patch}

\begin{patch}{TwoVariableGraphicsPagePatch2}
\begin{paste}{TwoVariableGraphicsPageFull2}{TwoVariableGraphicsPageEmpty2}
\pastebutton{TwoVariableGraphicsPageFull2}{\hidepaste}
\tab{5}\spadcommand{f(x:SF,y:SF):SF == sin(x)*cos(y)\bound{f }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TwoVariableGraphicsPageEmpty2}
\begin{paste}{TwoVariableGraphicsPageEmpty2}{TwoVariableGraphicsPagePatch2}
\pastebutton{TwoVariableGraphicsPageEmpty2}{\showpaste}
\tab{5}\spadcommand{f(x:SF,y:SF):SF == sin(x)*cos(y)\bound{f }}
\end{paste}\end{patch}

\begin{patch}{TwoVariableGraphicsPagePatch3}
\begin{paste}{TwoVariableGraphicsPageFull3}{TwoVariableGraphicsPageEmpty3}
\pastebutton{TwoVariableGraphicsPageFull3}{\hidepaste}
\tab{5}\spadgraph{draw(f,-\%pi..\%pi,-\%pi..\%pi)\free{f }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/twovariablegraphicspage3.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/twovariablegraphicspage3}}
\end{paste}\end{patch}

\begin{patch}{TwoVariableGraphicsPageEmpty3}
\begin{paste}{TwoVariableGraphicsPageEmpty3}{TwoVariableGraphicsPagePatch3}
\pastebutton{TwoVariableGraphicsPageEmpty3}{\showpaste}
\tab{5}\spadgraph{draw(f,-\%pi..\%pi,-\%pi..\%pi)\free{f }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{SpaceCurveGraphicsPage}{graphics.ht}{Parametric Space Curves}
\begin{chunk}{graphics.ht}
\begin{page}{SpaceCurveGraphicsPage}{Parametric Space Curves}
\beginscroll
This page describes the plotting in three dimensional space of a curve
defined by the parametric equations x = f(t), y = g(t), z = h(t),
where f, g, and h are functions of the parameter t which ranges over a
specified interval.  The basic draw command for this function utilizes
either the uncompiled functions or compiled functions format and uses
the \spadfun{curve} command to specify the three functions for the x,
y, and z components of the curve.  The general format for uncompiled
functions is:
\indent{5}\newline
{\em draw(curve(f(t),g(t),h(t)), t = a..b)}
\indent{0}\newline
where a..b is the segment defining the interval [a,b] over which the
parameter t ranges.  In this case the functions are not compiled until
the draw command is executed.  Here is an example:
\graphpaste{draw(curve(cos(t),sin(t),t), t=-12..12)}
In the case of compiled functions, the functions are named and
compiled independently.  This is useful if you intend to use the
functions often, or if the functions are long and complex.  The
following lines show functions whose parameters are of the type Small
Float. The functions are compiled and stored by Axiom when entered.
\indent{5}\newline
{\em NOTE:  It is only necessary to click on the draw command button to 
plot this example}.
\indent{0}\newline
\spadpaste{i1(t:SF):SF == sin(t)*cos(3*t/5) \bound{i1}}
\spadpaste{i2(t:SF):SF == cos(t)*cos(3*t/5) \bound{i2}}
\spadpaste{i3(t:SF):SF == cos(t)*sin(3*t/5) \bound{i3}}
Once the functions are compiled the draw command only needs the names
of the functions to execute.  Here is a compiled functions example:
\graphpaste{draw(curve(i1,i2,i3),0..15*\%pi) \free{i1 i2 i3}}
Note that the parameter range does not take the variable name as in
the case of uncompiled functions. It is understood that the indicated
range applies to the parameter of the functions, which in this case is t.
\endscroll
\autobuttons 
\end{page}

\begin{patch}{SpaceCurveGraphicsPagePatch1}
\begin{paste}{SpaceCurveGraphicsPageFull1}{SpaceCurveGraphicsPageEmpty1}
\pastebutton{SpaceCurveGraphicsPageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(curve(cos(t),sin(t),t), t=-12..12)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/spacecurvegraphicspage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/spacecurvegraphicspage1}}
\end{paste}\end{patch}

\begin{patch}{SpaceCurveGraphicsPageEmpty1}
\begin{paste}{SpaceCurveGraphicsPageEmpty1}{SpaceCurveGraphicsPagePatch1}
\pastebutton{SpaceCurveGraphicsPageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(curve(cos(t),sin(t),t), t=-12..12)}
\end{paste}\end{patch}

\begin{patch}{SpaceCurveGraphicsPagePatch2}
\begin{paste}{SpaceCurveGraphicsPageFull2}{SpaceCurveGraphicsPageEmpty2}
\pastebutton{SpaceCurveGraphicsPageFull2}{\hidepaste}
\tab{5}\spadcommand{i1(t:SF):SF == sin(t)*cos(3*t/5)\bound{i1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SpaceCurveGraphicsPageEmpty2}
\begin{paste}{SpaceCurveGraphicsPageEmpty2}{SpaceCurveGraphicsPagePatch2}
\pastebutton{SpaceCurveGraphicsPageEmpty2}{\showpaste}
\tab{5}\spadcommand{i1(t:SF):SF == sin(t)*cos(3*t/5)\bound{i1 }}
\end{paste}\end{patch}

\begin{patch}{SpaceCurveGraphicsPagePatch3}
\begin{paste}{SpaceCurveGraphicsPageFull3}{SpaceCurveGraphicsPageEmpty3}
\pastebutton{SpaceCurveGraphicsPageFull3}{\hidepaste}
\tab{5}\spadcommand{i2(t:SF):SF == cos(t)*cos(3*t/5)\bound{i2 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SpaceCurveGraphicsPageEmpty3}
\begin{paste}{SpaceCurveGraphicsPageEmpty3}{SpaceCurveGraphicsPagePatch3}
\pastebutton{SpaceCurveGraphicsPageEmpty3}{\showpaste}
\tab{5}\spadcommand{i2(t:SF):SF == cos(t)*cos(3*t/5)\bound{i2 }}
\end{paste}\end{patch}

\begin{patch}{SpaceCurveGraphicsPagePatch4}
\begin{paste}{SpaceCurveGraphicsPageFull4}{SpaceCurveGraphicsPageEmpty4}
\pastebutton{SpaceCurveGraphicsPageFull4}{\hidepaste}
\tab{5}\spadcommand{i3(t:SF):SF == cos(t)*sin(3*t/5)\bound{i3 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SpaceCurveGraphicsPageEmpty4}
\begin{paste}{SpaceCurveGraphicsPageEmpty4}{SpaceCurveGraphicsPagePatch4}
\pastebutton{SpaceCurveGraphicsPageEmpty4}{\showpaste}
\tab{5}\spadcommand{i3(t:SF):SF == cos(t)*sin(3*t/5)\bound{i3 }}
\end{paste}\end{patch}

\begin{patch}{SpaceCurveGraphicsPagePatch5}
\begin{paste}{SpaceCurveGraphicsPageFull5}{SpaceCurveGraphicsPageEmpty5}
\pastebutton{SpaceCurveGraphicsPageFull5}{\hidepaste}
\tab{5}\spadgraph{draw(curve(i1,i2,i3),0..15*\%pi)\free{i1 i2 i3 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/spacecurvegraphicspage5.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/spacecurvegraphicspage5}}
\end{paste}\end{patch}

\begin{patch}{SpaceCurveGraphicsPageEmpty5}
\begin{paste}{SpaceCurveGraphicsPageEmpty5}{SpaceCurveGraphicsPagePatch5}
\pastebutton{SpaceCurveGraphicsPageEmpty5}{\showpaste}
\tab{5}\spadgraph{draw(curve(i1,i2,i3),0..15*\%pi)\free{i1 i2 i3 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ParametricTubeGraphicsPage}{graphics.ht}{Parametric Tube Plots}
\begin{chunk}{graphics.ht}
\begin{page}{ParametricTubeGraphicsPage}{Parametric Tube Plots}
\beginscroll
This page describes the plotting in three dimensional space of a tube
around a parametric space curve defined by the parametric equations 
x = f(t), y = g(t), z = h(t), where f, g, and h are functions of the
parameter t which ranges over a specified interval.  The basic draw
command for this function utilizes either the uncompiled functions or
compiled functions format and uses the \spadfun{curve} command to
specify the three functions for the x, y, and z components of the
curve.  This uses the same format as that for space curves except that
it requires a specification for the radius of the tube.  If the radius
of the tube is 0, then the result is the space curve itself.  The
general format for uncompiled functions is:
\indent{5}\newline
{\em draw(curve(f(t),g(t),h(t)), t = a..b, tubeRadius == r)}
\indent{0}\newline
where a..b is the segment defining the interval [a,b] over which the
parameter t ranges, and the tubeRadius is indicated by the variable r.
In this case the functions are not compiled until the draw command is
executed.  Here is an example:
\graphpaste{draw(curve(sin(t)*cos(3*t/5), cos(t)*cos(3*t/5), 
cos(t)*sin(3*t/5)), t=0..15*\%pi,tubeRadius == .15)}
In the case of compiled functions, the functions are named and
compiled independently.  This is useful if you intend to use the
functions often, or if the functions are long and complex.  The
following lines show functions whose parameters are of the type Small
Float. The functions are compiled and stored by Axiom when entered.
\indent{5}\newline
{\em NOTE:  It is only necessary to click on the draw command button to 
plot this example}.
\indent{0}\newline
\spadpaste{t1(t:SF):SF == 4/(2-sin(3*t))*cos(2*t) \bound{t1}} 
\newline
\spadpaste{t2(t:SF):SF == 4/(2-sin(3*t))*sin(2*t) \bound{t2}} 
\newline
\spadpaste{t3(t:SF):SF == 4/(2-sin(3*t))*cos(3*t) \bound{t3}} 
\newline
Once the function is compiled the draw command only needs the names of
the functions to execute.  Here is a compiled functions example of a
trefoil knot:
\graphpaste{draw(curve(t1,t2,t3),0..2*\%pi,tubeRadius == .2) 
\free{t1 t2 t3}}
Note that the parameter range does not take the variable name as in
the case of uncompiled functions. It is understood that the indicated
range applies to the parameter of the functions, which in this case is
t.  Typically, the radius of the tube should be set between 0 and 1.
A radius of less than 0 results in it's positive counterpart and a
radius of greater than one causes self intersection.
\endscroll
\autobuttons 
\end{page}

\begin{patch}{ParametricTubeGraphicsPagePatch1}
\begin{paste}{ParametricTubeGraphicsPageFull1}{ParametricTubeGraphicsPageEmpty1}
\pastebutton{ParametricTubeGraphicsPageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(curve(sin(t)*cos(3*t/5), cos(t)*cos(3*t/5), cos(t)*sin(3*t/5)), t=0..15*\%pi,tubeRadius == .15)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/parametrictubegraphicspage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/parametrictubegraphicspage1}}
\end{paste}\end{patch}

\begin{patch}{ParametricTubeGraphicsPageEmpty1}
\begin{paste}{ParametricTubeGraphicsPageEmpty1}{ParametricTubeGraphicsPagePatch1}
\pastebutton{ParametricTubeGraphicsPageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(curve(sin(t)*cos(3*t/5), cos(t)*cos(3*t/5), cos(t)*sin(3*t/5)), t=0..15*\%pi,tubeRadius == .15)}
\end{paste}\end{patch}

\begin{patch}{ParametricTubeGraphicsPagePatch2}
\begin{paste}{ParametricTubeGraphicsPageFull2}{ParametricTubeGraphicsPageEmpty2}
\pastebutton{ParametricTubeGraphicsPageFull2}{\hidepaste}
\tab{5}\spadcommand{t1(t:SF):SF == 4/(2-sin(3*t))*cos(2*t)\bound{t1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ParametricTubeGraphicsPageEmpty2}
\begin{paste}{ParametricTubeGraphicsPageEmpty2}{ParametricTubeGraphicsPagePatch2}
\pastebutton{ParametricTubeGraphicsPageEmpty2}{\showpaste}
\tab{5}\spadcommand{t1(t:SF):SF == 4/(2-sin(3*t))*cos(2*t)\bound{t1 }}
\end{paste}\end{patch}

\begin{patch}{ParametricTubeGraphicsPagePatch3}
\begin{paste}{ParametricTubeGraphicsPageFull3}{ParametricTubeGraphicsPageEmpty3}
\pastebutton{ParametricTubeGraphicsPageFull3}{\hidepaste}
\tab{5}\spadcommand{t2(t:SF):SF == 4/(2-sin(3*t))*sin(2*t)\bound{t2 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ParametricTubeGraphicsPageEmpty3}
\begin{paste}{ParametricTubeGraphicsPageEmpty3}{ParametricTubeGraphicsPagePatch3}
\pastebutton{ParametricTubeGraphicsPageEmpty3}{\showpaste}
\tab{5}\spadcommand{t2(t:SF):SF == 4/(2-sin(3*t))*sin(2*t)\bound{t2 }}
\end{paste}\end{patch}

\begin{patch}{ParametricTubeGraphicsPagePatch4}
\begin{paste}{ParametricTubeGraphicsPageFull4}{ParametricTubeGraphicsPageEmpty4}
\pastebutton{ParametricTubeGraphicsPageFull4}{\hidepaste}
\tab{5}\spadcommand{t3(t:SF):SF == 4/(2-sin(3*t))*cos(3*t)\bound{t3 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ParametricTubeGraphicsPageEmpty4}
\begin{paste}{ParametricTubeGraphicsPageEmpty4}{ParametricTubeGraphicsPagePatch4}
\pastebutton{ParametricTubeGraphicsPageEmpty4}{\showpaste}
\tab{5}\spadcommand{t3(t:SF):SF == 4/(2-sin(3*t))*cos(3*t)\bound{t3 }}
\end{paste}\end{patch}

\begin{patch}{ParametricTubeGraphicsPagePatch5}
\begin{paste}{ParametricTubeGraphicsPageFull5}{ParametricTubeGraphicsPageEmpty5}
\pastebutton{ParametricTubeGraphicsPageFull5}{\hidepaste}
\tab{5}\spadgraph{draw(curve(t1,t2,t3),0..2*\%pi,tubeRadius == .2)\free{t1 t2 t3 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/parametrictubegraphicspage5.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/parametrictubegraphicspage5}}
\end{paste}\end{patch}

\begin{patch}{ParametricTubeGraphicsPageEmpty5}
\begin{paste}{ParametricTubeGraphicsPageEmpty5}{ParametricTubeGraphicsPagePatch5}
\pastebutton{ParametricTubeGraphicsPageEmpty5}{\showpaste}
\tab{5}\spadgraph{draw(curve(t1,t2,t3),0..2*\%pi,tubeRadius == .2)\free{t1 t2 t3 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ParametricSurfaceGraphicsPage}{graphics.ht}{Parametric Surfaces}
\begin{chunk}{graphics.ht}
\begin{page}{ParametricSurfaceGraphicsPage}{Parametric Surfaces}
\beginscroll
Graphing a surface defined by x = f(u,v), y = g(u,v), z = h(u,v). 
\newline This page describes the plotting of surfaces defined
by the parametric equations of two variables, x = f(u,v), y = g(u,v),
and z = h(u,v), for which the ranges of u and v are explicitly
defined.  The basic draw command for this function utilizes either the
uncompiled function or compiled function format and uses the
\spadfun{surface} command to specify the three functions for the x, y
and z components of the surface.  The general format for uncompiled
functions is:
\indent{5}\newline
{\em draw(surface(f(u,v),g(u,v),h(u,v)), u = a..b, v = c..d)}
\indent{0}\newline
where a..b and c..d are segments defining the intervals [a,b] and
[c,d] over which the parameters u and v span.  In this case the
functions are not compiled until the draw command is executed.  Here
is an example of a surface plotted using the parabolic cylindrical
coordinate system option:
\graphpaste{draw(surface(u*cos(v), u*sin(v),v*cos(u)),
u=-4..4,v=0..2*\%pi, coordinates== parabolicCylindrical)}
In the case of compiled functions, the functions are named and
compiled independently.  This is useful if you intend to use the
functions often, or if the functions are long and complex.  The
following lines show functions whose parameters are of the type Small
Float. The functions are compiled and stored by Axiom when entered.
\indent{5}\newline
{\em NOTE:  It is only necessary to click on the draw command button to 
plot this example}.
\indent{0}\newline
\spadpaste{n1(u:SF,v:SF):SF == u*cos(v) \bound{n1}} 
\newline
\spadpaste{n2(u:SF,v:SF):SF == u*sin(v) \bound{n2}} 
\newline
\spadpaste{n3(u:SF,v:SF):SF == u \bound{n3}}
Once the function is compiled the draw command only needs the names of
the functions to execute.  Here is a compiled functions example
plotted using the toroidal coordinate system option: \newline
\graphpaste{draw(surface(n1,n2,n3), 1.0..4.0, 1.0..4*\%pi,
             coordinates == toroidal(1\$SF)) \free{n1 n2 n3}}
Note that the parameter ranges do not take the variable names as in
the case of uncompiled functions.  The variables are entered in the
order in which they are defined in the function specification.  In
this case the first range specifies the u-variable and the second
range specifies the v-variable.
\endscroll
\autobuttons 
\end{page}

\begin{patch}{ParametricSurfaceGraphicsPagePatch1}
\begin{paste}{ParametricSurfaceGraphicsPageFull1}{ParametricSurfaceGraphicsPageEmpty1}
\pastebutton{ParametricSurfaceGraphicsPageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(surface(u*cos(v), u*sin(v),v*cos(u)),u=-4..4,v=0..2*\%pi, coordinates== parabolicCylindrical)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/parametricsurfacegraphicspage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/parametricsurfacegraphicspage1}}
\end{paste}\end{patch}

\begin{patch}{ParametricSurfaceGraphicsPageEmpty1}
\begin{paste}{ParametricSurfaceGraphicsPageEmpty1}{ParametricSurfaceGraphicsPagePatch1}
\pastebutton{ParametricSurfaceGraphicsPageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(surface(u*cos(v), u*sin(v),v*cos(u)),u=-4..4,v=0..2*\%pi, coordinates== parabolicCylindrical)}
\end{paste}\end{patch}

\begin{patch}{ParametricSurfaceGraphicsPagePatch2}
\begin{paste}{ParametricSurfaceGraphicsPageFull2}{ParametricSurfaceGraphicsPageEmpty2}
\pastebutton{ParametricSurfaceGraphicsPageFull2}{\hidepaste}
\tab{5}\spadcommand{n1(u:SF,v:SF):SF == u*cos(v)\bound{n1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ParametricSurfaceGraphicsPageEmpty2}
\begin{paste}{ParametricSurfaceGraphicsPageEmpty2}{ParametricSurfaceGraphicsPagePatch2}
\pastebutton{ParametricSurfaceGraphicsPageEmpty2}{\showpaste}
\tab{5}\spadcommand{n1(u:SF,v:SF):SF == u*cos(v)\bound{n1 }}
\end{paste}\end{patch}

\begin{patch}{ParametricSurfaceGraphicsPagePatch3}
\begin{paste}{ParametricSurfaceGraphicsPageFull3}{ParametricSurfaceGraphicsPageEmpty3}
\pastebutton{ParametricSurfaceGraphicsPageFull3}{\hidepaste}
\tab{5}\spadcommand{n2(u:SF,v:SF):SF == u*sin(v)\bound{n2 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ParametricSurfaceGraphicsPageEmpty3}
\begin{paste}{ParametricSurfaceGraphicsPageEmpty3}{ParametricSurfaceGraphicsPagePatch3}
\pastebutton{ParametricSurfaceGraphicsPageEmpty3}{\showpaste}
\tab{5}\spadcommand{n2(u:SF,v:SF):SF == u*sin(v)\bound{n2 }}
\end{paste}\end{patch}

\begin{patch}{ParametricSurfaceGraphicsPagePatch4}
\begin{paste}{ParametricSurfaceGraphicsPageFull4}{ParametricSurfaceGraphicsPageEmpty4}
\pastebutton{ParametricSurfaceGraphicsPageFull4}{\hidepaste}
\tab{5}\spadcommand{n3(u:SF,v:SF):SF == u\bound{n3 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ParametricSurfaceGraphicsPageEmpty4}
\begin{paste}{ParametricSurfaceGraphicsPageEmpty4}{ParametricSurfaceGraphicsPagePatch4}
\pastebutton{ParametricSurfaceGraphicsPageEmpty4}{\showpaste}
\tab{5}\spadcommand{n3(u:SF,v:SF):SF == u\bound{n3 }}
\end{paste}\end{patch}

\begin{patch}{ParametricSurfaceGraphicsPagePatch5}
\begin{paste}{ParametricSurfaceGraphicsPageFull5}{ParametricSurfaceGraphicsPageEmpty5}
\pastebutton{ParametricSurfaceGraphicsPageFull5}{\hidepaste}
\tab{5}\spadgraph{draw(surface(n1,n2,n3), 1.0..4.0, 1.0..4*\%pi, coordinates == toroidal(1$SF))\free{n1 n2 n3 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/parametricsurfacegraphicspage5.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/parametricsurfacegraphicspage5}}
\end{paste}\end{patch}

\begin{patch}{ParametricSurfaceGraphicsPageEmpty5}
\begin{paste}{ParametricSurfaceGraphicsPageEmpty5}{ParametricSurfaceGraphicsPagePatch5}
\pastebutton{ParametricSurfaceGraphicsPageEmpty5}{\showpaste}
\tab{5}\spadgraph{draw(surface(n1,n2,n3), 1.0..4.0, 1.0..4*\%pi, coordinates == toroidal(1$SF))\free{n1 n2 n3 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{3DObjectGraphicsPage}{graphics.ht}{Building 3D Objects}
\begin{chunk}{graphics.ht}
\begin{page}{3DObjectGraphicsPage}{Building 3D Objects}
\beginscroll
This page describes the Axiom facilities for creating three
dimensional objects constructed from geometric primitives.  The Axiom
operation \spadfun{create3Space()} creates a space to which points,
curves, and polygons can be added using the operations from the
\spadtype{ThreeSpace} domain.  The contents of this space can then be
displayed in a viewport using the \spadfun{makeViewport3D()} command.
It will be necessary to have these operations exposed in order to use
them. \indent{5}\newline {\em NOTE: It is only necessary to click on
the makeViewport3D command button to plot this curve example}.
\indent{0}\newline
Initially, the space which will hold the objects must be defined and
compiled, as in the following example:
\spadpaste{space := create3Space()\$(ThreeSpace SF) \bound{space}}
Now objects can be sent to this {\em space} as per the operations
allowed by the \spadtype{ThreeSpace} domain.  The following examples
place curves into
{\em space}.
\spadpaste{curve(space,[[0,20,20],[0,20,30],[0,30,30],[0,30,100], 
[0,20,100],[0,20,110],[0,50,110],[0,50,100],[0,40,100], [0,40,30],
[0,50,30],[0,50,20],[0,20,20]]) \bound{curveI}} 
\newline
\spadpaste{curve(space,[[0,80,20],[0,70,20],[0,70,110],[0,110,110], 
[0,120,100],[0,120,70],[0,115,65],[0,120,60],[0,120,30], [0,110,20],
[0,80,20],[0,80,30],[0,105,30],[0,110,35]]) \bound{curveB1}} 
\newline
\spadpaste{curve(space,[[0,110,35],[0,110,55],[0,105,60],[0,80,60],
[0,80,70], [0,105,70],[0,110,75],[0,110,95],[0,105,100],[0,80,100], 
[0,80,30]]) \bound{curveB2}} 
\newline
\spadpaste{closedCurve(space,[[0,140,20],[0,140,110],[0,150,110],
[0,170,50], [0,190,110],[0,200,110],[0,200,20],[0,190,20],[0,190,75], 
[0,175,35],[0,165,35],[0,150,75],[0,150,20]]) \bound{curveM}}
\spadpaste{closedCurve(space,[[200,0,20], [200,0,110], [185,0,110], 
[160,0,45], [160,0,110], [150,0,110], [150,0,20], [165,0,20], 
[190,0,85], [190,0,20]]) \bound{curveN}}
\spadpaste{closedCurve(space,[[140,0,20], [120,0,110], [110,0,110], 
[90,0,20], [100,0,20], [108,0,50], [123,0,50], [121,0,60], 
[110,0,60], [115,0,90], [130,0,20]]) \bound{curveA}}
\spadpaste{closedCurve(space,[[80,0,30], [80,0,100], [70,0,110], 
[40,0,110], [30,0,100], [30,0,90], [40,0,90], [40,0,95], 
[45,0,100], [65,0,100], [70,0,95], [70,0,35], [65,0,30], 
[45,0,30], [40,0,35], [40,0,60], [50,0,60], [50,0,70], 
[30,0,70], [30,0,30], [40,0,20], [70,0,20]]) \bound{curveG}}
Once {\em space} contains the desired elements a viewport is created 
and displayed with the following command:
\graphpaste{makeViewport3D(space,[title("Curves")])\$VIEW3D 
\free{space curveI curveB1 curveB2 curveM curveN curveA curveG}}
The parameters for \spadfun{makeViewport3D()} in this example are {\em
space}, which is the name of the three dimensional space that was
defined, and a string, "curve", which is the title for the viewport.
The tailing string {\em \$VIEW3D} exposes the command
\spadfun{makeViewport3D()} from the domain
\spadtype{ThreeDimensionalViewport} if these commands are unexposed.
\endscroll
\autobuttons 
\end{page}

\begin{patch}{3DObjectGraphicsPagePatch1}
\begin{paste}{3DObjectGraphicsPageFull1}{3DObjectGraphicsPageEmpty1}
\pastebutton{3DObjectGraphicsPageFull1}{\hidepaste}
\tab{5}\spadcommand{space := create3Space()$(ThreeSpace SF)\bound{space }}
\indentrel{3}\begin{verbatim}
   (1)  3-Space with 0 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{3DObjectGraphicsPageEmpty1}
\begin{paste}{3DObjectGraphicsPageEmpty1}{3DObjectGraphicsPagePatch1}
\pastebutton{3DObjectGraphicsPageEmpty1}{\showpaste}
\tab{5}\spadcommand{space := create3Space()$(ThreeSpace SF)\bound{space }}
\end{paste}\end{patch}

\begin{patch}{3DObjectGraphicsPagePatch2}
\begin{paste}{3DObjectGraphicsPageFull2}{3DObjectGraphicsPageEmpty2}
\pastebutton{3DObjectGraphicsPageFull2}{\hidepaste}
\tab{5}\spadcommand{curve(space,[[0,20,20],[0,20,30],[0,30,30],[0,30,100], [0,20,100],[0,20,110],[0,50,110],[0,50,100],[0,40,100], [0,40,30],[0,50,30],[0,50,20],[0,20,20]])\bound{curveI }}
\indentrel{3}\begin{verbatim}
   (2)  3-Space with 1 component
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{3DObjectGraphicsPageEmpty2}
\begin{paste}{3DObjectGraphicsPageEmpty2}{3DObjectGraphicsPagePatch2}
\pastebutton{3DObjectGraphicsPageEmpty2}{\showpaste}
\tab{5}\spadcommand{curve(space,[[0,20,20],[0,20,30],[0,30,30],[0,30,100], [0,20,100],[0,20,110],[0,50,110],[0,50,100],[0,40,100], [0,40,30],[0,50,30],[0,50,20],[0,20,20]])\bound{curveI }}
\end{paste}\end{patch}

\begin{patch}{3DObjectGraphicsPagePatch3}
\begin{paste}{3DObjectGraphicsPageFull3}{3DObjectGraphicsPageEmpty3}
\pastebutton{3DObjectGraphicsPageFull3}{\hidepaste}
\tab{5}\spadcommand{curve(space,[[0,80,20],[0,70,20],[0,70,110],[0,110,110], [0,120,100],[0,120,70],[0,115,65],[0,120,60],[0,120,30], [0,110,20],[0,80,20],[0,80,30],[0,105,30],[0,110,35]])\bound{curveB1 }}
\indentrel{3}\begin{verbatim}
   (3)  3-Space with 2 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{3DObjectGraphicsPageEmpty3}
\begin{paste}{3DObjectGraphicsPageEmpty3}{3DObjectGraphicsPagePatch3}
\pastebutton{3DObjectGraphicsPageEmpty3}{\showpaste}
\tab{5}\spadcommand{curve(space,[[0,80,20],[0,70,20],[0,70,110],[0,110,110], [0,120,100],[0,120,70],[0,115,65],[0,120,60],[0,120,30], [0,110,20],[0,80,20],[0,80,30],[0,105,30],[0,110,35]])\bound{curveB1 }}
\end{paste}\end{patch}

\begin{patch}{3DObjectGraphicsPagePatch4}
\begin{paste}{3DObjectGraphicsPageFull4}{3DObjectGraphicsPageEmpty4}
\pastebutton{3DObjectGraphicsPageFull4}{\hidepaste}
\tab{5}\spadcommand{curve(space,[[0,110,35],[0,110,55],[0,105,60],[0,80,60],[0,80,70], [0,105,70],[0,110,75],[0,110,95],[0,105,100],[0,80,100], [0,80,30]])\bound{curveB2 }}
\indentrel{3}\begin{verbatim}
   (4)  3-Space with 3 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{3DObjectGraphicsPageEmpty4}
\begin{paste}{3DObjectGraphicsPageEmpty4}{3DObjectGraphicsPagePatch4}
\pastebutton{3DObjectGraphicsPageEmpty4}{\showpaste}
\tab{5}\spadcommand{curve(space,[[0,110,35],[0,110,55],[0,105,60],[0,80,60],[0,80,70], [0,105,70],[0,110,75],[0,110,95],[0,105,100],[0,80,100], [0,80,30]])\bound{curveB2 }}
\end{paste}\end{patch}

\begin{patch}{3DObjectGraphicsPagePatch5}
\begin{paste}{3DObjectGraphicsPageFull5}{3DObjectGraphicsPageEmpty5}
\pastebutton{3DObjectGraphicsPageFull5}{\hidepaste}
\tab{5}\spadcommand{closedCurve(space,[[0,140,20],[0,140,110],[0,150,110],[0,170,50], [0,190,110],[0,200,110],[0,200,20],[0,190,20],[0,190,75], [0,175,35],[0,165,35],[0,150,75],[0,150,20]])\bound{curveM }}
\indentrel{3}\begin{verbatim}
   (5)  3-Space with 4 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{3DObjectGraphicsPageEmpty5}
\begin{paste}{3DObjectGraphicsPageEmpty5}{3DObjectGraphicsPagePatch5}
\pastebutton{3DObjectGraphicsPageEmpty5}{\showpaste}
\tab{5}\spadcommand{closedCurve(space,[[0,140,20],[0,140,110],[0,150,110],[0,170,50], [0,190,110],[0,200,110],[0,200,20],[0,190,20],[0,190,75], [0,175,35],[0,165,35],[0,150,75],[0,150,20]])\bound{curveM }}
\end{paste}\end{patch}

\begin{patch}{3DObjectGraphicsPagePatch6}
\begin{paste}{3DObjectGraphicsPageFull6}{3DObjectGraphicsPageEmpty6}
\pastebutton{3DObjectGraphicsPageFull6}{\hidepaste}
\tab{5}\spadcommand{closedCurve(space,[[200,0,20], [200,0,110], [185,0,110], [160,0,45], [160,0,110], [150,0,110], [150,0,20], [165,0,20], [190,0,85], [190,0,20]])\bound{curveN }}
\indentrel{3}\begin{verbatim}
   (6)  3-Space with 5 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{3DObjectGraphicsPageEmpty6}
\begin{paste}{3DObjectGraphicsPageEmpty6}{3DObjectGraphicsPagePatch6}
\pastebutton{3DObjectGraphicsPageEmpty6}{\showpaste}
\tab{5}\spadcommand{closedCurve(space,[[200,0,20], [200,0,110], [185,0,110], [160,0,45], [160,0,110], [150,0,110], [150,0,20], [165,0,20], [190,0,85], [190,0,20]])\bound{curveN }}
\end{paste}\end{patch}

\begin{patch}{3DObjectGraphicsPagePatch7}
\begin{paste}{3DObjectGraphicsPageFull7}{3DObjectGraphicsPageEmpty7}
\pastebutton{3DObjectGraphicsPageFull7}{\hidepaste}
\tab{5}\spadcommand{closedCurve(space,[[140,0,20], [120,0,110], [110,0,110], [90,0,20], [100,0,20], [108,0,50], [123,0,50], [121,0,60], [110,0,60], [115,0,90], [130,0,20]])\bound{curveA }}
\indentrel{3}\begin{verbatim}
   (7)  3-Space with 6 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{3DObjectGraphicsPageEmpty7}
\begin{paste}{3DObjectGraphicsPageEmpty7}{3DObjectGraphicsPagePatch7}
\pastebutton{3DObjectGraphicsPageEmpty7}{\showpaste}
\tab{5}\spadcommand{closedCurve(space,[[140,0,20], [120,0,110], [110,0,110], [90,0,20], [100,0,20], [108,0,50], [123,0,50], [121,0,60], [110,0,60], [115,0,90], [130,0,20]])\bound{curveA }}
\end{paste}\end{patch}

\begin{patch}{3DObjectGraphicsPagePatch8}
\begin{paste}{3DObjectGraphicsPageFull8}{3DObjectGraphicsPageEmpty8}
\pastebutton{3DObjectGraphicsPageFull8}{\hidepaste}
\tab{5}\spadcommand{closedCurve(space,[[80,0,30], [80,0,100], [70,0,110], [40,0,110], [30,0,100], [30,0,90], [40,0,90], [40,0,95], [45,0,100], [65,0,100], [70,0,95], [70,0,35], [65,0,30], [45,0,30], [40,0,35], [40,0,60], [50,0,60], [50,0,70], [30,0,70], [30,0,30], [40,0,20], [70,0,20]])\bound{curveG }}
\indentrel{3}\begin{verbatim}
   (8)  3-Space with 7 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{3DObjectGraphicsPageEmpty8}
\begin{paste}{3DObjectGraphicsPageEmpty8}{3DObjectGraphicsPagePatch8}
\pastebutton{3DObjectGraphicsPageEmpty8}{\showpaste}
\tab{5}\spadcommand{closedCurve(space,[[80,0,30], [80,0,100], [70,0,110], [40,0,110], [30,0,100], [30,0,90], [40,0,90], [40,0,95], [45,0,100], [65,0,100], [70,0,95], [70,0,35], [65,0,30], [45,0,30], [40,0,35], [40,0,60], [50,0,60], [50,0,70], [30,0,70], [30,0,30], [40,0,20], [70,0,20]])\bound{curveG }}
\end{paste}\end{patch}

\begin{patch}{3DObjectGraphicsPagePatch9}
\begin{paste}{3DObjectGraphicsPageFull9}{3DObjectGraphicsPageEmpty9}
\pastebutton{3DObjectGraphicsPageFull9}{\hidepaste}
\tab{5}\spadgraph{makeViewport3D(space,[title("Curves")])$VIEW3D\free{space curveI curveB1 curveB2 curveM curveN curveA curveG }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/3dobjectgraphicspage9.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/3dobjectgraphicspage9}}
\end{paste}\end{patch}

\begin{patch}{3DObjectGraphicsPageEmpty9}
\begin{paste}{3DObjectGraphicsPageEmpty9}{3DObjectGraphicsPagePatch9}
\pastebutton{3DObjectGraphicsPageEmpty9}{\showpaste}
\tab{5}\spadgraph{makeViewport3D(space,[title("Curves")])$VIEW3D\free{space curveI curveB1 curveB2 curveM curveN curveA curveG }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{TwoDimensionalGraphicsPage}{graphics.ht}
{Two Dimensional Graphics}
\pageto{notitle}{OneVariableGraphicsPage}
\pageto{notitle}{ParametricCurveGraphicsPage}
\pageto{notitle}{PolarGraphicsPage}
\pageto{notitle}{ImplicitCurveGraphicsPage}
\pageto{notitle}{ListPointsGraphicsPage}
\begin{chunk}{graphics.ht}
\begin{page}{TwoDimensionalGraphicsPage}{Two Dimensional Graphics}
\beginscroll
\beginmenu
\menulink{Functions of One Variable}{OneVariableGraphicsPage} 
\newline
Plot curves defined by an equation y = f(x).
\menulink{Parametric Curves}{ParametricCurveGraphicsPage} \newline
Plot curves defined by parametric equations x = f(t), y = g(t).
\menulink{Polar Coordinates}{PolarGraphicsPage} \newline
Plot curves given in polar form by an equation r = f(theta).
\menulink{Implicit Curves}{ImplicitCurveGraphicsPage} \newline
Plot non-singular curves defined by a polynomial equation
\menulink{Lists of Points}{ListPointsGraphicsPage} \newline
Plot lists of points in the (x,y)-plane.
% \menulink{Sequences}{SeqGraphicsPage} \newline
% Plot a sequence a1, a2, a3,...
% \menulink{Complex Functions}{CxFuncGraphicsPage} \newline
% Plot functions of a complex variable using grid plots.
\endmenu
\endscroll
\autobuttons \end{page}

\end{chunk}
\pagetitle{OneVariableGraphicsPage}{graphics.ht}{Functions of One Variable}
\begin{chunk}{graphics.ht}
\begin{page}{OneVariableGraphicsPage}{Functions of One Variable}
\beginscroll
Here we wish to plot a function y = f(x) on an interval [a,b].
As an example, let's take the function y = sin(tan(x)) - tan(sin(x))
on the interval [0,6].
Here is the simplest command that will do this:
\graphpaste{draw(sin(tan(x)) - tan(sin(x)),x = 0..6)}
Notice that Axiom compiled a function before the graph was put on the
screen.  The expression sin(tan(x)) - tan(sin(x)) was converted to a
compiled function so that it's value for various values of x could be
computed quickly and efficiently.  Let's graph the same function on a
different interval and this time we'll give the graph a title.  The
title is a String, which is an optional argument of the command
'draw'.
\graphpaste{draw(sin(tan(x)) - tan(sin(x)),x = 10..16,
title == "y = sin tan x - tan sin x")}
Once again the expression sin(tan(x)) - tan(sin(x)) was 
converted to a compiled function before any points were computed.
If you want to graph the same function on a number of intervals, it's
a good idea to write down a function definition so that the function
only has to be compiled once.
Here's an example:
\spadpaste{f(x) == (x-1)*(x-2)*(x-3) \bound{f}}
\newline
\graphpaste{draw(f, 0..2, title == "y = f(x) on \[0,2\]") \free{f}}
\newline
\graphpaste{draw(f, 0..4,title == "y = f(x) on \[0,4\]") \free{f}}
Notice that our titles can be whatever we want, as long as they are
enclosed by double quotes.  However, a title which is too long to fit
within the viewport title window will be clipped.
\endscroll
\autobuttons 
\end{page}

\begin{patch}{OneVariableGraphicsPagePatch1}
\begin{paste}{OneVariableGraphicsPageFull1}{OneVariableGraphicsPageEmpty1}
\pastebutton{OneVariableGraphicsPageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(sin(tan(x)) - tan(sin(x)),x = 0..6)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/onevariablegraphicspage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/onevariablegraphicspage1}}
\end{paste}\end{patch}

\begin{patch}{OneVariableGraphicsPageEmpty1}
\begin{paste}{OneVariableGraphicsPageEmpty1}{OneVariableGraphicsPagePatch1}
\pastebutton{OneVariableGraphicsPageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(sin(tan(x)) - tan(sin(x)),x = 0..6)}
\end{paste}\end{patch}

\begin{patch}{OneVariableGraphicsPagePatch2}
\begin{paste}{OneVariableGraphicsPageFull2}{OneVariableGraphicsPageEmpty2}
\pastebutton{OneVariableGraphicsPageFull2}{\hidepaste}
\tab{5}\spadgraph{draw(sin(tan(x)) - tan(sin(x)),x = 10..16,title == "y = sin tan x - tan sin x")}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/onevariablegraphicspage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/onevariablegraphicspage2}}
\end{paste}\end{patch}

\begin{patch}{OneVariableGraphicsPageEmpty2}
\begin{paste}{OneVariableGraphicsPageEmpty2}{OneVariableGraphicsPagePatch2}
\pastebutton{OneVariableGraphicsPageEmpty2}{\showpaste}
\tab{5}\spadgraph{draw(sin(tan(x)) - tan(sin(x)),x = 10..16,title == "y = sin tan x - tan sin x")}
\end{paste}\end{patch}

\begin{patch}{OneVariableGraphicsPagePatch3}
\begin{paste}{OneVariableGraphicsPageFull3}{OneVariableGraphicsPageEmpty3}
\pastebutton{OneVariableGraphicsPageFull3}{\hidepaste}
\tab{5}\spadcommand{f(x) == (x-1)*(x-2)*(x-3)\bound{f }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OneVariableGraphicsPageEmpty3}
\begin{paste}{OneVariableGraphicsPageEmpty3}{OneVariableGraphicsPagePatch3}
\pastebutton{OneVariableGraphicsPageEmpty3}{\showpaste}
\tab{5}\spadcommand{f(x) == (x-1)*(x-2)*(x-3)\bound{f }}
\end{paste}\end{patch}

\begin{patch}{OneVariableGraphicsPagePatch4}
\begin{paste}{OneVariableGraphicsPageFull4}{OneVariableGraphicsPageEmpty4}
\pastebutton{OneVariableGraphicsPageFull4}{\hidepaste}
\tab{5}\spadgraph{draw(f, 0..2, title == "y = f(x) on [0,2]")\free{f }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/OneVariableGraphicsPage4.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/OneVariableGraphicsPage4}}
\end{paste}\end{patch}

\begin{patch}{OneVariableGraphicsPageEmpty4}
\begin{paste}{OneVariableGraphicsPageEmpty4}{OneVariableGraphicsPagePatch4}
\pastebutton{OneVariableGraphicsPageEmpty4}{\showpaste}
\tab{5}\spadgraph{draw(f, 0..2, title == "y = f(x) on [0,2]")\free{f }}
\end{paste}\end{patch}

\begin{patch}{OneVariableGraphicsPagePatch5}
\begin{paste}{OneVariableGraphicsPageFull5}{OneVariableGraphicsPageEmpty5}
\pastebutton{OneVariableGraphicsPageFull5}{\hidepaste}
\tab{5}\spadgraph{draw(f, 0..4,title == "y = f(x) on [0,4]")\free{f }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/OneVariableGraphicsPage5.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/OneVariableGraphicsPage5}}
\end{paste}\end{patch}

\begin{patch}{OneVariableGraphicsPageEmpty5}
\begin{paste}{OneVariableGraphicsPageEmpty5}{OneVariableGraphicsPagePatch5}
\pastebutton{OneVariableGraphicsPageEmpty5}{\showpaste}
\tab{5}\spadgraph{draw(f, 0..4,title == "y = f(x) on [0,4]")\free{f }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ParametricCurveGraphicsPage}{graphics.ht}{Parametric Curves}
\begin{chunk}{graphics.ht}
\begin{page}{ParametricCurveGraphicsPage}{Parametric Curves}
\beginscroll
One way of producing interesting curves is by using parametric
equations.  Let x = f(t) and y = g(t) for two functions f and g as the
parameter t ranges over an interval \[a,b\].
Here's an example:
\graphpaste{draw(curve(sin(t)*sin(2*t)*sin(3*t), 
sin(4*t)*sin(5*t)*sin(6*t)), t = 0..2*\%pi)}
Here 0..2*\%pi represents the interval over which the variable t ranges.
In the case of parametric curves, Axiom will compile two functions,
one for each of the functions f and g.
You may also put a title on a graph.
The title may be an arbitrary string and is an optional argument
to the command 'draw'.
For example:
\graphpaste{draw(curve(cos(t), sin(t)), t = 0..2*\%pi, 
title == "The Unit Circle")}
If you plan on plotting x = f(t), y = g(t) as t ranges over several
intervals, you may want to define functions f and g, so that they need
not be recompiled every time you create a new graph.  Here's an
example:
\spadpaste{f(t:SF):SF == sin(3*t/4) \bound{f}} 
\newline
\spadpaste{g(t:SF):SF == sin(t) \bound{g}} 
\newline
\graphpaste{draw(curve(f,g), 0..\%pi) \free{f g}} 
\newline
\graphpaste{draw(curve(f,g) ,\%pi..2*\%pi) \free{f g}} 
\newline
\graphpaste{draw(curve(f,g), -4*\%pi..4*\%pi) \free{f g}}
These examples show how the curve changes as the range of 
parameter t varies.
\endscroll
\autobuttons 
\end{page}

\begin{patch}{ParametricCurveGraphicsPagePatch1}
\begin{paste}{ParametricCurveGraphicsPageFull1}{ParametricCurveGraphicsPageEmpty1}
\pastebutton{ParametricCurveGraphicsPageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(curve(sin(t)*sin(2*t)*sin(3*t), sin(4*t)*sin(5*t)*sin(6*t)), t = 0..2*\%pi)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/parametriccurvegraphicspage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/parametriccurvegraphicspage1}}
\end{paste}\end{patch}

\begin{patch}{ParametricCurveGraphicsPageEmpty1}
\begin{paste}{ParametricCurveGraphicsPageEmpty1}{ParametricCurveGraphicsPagePatch1}
\pastebutton{ParametricCurveGraphicsPageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(curve(sin(t)*sin(2*t)*sin(3*t), sin(4*t)*sin(5*t)*sin(6*t)), t = 0..2*\%pi)}
\end{paste}\end{patch}

\begin{patch}{ParametricCurveGraphicsPagePatch2}
\begin{paste}{ParametricCurveGraphicsPageFull2}{ParametricCurveGraphicsPageEmpty2}
\pastebutton{ParametricCurveGraphicsPageFull2}{\hidepaste}
\tab{5}\spadgraph{draw(curve(cos(t), sin(t)), t = 0..2*\%pi, title == "The Unit Circle")}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/parametriccurvegraphicspage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/parametriccurvegraphicspage2}}
\end{paste}\end{patch}

\begin{patch}{ParametricCurveGraphicsPageEmpty2}
\begin{paste}{ParametricCurveGraphicsPageEmpty2}{ParametricCurveGraphicsPagePatch2}
\pastebutton{ParametricCurveGraphicsPageEmpty2}{\showpaste}
\tab{5}\spadgraph{draw(curve(cos(t), sin(t)), t = 0..2*\%pi, title == "The Unit Circle")}
\end{paste}\end{patch}

\begin{patch}{ParametricCurveGraphicsPagePatch3}
\begin{paste}{ParametricCurveGraphicsPageFull3}{ParametricCurveGraphicsPageEmpty3}
\pastebutton{ParametricCurveGraphicsPageFull3}{\hidepaste}
\tab{5}\spadcommand{f(t:SF):SF == sin(3*t/4)\bound{f }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ParametricCurveGraphicsPageEmpty3}
\begin{paste}{ParametricCurveGraphicsPageEmpty3}{ParametricCurveGraphicsPagePatch3}
\pastebutton{ParametricCurveGraphicsPageEmpty3}{\showpaste}
\tab{5}\spadcommand{f(t:SF):SF == sin(3*t/4)\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ParametricCurveGraphicsPagePatch4}
\begin{paste}{ParametricCurveGraphicsPageFull4}{ParametricCurveGraphicsPageEmpty4}
\pastebutton{ParametricCurveGraphicsPageFull4}{\hidepaste}
\tab{5}\spadcommand{g(t:SF):SF == sin(t)\bound{g }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ParametricCurveGraphicsPageEmpty4}
\begin{paste}{ParametricCurveGraphicsPageEmpty4}{ParametricCurveGraphicsPagePatch4}
\pastebutton{ParametricCurveGraphicsPageEmpty4}{\showpaste}
\tab{5}\spadcommand{g(t:SF):SF == sin(t)\bound{g }}
\end{paste}\end{patch}

\begin{patch}{ParametricCurveGraphicsPagePatch5}
\begin{paste}{ParametricCurveGraphicsPageFull5}{ParametricCurveGraphicsPageEmpty5}
\pastebutton{ParametricCurveGraphicsPageFull5}{\hidepaste}
\tab{5}\spadgraph{draw(curve(f,g), 0..\%pi)\free{f g }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/parametriccurvegraphicspage5.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/parametriccurvegraphicspage5}}
\end{paste}\end{patch}

\begin{patch}{ParametricCurveGraphicsPageEmpty5}
\begin{paste}{ParametricCurveGraphicsPageEmpty5}{ParametricCurveGraphicsPagePatch5}
\pastebutton{ParametricCurveGraphicsPageEmpty5}{\showpaste}
\tab{5}\spadgraph{draw(curve(f,g), 0..\%pi)\free{f g }}
\end{paste}\end{patch}

\begin{patch}{ParametricCurveGraphicsPagePatch6}
\begin{paste}{ParametricCurveGraphicsPageFull6}{ParametricCurveGraphicsPageEmpty6}
\pastebutton{ParametricCurveGraphicsPageFull6}{\hidepaste}
\tab{5}\spadgraph{draw(curve(f,g) ,\%pi..2*\%pi)\free{f g }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/parametriccurvegraphicspage6.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/parametriccurvegraphicspage6}}
\end{paste}\end{patch}

\begin{patch}{ParametricCurveGraphicsPageEmpty6}
\begin{paste}{ParametricCurveGraphicsPageEmpty6}{ParametricCurveGraphicsPagePatch6}
\pastebutton{ParametricCurveGraphicsPageEmpty6}{\showpaste}
\tab{5}\spadgraph{draw(curve(f,g) ,\%pi..2*\%pi)\free{f g }}
\end{paste}\end{patch}

\begin{patch}{ParametricCurveGraphicsPagePatch7}
\begin{paste}{ParametricCurveGraphicsPageFull7}{ParametricCurveGraphicsPageEmpty7}
\pastebutton{ParametricCurveGraphicsPageFull7}{\hidepaste}
\tab{5}\spadgraph{draw(curve(f,g), -4*\%pi..4*\%pi)\free{f g }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/parametriccurvegraphicspage7.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/parametriccurvegraphicspage7}}
\end{paste}\end{patch}

\begin{patch}{ParametricCurveGraphicsPageEmpty7}
\begin{paste}{ParametricCurveGraphicsPageEmpty7}{ParametricCurveGraphicsPagePatch7}
\pastebutton{ParametricCurveGraphicsPageEmpty7}{\showpaste}
\tab{5}\spadgraph{draw(curve(f,g), -4*\%pi..4*\%pi)\free{f g }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{PolarGraphicsPage}{graphics.ht}{Polar Coordinates}
\begin{chunk}{graphics.ht}
\begin{page}{PolarGraphicsPage}{Polar Coordinates}
\beginscroll
Graphs in polar coordinates are given by an equation r = f(theta) as
theta ranges over an interval.
This is equivalent to the parametric curve x = f(theta) * cos(theta),
y = f(theta) * sin(theta) as theta ranges over the same interval.
You may create such curves using the command 'draw', with the optional
argument 'coordinates == polar'.
Here are some examples:
\graphpaste{draw(1,t = 0..2*\%pi,coordinates == polar, 
title == "The Unit Circle")} 
\newline
\graphpaste{draw(sin(17*t), t = 0..2*\%pi, coordinates == polar, 
title == "A Petal Curve")}
%When you don't specify an interval, Axiom will assume that you
%mean 0..2*\%pi.
You may also define your own functions, when you plan on plotting the
same curve as theta varies over several intervals.
\spadpaste{f(t) == cos(4*t/7) \bound{f}} 
\newline
\graphpaste{draw(f, 0..2*\%pi, coordinates == polar) \free{f}} 
\newline
\graphpaste{draw(f, 0..14*\%pi, coordinates == polar) \free{f}}
For information on plotting graphs in other coordinate systems see the
pages for the \spadtype{CoordinateSystems} domain.
\endscroll
\autobuttons 
\end{page}

\begin{patch}{PolarGraphicsPagePatch1}
\begin{paste}{PolarGraphicsPageFull1}{PolarGraphicsPageEmpty1}
\pastebutton{PolarGraphicsPageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(1,t = 0..2*\%pi,coordinates == polar, title == "The Unit Circle")}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/polargraphicspage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/polargraphicspage1}}
\end{paste}\end{patch}

\begin{patch}{PolarGraphicsPageEmpty1}
\begin{paste}{PolarGraphicsPageEmpty1}{PolarGraphicsPagePatch1}
\pastebutton{PolarGraphicsPageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(1,t = 0..2*\%pi,coordinates == polar, title == "The Unit Circle")}
\end{paste}\end{patch}

\begin{patch}{PolarGraphicsPagePatch2}
\begin{paste}{PolarGraphicsPageFull2}{PolarGraphicsPageEmpty2}
\pastebutton{PolarGraphicsPageFull2}{\hidepaste}
\tab{5}\spadgraph{draw(sin(17*t), t = 0..2*\%pi, coordinates == polar, title == "A Petal Curve")}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/polargraphicspage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/polargraphicspage2}}
\end{paste}\end{patch}

\begin{patch}{PolarGraphicsPageEmpty2}
\begin{paste}{PolarGraphicsPageEmpty2}{PolarGraphicsPagePatch2}
\pastebutton{PolarGraphicsPageEmpty2}{\showpaste}
\tab{5}\spadgraph{draw(sin(17*t), t = 0..2*\%pi, coordinates == polar, title == "A Petal Curve")}
\end{paste}\end{patch}

\begin{patch}{PolarGraphicsPagePatch3}
\begin{paste}{PolarGraphicsPageFull3}{PolarGraphicsPageEmpty3}
\pastebutton{PolarGraphicsPageFull3}{\hidepaste}
\tab{5}\spadcommand{f(t) == cos(4*t/7)\bound{f }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolarGraphicsPageEmpty3}
\begin{paste}{PolarGraphicsPageEmpty3}{PolarGraphicsPagePatch3}
\pastebutton{PolarGraphicsPageEmpty3}{\showpaste}
\tab{5}\spadcommand{f(t) == cos(4*t/7)\bound{f }}
\end{paste}\end{patch}

\begin{patch}{PolarGraphicsPagePatch4}
\begin{paste}{PolarGraphicsPageFull4}{PolarGraphicsPageEmpty4}
\pastebutton{PolarGraphicsPageFull4}{\hidepaste}
\tab{5}\spadgraph{draw(f, 0..2*\%pi, coordinates == polar)\free{f }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/polargraphicspage4.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/polargraphicspage4}}
\end{paste}\end{patch}

\begin{patch}{PolarGraphicsPageEmpty4}
\begin{paste}{PolarGraphicsPageEmpty4}{PolarGraphicsPagePatch4}
\pastebutton{PolarGraphicsPageEmpty4}{\showpaste}
\tab{5}\spadgraph{draw(f, 0..2*\%pi, coordinates == polar)\free{f }}
\end{paste}\end{patch}

\begin{patch}{PolarGraphicsPagePatch5}
\begin{paste}{PolarGraphicsPageFull5}{PolarGraphicsPageEmpty5}
\pastebutton{PolarGraphicsPageFull5}{\hidepaste}
\tab{5}\spadgraph{draw(f, 0..14*\%pi, coordinates == polar)\free{f }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/polargraphicspage5.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/polargraphicspage5}}
\end{paste}\end{patch}

\begin{patch}{PolarGraphicsPageEmpty5}
\begin{paste}{PolarGraphicsPageEmpty5}{PolarGraphicsPagePatch5}
\pastebutton{PolarGraphicsPageEmpty5}{\showpaste}
\tab{5}\spadgraph{draw(f, 0..14*\%pi, coordinates == polar)\free{f }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ImplicitCurveGraphicsPage}{graphics.ht}{Implicit Curves}
\begin{chunk}{graphics.ht}
\begin{page}{ImplicitCurveGraphicsPage}{Implicit Curves}
\beginscroll
Axiom has facilities for graphing a non-singular algebraic curve
in a rectangular region of the plane.
An algebraic curve is a curve defined by a polynomial equation
p(x,y) = 0.
Non-singular means that the curve is "smooth" in that it does not
cross itself or come to a point (cusp).
Algebraically, this means that for any point (a,b) on the curve
(i.e. a point such that p(a,b) = 0), the partial derivatives
dp/dx(a,b) and dp/dy(a,b) are not both zero.
We require that the polynomial have rational or integral coefficients.
Here is a Cartesian ovals algebraic curve example:
(click on the draw button to execute this example)
\spadpaste{p := ((x**2 + y**2 + 1) - 8*x)**2 - 
(8*(x**2 + y**2 + 1) - 4*x - 1) \bound{p} }
\graphpaste{draw(p = 0, x, y, range == \[-1..11, -7..7\], 
title == "Cartesian Ovals") \free{p}}
{\em A range must be declared for each variable specified in the 
algebraic curve equation}.
\endscroll
\autobuttons 
\end{page}

\begin{patch}{ImplicitCurveGraphicsPagePatch1}
\begin{paste}{ImplicitCurveGraphicsPageFull1}{ImplicitCurveGraphicsPageEmpty1}
\pastebutton{ImplicitCurveGraphicsPageFull1}{\hidepaste}
\tab{5}\spadcommand{p := ((x**2 + y**2 + 1) - 8*x)**2 - (8*(x**2 + y**2 + 1) - 4*x - 1)\bound{p }}
\indentrel{3}\begin{verbatim}
   (1)
    4      2            2    4      3      2
   y  + (2x  - 16x - 6)y  + x  - 16x  + 58x  - 12x - 6
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ImplicitCurveGraphicsPageEmpty1}
\begin{paste}{ImplicitCurveGraphicsPageEmpty1}{ImplicitCurveGraphicsPagePatch1}
\pastebutton{ImplicitCurveGraphicsPageEmpty1}{\showpaste}
\tab{5}\spadcommand{p := ((x**2 + y**2 + 1) - 8*x)**2 - (8*(x**2 + y**2 + 1) - 4*x - 1)\bound{p }}
\end{paste}\end{patch}

\begin{patch}{ImplicitCurveGraphicsPagePatch2}
\begin{paste}{ImplicitCurveGraphicsPageFull2}{ImplicitCurveGraphicsPageEmpty2}
\pastebutton{ImplicitCurveGraphicsPageFull2}{\hidepaste}
\tab{5}\spadgraph{draw(p = 0, x, y, range == [-1..11, -7..7], title == "Cartesian Ovals")\free{p }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/implicitcurvegraphicspage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/implicitcurvegraphicspage2}}
\end{paste}\end{patch}

\begin{patch}{ImplicitCurveGraphicsPageEmpty2}
\begin{paste}{ImplicitCurveGraphicsPageEmpty2}{ImplicitCurveGraphicsPagePatch2}
\pastebutton{ImplicitCurveGraphicsPageEmpty2}{\showpaste}
\tab{5}\spadgraph{draw(p = 0, x, y, range == [-1..11, -7..7], title == "Cartesian Ovals")\free{p }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ListPointsGraphicsPage}{graphics.ht}{Lists of Points}
\begin{chunk}{graphics.ht}
\begin{page}{ListPointsGraphicsPage}{Lists of Points}
\beginscroll
Axiom has the ability to create lists of points in a two dimensional
graphics viewport.  This is done by utilizing the \spadtype{GraphImage} 
and \spadtype{TwoDimensionalViewport} domain facilities.
\indent{5}\newline
{\em NOTE:  It is only necessary to click on the makeViewport2D command 
button to plot this curve example}.
\indent{0}\newline
In this example, the \spadfun{makeGraphImage} command takes a list of
lists of points parameter, a list of colors for each point in the
graph, a list of colors for each line in the graph, and a list of
numbers which indicate the size of each point in the graph.  The
following lines create list of lists of points which can be read be
made into two dimensional graph images.
\spadpaste{p1 := point [1::SF,1::SF]\$(Point SF) \bound{p1}} 
\newline
\spadpaste{p2 := point [0::SF,1::SF]\$(Point SF) \bound{p2}} 
\newline
\spadpaste{p3 := point [0::SF,0::SF]\$(Point SF) \bound{p3}} 
\newline
\spadpaste{p4 := point [1::SF,0::SF]\$(Point SF) \bound{p4}} 
\newline
\spadpaste{p5 := point [1::SF,.5::SF]\$(Point SF) \bound{p5}} 
\newline
\spadpaste{p6 := point [.5::SF,0::SF]\$(Point SF) \bound{p6}} 
\newline
\spadpaste{p7 := point [0::SF,0.5::SF]\$(Point SF) \bound{p7}} 
\newline
\spadpaste{p8 := point [.5::SF,1::SF]\$(Point SF) \bound{p8}} 
\newline
\spadpaste{p9 := point [.25::SF,.25::SF]\$(Point SF) \bound{p9}} 
\newline
\spadpaste{p10 := point [.25::SF,.75::SF]\$(Point SF) \bound{p10}} 
\newline
\spadpaste{p11 := point [.75::SF,.75::SF]\$(Point SF) \bound{p11}} 
\newline
\spadpaste{p12 := point [.75::SF,.25::SF]\$(Point SF) \bound{p12}} 
\newline
\spadpaste{llp := [[p1,p2],[p2,p3],[p3,p4],[p4,p1],[p5,p6],[p6,p7],
[p7,p8],[p8,p5],[p9,p10],[p10,p11],[p11,p12],[p12,p9]] \bound{llp} 
\free{p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12}} 
\newline
These lines set the point color and size, and the line color for 
all components of the graph.
\spadpaste{size1 := 6::PositiveInteger \bound{size1}} 
\newline
\spadpaste{size2 := 8::PositiveInteger \bound{size2}} 
\newline
\spadpaste{size3 := 10::PositiveInteger \bound{size3}} 
\newline
\spadpaste{lsize := [size1, size1, size1, size1, size2, size2, size2, 
size2, size3, size3, size3, size3] \bound{lsize} 
\free{size1 size2 size3}} 
\newline
\spadpaste{pc1 := pastel red() \bound{pc1}} 
\newline
\spadpaste{pc2 := dim green() \bound{pc2}} 
\newline
\spadpaste{pc3 := pastel yellow() \bound{pc3}} 
\newline
\spadpaste{lpc := [pc1, pc1, pc1, pc1, pc2, pc2, pc2, pc2, pc3, pc3, 
pc3, pc3] \bound{lpc} \free{pc1 pc2 pc3}} 
\newline
\spadpaste{lc := [pastel blue(), light yellow(), dim green(), 
bright red(), light green(), dim yellow(), bright blue(), 
dark red(), pastel red(), light blue(), dim green(), 
light yellow()] \bound{lc}} 
\newline
Now the graph image is created and named according to the component
specifications indicated above.  The \spadfun{makeViewport2D} command
then creates a two dimensional viewport for this graph according to
the list of options specified within the brackets.
\spadpaste{g := makeGraphImage(llp,lpc,lc,lsize)\$GRIMAGE \bound{g} 
\free{llp lpc lc lsize}} 
\newline
\graphpaste{makeViewport2D(g,[title("Lines")])\$VIEW2D \free{g}}
The \spadfun{makeViewport2D} command takes a list of options as a
parameter.  In this example the string "Lines" is designated as the
viewport's title.
\endscroll
\autobuttons 
\end{page}

\begin{patch}{ListPointsGraphicsPagePatch1}
\begin{paste}{ListPointsGraphicsPageFull1}{ListPointsGraphicsPageEmpty1}
\pastebutton{ListPointsGraphicsPageFull1}{\hidepaste}
\tab{5}\spadcommand{p1 := point [1::SF,1::SF]$(Point SF)\bound{p1 }}
\indentrel{3}\begin{verbatim}
   (1)  [1.0,1.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty1}
\begin{paste}{ListPointsGraphicsPageEmpty1}{ListPointsGraphicsPagePatch1}
\pastebutton{ListPointsGraphicsPageEmpty1}{\showpaste}
\tab{5}\spadcommand{p1 := point [1::SF,1::SF]$(Point SF)\bound{p1 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch2}
\begin{paste}{ListPointsGraphicsPageFull2}{ListPointsGraphicsPageEmpty2}
\pastebutton{ListPointsGraphicsPageFull2}{\hidepaste}
\tab{5}\spadcommand{p2 := point [0::SF,1::SF]$(Point SF)\bound{p2 }}
\indentrel{3}\begin{verbatim}
   (2)  [0.0,1.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty2}
\begin{paste}{ListPointsGraphicsPageEmpty2}{ListPointsGraphicsPagePatch2}
\pastebutton{ListPointsGraphicsPageEmpty2}{\showpaste}
\tab{5}\spadcommand{p2 := point [0::SF,1::SF]$(Point SF)\bound{p2 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch3}
\begin{paste}{ListPointsGraphicsPageFull3}{ListPointsGraphicsPageEmpty3}
\pastebutton{ListPointsGraphicsPageFull3}{\hidepaste}
\tab{5}\spadcommand{p3 := point [0::SF,0::SF]$(Point SF)\bound{p3 }}
\indentrel{3}\begin{verbatim}
   (3)  [0.0,0.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty3}
\begin{paste}{ListPointsGraphicsPageEmpty3}{ListPointsGraphicsPagePatch3}
\pastebutton{ListPointsGraphicsPageEmpty3}{\showpaste}
\tab{5}\spadcommand{p3 := point [0::SF,0::SF]$(Point SF)\bound{p3 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch4}
\begin{paste}{ListPointsGraphicsPageFull4}{ListPointsGraphicsPageEmpty4}
\pastebutton{ListPointsGraphicsPageFull4}{\hidepaste}
\tab{5}\spadcommand{p4 := point [1::SF,0::SF]$(Point SF)\bound{p4 }}
\indentrel{3}\begin{verbatim}
   (4)  [1.0,0.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty4}
\begin{paste}{ListPointsGraphicsPageEmpty4}{ListPointsGraphicsPagePatch4}
\pastebutton{ListPointsGraphicsPageEmpty4}{\showpaste}
\tab{5}\spadcommand{p4 := point [1::SF,0::SF]$(Point SF)\bound{p4 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch5}
\begin{paste}{ListPointsGraphicsPageFull5}{ListPointsGraphicsPageEmpty5}
\pastebutton{ListPointsGraphicsPageFull5}{\hidepaste}
\tab{5}\spadcommand{p5 := point [1::SF,.5::SF]$(Point SF)\bound{p5 }}
\indentrel{3}\begin{verbatim}
   (5)  [1.0,0.5]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty5}
\begin{paste}{ListPointsGraphicsPageEmpty5}{ListPointsGraphicsPagePatch5}
\pastebutton{ListPointsGraphicsPageEmpty5}{\showpaste}
\tab{5}\spadcommand{p5 := point [1::SF,.5::SF]$(Point SF)\bound{p5 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch6}
\begin{paste}{ListPointsGraphicsPageFull6}{ListPointsGraphicsPageEmpty6}
\pastebutton{ListPointsGraphicsPageFull6}{\hidepaste}
\tab{5}\spadcommand{p6 := point [.5::SF,0::SF]$(Point SF)\bound{p6 }}
\indentrel{3}\begin{verbatim}
   (6)  [0.5,0.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty6}
\begin{paste}{ListPointsGraphicsPageEmpty6}{ListPointsGraphicsPagePatch6}
\pastebutton{ListPointsGraphicsPageEmpty6}{\showpaste}
\tab{5}\spadcommand{p6 := point [.5::SF,0::SF]$(Point SF)\bound{p6 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch7}
\begin{paste}{ListPointsGraphicsPageFull7}{ListPointsGraphicsPageEmpty7}
\pastebutton{ListPointsGraphicsPageFull7}{\hidepaste}
\tab{5}\spadcommand{p7 := point [0::SF,0.5::SF]$(Point SF)\bound{p7 }}
\indentrel{3}\begin{verbatim}
   (7)  [0.0,0.5]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty7}
\begin{paste}{ListPointsGraphicsPageEmpty7}{ListPointsGraphicsPagePatch7}
\pastebutton{ListPointsGraphicsPageEmpty7}{\showpaste}
\tab{5}\spadcommand{p7 := point [0::SF,0.5::SF]$(Point SF)\bound{p7 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch8}
\begin{paste}{ListPointsGraphicsPageFull8}{ListPointsGraphicsPageEmpty8}
\pastebutton{ListPointsGraphicsPageFull8}{\hidepaste}
\tab{5}\spadcommand{p8 := point [.5::SF,1::SF]$(Point SF)\bound{p8 }}
\indentrel{3}\begin{verbatim}
   (8)  [0.5,1.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty8}
\begin{paste}{ListPointsGraphicsPageEmpty8}{ListPointsGraphicsPagePatch8}
\pastebutton{ListPointsGraphicsPageEmpty8}{\showpaste}
\tab{5}\spadcommand{p8 := point [.5::SF,1::SF]$(Point SF)\bound{p8 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch9}
\begin{paste}{ListPointsGraphicsPageFull9}{ListPointsGraphicsPageEmpty9}
\pastebutton{ListPointsGraphicsPageFull9}{\hidepaste}
\tab{5}\spadcommand{p9 := point [.25::SF,.25::SF]$(Point SF)\bound{p9 }}
\indentrel{3}\begin{verbatim}
   (9)  [0.25,0.25]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty9}
\begin{paste}{ListPointsGraphicsPageEmpty9}{ListPointsGraphicsPagePatch9}
\pastebutton{ListPointsGraphicsPageEmpty9}{\showpaste}
\tab{5}\spadcommand{p9 := point [.25::SF,.25::SF]$(Point SF)\bound{p9 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch10}
\begin{paste}{ListPointsGraphicsPageFull10}{ListPointsGraphicsPageEmpty10}
\pastebutton{ListPointsGraphicsPageFull10}{\hidepaste}
\tab{5}\spadcommand{p10 := point [.25::SF,.75::SF]$(Point SF)\bound{p10 }}
\indentrel{3}\begin{verbatim}
   (10)  [0.25,0.75]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty10}
\begin{paste}{ListPointsGraphicsPageEmpty10}{ListPointsGraphicsPagePatch10}
\pastebutton{ListPointsGraphicsPageEmpty10}{\showpaste}
\tab{5}\spadcommand{p10 := point [.25::SF,.75::SF]$(Point SF)\bound{p10 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch11}
\begin{paste}{ListPointsGraphicsPageFull11}{ListPointsGraphicsPageEmpty11}
\pastebutton{ListPointsGraphicsPageFull11}{\hidepaste}
\tab{5}\spadcommand{p11 := point [.75::SF,.75::SF]$(Point SF)\bound{p11 }}
\indentrel{3}\begin{verbatim}
   (11)  [0.75,0.75]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty11}
\begin{paste}{ListPointsGraphicsPageEmpty11}{ListPointsGraphicsPagePatch11}
\pastebutton{ListPointsGraphicsPageEmpty11}{\showpaste}
\tab{5}\spadcommand{p11 := point [.75::SF,.75::SF]$(Point SF)\bound{p11 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch12}
\begin{paste}{ListPointsGraphicsPageFull12}{ListPointsGraphicsPageEmpty12}
\pastebutton{ListPointsGraphicsPageFull12}{\hidepaste}
\tab{5}\spadcommand{p12 := point [.75::SF,.25::SF]$(Point SF)\bound{p12 }}
\indentrel{3}\begin{verbatim}
   (12)  [0.75,0.25]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty12}
\begin{paste}{ListPointsGraphicsPageEmpty12}{ListPointsGraphicsPagePatch12}
\pastebutton{ListPointsGraphicsPageEmpty12}{\showpaste}
\tab{5}\spadcommand{p12 := point [.75::SF,.25::SF]$(Point SF)\bound{p12 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch13}
\begin{paste}{ListPointsGraphicsPageFull13}{ListPointsGraphicsPageEmpty13}
\pastebutton{ListPointsGraphicsPageFull13}{\hidepaste}
\tab{5}\spadcommand{llp := [[p1,p2],[p2,p3],[p3,p4],[p4,p1],[p5,p6],[p6,p7],[p7,p8],[p8,p5],[p9,p10],[p10,p11],[p11,p12],[p12,p9]]\bound{llp }\free{p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 }}
\indentrel{3}\begin{verbatim}
   (13)
   [[[1.0,1.0],[0.0,1.0]], [[0.0,1.0],[0.0,0.0]],
    [[0.0,0.0],[1.0,0.0]], [[1.0,0.0],[1.0,1.0]],
    [[1.0,0.5],[0.5,0.0]], [[0.5,0.0],[0.0,0.5]],
    [[0.0,0.5],[0.5,1.0]], [[0.5,1.0],[1.0,0.5]],
    [[0.25,0.25],[0.25,0.75]], [[0.25,0.75],[0.75,0.75]],
    [[0.75,0.75],[0.75,0.25]], [[0.75,0.25],[0.25,0.25]]]
                      Type: List List Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty13}
\begin{paste}{ListPointsGraphicsPageEmpty13}{ListPointsGraphicsPagePatch13}
\pastebutton{ListPointsGraphicsPageEmpty13}{\showpaste}
\tab{5}\spadcommand{llp := [[p1,p2],[p2,p3],[p3,p4],[p4,p1],[p5,p6],[p6,p7],[p7,p8],[p8,p5],[p9,p10],[p10,p11],[p11,p12],[p12,p9]]\bound{llp }\free{p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch14}
\begin{paste}{ListPointsGraphicsPageFull14}{ListPointsGraphicsPageEmpty14}
\pastebutton{ListPointsGraphicsPageFull14}{\hidepaste}
\tab{5}\spadcommand{size1 := 6::PositiveInteger\bound{size1 }}
\indentrel{3}\begin{verbatim}
   (14)  6
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty14}
\begin{paste}{ListPointsGraphicsPageEmpty14}{ListPointsGraphicsPagePatch14}
\pastebutton{ListPointsGraphicsPageEmpty14}{\showpaste}
\tab{5}\spadcommand{size1 := 6::PositiveInteger\bound{size1 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch15}
\begin{paste}{ListPointsGraphicsPageFull15}{ListPointsGraphicsPageEmpty15}
\pastebutton{ListPointsGraphicsPageFull15}{\hidepaste}
\tab{5}\spadcommand{size2 := 8::PositiveInteger\bound{size2 }}
\indentrel{3}\begin{verbatim}
   (15)  8
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty15}
\begin{paste}{ListPointsGraphicsPageEmpty15}{ListPointsGraphicsPagePatch15}
\pastebutton{ListPointsGraphicsPageEmpty15}{\showpaste}
\tab{5}\spadcommand{size2 := 8::PositiveInteger\bound{size2 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch16}
\begin{paste}{ListPointsGraphicsPageFull16}{ListPointsGraphicsPageEmpty16}
\pastebutton{ListPointsGraphicsPageFull16}{\hidepaste}
\tab{5}\spadcommand{size3 := 10::PositiveInteger\bound{size3 }}
\indentrel{3}\begin{verbatim}
   (16)  10
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty16}
\begin{paste}{ListPointsGraphicsPageEmpty16}{ListPointsGraphicsPagePatch16}
\pastebutton{ListPointsGraphicsPageEmpty16}{\showpaste}
\tab{5}\spadcommand{size3 := 10::PositiveInteger\bound{size3 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch17}
\begin{paste}{ListPointsGraphicsPageFull17}{ListPointsGraphicsPageEmpty17}
\pastebutton{ListPointsGraphicsPageFull17}{\hidepaste}
\tab{5}\spadcommand{lsize := [size1, size1, size1, size1, size2, size2, size2, size2, size3, size3, size3, size3]\bound{lsize }\free{size1 size2 size3 }}
\indentrel{3}\begin{verbatim}
   (17)  [6,6,6,6,8,8,8,8,10,10,10,10]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty17}
\begin{paste}{ListPointsGraphicsPageEmpty17}{ListPointsGraphicsPagePatch17}
\pastebutton{ListPointsGraphicsPageEmpty17}{\showpaste}
\tab{5}\spadcommand{lsize := [size1, size1, size1, size1, size2, size2, size2, size2, size3, size3, size3, size3]\bound{lsize }\free{size1 size2 size3 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch18}
\begin{paste}{ListPointsGraphicsPageFull18}{ListPointsGraphicsPageEmpty18}
\pastebutton{ListPointsGraphicsPageFull18}{\hidepaste}
\tab{5}\spadcommand{pc1 := pastel red()\bound{pc1 }}
\indentrel{3}\begin{verbatim}
   (18)  [Hue: 1  Weight: 1.0] from the Pastel palette
                                          Type: Palette
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty18}
\begin{paste}{ListPointsGraphicsPageEmpty18}{ListPointsGraphicsPagePatch18}
\pastebutton{ListPointsGraphicsPageEmpty18}{\showpaste}
\tab{5}\spadcommand{pc1 := pastel red()\bound{pc1 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch19}
\begin{paste}{ListPointsGraphicsPageFull19}{ListPointsGraphicsPageEmpty19}
\pastebutton{ListPointsGraphicsPageFull19}{\hidepaste}
\tab{5}\spadcommand{pc2 := dim green()\bound{pc2 }}
\indentrel{3}\begin{verbatim}
   (19)  [Hue: 14  Weight: 1.0] from the Dim palette
                                          Type: Palette
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty19}
\begin{paste}{ListPointsGraphicsPageEmpty19}{ListPointsGraphicsPagePatch19}
\pastebutton{ListPointsGraphicsPageEmpty19}{\showpaste}
\tab{5}\spadcommand{pc2 := dim green()\bound{pc2 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch20}
\begin{paste}{ListPointsGraphicsPageFull20}{ListPointsGraphicsPageEmpty20}
\pastebutton{ListPointsGraphicsPageFull20}{\hidepaste}
\tab{5}\spadcommand{pc3 := pastel yellow()\bound{pc3 }}
\indentrel{3}\begin{verbatim}
   (20)  [Hue: 11  Weight: 1.0] from the Pastel palette
                                          Type: Palette
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty20}
\begin{paste}{ListPointsGraphicsPageEmpty20}{ListPointsGraphicsPagePatch20}
\pastebutton{ListPointsGraphicsPageEmpty20}{\showpaste}
\tab{5}\spadcommand{pc3 := pastel yellow()\bound{pc3 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch21}
\begin{paste}{ListPointsGraphicsPageFull21}{ListPointsGraphicsPageEmpty21}
\pastebutton{ListPointsGraphicsPageFull21}{\hidepaste}
\tab{5}\spadcommand{lpc := [pc1, pc1, pc1, pc1, pc2, pc2, pc2, pc2, pc3, pc3, pc3, pc3]\bound{lpc }\free{pc1 pc2 pc3 }}
\indentrel{3}\begin{verbatim}
   (21)
   [[Hue: 1  Weight: 1.0] from the Pastel palette,
    [Hue: 1  Weight: 1.0] from the Pastel palette,
    [Hue: 1  Weight: 1.0] from the Pastel palette,
    [Hue: 1  Weight: 1.0] from the Pastel palette,
    [Hue: 14  Weight: 1.0] from the Dim palette,
    [Hue: 14  Weight: 1.0] from the Dim palette,
    [Hue: 14  Weight: 1.0] from the Dim palette,
    [Hue: 14  Weight: 1.0] from the Dim palette,
    [Hue: 11  Weight: 1.0] from the Pastel palette,
    [Hue: 11  Weight: 1.0] from the Pastel palette,
    [Hue: 11  Weight: 1.0] from the Pastel palette,
    [Hue: 11  Weight: 1.0] from the Pastel palette]
                                     Type: List Palette
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty21}
\begin{paste}{ListPointsGraphicsPageEmpty21}{ListPointsGraphicsPagePatch21}
\pastebutton{ListPointsGraphicsPageEmpty21}{\showpaste}
\tab{5}\spadcommand{lpc := [pc1, pc1, pc1, pc1, pc2, pc2, pc2, pc2, pc3, pc3, pc3, pc3]\bound{lpc }\free{pc1 pc2 pc3 }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch22}
\begin{paste}{ListPointsGraphicsPageFull22}{ListPointsGraphicsPageEmpty22}
\pastebutton{ListPointsGraphicsPageFull22}{\hidepaste}
\tab{5}\spadcommand{lc := [pastel blue(), light yellow(), dim green(), bright red(), light green(), dim yellow(), bright blue(), dark red(), pastel red(), light blue(), dim green(), light yellow()]\bound{lc }}
\indentrel{3}\begin{verbatim}
   (22)
   [[Hue: 22  Weight: 1.0] from the Pastel palette,
    [Hue: 11  Weight: 1.0] from the Light palette,
    [Hue: 14  Weight: 1.0] from the Dim palette,
    [Hue: 1  Weight: 1.0] from the Bright palette,
    [Hue: 14  Weight: 1.0] from the Light palette,
    [Hue: 11  Weight: 1.0] from the Dim palette,
    [Hue: 22  Weight: 1.0] from the Bright palette,
    [Hue: 1  Weight: 1.0] from the Dark palette,
    [Hue: 1  Weight: 1.0] from the Pastel palette,
    [Hue: 22  Weight: 1.0] from the Light palette,
    [Hue: 14  Weight: 1.0] from the Dim palette,
    [Hue: 11  Weight: 1.0] from the Light palette]
                                     Type: List Palette
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty22}
\begin{paste}{ListPointsGraphicsPageEmpty22}{ListPointsGraphicsPagePatch22}
\pastebutton{ListPointsGraphicsPageEmpty22}{\showpaste}
\tab{5}\spadcommand{lc := [pastel blue(), light yellow(), dim green(), bright red(), light green(), dim yellow(), bright blue(), dark red(), pastel red(), light blue(), dim green(), light yellow()]\bound{lc }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch23}
\begin{paste}{ListPointsGraphicsPageFull23}{ListPointsGraphicsPageEmpty23}
\pastebutton{ListPointsGraphicsPageFull23}{\hidepaste}
\tab{5}\spadcommand{g := makeGraphImage(llp,lpc,lc,lsize)$GRIMAGE\bound{g }\free{llp lpc lc lsize }}
\indentrel{3}\begin{verbatim}
   (23)  Graph with 12 point lists
                                       Type: GraphImage
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty23}
\begin{paste}{ListPointsGraphicsPageEmpty23}{ListPointsGraphicsPagePatch23}
\pastebutton{ListPointsGraphicsPageEmpty23}{\showpaste}
\tab{5}\spadcommand{g := makeGraphImage(llp,lpc,lc,lsize)$GRIMAGE\bound{g }\free{llp lpc lc lsize }}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPagePatch24}
\begin{paste}{ListPointsGraphicsPageFull24}{ListPointsGraphicsPageEmpty24}
\pastebutton{ListPointsGraphicsPageFull24}{\hidepaste}
\tab{5}\spadgraph{makeViewport2D(g,[title("Lines")])$VIEW2D\free{g }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/listpointsgraphicspage24.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/listpointsgraphicspage24}}
\end{paste}\end{patch}

\begin{patch}{ListPointsGraphicsPageEmpty24}
\begin{paste}{ListPointsGraphicsPageEmpty24}{ListPointsGraphicsPagePatch24}
\pastebutton{ListPointsGraphicsPageEmpty24}{\showpaste}
\tab{5}\spadgraph{makeViewport2D(g,[title("Lines")])$VIEW2D\free{g }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ViewportPage}{graphics.ht}{Stand-alone Viewport}
\begin{chunk}{graphics.ht}
\begin{page}{ViewportPage}{Stand-alone Viewport}
\beginscroll
To get a viewport on a Hyperdoc page, you first need to
create one in Axiom and write it out to a
file that Hyperdoc can call up. \newline
For example, here we draw a saddle function and assign
the result to the variable \spad{v}:
\newline
\graphpaste{v := draw(x*x-y*y,x=-1..1,y=-1..1) \bound{v}} 
\newline
Now that we've created the viewport, we want to write
the data out to a file. \newline
To do this, we use the \spadfunFrom{write}{ThreeDimensionalViewport}
command which takes the following arguments: the viewport to write
out, the title of the file to write it out to, and an optional
argument telling the write command what type (or types) of data you
want to write in additional to the one Axiom will always write
out. The optional argument could be a string, like "pixmap", or a list
of strings, like \["postscript","pixmap"\].  Hyperdoc needs a
"pixmap" data type to include a graph in a page so in this case, we
write the viewport and tell it to also write a "pixmap" file, as well:
\newline
\spadpaste{write(v,"saddle","pixmap") \free{v}}
\newline
Now we want to put this viewport into a Hyperdoc page.
Say you've created a viewport and written it out
to a file called "/tmp/mobius". (Axiom actually
tags a ".view" at the end of a viewport data file to
make it easier to spot when you're rummaging through
your file system, but you needn't worry about that here
since Axiom will always automatically add on a
".view" for you.)  \newline

{\bf Including Viewports} \newline
To put a viewport in a
Hyperdoc page, include the following line in your Hyperdoc
source code: \newline
\space{5}\\viewport\{/tmp/mobius\} \newline
You will get this on your page: \newline
%%%\space{4}\viewport{/tmp/mobius}\newline
%\space{4}\spadviewport{mobius}\newline
\centerline{\spadviewport{mobius}}\newline

{\bf Creating Viewport Buttons} \newline
To make an active button that would make this viewport
come to life, include the following: \newline
\space{5}\\viewportbutton\{ViewButton\}\{/tmp/mobius\} \newline
this creates this button...\newline
%%%\centerline{\viewportbutton{ViewButton}{/tmp/mobius}}\newline
\centerline{\spadviewportbutton{ViewButton}{mobius}}\newline

{\bf Creating Active Viewports} \newline
To merge the two things descibed above, namely, getting a picture of a
viewport and creating a button to invoke a live viewport, you can do
the following: \newline

%\space{5}\\viewportasbutton\{/tmp/mobius\} \newline
\centerline{\\viewportasbutton\{/tmp/mobius\}}\newline

This would create a picture of a viewport that is an active
button as well. Try it:

%%%\space{5}\viewportasbutton{/tmp/mobius} \newline
%\space{5}\spadviewportasbutton{mobius} \newline
\centerline{\spadviewportasbutton{mobius}}\newline

{\bf Including Viewports Distributed with Axiom} \newline
All the above commands have counterparts that allow you to
access viewports that are already packaged with Axiom.
To include those viewports, just add on an "axiom" prefix
to the above commands: \newline

\centerline{\\axiomviewport\{vA\} for \\viewport\{vA\}}
\centerline{\\axiomviewportbutton\{vB\} for \\viewportbutton\{vB\}}
\centerline{\\axiomviewportasbutton\{vC\} for \\viewportasbutton\{vC\}} 
\newline

All these macros really do is include some path that
indicates where Axiom stores the viewports.
\newline
\endscroll
\autobuttons 
\end{page}

\begin{patch}{ViewportPagePatch1}
\begin{paste}{ViewportPageFull1}{ViewportPageEmpty1}
\pastebutton{ViewportPageFull1}{\hidepaste}
\tab{5}\spadgraph{v := draw(x*x-y*y,x=-1..1,y=-1..1)\bound{v }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/viewportpage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/viewportpage1}}
\end{paste}\end{patch}

\begin{patch}{ViewportPageEmpty1}
\begin{paste}{ViewportPageEmpty1}{ViewportPagePatch1}
\pastebutton{ViewportPageEmpty1}{\showpaste}
\tab{5}\spadgraph{v := draw(x*x-y*y,x=-1..1,y=-1..1)\bound{v }}
\end{paste}\end{patch}

\begin{patch}{ViewportPagePatch2}
\begin{paste}{ViewportPageFull2}{ViewportPageEmpty2}
\pastebutton{ViewportPageFull2}{\hidepaste}
\tab{5}\spadcommand{write(v,"saddle","pixmap")\free{v }}
\indentrel{3}\begin{verbatim}
   (2)  "NIL"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ViewportPageEmpty2}
\begin{paste}{ViewportPageEmpty2}{ViewportPagePatch2}
\pastebutton{ViewportPageEmpty2}{\showpaste}
\tab{5}\spadcommand{write(v,"saddle","pixmap")\free{v }}
\end{paste}\end{patch}

\end{chunk}
\section{grpthry.ht}
\pagetitle{GroupTheoryPage}{grpthry.ht}{Group Theory}
\pageto{notitle}{InfoGroupTheoryPage}
\pageto{notitle}{InfoRepTheoryPage}
\pageto{notitle}{RepA6Page}
\begin{chunk}{grpthry.ht}
\begin{page}{GroupTheoryPage}{Group Theory}
% authors: H. Gollan, J. Grabmeier, August 1989
\beginscroll
Axiom can work with individual permutations, permutation
groups and do representation theory.
\horizontalline
\newline
\beginmenu
\menulink{Info on Group Theory}{InfoGroupTheoryPage}


%\menulink{Permutation}{PermutationXmpPage}
%Calculating within symmetric groups.

%\menulink{Permutation Groups}{PermutationGroupXmpPage}
%Working with subgroups of a symmetric group.

%\menulink{Permutation Group Examples}{PermutationGroupExampleXmpPage}
%Working with permutation groups, predefined in the system as Rubik's 
%group.

\menulink{Info on Representation Theory}{InfoRepTheoryPage}

%\menulink{Irreducible Representations of Symmetric Groups}
%{IrrRepSymNatXmpPage}
%Alfred Young's natural form for these representations.

%\menulink{Representations of Higher Degree}
%{RepresentationPackage1XmpPage}
%Constructing new representations by symmetric and antisymmetric
%tensors.

%\menulink{Decomposing Representations}
%{RepresentationPackage2XmpPage}
%Parker's `Meat-Axe', working in prime characteristics.

\menulink{Representations of \texht{$A_6$}{A6}}{RepA6Page}
The irreducible representations of the alternating group
\texht{$A_6$}{A6} over fields of characteristic 2.
\endmenu
\endscroll
\autobuttons \end{page}

\end{chunk}
\pagetitle{RepA6Page}{grpthry.ht}{Representations of $A_6$ A6}
\begin{chunk}{grpthry.ht}
\begin{page}{RepA6Page}{Representations of \texht{$A_6$}{A6}}
% author: J. Grabmeier,  08/08/89
\beginscroll
In what follows you'll see how to use Axiom to get all the irreducible
representations of the alternating group \texht{$A_6$}{A6} over the
field with two elements (GF 2).  First, we generate \texht{$A_6$}{A6}
by a three-cycle: x = (1,2,3) and a 5-cycle: y = (2,3,4,5,6).  Next we
have Axiom calculate the permutation representation over the integers
and over GF 2:
\spadpaste{genA6 : LIST PERM INT := [cycle [1,2,3],cycle [2,3,4,5,6]] 
\bound{genA6}}
\spadpaste{pRA6 := permutationRepresentation (genA6, 6) \bound{pRA6} 
\free{genA6}
}
Now we apply Parker's 'Meat-Axe' and split it:
\spadpaste{sp0 := meatAxe (pRA6::(LIST MATRIX PF 2)) \free{pRA6} 
\bound{sp0}}
We have found the trivial module as a quotient module
and a 5-dimensional sub-module.
Try to split again:
\spadpaste{sp1 := meatAxe sp0.1 \bound{sp1}}
and we find a 4-dimensional sub-module and the trivial one again.
Now we can test if this representaton is absolutely irreducible:
\spadpaste{isAbsolutelyIrreducible? sp1.2 }
and we see that this 4-dimensional representation is absolutely
irreducible.  So, we have found a second irreducible representation.
Now, we construct a representation by reducing an irreducible one of
the symmetric group S_6 over the integers mod 2.  We take the one
labelled by the partition [2,2,1,1] and restrict it to
\texht{$A_6$}{A6}:
\spadpaste{d2211 := irreducibleRepresentation ([2,2,1,1],genA6) 
\bound{d2211} }
Now split it:
\spadpaste{d2211m2 := d2211:: (LIST MATRIX PF 2); 
sp2 := meatAxe d2211m2 \free{d2211}
\bound{sp2}}
This gave both a five and a four dimensional representation.
Now we take the 4-dimensional one
and we shall see that it is absolutely irreducible:
\spadpaste{isAbsolutelyIrreducible? sp2.1}
The two 4-dimensional representations are not equivalent:
\spadpaste{areEquivalent? (sp1.2, sp2.1)}
So we have found a third irreducible representation.
Now we construct a new representation using the tensor product
and try to split it:
\spadpaste{dA6d16 := tensorProduct(sp1.2,sp2.1); 
meatAxe dA6d16 \bound{dA6d16}}
The representation is irreducible, but it may be not 
absolutely irreducible.
\spadpaste{isAbsolutelyIrreducible? dA6d16}
So let's try the same procedure over the field with 4 elements:
\spadpaste{sp3 := meatAxe (dA6d16 :: (LIST MATRIX FF(2,2))) \bound{sp3}}
Now we find two 8-dimensional representations, dA6d8a and dA6d8b.
Both are absolutely irreducible...
\spadpaste{isAbsolutelyIrreducible?  sp3.1}
\spadpaste{isAbsolutelyIrreducible?  sp3.2}
and they are not equivalent:
\spadpaste{areEquivalent? (sp3.1,sp3.2)}
So we have found five absolutely irreducible representations 
of \texht{$A_6$}{A6}
in characteristic 2.
General theory now tells us that there are no more irreducible ones.
Here, for future reference are all the absolutely irreducible 2-modular
representations of \texht{$A_6$}{A6}
\spadpaste{sp0.2 \free{sp0}}
\spadpaste{sp1.2 \free{sp1}}
\spadpaste{sp2.1 \free{sp2}}
\spadpaste{sp3.1 \free{sp3}}
\spadpaste{sp3.2 \free{sp3}}
And here again is the irreducible, but not absolutely irreducible
representations of \texht{$A_6$}{A6} over GF 2
\spadpaste{dA6d16 \free{dA6d16}}
\endscroll
\autobuttons 
\end{page}

\begin{patch}{RepA6PagePatch1}
\begin{paste}{RepA6PageFull1}{RepA6PageEmpty1}
\pastebutton{RepA6PageFull1}{\hidepaste}
\tab{5}\spadcommand{genA6 : LIST PERM INT := [cycle [1,2,3],cycle [2,3,4,5,6]]\bound{genA6 }}
\indentrel{3}\begin{verbatim}
   (1)  [(1 2 3),(2 3 4 5 6)]
                         Type: List Permutation Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RepA6PageEmpty1}
\begin{paste}{RepA6PageEmpty1}{RepA6PagePatch1}
\pastebutton{RepA6PageEmpty1}{\showpaste}
\tab{5}\spadcommand{genA6 : LIST PERM INT := [cycle [1,2,3],cycle [2,3,4,5,6]]\bound{genA6 }}
\end{paste}\end{patch}

\begin{patch}{RepA6PagePatch2}
\begin{paste}{RepA6PageFull2}{RepA6PageEmpty2}
\pastebutton{RepA6PageFull2}{\hidepaste}
\tab{5}\spadcommand{pRA6 := permutationRepresentation (genA6, 6)\bound{pRA6 }\free{genA6 }}
\indentrel{3}\begin{verbatim}
         Ú0  0  1  0  0  0¿ Ú1  0  0  0  0  0¿
         ³                ³ ³                ³
         ³1  0  0  0  0  0³ ³0  0  0  0  0  1³
         ³                ³ ³                ³
         ³0  1  0  0  0  0³ ³0  1  0  0  0  0³
   (2)  [³                ³,³                ³]
         ³0  0  0  1  0  0³ ³0  0  1  0  0  0³
         ³                ³ ³                ³
         ³0  0  0  0  1  0³ ³0  0  0  1  0  0³
         ³                ³ ³                ³
         À0  0  0  0  0  1Ù À0  0  0  0  1  0Ù
                              Type: List Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RepA6PageEmpty2}
\begin{paste}{RepA6PageEmpty2}{RepA6PagePatch2}
\pastebutton{RepA6PageEmpty2}{\showpaste}
\tab{5}\spadcommand{pRA6 := permutationRepresentation (genA6, 6)\bound{pRA6 }\free{genA6 }}
\end{paste}\end{patch}

\begin{patch}{RepA6PagePatch3}
\begin{paste}{RepA6PageFull3}{RepA6PageEmpty3}
\pastebutton{RepA6PageFull3}{\hidepaste}
\tab{5}\spadcommand{sp0 := meatAxe (pRA6::(LIST MATRIX PF 2))\free{pRA6 }\bound{sp0 }}
\indentrel{3}\begin{verbatim}
   Fingerprint element in generated algebra is singular
     A proper cyclic submodule is found.
     Transition matrix computed
     The inverse of the transition matrix computed
     Now transform the matrices
          Ú0  0  1  0  0¿ Ú1  0  0  0  0¿
          ³             ³ ³             ³
          ³1  0  0  0  0³ ³1  1  1  1  1³
          ³             ³ ³             ³
   (3)  [[³0  1  0  0  0³,³0  1  0  0  0³],[[1],[1]]]
          ³             ³ ³             ³
          ³0  0  0  1  0³ ³0  0  1  0  0³
          ³             ³ ³             ³
          À0  0  0  0  1Ù À0  0  0  1  0Ù
                    Type: List List Matrix PrimeField 2
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RepA6PageEmpty3}
\begin{paste}{RepA6PageEmpty3}{RepA6PagePatch3}
\pastebutton{RepA6PageEmpty3}{\showpaste}
\tab{5}\spadcommand{sp0 := meatAxe (pRA6::(LIST MATRIX PF 2))\free{pRA6 }\bound{sp0 }}
\end{paste}\end{patch}

\begin{patch}{RepA6PagePatch4}
\begin{paste}{RepA6PageFull4}{RepA6PageEmpty4}
\pastebutton{RepA6PageFull4}{\hidepaste}
\tab{5}\spadcommand{sp1 := meatAxe sp0.1\bound{sp1 }}
\indentrel{3}\begin{verbatim}
   Fingerprint element in generated algebra is singular
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
    We know that all the cyclic submodules generated by a
  ll
      non-trivial element of the singular matrix under vi
  ew are
      not proper, hence Norton's irreducibility test can 
  be done:
     A proper cyclic submodule is found.
     Transition matrix computed
     The inverse of the transition matrix computed
     Now transform the matrices
    Representation is not irreducible and it will be spli
  t:
                    Ú0  1  0  0¿ Ú0  1  1  1¿
                    ³          ³ ³          ³
                    ³0  0  1  0³ ³1  1  0  1³
   (4)  [[[1],[1]],[³          ³,³          ³]]
                    ³1  0  0  0³ ³1  1  1  0³
                    ³          ³ ³          ³
                    À0  0  0  1Ù À1  1  1  1Ù
                    Type: List List Matrix PrimeField 2
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RepA6PageEmpty4}
\begin{paste}{RepA6PageEmpty4}{RepA6PagePatch4}
\pastebutton{RepA6PageEmpty4}{\showpaste}
\tab{5}\spadcommand{sp1 := meatAxe sp0.1\bound{sp1 }}
\end{paste}\end{patch}

\begin{patch}{RepA6PagePatch5}
\begin{paste}{RepA6PageFull5}{RepA6PageEmpty5}
\pastebutton{RepA6PageFull5}{\hidepaste}
\tab{5}\spadcommand{isAbsolutelyIrreducible? sp1.2}
\indentrel{3}\begin{verbatim}
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra has
     one-dimensional kernel
    We know that all the cyclic submodules generated by a
  ll
      non-trivial element of the singular matrix under vi
  ew are
      not proper, hence Norton's irreducibility test can 
  be done:
     The generated cyclic submodule was not proper
     Representation is absolutely irreducible
   (5)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RepA6PageEmpty5}
\begin{paste}{RepA6PageEmpty5}{RepA6PagePatch5}
\pastebutton{RepA6PageEmpty5}{\showpaste}
\tab{5}\spadcommand{isAbsolutelyIrreducible? sp1.2}
\end{paste}\end{patch}

\begin{patch}{RepA6PagePatch6}
\begin{paste}{RepA6PageFull6}{RepA6PageEmpty6}
\pastebutton{RepA6PageFull6}{\hidepaste}
\tab{5}\spadcommand{d2211 := irreducibleRepresentation ([2,2,1,1],genA6)\bound{d2211 }}
\indentrel{3}\begin{verbatim}
   (6)
    Ú1  0  0  - 1   1    0    0    0    0 ¿
    ³                                     ³
    ³0  1  0   1    0    1    0    0    0 ³
    ³                                     ³
    ³0  0  1   0    1   - 1   0    0    0 ³
    ³                                     ³
    ³0  0  0  - 1   0    0   - 1   0    0 ³
    ³                                     ³
   [³0  0  0   0   - 1   0    0   - 1   0 ³,
    ³                                     ³
    ³0  0  0   0    0   - 1   0    0   - 1³
    ³                                     ³
    ³0  0  0   1    0    0    0    0    0 ³
    ³                                     ³
    ³0  0  0   0    1    0    0    0    0 ³
    ³                                     ³
    À0  0  0   0    0    1    0    0    0 Ù
    Ú 0    0   1   0   0  0   1   0  0¿
    ³                                 ³
    ³ 0    0   0   0   1  0  - 1  0  0³
    ³                                 ³
    ³ 0    0   0   0   0  1   1   0  0³
    ³                                 ³
    ³ 0    0   0   0   0  0   1   1  0³
    ³                                 ³
    ³ 0    0   0   0   0  0  - 1  0  1³]
    ³                                 ³
    ³ 0    0   0   0   0  0   1   0  0³
    ³                                 ³
    ³- 1   0   0   0   0  0  - 1  0  0³
    ³                                 ³
    ³ 0   - 1  0   0   0  0   1   0  0³
    ³                                 ³
    À 0    0   0  - 1  0  0  - 1  0  0Ù
                              Type: List Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RepA6PageEmpty6}
\begin{paste}{RepA6PageEmpty6}{RepA6PagePatch6}
\pastebutton{RepA6PageEmpty6}{\showpaste}
\tab{5}\spadcommand{d2211 := irreducibleRepresentation ([2,2,1,1],genA6)\bound{d2211 }}
\end{paste}\end{patch}

\begin{patch}{RepA6PagePatch7}
\begin{paste}{RepA6PageFull7}{RepA6PageEmpty7}
\pastebutton{RepA6PageFull7}{\hidepaste}
\tab{5}\spadcommand{d2211m2 := d2211:: (LIST MATRIX PF 2); sp2 := meatAxe d2211m2\free{d2211 }\bound{sp2 }}
\indentrel{3}\begin{verbatim}
   Fingerprint element in generated algebra is singular
     A proper cyclic submodule is found.
     Transition matrix computed
     The inverse of the transition matrix computed
     Now transform the matrices
   (7)
     Ú1  0  1  1¿ Ú0  0  1  0¿
     ³          ³ ³          ³
     ³0  1  0  1³ ³1  1  1  1³
   [[³          ³,³          ³],
     ³1  1  0  0³ ³1  0  1  1³
     ³          ³ ³          ³
     À0  1  0  0Ù À0  1  0  1Ù
     Ú1  0  0  0  0¿ Ú1  1  1  0  0¿
     ³             ³ ³             ³
     ³0  1  1  1  1³ ³0  0  1  1  1³
     ³             ³ ³             ³
    [³0  1  1  0  0³,³1  0  0  1  0³]]
     ³             ³ ³             ³
     ³0  1  0  1  0³ ³0  0  1  0  1³
     ³             ³ ³             ³
     À0  1  1  1  0Ù À1  0  0  1  1Ù
                    Type: List List Matrix PrimeField 2
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RepA6PageEmpty7}
\begin{paste}{RepA6PageEmpty7}{RepA6PagePatch7}
\pastebutton{RepA6PageEmpty7}{\showpaste}
\tab{5}\spadcommand{d2211m2 := d2211:: (LIST MATRIX PF 2); sp2 := meatAxe d2211m2\free{d2211 }\bound{sp2 }}
\end{paste}\end{patch}

\begin{patch}{RepA6PagePatch8}
\begin{paste}{RepA6PageFull8}{RepA6PageEmpty8}
\pastebutton{RepA6PageFull8}{\hidepaste}
\tab{5}\spadcommand{isAbsolutelyIrreducible? sp2.1}
\indentrel{3}\begin{verbatim}
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra has
     one-dimensional kernel
    We know that all the cyclic submodules generated by a
  ll
      non-trivial element of the singular matrix under vi
  ew are
      not proper, hence Norton's irreducibility test can 
  be done:
     The generated cyclic submodule was not proper
     Representation is absolutely irreducible
   (8)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RepA6PageEmpty8}
\begin{paste}{RepA6PageEmpty8}{RepA6PagePatch8}
\pastebutton{RepA6PageEmpty8}{\showpaste}
\tab{5}\spadcommand{isAbsolutelyIrreducible? sp2.1}
\end{paste}\end{patch}

\begin{patch}{RepA6PagePatch9}
\begin{paste}{RepA6PageFull9}{RepA6PageEmpty9}
\pastebutton{RepA6PageFull9}{\hidepaste}
\tab{5}\spadcommand{areEquivalent? (sp1.2, sp2.1)}
\indentrel{3}\begin{verbatim}
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra has
     one-dimensional kernel
     There is no isomorphism, as the only possible one
       fails to do the necessary base change

   Representations are not equivalent.
   (9)  [0]
                              Type: Matrix PrimeField 2
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RepA6PageEmpty9}
\begin{paste}{RepA6PageEmpty9}{RepA6PagePatch9}
\pastebutton{RepA6PageEmpty9}{\showpaste}
\tab{5}\spadcommand{areEquivalent? (sp1.2, sp2.1)}
\end{paste}\end{patch}

\begin{patch}{RepA6PagePatch10}
\begin{paste}{RepA6PageFull10}{RepA6PageEmpty10}
\pastebutton{RepA6PageFull10}{\hidepaste}
\tab{5}\spadcommand{dA6d16 := tensorProduct(sp1.2,sp2.1); meatAxe dA6d16\bound{dA6d16 }}
\indentrel{3}\begin{verbatim}
  Fingerprint element in generated algebra is non-singula
  r
   Fingerprint element in generated algebra is singular
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
  Fingerprint element in generated algebra is non-singula
  r
   Fingerprint element in generated algebra is singular
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
   Fingerprint element in generated algebra is singular
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
    We know that all the cyclic submodules generated by a
  ll
      non-trivial element of the singular matrix under vi
  ew are
      not proper, hence Norton's irreducibility test can 
  be done:
     The generated cyclic submodule was not proper
     Representation is irreducible, but we don't know
       whether it is absolutely irreducible
   (10)
   [
      Ú0  0  0  0  0  0  0  0  1  0  1  0  0  0  0  0¿
      ³                                              ³
      ³0  0  0  0  0  0  0  0  0  1  1  1  0  0  0  0³
      ³                                              ³
      ³0  0  0  0  0  0  0  0  1  0  0  0  0  0  0  0³
      ³                                              ³
      ³0  0  0  0  0  0  0  0  1  1  0  0  0  0  0  0³
      ³                                              ³
      ³1  0  1  0  0  0  0  0  0  0  0  0  0  0  0  0³
      ³                                              ³
      ³0  1  1  1  0  0  0  0  0  0  0  0  0  0  0  0³
      ³                                              ³
      ³1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0³
      ³                                              ³
      ³1  1  0  0  0  0  0  0  0  0  0  0  0  0  0  0³
     [³                                              ³,
      ³0  0  0  0  1  0  1  0  0  0  0  0  0  0  0  0³
      ³                                              ³
      ³0  0  0  0  0  1  1  1  0  0  0  0  0  0  0  0³
      ³                                              ³
      ³0  0  0  0  1  0  0  0  0  0  0  0  0  0  0  0³
      ³                                              ³
      ³0  0  0  0  1  1  0  0  0  0  0  0  0  0  0  0³
      ³                                              ³
      ³0  0  0  0  0  0  0  0  0  0  0  0  1  0  1  0³
      ³                                              ³
      ³0  0  0  0  0  0  0  0  0  0  0  0  0  1  1  1³
      ³                                              ³
      ³0  0  0  0  0  0  0  0  0  0  0  0  1  0  0  0³
      ³                                              ³
      À0  0  0  0  0  0  0  0  0  0  0  0  1  1  0  0Ù
      Ú0  0  0  0  0  1  1  0  0  1  1  0  0  1  1  0¿
      ³                                              ³
      ³0  0  0  0  0  1  0  1  0  1  0  1  0  1  0  1³
      ³                                              ³
      ³0  0  0  0  1  1  1  0  1  1  1  0  1  1  1  0³
      ³                                              ³
      ³0  0  0  0  0  1  1  1  0  1  1  1  0  1  1  1³
      ³                                              ³
      ³0  1  1  0  0  1  1  0  0  1  1  0  0  1  1  0³
      ³                                              ³
      ³0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1³
      ³                                              ³
      ³1  1  1  0  1  1  1  0  1  1  1  0  1  1  1  0³
      ³                                              ³
      ³0  1  1  1  0  1  1  1  0  1  1  1  0  1  1  1³
      ³                                              ³]
      ³0  1  1  0  0  0  0  0  0  1  1  0  0  1  1  0³
      ³                                              ³
      ³0  1  0  1  0  0  0  0  0  1  0  1  0  1  0  1³
      ³                                              ³
      ³1  1  1  0  0  0  0  0  1  1  1  0  1  1  1  0³
      ³                                              ³
      ³0  1  1  1  0  0  0  0  0  1  1  1  0  1  1  1³
      ³                                              ³
      ³0  1  1  0  0  1  1  0  0  0  0  0  0  1  1  0³
      ³                                              ³
      ³0  1  0  1  0  1  0  1  0  0  0  0  0  1  0  1³
      ³                                              ³
      ³1  1  1  0  1  1  1  0  0  0  0  0  1  1  1  0³
      ³                                              ³
      À0  1  1  1  0  1  1  1  0  0  0  0  0  1  1  1Ù
     ]
                    Type: List List Matrix PrimeField 2
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RepA6PageEmpty10}
\begin{paste}{RepA6PageEmpty10}{RepA6PagePatch10}
\pastebutton{RepA6PageEmpty10}{\showpaste}
\tab{5}\spadcommand{dA6d16 := tensorProduct(sp1.2,sp2.1); meatAxe dA6d16\bound{dA6d16 }}
\end{paste}\end{patch}

\begin{patch}{RepA6PagePatch11}
\begin{paste}{RepA6PageFull11}{RepA6PageEmpty11}
\pastebutton{RepA6PageFull11}{\hidepaste}
\tab{5}\spadcommand{isAbsolutelyIrreducible? dA6d16}
\indentrel{3}\begin{verbatim}
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   We have not found a one-dimensional kernel so far,
     as we do a random search you could try again
   (11)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RepA6PageEmpty11}
\begin{paste}{RepA6PageEmpty11}{RepA6PagePatch11}
\pastebutton{RepA6PageEmpty11}{\showpaste}
\tab{5}\spadcommand{isAbsolutelyIrreducible? dA6d16}
\end{paste}\end{patch}

\begin{patch}{RepA6PagePatch12}
\begin{paste}{RepA6PageFull12}{RepA6PageEmpty12}
\pastebutton{RepA6PageFull12}{\hidepaste}
\tab{5}\spadcommand{sp3 := meatAxe (dA6d16 :: (LIST MATRIX FF(2,2)))\bound{sp3 }}
\indentrel{3}\begin{verbatim}
  Fingerprint element in generated algebra is non-singula
  r
   Fingerprint element in generated algebra is singular
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
  Fingerprint element in generated algebra is non-singula
  r
   Fingerprint element in generated algebra is singular
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
   Fingerprint element in generated algebra is singular
     The generated cyclic submodule was not proper
     The generated cyclic submodule was not proper
     A proper cyclic submodule is found.
     Transition matrix computed
     The inverse of the transition matrix computed
     Now transform the matrices
   (12)
   [
     [
   [[%A,%A + 1,0,%A,1,%A + 1,0,0],
    [0,0,%A,%A + 1,%A,%A,0,0],
    [%A,%A + 1,%A,1,%A + 1,0,0,0],
    [%A,%A + 1,%A,1,%A,0,0,0],
    [%A + 1,1,1,1,0,0,%A + 1,%A],
    [0,0,%A + 1,1,0,0,%A,0], [1,0,1,1,0,0,0,0],
    [1,1,0,0,0,0,0,0]]
       ,

   [[1,0,%A,0,1,1,%A,%A + 1],
    [1,%A + 1,0,0,0,%A + 1,1,%A + 1],
    [%A,1,%A + 1,%A + 1,%A + 1,1,%A,0],
    [%A + 1,%A + 1,0,0,1,%A + 1,1,1],
    [1,0,%A + 1,0,1,1,%A,%A],
    [0,0,%A + 1,%A + 1,%A + 1,1,1,%A], [0,0,1,0,0,1,0,1],
    [0,%A,0,%A,1,%A + 1,%A + 1,%A]]
       ]
     ,

      Ú0     1       1     %A + 1  0  0  0  0¿
      ³                                      ³
      ³1     1     %A + 1    0     0  0  0  0³
      ³                                      ³
      ³%A    0       0       0     0  0  0  0³
      ³                                      ³
      ³1     %A      0       0     0  0  0  0³
     [³                                      ³,
      ³%A  %A + 1    1       1     1  0  1  1³
      ³                                      ³
      ³0     0       %A      1     0  1  0  1³
      ³                                      ³
      ³%A    1       0       1     1  1  0  0³
      ³                                      ³
      À1     %A    %A + 1    %A    0  1  0  0Ù

   [[%A + 1,1,%A,0,0,%A + 1,0,1],
    [0,%A,1,1,1,0,%A + 1,%A],
    [0,%A + 1,0,%A + 1,%A + 1,1,%A + 1,%A],
    [1,%A + 1,1,%A + 1,0,0,%A + 1,1],
    [0,%A,0,%A + 1,%A + 1,0,0,%A + 1],
    [%A + 1,0,%A + 1,%A,0,%A + 1,0,%A + 1],
    [0,1,0,1,%A + 1,0,%A + 1,%A + 1],
    [%A,%A,%A,1,%A,%A,1,%A + 1]]
       ]
     ]
                Type: List List Matrix FiniteField(2,2)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RepA6PageEmpty12}
\begin{paste}{RepA6PageEmpty12}{RepA6PagePatch12}
\pastebutton{RepA6PageEmpty12}{\showpaste}
\tab{5}\spadcommand{sp3 := meatAxe (dA6d16 :: (LIST MATRIX FF(2,2)))\bound{sp3 }}
\end{paste}\end{patch}

\begin{patch}{RepA6PagePatch13}
\begin{paste}{RepA6PageFull13}{RepA6PageEmpty13}
\pastebutton{RepA6PageFull13}{\hidepaste}
\tab{5}\spadcommand{isAbsolutelyIrreducible? sp3.1}
\indentrel{3}\begin{verbatim}
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra has
     one-dimensional kernel
    We know that all the cyclic submodules generated by a
  ll
      non-trivial element of the singular matrix under vi
  ew are
      not proper, hence Norton's irreducibility test can 
  be done:
     The generated cyclic submodule was not proper
     Representation is absolutely irreducible
   (13)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RepA6PageEmpty13}
\begin{paste}{RepA6PageEmpty13}{RepA6PagePatch13}
\pastebutton{RepA6PageEmpty13}{\showpaste}
\tab{5}\spadcommand{isAbsolutelyIrreducible? sp3.1}
\end{paste}\end{patch}

\begin{patch}{RepA6PagePatch14}
\begin{paste}{RepA6PageFull14}{RepA6PageEmpty14}
\pastebutton{RepA6PageFull14}{\hidepaste}
\tab{5}\spadcommand{isAbsolutelyIrreducible? sp3.2}
\indentrel{3}\begin{verbatim}
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra has
     one-dimensional kernel
    We know that all the cyclic submodules generated by a
  ll
      non-trivial element of the singular matrix under vi
  ew are
      not proper, hence Norton's irreducibility test can 
  be done:
     The generated cyclic submodule was not proper
     Representation is absolutely irreducible
   (14)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RepA6PageEmpty14}
\begin{paste}{RepA6PageEmpty14}{RepA6PagePatch14}
\pastebutton{RepA6PageEmpty14}{\showpaste}
\tab{5}\spadcommand{isAbsolutelyIrreducible? sp3.2}
\end{paste}\end{patch}

\begin{patch}{RepA6PagePatch15}
\begin{paste}{RepA6PageFull15}{RepA6PageEmpty15}
\pastebutton{RepA6PageFull15}{\hidepaste}
\tab{5}\spadcommand{areEquivalent? (sp3.1,sp3.2)}
\indentrel{3}\begin{verbatim}
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra does
     not have a one-dimensional kernel
   Random element in generated algebra has
     one-dimensional kernel
     There is no isomorphism, as the only possible one
       fails to do the necessary base change

   Representations are not equivalent.
   (15)  [0]
                          Type: Matrix FiniteField(2,2)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RepA6PageEmpty15}
\begin{paste}{RepA6PageEmpty15}{RepA6PagePatch15}
\pastebutton{RepA6PageEmpty15}{\showpaste}
\tab{5}\spadcommand{areEquivalent? (sp3.1,sp3.2)}
\end{paste}\end{patch}

\begin{patch}{RepA6PagePatch16}
\begin{paste}{RepA6PageFull16}{RepA6PageEmpty16}
\pastebutton{RepA6PageFull16}{\hidepaste}
\tab{5}\spadcommand{sp0.2\free{sp0 }}
\indentrel{3}\begin{verbatim}
   (16)  [[1],[1]]
                         Type: List Matrix PrimeField 2
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RepA6PageEmpty16}
\begin{paste}{RepA6PageEmpty16}{RepA6PagePatch16}
\pastebutton{RepA6PageEmpty16}{\showpaste}
\tab{5}\spadcommand{sp0.2\free{sp0 }}
\end{paste}\end{patch}

\begin{patch}{RepA6PagePatch17}
\begin{paste}{RepA6PageFull17}{RepA6PageEmpty17}
\pastebutton{RepA6PageFull17}{\hidepaste}
\tab{5}\spadcommand{sp1.2\free{sp1 }}
\indentrel{3}\begin{verbatim}
          Ú0  1  0  0¿ Ú0  1  1  1¿
          ³          ³ ³          ³
          ³0  0  1  0³ ³1  1  0  1³
   (17)  [³          ³,³          ³]
          ³1  0  0  0³ ³1  1  1  0³
          ³          ³ ³          ³
          À0  0  0  1Ù À1  1  1  1Ù
                         Type: List Matrix PrimeField 2
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RepA6PageEmpty17}
\begin{paste}{RepA6PageEmpty17}{RepA6PagePatch17}
\pastebutton{RepA6PageEmpty17}{\showpaste}
\tab{5}\spadcommand{sp1.2\free{sp1 }}
\end{paste}\end{patch}

\begin{patch}{RepA6PagePatch18}
\begin{paste}{RepA6PageFull18}{RepA6PageEmpty18}
\pastebutton{RepA6PageFull18}{\hidepaste}
\tab{5}\spadcommand{sp2.1\free{sp2 }}
\indentrel{3}\begin{verbatim}
          Ú1  0  1  1¿ Ú0  0  1  0¿
          ³          ³ ³          ³
          ³0  1  0  1³ ³1  1  1  1³
   (18)  [³          ³,³          ³]
          ³1  1  0  0³ ³1  0  1  1³
          ³          ³ ³          ³
          À0  1  0  0Ù À0  1  0  1Ù
                         Type: List Matrix PrimeField 2
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RepA6PageEmpty18}
\begin{paste}{RepA6PageEmpty18}{RepA6PagePatch18}
\pastebutton{RepA6PageEmpty18}{\showpaste}
\tab{5}\spadcommand{sp2.1\free{sp2 }}
\end{paste}\end{patch}

\begin{patch}{RepA6PagePatch19}
\begin{paste}{RepA6PageFull19}{RepA6PageEmpty19}
\pastebutton{RepA6PageFull19}{\hidepaste}
\tab{5}\spadcommand{sp3.1\free{sp3 }}
\indentrel{3}\begin{verbatim}
   (19)
   [
   [[%A,%A + 1,0,%A,1,%A + 1,0,0],
    [0,0,%A,%A + 1,%A,%A,0,0],
    [%A,%A + 1,%A,1,%A + 1,0,0,0],
    [%A,%A + 1,%A,1,%A,0,0,0],
    [%A + 1,1,1,1,0,0,%A + 1,%A],
    [0,0,%A + 1,1,0,0,%A,0], [1,0,1,1,0,0,0,0],
    [1,1,0,0,0,0,0,0]]
     ,

   [[1,0,%A,0,1,1,%A,%A + 1],
    [1,%A + 1,0,0,0,%A + 1,1,%A + 1],
    [%A,1,%A + 1,%A + 1,%A + 1,1,%A,0],
    [%A + 1,%A + 1,0,0,1,%A + 1,1,1],
    [1,0,%A + 1,0,1,1,%A,%A],
    [0,0,%A + 1,%A + 1,%A + 1,1,1,%A], [0,0,1,0,0,1,0,1],
    [0,%A,0,%A,1,%A + 1,%A + 1,%A]]
     ]
                     Type: List Matrix FiniteField(2,2)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RepA6PageEmpty19}
\begin{paste}{RepA6PageEmpty19}{RepA6PagePatch19}
\pastebutton{RepA6PageEmpty19}{\showpaste}
\tab{5}\spadcommand{sp3.1\free{sp3 }}
\end{paste}\end{patch}

\begin{patch}{RepA6PagePatch20}
\begin{paste}{RepA6PageFull20}{RepA6PageEmpty20}
\pastebutton{RepA6PageFull20}{\hidepaste}
\tab{5}\spadcommand{sp3.2\free{sp3 }}
\indentrel{3}\begin{verbatim}
   (20)
    Ú0     1       1     %A + 1  0  0  0  0¿
    ³                                      ³
    ³1     1     %A + 1    0     0  0  0  0³
    ³                                      ³
    ³%A    0       0       0     0  0  0  0³
    ³                                      ³
    ³1     %A      0       0     0  0  0  0³
   [³                                      ³,
    ³%A  %A + 1    1       1     1  0  1  1³
    ³                                      ³
    ³0     0       %A      1     0  1  0  1³
    ³                                      ³
    ³%A    1       0       1     1  1  0  0³
    ³                                      ³
    À1     %A    %A + 1    %A    0  1  0  0Ù

   [[%A + 1,1,%A,0,0,%A + 1,0,1],
    [0,%A,1,1,1,0,%A + 1,%A],
    [0,%A + 1,0,%A + 1,%A + 1,1,%A + 1,%A],
    [1,%A + 1,1,%A + 1,0,0,%A + 1,1],
    [0,%A,0,%A + 1,%A + 1,0,0,%A + 1],
    [%A + 1,0,%A + 1,%A,0,%A + 1,0,%A + 1],
    [0,1,0,1,%A + 1,0,%A + 1,%A + 1],
    [%A,%A,%A,1,%A,%A,1,%A + 1]]
     ]
                     Type: List Matrix FiniteField(2,2)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RepA6PageEmpty20}
\begin{paste}{RepA6PageEmpty20}{RepA6PagePatch20}
\pastebutton{RepA6PageEmpty20}{\showpaste}
\tab{5}\spadcommand{sp3.2\free{sp3 }}
\end{paste}\end{patch}

\begin{patch}{RepA6PagePatch21}
\begin{paste}{RepA6PageFull21}{RepA6PageEmpty21}
\pastebutton{RepA6PageFull21}{\hidepaste}
\tab{5}\spadcommand{dA6d16\free{dA6d16 }}
\indentrel{3}\begin{verbatim}
   (21)
    Ú0  0  0  0  1  0  1  1  0  0  0  0  0  0  0  0¿
    ³                                              ³
    ³0  0  0  0  0  1  0  1  0  0  0  0  0  0  0  0³
    ³                                              ³
    ³0  0  0  0  1  1  0  0  0  0  0  0  0  0  0  0³
    ³                                              ³
    ³0  0  0  0  0  1  0  0  0  0  0  0  0  0  0  0³
    ³                                              ³
    ³0  0  0  0  0  0  0  0  1  0  1  1  0  0  0  0³
    ³                                              ³
    ³0  0  0  0  0  0  0  0  0  1  0  1  0  0  0  0³
    ³                                              ³
    ³0  0  0  0  0  0  0  0  1  1  0  0  0  0  0  0³
    ³                                              ³
    ³0  0  0  0  0  0  0  0  0  1  0  0  0  0  0  0³
   [³                                              ³,
    ³1  0  1  1  0  0  0  0  0  0  0  0  0  0  0  0³
    ³                                              ³
    ³0  1  0  1  0  0  0  0  0  0  0  0  0  0  0  0³
    ³                                              ³
    ³1  1  0  0  0  0  0  0  0  0  0  0  0  0  0  0³
    ³                                              ³
    ³0  1  0  0  0  0  0  0  0  0  0  0  0  0  0  0³
    ³                                              ³
    ³0  0  0  0  0  0  0  0  0  0  0  0  1  0  1  1³
    ³                                              ³
    ³0  0  0  0  0  0  0  0  0  0  0  0  0  1  0  1³
    ³                                              ³
    ³0  0  0  0  0  0  0  0  0  0  0  0  1  1  0  0³
    ³                                              ³
    À0  0  0  0  0  0  0  0  0  0  0  0  0  1  0  0Ù
    Ú0  0  0  0  0  0  1  0  0  0  1  0  0  0  1  0¿
    ³                                              ³
    ³0  0  0  0  1  1  1  1  1  1  1  1  1  1  1  1³
    ³                                              ³
    ³0  0  0  0  1  0  1  1  1  0  1  1  1  0  1  1³
    ³                                              ³
    ³0  0  0  0  0  1  0  1  0  1  0  1  0  1  0  1³
    ³                                              ³
    ³0  0  1  0  0  0  1  0  0  0  0  0  0  0  1  0³
    ³                                              ³
    ³1  1  1  1  1  1  1  1  0  0  0  0  1  1  1  1³
    ³                                              ³
    ³1  0  1  1  1  0  1  1  0  0  0  0  1  0  1  1³
    ³                                              ³
    ³0  1  0  1  0  1  0  1  0  0  0  0  0  1  0  1³
    ³                                              ³]
    ³0  0  1  0  0  0  1  0  0  0  1  0  0  0  0  0³
    ³                                              ³
    ³1  1  1  1  1  1  1  1  1  1  1  1  0  0  0  0³
    ³                                              ³
    ³1  0  1  1  1  0  1  1  1  0  1  1  0  0  0  0³
    ³                                              ³
    ³0  1  0  1  0  1  0  1  0  1  0  1  0  0  0  0³
    ³                                              ³
    ³0  0  1  0  0  0  1  0  0  0  1  0  0  0  1  0³
    ³                                              ³
    ³1  1  1  1  1  1  1  1  1  1  1  1  1  1  1  1³
    ³                                              ³
    ³1  0  1  1  1  0  1  1  1  0  1  1  1  0  1  1³
    ³                                              ³
    À0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1Ù
                         Type: List Matrix PrimeField 2
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RepA6PageEmpty21}
\begin{paste}{RepA6PageEmpty21}{RepA6PagePatch21}
\pastebutton{RepA6PageEmpty21}{\showpaste}
\tab{5}\spadcommand{dA6d16\free{dA6d16 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{InfoRepTheoryPage}{grpthry.ht}{Representation Theory}
\begin{chunk}{grpthry.ht}
\begin{page}{InfoRepTheoryPage}{Representation Theory}
\beginscroll
\horizontalline
Representation theory for finite groups studies finite groups by
embedding them in a general linear group over a field or an integral
domain.  Hence, we are representing each element of the group by an
invertible matrix.  Two matrix representations of a given group are
equivalent, if, by changing the basis of the underlying space, you can
go from one to the other.  When you change bases, you transform the
matrices that are the images of elements by conjugating them by an
invertible matrix.
\newline
\newline
If we can find a subspace which is fixed under the image of the group,
then there exists a `base change' after which all the representing
matrices are in upper triangular block form. The block matrices on
the main diagonal give a new representation of the group of lower
degree.  Such a representation is said to be `reducible'.
\newline
\beginmenu
%\menulink{Irreducible Representations of Symmetric Groups}
%{IrrRepSymNatXmpPage}

%Alfred Young's natural form for these representations.

%\menulink{Representations of Higher Degree}
%{RepresentationPackage1XmpPage}
%Constructing new representations by symmetric and antisymmetric
%tensors.

%\menulink{Decomposing Representations}
%{RepresentationPackage2XmpPage}
%Parker's `Meat-Axe', working in prime characteristics.

\menulink{Representations of \texht{$A_6$}{A6}}{RepA6Page}
The irreducible representations of the alternating group
\texht{$A_6$}{A6} over fields of characteristic 2.
\endmenu
\endscroll
\autobuttons \end{page}

\end{chunk}
\pagetitle{InfoGroupTheoryPage}{grpthry.ht}{Group Theory}
\begin{chunk}{grpthry.ht}
\begin{page}{InfoGroupTheoryPage}{Group Theory}
%%
%% Johannes Grabmeier 03/02/90
%%
\beginscroll
A {\it group} is a set G together with an associative operation *
satisfying the axioms of existence of a unit element and an inverse of
every element of the group.  The Axiom category \spadtype{Group}
represents this setting.  Many data structures in Axiom are groups and
therefore there is a large variety of examples as fields and
polynomials, although the main interest there is not the group
structure.

To work with and in groups in a concrete manner some way of
representing groups has to be chosen. A group can be given as a list
of generators and a set of relations. If there are no relations, then
we have a {\it free group}, realized in the domain
\spadtype{FreeMonoid} which won't be discussed here.  We consider {\it
permutation groups}, where a group is realized as a subgroup of the
symmetric group of a set, i.e.  the group of all bijections of a set,
the operation being the composition of maps.  Indeed, every group can
be realized this way, although this may not be practical.

Furthermore group elements can be given as invertible matrices.  The
group operation is reflected by matrix multiplication.  More precise
in representation theory group homomophisms from a group to general
linear groups are contructed.  Some algorithms are implemented in
Axiom.
\newline
%\beginmenu
%\menulink{Permutation}{PermutationXmpPage}
%Calculating within symmetric groups.

%\menulink{Permutation Groups}{PermutationGroupXmpPage}
%Working with subgroups of a symmetric group.

%\menulink{Permutation Group Examples}
%{PermutationGroupExampleXmpPage}
%Working with permutation groups, predefined 
in the system as Rubik's group.
%\endmenu
\endscroll
\autobuttons \end{page}

\end{chunk}
\section{gstbl.ht}
\pagetitle{GeneralSparseTableXmpPage}{gstbl.ht}{GeneralSparseTable}
\pageto{notitle}{TableXmpPage}
\begin{chunk}{gstbl.ht}
\begin{page}{GeneralSparseTableXmpPage}{GeneralSparseTable}
\beginscroll

Sometimes when working with tables there is a natural value to use as
the entry in all but a few cases.  The \spadtype{GeneralSparseTable}
constructor can be used to provide any table type with a default value
for entries.  See \downlink{`Table'}{TableXmpPage}\ignore{Table} for
general information about tables.
\showBlurb{GeneralSparseTable}

Suppose we launched a fund-raising campaign to raise fifty thousand
dollars.  To record the contributions, we want a table with strings as
keys (for the names) and integer entries (for the amount).  In a data
base of cash contributions, unless someone has been explicitly
entered, it is reasonable to assume they have made a zero dollar
contribution.
\xtc{
This creates a keyed access file with default entry \spad{0}.
}{
\spadpaste{patrons: GeneralSparseTable(String, Integer, 
KeyedAccessFile(Integer), 0) := table() ; \bound{patrons}}
}
\xtc{
Now \spad{patrons} can be used just as any other table.
Here we record two gifts.
}{
\spadpaste{patrons."Smith" := 10500 \free{patrons}\bound{smith}}
}
\xtc{
}{
\spadpaste{patrons."Jones" := 22000 \free{smith}\bound{jones}}
}
\xtc{
Now let us look up the size of the contributions from Jones and Stingy.
}{
\spadpaste{patrons."Jones"  \free{jones}}
}
\xtc{
}{
\spadpaste{patrons."Stingy" \free{jones}}
}
\xtc{
Have we met our seventy thousand dollar goal?
}{
\spadpaste{reduce(+, entries patrons) \free{jones}}
}
\noOutputXtc{
So the project is cancelled and we can delete the data base:
}{
\spadpaste{)system rm -r kaf*.sdata \free{patrons}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{GeneralSparseTableXmpPagePatch1}
\begin{paste}{GeneralSparseTableXmpPageFull1}{GeneralSparseTableXmpPageEmpty1}
\pastebutton{GeneralSparseTableXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{patrons: GeneralSparseTable(String, Integer, KeyedAccessFile(Integer), 0) := table() ;\bound{patrons }}
\indentrel{3}\begin{verbatim}
Type: GeneralSparseTable(String,Integer,KeyedAccessFile Integer,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{GeneralSparseTableXmpPageEmpty1}
\begin{paste}{GeneralSparseTableXmpPageEmpty1}{GeneralSparseTableXmpPagePatch1}
\pastebutton{GeneralSparseTableXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{patrons: GeneralSparseTable(String, Integer, KeyedAccessFile(Integer), 0) := table() ;\bound{patrons }}
\end{paste}\end{patch}

\begin{patch}{GeneralSparseTableXmpPagePatch2}
\begin{paste}{GeneralSparseTableXmpPageFull2}{GeneralSparseTableXmpPageEmpty2}
\pastebutton{GeneralSparseTableXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{patrons."Smith" := 10500\free{patrons }\bound{smith }}
\indentrel{3}\begin{verbatim}
   (2)  10500
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{GeneralSparseTableXmpPageEmpty2}
\begin{paste}{GeneralSparseTableXmpPageEmpty2}{GeneralSparseTableXmpPagePatch2}
\pastebutton{GeneralSparseTableXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{patrons."Smith" := 10500\free{patrons }\bound{smith }}
\end{paste}\end{patch}

\begin{patch}{GeneralSparseTableXmpPagePatch3}
\begin{paste}{GeneralSparseTableXmpPageFull3}{GeneralSparseTableXmpPageEmpty3}
\pastebutton{GeneralSparseTableXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{patrons."Jones" := 22000\free{smith }\bound{jones }}
\indentrel{3}\begin{verbatim}
   (3)  22000
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{GeneralSparseTableXmpPageEmpty3}
\begin{paste}{GeneralSparseTableXmpPageEmpty3}{GeneralSparseTableXmpPagePatch3}
\pastebutton{GeneralSparseTableXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{patrons."Jones" := 22000\free{smith }\bound{jones }}
\end{paste}\end{patch}

\begin{patch}{GeneralSparseTableXmpPagePatch4}
\begin{paste}{GeneralSparseTableXmpPageFull4}{GeneralSparseTableXmpPageEmpty4}
\pastebutton{GeneralSparseTableXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{patrons."Jones"\free{jones }}
\indentrel{3}\begin{verbatim}
   (4)  22000
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{GeneralSparseTableXmpPageEmpty4}
\begin{paste}{GeneralSparseTableXmpPageEmpty4}{GeneralSparseTableXmpPagePatch4}
\pastebutton{GeneralSparseTableXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{patrons."Jones"\free{jones }}
\end{paste}\end{patch}

\begin{patch}{GeneralSparseTableXmpPagePatch5}
\begin{paste}{GeneralSparseTableXmpPageFull5}{GeneralSparseTableXmpPageEmpty5}
\pastebutton{GeneralSparseTableXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{patrons."Stingy"\free{jones }}
\indentrel{3}\begin{verbatim}
   (5)  0
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{GeneralSparseTableXmpPageEmpty5}
\begin{paste}{GeneralSparseTableXmpPageEmpty5}{GeneralSparseTableXmpPagePatch5}
\pastebutton{GeneralSparseTableXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{patrons."Stingy"\free{jones }}
\end{paste}\end{patch}

\begin{patch}{GeneralSparseTableXmpPagePatch6}
\begin{paste}{GeneralSparseTableXmpPageFull6}{GeneralSparseTableXmpPageEmpty6}
\pastebutton{GeneralSparseTableXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{reduce(+, entries patrons)\free{jones }}
\indentrel{3}\begin{verbatim}
   (6)  32500
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{GeneralSparseTableXmpPageEmpty6}
\begin{paste}{GeneralSparseTableXmpPageEmpty6}{GeneralSparseTableXmpPagePatch6}
\pastebutton{GeneralSparseTableXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{reduce(+, entries patrons)\free{jones }}
\end{paste}\end{patch}

\begin{patch}{GeneralSparseTableXmpPagePatch7}
\begin{paste}{GeneralSparseTableXmpPageFull7}{GeneralSparseTableXmpPageEmpty7}
\pastebutton{GeneralSparseTableXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{)system rm -r kaf*.sdata\free{patrons }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{GeneralSparseTableXmpPageEmpty7}
\begin{paste}{GeneralSparseTableXmpPageEmpty7}{GeneralSparseTableXmpPagePatch7}
\pastebutton{GeneralSparseTableXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{)system rm -r kaf*.sdata\free{patrons }}
\end{paste}\end{patch}

\end{chunk}
\section{heap.ht}
\pagetitle{HeapXmpPage}{heap.ht}{Heap}
\pageto{notitle}{FlexibleArrayXmpPage}
\begin{chunk}{heap.ht}
\begin{page}{HeapXmpPage}{Heap}
\beginscroll
The domain \spadtype{Heap(S)} implements a priority queue of objects
of type \spad{S} such that the operation \spadfunX{extract} removes
and returns the maximum element.  The implementation represents heaps
as flexible arrays (see \downlink{`FlexibleArray'}{FlexibleArrayXmpPage}
\ignore{FlexibleArray}).  The representation and algorithms give
complexity of \texht{$O(\log(n))$}{O(log n)} for insertion and
extractions, and \texht{$O(n)$}{O(n)} for construction.
\xtc{
Create a heap of six elements.
}{
\spadpaste{h := heap [-4,9,11,2,7,-7]\bound{h}}
}
\xtc{
Use \spadfunX{insert} to add an element.
}{
\spadpaste{insert!(3,h)\bound{h1}\free{h}}
}
\xtc{
The operation \spadfunX{extract} removes and returns
the maximum element.
}{
\spadpaste{extract! h\bound{h2}\free{h1}}
}
\xtc{
The internal structure of \spad{h} has been
appropriately adjusted.
}{
\spadpaste{h\free{h2}}
}
\xtc{
Now \spadfunX{extract} elements repeatedly
until none are left, collecting the elements in a list.
}{
\spadpaste{[extract!(h) while not empty?(h)]\bound{h2}}
}
\xtc{
Another way to produce the same result is by defining
a \userfun{heapsort} function.
}{
\spadpaste{heapsort(x) == (empty? x => []; cons(extract!(x),heapsort x))
\bound{f}}
}
\xtc{
Create another sample heap.
}{
\spadpaste{h1 := heap [17,-4,9,-11,2,7,-7]\bound{h1}}
}
\xtc{
Apply \spadfun{heapsort} to present elements in order.
}{
\spadpaste{heapsort h1\free{f}}
}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\section{hexadec.ht}
\pagetitle{HexExpansionXmpPage}{hexadec.ht}{HexadecimalExpansion}
\pagepic{ps/v71hexexpansionxmppage.eps}{HexExpansionXmpPage}{0.50}
\pagefrom{Axiom Number Types}{NumberPage}
\pagefrom{Integer}{IntegerXmpPage}
\pageto{DecimalExpansion}{DecimalExpansionXmpPage}
\pageto{BinaryExpansion}{BinaryExpansionXmpPage}
\pageto{RadixExpansion}{RadixExpansionXmpPage}
\begin{chunk}{hexadec.ht}
\begin{page}{HexExpansionXmpPage}{HexadecimalExpansion}
\beginscroll
All rationals have repeating hexadecimal expansions.  The operation
\spadfunFrom{hex}{HexadecimalExpansion} returns these expansions of
type \spadtype{HexadecimalExpansion}.  Operations to access the
individual numerals of a hexadecimal expansion can be obtained by
converting the value to \spadtype{RadixExpansion(16)}.  More examples
of expansions are available in the
\downlink{`DecimalExpansion'}{DecimalExpansionXmpPage}
\ignore{DecimalExpansion},
\downlink{`BinaryExpansion'}{BinaryExpansionXmpPage}
\ignore{BinaryExpansion}, and
\downlink{`RadixExpansion'}{RadixExpansionXmpPage}
\ignore{RadixExpansion}.

\showBlurb{HexadecimalExpansion}

\xtc{
This is a hexadecimal expansion of a rational number.
}{
\spadpaste{r := hex(22/7) \bound{r}}
}
\xtc{
Arithmetic is exact.
}{
\spadpaste{r + hex(6/7) \free{r}}
}
\xtc{
The period of the expansion can be short or long \ldots
}{
\spadpaste{[hex(1/i) for i in 350..354] }
}
\xtc{
or very long!
}{
\spadpaste{hex(1/1007) }
}
\xtc{
These numbers are bona fide algebraic objects.
}{
\spadpaste{p := hex(1/4)*x**2 + hex(2/3)*x + hex(4/9)  \bound{p}}
}
\xtc{
}{
\spadpaste{q := D(p, x) \free{p}\bound{q}}
}
\xtc{
}{
\spadpaste{g := gcd(p, q)            \free{p}\free{q}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{HexExpansionXmpPagePatch1}
\begin{paste}{HexExpansionXmpPageFull1}{HexExpansionXmpPageEmpty1}
\pastebutton{HexExpansionXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{r := hex(22/7)\bound{r }}
\indentrel{3}\begin{verbatim}
          ___
   (1)  3.249
                             Type: HexadecimalExpansion
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{HexExpansionXmpPageEmpty1}
\begin{paste}{HexExpansionXmpPageEmpty1}{HexExpansionXmpPagePatch1}
\pastebutton{HexExpansionXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{r := hex(22/7)\bound{r }}
\end{paste}\end{patch}

\begin{patch}{HexExpansionXmpPagePatch2}
\begin{paste}{HexExpansionXmpPageFull2}{HexExpansionXmpPageEmpty2}
\pastebutton{HexExpansionXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{r + hex(6/7)\free{r }}
\indentrel{3}\begin{verbatim}
   (2)  4
                             Type: HexadecimalExpansion
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{HexExpansionXmpPageEmpty2}
\begin{paste}{HexExpansionXmpPageEmpty2}{HexExpansionXmpPagePatch2}
\pastebutton{HexExpansionXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{r + hex(6/7)\free{r }}
\end{paste}\end{patch}

\begin{patch}{HexExpansionXmpPagePatch3}
\begin{paste}{HexExpansionXmpPageFull3}{HexExpansionXmpPageEmpty3}
\pastebutton{HexExpansionXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{[hex(1/i) for i in 350..354]}
\indentrel{3}\begin{verbatim}
   (3)
       _______________    _________      _____
   [0.00BB3EE721A54D88, 0.00BAB6561, 0.00BA2E8,
      ______________________
    0.00B9A7862A0FF465879D5F,
       _____________________________
    0.00B92143FA36F5E02E4850FE8DBD78]
                        Type: List HexadecimalExpansion
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{HexExpansionXmpPageEmpty3}
\begin{paste}{HexExpansionXmpPageEmpty3}{HexExpansionXmpPagePatch3}
\pastebutton{HexExpansionXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{[hex(1/i) for i in 350..354]}
\end{paste}\end{patch}

\begin{patch}{HexExpansionXmpPagePatch4}
\begin{paste}{HexExpansionXmpPageFull4}{HexExpansionXmpPageEmpty4}
\pastebutton{HexExpansionXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{hex(1/1007)}
\indentrel{3}\begin{verbatim}
   (4)
   0.
     OVERBAR
        0041149783F0BF2C7D13933192AF6980619EE345E91EC2BB9
          D5CCA5C071E40926E54E8DDAE24196C0B2F8A0AAD60DBA5
          7F5D4C8536262210C74F1
                             Type: HexadecimalExpansion
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{HexExpansionXmpPageEmpty4}
\begin{paste}{HexExpansionXmpPageEmpty4}{HexExpansionXmpPagePatch4}
\pastebutton{HexExpansionXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{hex(1/1007)}
\end{paste}\end{patch}

\begin{patch}{HexExpansionXmpPagePatch5}
\begin{paste}{HexExpansionXmpPageFull5}{HexExpansionXmpPageEmpty5}
\pastebutton{HexExpansionXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{p := hex(1/4)*x**2 + hex(2/3)*x + hex(4/9)\bound{p }}
\indentrel{3}\begin{verbatim}
            2     _      ___
   (5)  0.4x  + 0.Ax + 0.71C
                  Type: Polynomial HexadecimalExpansion
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{HexExpansionXmpPageEmpty5}
\begin{paste}{HexExpansionXmpPageEmpty5}{HexExpansionXmpPagePatch5}
\pastebutton{HexExpansionXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{p := hex(1/4)*x**2 + hex(2/3)*x + hex(4/9)\bound{p }}
\end{paste}\end{patch}

\begin{patch}{HexExpansionXmpPagePatch6}
\begin{paste}{HexExpansionXmpPageFull6}{HexExpansionXmpPageEmpty6}
\pastebutton{HexExpansionXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{q := D(p, x)\free{p }\bound{q }}
\indentrel{3}\begin{verbatim}
                 _
   (6)  0.8x + 0.A
                  Type: Polynomial HexadecimalExpansion
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{HexExpansionXmpPageEmpty6}
\begin{paste}{HexExpansionXmpPageEmpty6}{HexExpansionXmpPagePatch6}
\pastebutton{HexExpansionXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{q := D(p, x)\free{p }\bound{q }}
\end{paste}\end{patch}

\begin{patch}{HexExpansionXmpPagePatch7}
\begin{paste}{HexExpansionXmpPageFull7}{HexExpansionXmpPageEmpty7}
\pastebutton{HexExpansionXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{g := gcd(p, q)\free{p }\free{q }}
\indentrel{3}\begin{verbatim}
              _
   (7)  x + 1.5
                  Type: Polynomial HexadecimalExpansion
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{HexExpansionXmpPageEmpty7}
\begin{paste}{HexExpansionXmpPageEmpty7}{HexExpansionXmpPagePatch7}
\pastebutton{HexExpansionXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{g := gcd(p, q)\free{p }\free{q }}
\end{paste}\end{patch}

\end{chunk}
\section{int.ht}
\pagetitle{IntegerXmpPage}{int.ht}{Integer}
\pagepic{ps/v71integerxmppage.eps}{IntegerXmpPage}{0.50}
\pagefrom{Integers}{IntegerPage}
\pageto{Numbers}{ugIntroNumbersPage}
\pageto{IntegerNumberTheoryFunctions}{IntNumberTheoryFnsXmpPage}
\pageto{DecimalExpansion}{DecimalExpansionXmpPage}
\pageto{BinaryExpansion}{BinaryExpansionXmpPage}
\pageto{HexadecimalExpansion}{HexExpansionXmpPage}
\pageto{RadixExpansion}{RadixExpansionXmpPage}
\pageto{Basic Functions}{ugxIntegerBasicPage}
\pageto{Primes and Factorization}{ugxIntegerPrimesPage}
\pageto{Some Number Theoretic Functions}{ugxIntegerNTPage}
\begin{chunk}{int.ht}
\begin{page}{IntegerXmpPage}{Integer}
\beginscroll

Axiom provides many operations for manipulating arbitrary precision
integers.  In this section we will show some of those that come from
\spadtype{Integer} itself plus some that are implemented in other
packages.  More examples of using integers are in the following
sections:
\downlink{``Numbers''}{ugIntroNumbersPage} in section 1.5
\downlink{`IntegerNumberTheoryFunctions'}
{IntNumberTheoryFnsXmpPage}
\ignore{IntegerNumberTheoryFunctions},
\downlink{`DecimalExpansion'}{DecimalExpansionXmpPage}
\ignore{DecimalExpansion},
\downlink{`BinaryExpansion'}{BinaryExpansionXmpPage}
\ignore{BinaryExpansion},
\downlink{`HexadecimalExpansion'}{HexExpansionXmpPage}
\ignore{HexadecimalExpansion},
and
\downlink{`RadixExpansion'}{RadixExpansionXmpPage}
\ignore{RadixExpansion}.

\beginmenu
    \menudownlink{{9.34.1. Basic Functions}}{ugxIntegerBasicPage}
    \menudownlink{{9.34.2. Primes and Factorization}}
                   {ugxIntegerPrimesPage}
    \menudownlink{{9.34.3. Some Number Theoretic Functions}}
                  {ugxIntegerNTPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugxIntegerBasicPage}{int.ht}{Basic Functions}
\pagepic{ps/v71ugxintegerbasicpage.eps}{ugxIntegerBasicPage}{0.50}
\pagefrom{Integer}{IntegerXmpPage}
\pageto{Fraction}{FractionXmpPage}
\pageto{Unions}{ugTypesUnionsPage}
\pageto{Records}{ugTypesRecordsPage}
\begin{chunk}{int.ht}
\begin{page}{ugxIntegerBasicPage}{Basic Functions}
\beginscroll

\labelSpace{3pc}
\xtc{
The size of an integer in Axiom is only limited by the amount of
computer storage you have available.
The usual arithmetic operations are available.
}{
\spadpaste{2**(5678 - 4856 + 2 * 17)}
}

\xtc{
There are a number of ways of working with the sign of an integer.
Let's use this \spad{x} as an example.
}{
\spadpaste{x := -101 \bound{x}}
}
\xtc{
First of all, there is the absolute value function.
}{
\spadpaste{abs(x) \free{x}}
}
\xtc{
The \spadfunFrom{sign}{Integer} operation returns \spad{-1} if its
argument is negative, \spad{0} if zero and \spad{1} if positive.
}{
\spadpaste{sign(x) \free{x}}
}
%
\xtc{
You can determine if an integer is negative in several other ways.
}{
\spadpaste{x < 0 \free{x}}
}
\xtc{
}{
\spadpaste{x <= -1 \free{x}}
}
\xtc{
}{
\spadpaste{negative?(x) \free{x}}
}
%
\xtc{
Similarly, you can find out if it is positive.
}{
\spadpaste{x > 0 \free{x}}
}
\xtc{
}{
\spadpaste{x >= 1 \free{x}}
}
\xtc{
}{
\spadpaste{positive?(x) \free{x}}
}
\xtc{
This is the recommended way of determining whether an integer is zero.
}{
\spadpaste{zero?(x) \free{x}}
}

\beginImportant
Use the \spadfunFrom{zero?}{Integer} operation whenever you are
testing any mathematical object for equality with zero.  This is
usually more efficient that using \spadop{=} (think of matrices: it is
easier to tell if a matrix is zero by just checking term by term than
constructing another ``zero'' matrix and comparing the two matrices
term by term) and also avoids the problem that \spadop{=} is usually
used for creating equations.
\endImportant

\xtc{
This is the recommended way of determining
whether an integer is equal to one.
}{
\spadpaste{one?(x) \free{x}}
}

\xtc{
This syntax is used to test equality using \spadopFrom{=}{Integer}.
It says that you want a \spadtype{Boolean} (\spad{true} or
\spad{false}) answer rather than an equation.
}{
\spadpaste{(x = -101)@Boolean \free{x}}
}

\xtc{
The operations \spadfunFrom{odd?}{Integer} and
\spadfunFrom{even?}{Integer} determine whether an integer is odd or
even, respectively.  They each return a \spadtype{Boolean} object.
}{
\spadpaste{odd?(x) \free{x}}
}
\xtc{
}{
\spadpaste{even?(x) \free{x}}
}
\xtc{
The operation \spadfunFrom{gcd}{Integer} computes the greatest common
divisor of two integers.
}{
\spadpaste{gcd(56788,43688)}
}
\xtc{
The operation
\spadfunFrom{lcm}{Integer} computes their least common multiple.
}{
\spadpaste{lcm(56788,43688)}
}
\xtc{
To determine the maximum of two integers, use \spadfunFrom{max}{Integer}.
}{
\spadpaste{max(678,567)}
}
\xtc{
To determine the minimum, use \spadfunFrom{min}{Integer}.
}{
\spadpaste{min(678,567)}
}

\xtc{
The \spadfun{reduce} operation is used to extend
binary operations to more than two arguments.
For example, you can use \spadfun{reduce} to find the maximum integer in
a list or compute the least common multiple of all integers in the list.
}{
\spadpaste{reduce(max,[2,45,-89,78,100,-45])}
}
\xtc{
}{
\spadpaste{reduce(min,[2,45,-89,78,100,-45])}
}
\xtc{
}{
\spadpaste{reduce(gcd,[2,45,-89,78,100,-45])}
}
\xtc{
}{
\spadpaste{reduce(lcm,[2,45,-89,78,100,-45])}
}

\xtc{
The infix operator ``/'' is {\it not} used to compute the quotient
of integers.
Rather, it is used to create rational numbers as described in
\downlink{`Fraction'}{FractionXmpPage}\ignore{Fraction}.
}{
\spadpaste{13 / 4}
}
\xtc{
The infix operation \spadfunFrom{quo}{Integer} computes the integer
quotient.
}{
\spadpaste{13 quo 4}
}
\xtc{
The infix operation \spadfunFrom{rem}{Integer} computes the integer
remainder.
}{
\spadpaste{13 rem 4}
}
\xtc{
One integer is evenly divisible by another if the remainder is zero.
The operation \spadfunFrom{exquo}{Integer} can also be used.
See \downlink{``Unions''}{ugTypesUnionsPage} in Section 2.5
\ignore{ugTypesUnions} for an example.
}{
\spadpaste{zero?(167604736446952 rem 2003644)}
}

\xtc{
The operation \spadfunFrom{divide}{Integer} returns a record of the
quotient and remainder and thus is more efficient when both are needed.
}{
\spadpaste{d := divide(13,4) \bound{d}}
}
\xtc{
}{
\spadpaste{d.quotient \free{d}}
}
\xtc{
Records are discussed in detail in 
\downlink{``Records''}{ugTypesRecordsPage} in Section 2.4
\ignore{ugTypesRecords}.
}{
\spadpaste{d.remainder \free{d}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxIntegerBasicPagePatch1}
\begin{paste}{ugxIntegerBasicPageFull1}{ugxIntegerBasicPageEmpty1}
\pastebutton{ugxIntegerBasicPageFull1}{\hidepaste}
\tab{5}\spadcommand{2**(5678 - 4856 + 2 * 17)}
\indentrel{3}\begin{verbatim}
   (1)
  480481077043500814718154092512592439123952613987168226_
   34738556100880842000763082930863425270914120837430745_
   72278211496076276922026433435687527334980249539302425_
   42523045817764949544214392905306388478705146745768073_
   877141698859815495632935288783334250628775936
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty1}
\begin{paste}{ugxIntegerBasicPageEmpty1}{ugxIntegerBasicPagePatch1}
\pastebutton{ugxIntegerBasicPageEmpty1}{\showpaste}
\tab{5}\spadcommand{2**(5678 - 4856 + 2 * 17)}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch2}
\begin{paste}{ugxIntegerBasicPageFull2}{ugxIntegerBasicPageEmpty2}
\pastebutton{ugxIntegerBasicPageFull2}{\hidepaste}
\tab{5}\spadcommand{x := -101\bound{x }}
\indentrel{3}\begin{verbatim}
   (2)  - 101
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty2}
\begin{paste}{ugxIntegerBasicPageEmpty2}{ugxIntegerBasicPagePatch2}
\pastebutton{ugxIntegerBasicPageEmpty2}{\showpaste}
\tab{5}\spadcommand{x := -101\bound{x }}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch3}
\begin{paste}{ugxIntegerBasicPageFull3}{ugxIntegerBasicPageEmpty3}
\pastebutton{ugxIntegerBasicPageFull3}{\hidepaste}
\tab{5}\spadcommand{abs(x)\free{x }}
\indentrel{3}\begin{verbatim}
   (3)  101
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty3}
\begin{paste}{ugxIntegerBasicPageEmpty3}{ugxIntegerBasicPagePatch3}
\pastebutton{ugxIntegerBasicPageEmpty3}{\showpaste}
\tab{5}\spadcommand{abs(x)\free{x }}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch4}
\begin{paste}{ugxIntegerBasicPageFull4}{ugxIntegerBasicPageEmpty4}
\pastebutton{ugxIntegerBasicPageFull4}{\hidepaste}
\tab{5}\spadcommand{sign(x)\free{x }}
\indentrel{3}\begin{verbatim}
   (4)  - 1
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty4}
\begin{paste}{ugxIntegerBasicPageEmpty4}{ugxIntegerBasicPagePatch4}
\pastebutton{ugxIntegerBasicPageEmpty4}{\showpaste}
\tab{5}\spadcommand{sign(x)\free{x }}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch5}
\begin{paste}{ugxIntegerBasicPageFull5}{ugxIntegerBasicPageEmpty5}
\pastebutton{ugxIntegerBasicPageFull5}{\hidepaste}
\tab{5}\spadcommand{x < 0\free{x }}
\indentrel{3}\begin{verbatim}
   (5)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty5}
\begin{paste}{ugxIntegerBasicPageEmpty5}{ugxIntegerBasicPagePatch5}
\pastebutton{ugxIntegerBasicPageEmpty5}{\showpaste}
\tab{5}\spadcommand{x < 0\free{x }}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch6}
\begin{paste}{ugxIntegerBasicPageFull6}{ugxIntegerBasicPageEmpty6}
\pastebutton{ugxIntegerBasicPageFull6}{\hidepaste}
\tab{5}\spadcommand{x <= -1\free{x }}
\indentrel{3}\begin{verbatim}
   (6)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty6}
\begin{paste}{ugxIntegerBasicPageEmpty6}{ugxIntegerBasicPagePatch6}
\pastebutton{ugxIntegerBasicPageEmpty6}{\showpaste}
\tab{5}\spadcommand{x <= -1\free{x }}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch7}
\begin{paste}{ugxIntegerBasicPageFull7}{ugxIntegerBasicPageEmpty7}
\pastebutton{ugxIntegerBasicPageFull7}{\hidepaste}
\tab{5}\spadcommand{negative?(x)\free{x }}
\indentrel{3}\begin{verbatim}
   (7)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty7}
\begin{paste}{ugxIntegerBasicPageEmpty7}{ugxIntegerBasicPagePatch7}
\pastebutton{ugxIntegerBasicPageEmpty7}{\showpaste}
\tab{5}\spadcommand{negative?(x)\free{x }}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch8}
\begin{paste}{ugxIntegerBasicPageFull8}{ugxIntegerBasicPageEmpty8}
\pastebutton{ugxIntegerBasicPageFull8}{\hidepaste}
\tab{5}\spadcommand{x > 0\free{x }}
\indentrel{3}\begin{verbatim}
   (8)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty8}
\begin{paste}{ugxIntegerBasicPageEmpty8}{ugxIntegerBasicPagePatch8}
\pastebutton{ugxIntegerBasicPageEmpty8}{\showpaste}
\tab{5}\spadcommand{x > 0\free{x }}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch9}
\begin{paste}{ugxIntegerBasicPageFull9}{ugxIntegerBasicPageEmpty9}
\pastebutton{ugxIntegerBasicPageFull9}{\hidepaste}
\tab{5}\spadcommand{x >= 1\free{x }}
\indentrel{3}\begin{verbatim}
   (9)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty9}
\begin{paste}{ugxIntegerBasicPageEmpty9}{ugxIntegerBasicPagePatch9}
\pastebutton{ugxIntegerBasicPageEmpty9}{\showpaste}
\tab{5}\spadcommand{x >= 1\free{x }}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch10}
\begin{paste}{ugxIntegerBasicPageFull10}{ugxIntegerBasicPageEmpty10}
\pastebutton{ugxIntegerBasicPageFull10}{\hidepaste}
\tab{5}\spadcommand{positive?(x)\free{x }}
\indentrel{3}\begin{verbatim}
   (10)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty10}
\begin{paste}{ugxIntegerBasicPageEmpty10}{ugxIntegerBasicPagePatch10}
\pastebutton{ugxIntegerBasicPageEmpty10}{\showpaste}
\tab{5}\spadcommand{positive?(x)\free{x }}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch11}
\begin{paste}{ugxIntegerBasicPageFull11}{ugxIntegerBasicPageEmpty11}
\pastebutton{ugxIntegerBasicPageFull11}{\hidepaste}
\tab{5}\spadcommand{zero?(x)\free{x }}
\indentrel{3}\begin{verbatim}
   (11)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty11}
\begin{paste}{ugxIntegerBasicPageEmpty11}{ugxIntegerBasicPagePatch11}
\pastebutton{ugxIntegerBasicPageEmpty11}{\showpaste}
\tab{5}\spadcommand{zero?(x)\free{x }}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch12}
\begin{paste}{ugxIntegerBasicPageFull12}{ugxIntegerBasicPageEmpty12}
\pastebutton{ugxIntegerBasicPageFull12}{\hidepaste}
\tab{5}\spadcommand{one?(x)\free{x }}
\indentrel{3}\begin{verbatim}
   (12)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty12}
\begin{paste}{ugxIntegerBasicPageEmpty12}{ugxIntegerBasicPagePatch12}
\pastebutton{ugxIntegerBasicPageEmpty12}{\showpaste}
\tab{5}\spadcommand{one?(x)\free{x }}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch13}
\begin{paste}{ugxIntegerBasicPageFull13}{ugxIntegerBasicPageEmpty13}
\pastebutton{ugxIntegerBasicPageFull13}{\hidepaste}
\tab{5}\spadcommand{(x = -101)@Boolean\free{x }}
\indentrel{3}\begin{verbatim}
   (13)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty13}
\begin{paste}{ugxIntegerBasicPageEmpty13}{ugxIntegerBasicPagePatch13}
\pastebutton{ugxIntegerBasicPageEmpty13}{\showpaste}
\tab{5}\spadcommand{(x = -101)@Boolean\free{x }}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch14}
\begin{paste}{ugxIntegerBasicPageFull14}{ugxIntegerBasicPageEmpty14}
\pastebutton{ugxIntegerBasicPageFull14}{\hidepaste}
\tab{5}\spadcommand{odd?(x)\free{x }}
\indentrel{3}\begin{verbatim}
   (14)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty14}
\begin{paste}{ugxIntegerBasicPageEmpty14}{ugxIntegerBasicPagePatch14}
\pastebutton{ugxIntegerBasicPageEmpty14}{\showpaste}
\tab{5}\spadcommand{odd?(x)\free{x }}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch15}
\begin{paste}{ugxIntegerBasicPageFull15}{ugxIntegerBasicPageEmpty15}
\pastebutton{ugxIntegerBasicPageFull15}{\hidepaste}
\tab{5}\spadcommand{even?(x)\free{x }}
\indentrel{3}\begin{verbatim}
   (15)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty15}
\begin{paste}{ugxIntegerBasicPageEmpty15}{ugxIntegerBasicPagePatch15}
\pastebutton{ugxIntegerBasicPageEmpty15}{\showpaste}
\tab{5}\spadcommand{even?(x)\free{x }}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch16}
\begin{paste}{ugxIntegerBasicPageFull16}{ugxIntegerBasicPageEmpty16}
\pastebutton{ugxIntegerBasicPageFull16}{\hidepaste}
\tab{5}\spadcommand{gcd(56788,43688)}
\indentrel{3}\begin{verbatim}
   (16)  4
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty16}
\begin{paste}{ugxIntegerBasicPageEmpty16}{ugxIntegerBasicPagePatch16}
\pastebutton{ugxIntegerBasicPageEmpty16}{\showpaste}
\tab{5}\spadcommand{gcd(56788,43688)}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch17}
\begin{paste}{ugxIntegerBasicPageFull17}{ugxIntegerBasicPageEmpty17}
\pastebutton{ugxIntegerBasicPageFull17}{\hidepaste}
\tab{5}\spadcommand{lcm(56788,43688)}
\indentrel{3}\begin{verbatim}
   (17)  620238536
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty17}
\begin{paste}{ugxIntegerBasicPageEmpty17}{ugxIntegerBasicPagePatch17}
\pastebutton{ugxIntegerBasicPageEmpty17}{\showpaste}
\tab{5}\spadcommand{lcm(56788,43688)}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch18}
\begin{paste}{ugxIntegerBasicPageFull18}{ugxIntegerBasicPageEmpty18}
\pastebutton{ugxIntegerBasicPageFull18}{\hidepaste}
\tab{5}\spadcommand{max(678,567)}
\indentrel{3}\begin{verbatim}
   (18)  678
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty18}
\begin{paste}{ugxIntegerBasicPageEmpty18}{ugxIntegerBasicPagePatch18}
\pastebutton{ugxIntegerBasicPageEmpty18}{\showpaste}
\tab{5}\spadcommand{max(678,567)}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch19}
\begin{paste}{ugxIntegerBasicPageFull19}{ugxIntegerBasicPageEmpty19}
\pastebutton{ugxIntegerBasicPageFull19}{\hidepaste}
\tab{5}\spadcommand{min(678,567)}
\indentrel{3}\begin{verbatim}
   (19)  567
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty19}
\begin{paste}{ugxIntegerBasicPageEmpty19}{ugxIntegerBasicPagePatch19}
\pastebutton{ugxIntegerBasicPageEmpty19}{\showpaste}
\tab{5}\spadcommand{min(678,567)}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch20}
\begin{paste}{ugxIntegerBasicPageFull20}{ugxIntegerBasicPageEmpty20}
\pastebutton{ugxIntegerBasicPageFull20}{\hidepaste}
\tab{5}\spadcommand{reduce(max,[2,45,-89,78,100,-45])}
\indentrel{3}\begin{verbatim}
   (20)  100
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty20}
\begin{paste}{ugxIntegerBasicPageEmpty20}{ugxIntegerBasicPagePatch20}
\pastebutton{ugxIntegerBasicPageEmpty20}{\showpaste}
\tab{5}\spadcommand{reduce(max,[2,45,-89,78,100,-45])}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch21}
\begin{paste}{ugxIntegerBasicPageFull21}{ugxIntegerBasicPageEmpty21}
\pastebutton{ugxIntegerBasicPageFull21}{\hidepaste}
\tab{5}\spadcommand{reduce(min,[2,45,-89,78,100,-45])}
\indentrel{3}\begin{verbatim}
   (21)  - 89
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty21}
\begin{paste}{ugxIntegerBasicPageEmpty21}{ugxIntegerBasicPagePatch21}
\pastebutton{ugxIntegerBasicPageEmpty21}{\showpaste}
\tab{5}\spadcommand{reduce(min,[2,45,-89,78,100,-45])}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch22}
\begin{paste}{ugxIntegerBasicPageFull22}{ugxIntegerBasicPageEmpty22}
\pastebutton{ugxIntegerBasicPageFull22}{\hidepaste}
\tab{5}\spadcommand{reduce(gcd,[2,45,-89,78,100,-45])}
\indentrel{3}\begin{verbatim}
   (22)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty22}
\begin{paste}{ugxIntegerBasicPageEmpty22}{ugxIntegerBasicPagePatch22}
\pastebutton{ugxIntegerBasicPageEmpty22}{\showpaste}
\tab{5}\spadcommand{reduce(gcd,[2,45,-89,78,100,-45])}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch23}
\begin{paste}{ugxIntegerBasicPageFull23}{ugxIntegerBasicPageEmpty23}
\pastebutton{ugxIntegerBasicPageFull23}{\hidepaste}
\tab{5}\spadcommand{reduce(lcm,[2,45,-89,78,100,-45])}
\indentrel{3}\begin{verbatim}
   (23)  1041300
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty23}
\begin{paste}{ugxIntegerBasicPageEmpty23}{ugxIntegerBasicPagePatch23}
\pastebutton{ugxIntegerBasicPageEmpty23}{\showpaste}
\tab{5}\spadcommand{reduce(lcm,[2,45,-89,78,100,-45])}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch24}
\begin{paste}{ugxIntegerBasicPageFull24}{ugxIntegerBasicPageEmpty24}
\pastebutton{ugxIntegerBasicPageFull24}{\hidepaste}
\tab{5}\spadcommand{13 / 4}
\indentrel{3}\begin{verbatim}
         13
   (24)  ÄÄ
          4
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty24}
\begin{paste}{ugxIntegerBasicPageEmpty24}{ugxIntegerBasicPagePatch24}
\pastebutton{ugxIntegerBasicPageEmpty24}{\showpaste}
\tab{5}\spadcommand{13 / 4}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch25}
\begin{paste}{ugxIntegerBasicPageFull25}{ugxIntegerBasicPageEmpty25}
\pastebutton{ugxIntegerBasicPageFull25}{\hidepaste}
\tab{5}\spadcommand{13 quo 4}
\indentrel{3}\begin{verbatim}
   (25)  3
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty25}
\begin{paste}{ugxIntegerBasicPageEmpty25}{ugxIntegerBasicPagePatch25}
\pastebutton{ugxIntegerBasicPageEmpty25}{\showpaste}
\tab{5}\spadcommand{13 quo 4}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch26}
\begin{paste}{ugxIntegerBasicPageFull26}{ugxIntegerBasicPageEmpty26}
\pastebutton{ugxIntegerBasicPageFull26}{\hidepaste}
\tab{5}\spadcommand{13 rem 4}
\indentrel{3}\begin{verbatim}
   (26)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty26}
\begin{paste}{ugxIntegerBasicPageEmpty26}{ugxIntegerBasicPagePatch26}
\pastebutton{ugxIntegerBasicPageEmpty26}{\showpaste}
\tab{5}\spadcommand{13 rem 4}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch27}
\begin{paste}{ugxIntegerBasicPageFull27}{ugxIntegerBasicPageEmpty27}
\pastebutton{ugxIntegerBasicPageFull27}{\hidepaste}
\tab{5}\spadcommand{zero?(167604736446952 rem 2003644)}
\indentrel{3}\begin{verbatim}
   (27)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty27}
\begin{paste}{ugxIntegerBasicPageEmpty27}{ugxIntegerBasicPagePatch27}
\pastebutton{ugxIntegerBasicPageEmpty27}{\showpaste}
\tab{5}\spadcommand{zero?(167604736446952 rem 2003644)}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch28}
\begin{paste}{ugxIntegerBasicPageFull28}{ugxIntegerBasicPageEmpty28}
\pastebutton{ugxIntegerBasicPageFull28}{\hidepaste}
\tab{5}\spadcommand{d := divide(13,4)\bound{d }}
\indentrel{3}\begin{verbatim}
   (28)  [quotient= 3,remainder= 1]
     Type: Record(quotient: Integer,remainder: Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty28}
\begin{paste}{ugxIntegerBasicPageEmpty28}{ugxIntegerBasicPagePatch28}
\pastebutton{ugxIntegerBasicPageEmpty28}{\showpaste}
\tab{5}\spadcommand{d := divide(13,4)\bound{d }}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch29}
\begin{paste}{ugxIntegerBasicPageFull29}{ugxIntegerBasicPageEmpty29}
\pastebutton{ugxIntegerBasicPageFull29}{\hidepaste}
\tab{5}\spadcommand{d.quotient\free{d }}
\indentrel{3}\begin{verbatim}
   (29)  3
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty29}
\begin{paste}{ugxIntegerBasicPageEmpty29}{ugxIntegerBasicPagePatch29}
\pastebutton{ugxIntegerBasicPageEmpty29}{\showpaste}
\tab{5}\spadcommand{d.quotient\free{d }}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPagePatch30}
\begin{paste}{ugxIntegerBasicPageFull30}{ugxIntegerBasicPageEmpty30}
\pastebutton{ugxIntegerBasicPageFull30}{\hidepaste}
\tab{5}\spadcommand{d.remainder\free{d }}
\indentrel{3}\begin{verbatim}
   (30)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerBasicPageEmpty30}
\begin{paste}{ugxIntegerBasicPageEmpty30}{ugxIntegerBasicPagePatch30}
\pastebutton{ugxIntegerBasicPageEmpty30}{\showpaste}
\tab{5}\spadcommand{d.remainder\free{d }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxIntegerPrimesPage}{int.ht}{Primes and Factorization}
\pagepic{ps/v71ugxintegerprimespage.eps}{ugxIntegerPrimesPage}{0.50}
\pagefrom{Integers}{IntegerPage}
\pagefrom{Integer}{IntegerXmpPage}
\pageto{Factored}{FactoredXmpPage}
\pageto{Complex}{ComplexXmpPage}
\begin{chunk}{int.ht}
\begin{page}{ugxIntegerPrimesPage}{Primes and Factorization}
\beginscroll

\labelSpace{3pc}
\xtc{
Use the operation \spadfunFrom{factor}{Integer} to factor integers.
It returns an object of type \spadtype{Factored Integer}.
See \downlink{`Factored'}{FactoredXmpPage}\ignore{Factored} 
for a discussion of the
manipulation of factored objects.
}{
\spadpaste{factor 102400}
}

\xtc{
The operation \spadfunFrom{prime?}{Integer} returns \spad{true} or
\spad{false} depending on whether its argument is a prime.
}{
\spadpaste{prime? 7}
}
\xtc{
}{
\spadpaste{prime? 8}
}
\xtc{
The operation \spadfunFrom{nextPrime}{IntegerPrimesPackage} returns the
least prime number greater than its argument.
}{
\spadpaste{nextPrime 100}
}
\xtc{
The operation
\spadfunFrom{prevPrime}{IntegerPrimesPackage} returns the greatest prime
number less than its argument.
}{
\spadpaste{prevPrime 100}
}
\xtc{
To compute all primes between two integers (inclusively), use the
operation \spadfunFrom{primes}{IntegerPrimesPackage}.
}{
\spadpaste{primes(100,175)}
}
\xtc{
You might sometimes want to see the factorization of an integer
when it is considered a {\it Gaussian integer}.
See \downlink{`Complex'}{ComplexXmpPage}\ignore{Complex} for more details.
}{
\spadpaste{factor(2 :: Complex Integer)}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxIntegerPrimesPagePatch1}
\begin{paste}{ugxIntegerPrimesPageFull1}{ugxIntegerPrimesPageEmpty1}
\pastebutton{ugxIntegerPrimesPageFull1}{\hidepaste}
\tab{5}\spadcommand{factor 102400}
\indentrel{3}\begin{verbatim}
         12 2
   (1)  2  5
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerPrimesPageEmpty1}
\begin{paste}{ugxIntegerPrimesPageEmpty1}{ugxIntegerPrimesPagePatch1}
\pastebutton{ugxIntegerPrimesPageEmpty1}{\showpaste}
\tab{5}\spadcommand{factor 102400}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerPrimesPagePatch2}
\begin{paste}{ugxIntegerPrimesPageFull2}{ugxIntegerPrimesPageEmpty2}
\pastebutton{ugxIntegerPrimesPageFull2}{\hidepaste}
\tab{5}\spadcommand{prime? 7}
\indentrel{3}\begin{verbatim}
   (2)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerPrimesPageEmpty2}
\begin{paste}{ugxIntegerPrimesPageEmpty2}{ugxIntegerPrimesPagePatch2}
\pastebutton{ugxIntegerPrimesPageEmpty2}{\showpaste}
\tab{5}\spadcommand{prime? 7}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerPrimesPagePatch3}
\begin{paste}{ugxIntegerPrimesPageFull3}{ugxIntegerPrimesPageEmpty3}
\pastebutton{ugxIntegerPrimesPageFull3}{\hidepaste}
\tab{5}\spadcommand{prime? 8}
\indentrel{3}\begin{verbatim}
   (3)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerPrimesPageEmpty3}
\begin{paste}{ugxIntegerPrimesPageEmpty3}{ugxIntegerPrimesPagePatch3}
\pastebutton{ugxIntegerPrimesPageEmpty3}{\showpaste}
\tab{5}\spadcommand{prime? 8}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerPrimesPagePatch4}
\begin{paste}{ugxIntegerPrimesPageFull4}{ugxIntegerPrimesPageEmpty4}
\pastebutton{ugxIntegerPrimesPageFull4}{\hidepaste}
\tab{5}\spadcommand{nextPrime 100}
\indentrel{3}\begin{verbatim}
   (4)  101
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerPrimesPageEmpty4}
\begin{paste}{ugxIntegerPrimesPageEmpty4}{ugxIntegerPrimesPagePatch4}
\pastebutton{ugxIntegerPrimesPageEmpty4}{\showpaste}
\tab{5}\spadcommand{nextPrime 100}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerPrimesPagePatch5}
\begin{paste}{ugxIntegerPrimesPageFull5}{ugxIntegerPrimesPageEmpty5}
\pastebutton{ugxIntegerPrimesPageFull5}{\hidepaste}
\tab{5}\spadcommand{prevPrime 100}
\indentrel{3}\begin{verbatim}
   (5)  97
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerPrimesPageEmpty5}
\begin{paste}{ugxIntegerPrimesPageEmpty5}{ugxIntegerPrimesPagePatch5}
\pastebutton{ugxIntegerPrimesPageEmpty5}{\showpaste}
\tab{5}\spadcommand{prevPrime 100}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerPrimesPagePatch6}
\begin{paste}{ugxIntegerPrimesPageFull6}{ugxIntegerPrimesPageEmpty6}
\pastebutton{ugxIntegerPrimesPageFull6}{\hidepaste}
\tab{5}\spadcommand{primes(100,175)}
\indentrel{3}\begin{verbatim}
   (6)
   [173, 167, 163, 157, 151, 149, 139, 137, 131, 127,
    113, 109, 107, 103, 101]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerPrimesPageEmpty6}
\begin{paste}{ugxIntegerPrimesPageEmpty6}{ugxIntegerPrimesPagePatch6}
\pastebutton{ugxIntegerPrimesPageEmpty6}{\showpaste}
\tab{5}\spadcommand{primes(100,175)}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerPrimesPagePatch7}
\begin{paste}{ugxIntegerPrimesPageFull7}{ugxIntegerPrimesPageEmpty7}
\pastebutton{ugxIntegerPrimesPageFull7}{\hidepaste}
\tab{5}\spadcommand{factor(2 :: Complex Integer)}
\indentrel{3}\begin{verbatim}
                     2
   (7)  - %i (1 + %i)
                         Type: Factored Complex Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerPrimesPageEmpty7}
\begin{paste}{ugxIntegerPrimesPageEmpty7}{ugxIntegerPrimesPagePatch7}
\pastebutton{ugxIntegerPrimesPageEmpty7}{\showpaste}
\tab{5}\spadcommand{factor(2 :: Complex Integer)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxIntegerNTPage}{int.ht}{Some Number Theoretic Functions}
\pagepic{ps/v71ugxintegerntpage.eps}{ugxIntegerNTPage}{0.50}
\pagefrom{Integer}{IntegerXmpPage}
\pageto{IntegerNumberTheoryFunctions}{IntNumberTheoryFnsXmpPage}
\begin{chunk}{int.ht}
\begin{page}{ugxIntegerNTPage}{Some Number Theoretic Functions}
\beginscroll

Axiom provides several number theoretic operations for integers.
More examples are in \downlink{`IntegerNumberTheoryFunctions'}
{IntNumberTheoryFnsXmpPage}\ignore{IntegerNumberTheoryFunctions}.

\labelSpace{1pc}
\xtc{
The operation \spadfunFrom{fibonacci}{IntegerNumberTheoryFunctions}
computes the Fibonacci numbers.
The algorithm has running time
\texht{$O\,(\log^3(n))$}{O(\spad{log(n)**3})} for argument \spad{n}.
}{
\spadpaste{[fibonacci(k) for k in 0..]}
}
\xtc{
The operation \spadfunFrom{legendre}{IntegerNumberTheoryFunctions}
computes the Legendre symbol for its two integer arguments where the
second one is prime.
If you know the second argument to be prime, use
\spadfunFrom{jacobi}{IntegerNumberTheoryFunctions} instead where no check
is made.
}{
\spadpaste{[legendre(i,11) for i in 0..10]}
}
\xtc{
The operation \spadfunFrom{jacobi}{IntegerNumberTheoryFunctions} computes
the Jacobi symbol for its two integer arguments.
By convention, \spad{0} is returned if the greatest common divisor of the
numerator and denominator is not \spad{1}.
}{
\spadpaste{[jacobi(i,15) for i in 0..9]}
}
\xtc{
The operation \spadfunFrom{eulerPhi}{IntegerNumberTheoryFunctions} computes
the values of Euler's \texht{$\phi$}{phi}-function where
\texht{$\phi(n)$}{\spad{phi(n)}}
equals the number of positive integers
less than or equal to \spad{n} that are relatively prime to
the positive integer \spad{n}.
}{
\spadpaste{[eulerPhi i for i in 1..]}
}
\xtc{
The operation \spadfunFrom{moebiusMu}{IntegerNumberTheoryFunctions}
computes the \texht{M\"{o}bius $\mu$}{Moebius mu} function.
}{
\spadpaste{[moebiusMu i for i in 1..]}
}

\xtc{
Although they have somewhat limited utility, Axiom provides
Roman numerals.
}{
\spadpaste{a := roman(78) \bound{a}}
}
\xtc{
}{
\spadpaste{b := roman(87) \bound{b}}
}
\xtc{
}{
\spadpaste{a + b \free{a}\free{b}}
}
\xtc{
}{
\spadpaste{a * b \free{a}\free{b}}
}
\xtc{
}{
\spadpaste{b rem a \free{a}\free{b}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxIntegerNTPagePatch1}
\begin{paste}{ugxIntegerNTPageFull1}{ugxIntegerNTPageEmpty1}
\pastebutton{ugxIntegerNTPageFull1}{\hidepaste}
\tab{5}\spadcommand{[fibonacci(k) for k in 0..]}
\indentrel{3}\begin{verbatim}
   (1)  [0,1,1,2,3,5,8,13,21,34,...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerNTPageEmpty1}
\begin{paste}{ugxIntegerNTPageEmpty1}{ugxIntegerNTPagePatch1}
\pastebutton{ugxIntegerNTPageEmpty1}{\showpaste}
\tab{5}\spadcommand{[fibonacci(k) for k in 0..]}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerNTPagePatch2}
\begin{paste}{ugxIntegerNTPageFull2}{ugxIntegerNTPageEmpty2}
\pastebutton{ugxIntegerNTPageFull2}{\hidepaste}
\tab{5}\spadcommand{[legendre(i,11) for i in 0..10]}
\indentrel{3}\begin{verbatim}
   (2)  [0,1,- 1,1,1,1,- 1,- 1,- 1,1,- 1]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerNTPageEmpty2}
\begin{paste}{ugxIntegerNTPageEmpty2}{ugxIntegerNTPagePatch2}
\pastebutton{ugxIntegerNTPageEmpty2}{\showpaste}
\tab{5}\spadcommand{[legendre(i,11) for i in 0..10]}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerNTPagePatch3}
\begin{paste}{ugxIntegerNTPageFull3}{ugxIntegerNTPageEmpty3}
\pastebutton{ugxIntegerNTPageFull3}{\hidepaste}
\tab{5}\spadcommand{[jacobi(i,15) for i in 0..9]}
\indentrel{3}\begin{verbatim}
   (3)  [0,1,1,0,1,0,0,- 1,1,0]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerNTPageEmpty3}
\begin{paste}{ugxIntegerNTPageEmpty3}{ugxIntegerNTPagePatch3}
\pastebutton{ugxIntegerNTPageEmpty3}{\showpaste}
\tab{5}\spadcommand{[jacobi(i,15) for i in 0..9]}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerNTPagePatch4}
\begin{paste}{ugxIntegerNTPageFull4}{ugxIntegerNTPageEmpty4}
\pastebutton{ugxIntegerNTPageFull4}{\hidepaste}
\tab{5}\spadcommand{[eulerPhi i for i in 1..]}
\indentrel{3}\begin{verbatim}
   (4)  [1,1,2,2,4,2,6,4,6,4,...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerNTPageEmpty4}
\begin{paste}{ugxIntegerNTPageEmpty4}{ugxIntegerNTPagePatch4}
\pastebutton{ugxIntegerNTPageEmpty4}{\showpaste}
\tab{5}\spadcommand{[eulerPhi i for i in 1..]}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerNTPagePatch5}
\begin{paste}{ugxIntegerNTPageFull5}{ugxIntegerNTPageEmpty5}
\pastebutton{ugxIntegerNTPageFull5}{\hidepaste}
\tab{5}\spadcommand{[moebiusMu i for i in 1..]}
\indentrel{3}\begin{verbatim}
   (5)  [1,- 1,- 1,0,- 1,1,- 1,0,0,1,...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerNTPageEmpty5}
\begin{paste}{ugxIntegerNTPageEmpty5}{ugxIntegerNTPagePatch5}
\pastebutton{ugxIntegerNTPageEmpty5}{\showpaste}
\tab{5}\spadcommand{[moebiusMu i for i in 1..]}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerNTPagePatch6}
\begin{paste}{ugxIntegerNTPageFull6}{ugxIntegerNTPageEmpty6}
\pastebutton{ugxIntegerNTPageFull6}{\hidepaste}
\tab{5}\spadcommand{a := roman(78)\bound{a }}
\indentrel{3}\begin{verbatim}
   (6)  LXXVIII
                                     Type: RomanNumeral
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerNTPageEmpty6}
\begin{paste}{ugxIntegerNTPageEmpty6}{ugxIntegerNTPagePatch6}
\pastebutton{ugxIntegerNTPageEmpty6}{\showpaste}
\tab{5}\spadcommand{a := roman(78)\bound{a }}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerNTPagePatch7}
\begin{paste}{ugxIntegerNTPageFull7}{ugxIntegerNTPageEmpty7}
\pastebutton{ugxIntegerNTPageFull7}{\hidepaste}
\tab{5}\spadcommand{b := roman(87)\bound{b }}
\indentrel{3}\begin{verbatim}
   (7)  LXXXVII
                                     Type: RomanNumeral
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerNTPageEmpty7}
\begin{paste}{ugxIntegerNTPageEmpty7}{ugxIntegerNTPagePatch7}
\pastebutton{ugxIntegerNTPageEmpty7}{\showpaste}
\tab{5}\spadcommand{b := roman(87)\bound{b }}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerNTPagePatch8}
\begin{paste}{ugxIntegerNTPageFull8}{ugxIntegerNTPageEmpty8}
\pastebutton{ugxIntegerNTPageFull8}{\hidepaste}
\tab{5}\spadcommand{a + b\free{a }\free{b }}
\indentrel{3}\begin{verbatim}
   (8)  CLXV
                                     Type: RomanNumeral
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerNTPageEmpty8}
\begin{paste}{ugxIntegerNTPageEmpty8}{ugxIntegerNTPagePatch8}
\pastebutton{ugxIntegerNTPageEmpty8}{\showpaste}
\tab{5}\spadcommand{a + b\free{a }\free{b }}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerNTPagePatch9}
\begin{paste}{ugxIntegerNTPageFull9}{ugxIntegerNTPageEmpty9}
\pastebutton{ugxIntegerNTPageFull9}{\hidepaste}
\tab{5}\spadcommand{a * b\free{a }\free{b }}
\indentrel{3}\begin{verbatim}
   (9)  MMMMMMDCCLXXXVI
                                     Type: RomanNumeral
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerNTPageEmpty9}
\begin{paste}{ugxIntegerNTPageEmpty9}{ugxIntegerNTPagePatch9}
\pastebutton{ugxIntegerNTPageEmpty9}{\showpaste}
\tab{5}\spadcommand{a * b\free{a }\free{b }}
\end{paste}\end{patch}

\begin{patch}{ugxIntegerNTPagePatch10}
\begin{paste}{ugxIntegerNTPageFull10}{ugxIntegerNTPageEmpty10}
\pastebutton{ugxIntegerNTPageFull10}{\hidepaste}
\tab{5}\spadcommand{b rem a\free{a }\free{b }}
\indentrel{3}\begin{verbatim}
   (10)  IX
                                     Type: RomanNumeral
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxIntegerNTPageEmpty10}
\begin{paste}{ugxIntegerNTPageEmpty10}{ugxIntegerNTPagePatch10}
\pastebutton{ugxIntegerNTPageEmpty10}{\showpaste}
\tab{5}\spadcommand{b rem a\free{a }\free{b }}
\end{paste}\end{patch}

\end{chunk}
\section{intheory.ht}
\pagetitle{IntNumberTheoryFnsXmpPage}{intheory.ht}
{IntegerNumberTheoryFunctions}
\pagepic{ps/v71intnumbertheoryfnsxmppage.eps}{IntNumberTheoryFnsXmpPage}{0.50}
\pagefrom{Integers}{IntegerPage}
\pagefrom{Integer}{IntegerXmpPage}
\pagefrom{Some Number Theoretic Functions}{ugxIntegerNTPage}
\begin{chunk}{intheory.ht}
\begin{page}{IntNumberTheoryFnsXmpPage}
{IntegerNumberTheoryFunctions}
\beginscroll

The \spadtype{IntegerNumberTheoryFunctions} package contains a variety
of operations of interest to number theorists.  Many of these
operations deal with divisibility properties of integers.  (Recall
that an integer \spad{a} divides an integer \spad{b} if there is an
integer \spad{c} such that \spad{b = a * c}.)

\xtc{
The operation \spadfunFrom{divisors}{IntegerNumberTheoryFunctions}
returns a list of the divisors of an integer.
}{
\spadpaste{div144 := divisors(144) \bound{div144}}
}
\xtc{
You can now compute the number of divisors of \spad{144} and the sum of
the divisors of \spad{144} by counting and summing the elements of the
list we just created.
}{
\spadpaste{\#(div144) \free{div144}}
}
\xtc{
}{
\spadpaste{reduce(+,div144) \free{div144}}
}

Of course, you can compute the number of divisors of an integer \spad{n},
usually denoted \spad{d(n)}, and the sum of the divisors of an integer
\spad{n}, usually denoted \spad{\texht{$\sigma$}{sigma}(n)},
without ever listing the divisors of \spad{n}.

\xtc{
In Axiom, you can simply call the operations
\spadfunFrom{numberOfDivisors}{IntegerNumberTheoryFunctions} and
\spadfunFrom{sumOfDivisors}{IntegerNumberTheoryFunctions}.
}{
\spadpaste{numberOfDivisors(144)}
}
\xtc{
}{
\spadpaste{sumOfDivisors(144)}
}

The key is that \spad{d(n)} and
\spad{\texht{$\sigma$}{sigma}(n)}
are ``multiplicative functions.''
This means that when \spad{n} and \spad{m} are relatively prime, 
that is, when
\spad{n} and \spad{m} have no prime factor in common, then
\spad{d(nm) = d(n) d(m)} and
\spad{\texht{$\sigma$}{sigma}(nm) = \texht{$\sigma$}{sigma}(n)
\texht{$\sigma$}{sigma}(m)}.
Note that these functions are trivial to compute when \spad{n} is a prime
power and are computed for general \spad{n} from the prime factorization
of \spad{n}.
Other examples of multiplicative functions are
\spad{\texht{$\sigma_k$}{sigma_k}(n)}, the sum of the \eth{\spad{k}} 
powers of the divisors of \spad{n} and 
\texht{$\varphi(n)$}{\spad{phi(n)}}, the
number of integers between 1 and \spad{n} which are prime to \spad{n}.
The corresponding Axiom operations are called
\spadfunFrom{sumOfKthPowerDivisors}{IntegerNumberTheoryFunctions} and
\spadfunFrom{eulerPhi}{IntegerNumberTheoryFunctions}.

An interesting function is \spad{\texht{$\mu$}{mu}(n)},
the \texht{M\"{o}bius $\mu$}{Moebius mu} function, defined
as follows:
\spad{\texht{$\mu$}{mu}(1) = 1}, \spad{\texht{$\mu$}{mu}(n) = 0},
when \spad{n} is divisible by a
square, and
\spad{\texht{$\mu = {(-1)}^k$}{mu(n) = (-1) ** k}}, when \spad{n}
is the product of \spad{k} distinct primes.
The corresponding Axiom operation is
\spadfunFrom{moebiusMu}{IntegerNumberTheoryFunctions}.
This function occurs in the following theorem:

\noindent
{\bf Theorem} (\texht{M\"{o}bius}{Moebius} Inversion Formula): \newline
%\texht{\begin{quotation}\noindent}{\newline\indent{5}}
Let \spad{f(n)} be a function on the positive integers and let \spad{F(n)}
be defined by
\texht{\narrowDisplay{F(n) = \sum_{d \mid n} f(n)}}{\spad{F(n) =}
sum of \spad{f(n)} over \spad{d | n}}
where the sum is taken over the positive divisors of \spad{n}.
Then the values of \spad{f(n)} can be recovered from the values of
\spad{F(n)}:
\texht{\narrowDisplay{f(n) = \sum_{d \mid n} \mu(n) F({{n}\over {d}})}}
{\spad{f(n) =}
sum of \spad{mu(n) F(n/d)} over \spad{d | n},}
where again the sum is taken over the positive divisors of \spad{n}.

\xtc{
When \spad{f(n) = 1}, then \spad{F(n) = d(n)}.
Thus, if you sum \spad{\texht{$\mu$}{mu}(d) \texht{$\cdot$}{*} d(n/d)}
over the positive divisors
\spad{d} of \spad{n}, you should always get \spad{1}.
}{
\spadpaste{f1(n) == reduce(+,[moebiusMu(d) * numberOfDivisors(quo(n,d)) 
for d in divisors(n)]) \bound{f1}}
}
\xtc{
}{
\spadpaste{f1(200) \free{f1}}
}
\xtc{
}{
\spadpaste{f1(846) \free{f1}}
}
\xtc{
Similarly, 
when \spad{f(n) = n}, then \spad{F(n) = \texht{$\sigma$}{sigma}(n)}.
Thus, if you sum \spad{\texht{$\mu$}{mu}(d) \texht{$\cdot$}{*}
\texht{$\sigma$}{sigma}(n/d)} over the positive divisors
\spad{d} of \spad{n}, you should always get \spad{n}.
}{
\spadpaste{f2(n) == reduce(+,[moebiusMu(d) * sumOfDivisors(quo(n,d)) 
for d in divisors(n)]) \bound{f2}}
}
\xtc{
}{
\spadpaste{f2(200) \free{f2}}
}
\xtc{
}{
\spadpaste{f2(846) \free{f2}}
}


The Fibonacci numbers are defined by \spad{F(1) = F(2) = 1} and
\spad{F(n) = F(n-1) + F(n-2)} for \spad{n = 3,4, ...}.
\xtc{
The operation \spadfunFrom{fibonacci}{IntegerNumberTheoryFunctions}
computes the \eth{\spad{n}} Fibonacci number.
}{
\spadpaste{fibonacci(25)}
}
\xtc{
}{
\spadpaste{[fibonacci(n) for n in 1..15]}
}
\xtc{
Fibonacci numbers can also be expressed as sums of binomial coefficients.
}{
\spadpaste{fib(n) == reduce(+,[binomial(n-1-k,k) 
for k in 0..quo(n-1,2)]) \bound{fib}}
}
\xtc{
}{
\spadpaste{fib(25) \free{fib}}
}
\xtc{
}{
\spadpaste{[fib(n) for n in 1..15] \free{fib}}
}

Quadratic symbols can be computed with the operations
\spadfunFrom{legendre}{IntegerNumberTheoryFunctions} and
\spadfunFrom{jacobi}{IntegerNumberTheoryFunctions}.
The Legendre symbol
\texht{$\left({a \over p}\right)$}{\spad{(a/p)}}
is defined for integers \spad{a} and
\spad{p} with \spad{p} an odd prime number.
By definition, \texht{$\left({a \over p}\right)$}{\spad{(a/p) = +1}},
when \spad{a} is a square \spad{(mod p)},
\texht{$\left({a \over p}\right)$}{\spad{(a/p) = -1}},
when \spad{a} is not a square \spad{(mod p)}, and
\texht{$\left({a \over p}\right)$}{\spad{(a/p) = 0}},
when \spad{a} is divisible by \spad{p}.
\xtc{
You compute \texht{$\left({a \over p}\right)$}{\spad{(a/p)}}
via the command \spad{legendre(a,p)}.
}{
\spadpaste{legendre(3,5)}
}
\xtc{
}{
\spadpaste{legendre(23,691)}
}
The Jacobi symbol \texht{$\left({a \over n}\right)$}{\spad{(a/n)}}
is the usual extension of the Legendre
symbol, where \spad{n} is an arbitrary integer.
The most important property of the Jacobi symbol is the following:
if \spad{K} is a quadratic field with discriminant \spad{d} and quadratic
character \texht{$\chi$}{\spad{chi}},
then \texht{$\chi$}{\spad{chi}}\spad{(n) = (d/n)}.
Thus, you can use the Jacobi symbol
to compute, say, the class numbers of
imaginary quadratic fields from a standard class number formula.
\xtc{
This function computes the class number of the imaginary
quadratic field with discriminant \spad{d}.
}{
\spadpaste{h(d) == quo(reduce(+, [jacobi(d,k) for k in 1..quo(-d, 2)]), 
2 - jacobi(d,2)) \bound{h}}
}
\xtc{
}{
\spadpaste{h(-163) \free{h}}   
}
\xtc{
}{
\spadpaste{h(-499) \free{h}}   
}
\xtc{
}{
\spadpaste{h(-1832) \free{h}}  
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{IntNumberTheoryFnsXmpPagePatch1}
\begin{paste}{IntNumberTheoryFnsXmpPageFull1}{IntNumberTheoryFnsXmpPageEmpty1}
\pastebutton{IntNumberTheoryFnsXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{div144 := divisors(144)\bound{div144 }}
\indentrel{3}\begin{verbatim}
   (1)  [1,2,3,4,6,8,9,12,16,18,24,36,48,72,144]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPageEmpty1}
\begin{paste}{IntNumberTheoryFnsXmpPageEmpty1}{IntNumberTheoryFnsXmpPagePatch1}
\pastebutton{IntNumberTheoryFnsXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{div144 := divisors(144)\bound{div144 }}
\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPagePatch2}
\begin{paste}{IntNumberTheoryFnsXmpPageFull2}{IntNumberTheoryFnsXmpPageEmpty2}
\pastebutton{IntNumberTheoryFnsXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{\#(div144)\free{div144 }}
\indentrel{3}\begin{verbatim}
   (2)  15
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPageEmpty2}
\begin{paste}{IntNumberTheoryFnsXmpPageEmpty2}{IntNumberTheoryFnsXmpPagePatch2}
\pastebutton{IntNumberTheoryFnsXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{\#(div144)\free{div144 }}
\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPagePatch3}
\begin{paste}{IntNumberTheoryFnsXmpPageFull3}{IntNumberTheoryFnsXmpPageEmpty3}
\pastebutton{IntNumberTheoryFnsXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{reduce(+,div144)\free{div144 }}
\indentrel{3}\begin{verbatim}
   (3)  403
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPageEmpty3}
\begin{paste}{IntNumberTheoryFnsXmpPageEmpty3}{IntNumberTheoryFnsXmpPagePatch3}
\pastebutton{IntNumberTheoryFnsXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{reduce(+,div144)\free{div144 }}
\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPagePatch4}
\begin{paste}{IntNumberTheoryFnsXmpPageFull4}{IntNumberTheoryFnsXmpPageEmpty4}
\pastebutton{IntNumberTheoryFnsXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{numberOfDivisors(144)}
\indentrel{3}\begin{verbatim}
   (4)  15
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPageEmpty4}
\begin{paste}{IntNumberTheoryFnsXmpPageEmpty4}{IntNumberTheoryFnsXmpPagePatch4}
\pastebutton{IntNumberTheoryFnsXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{numberOfDivisors(144)}
\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPagePatch5}
\begin{paste}{IntNumberTheoryFnsXmpPageFull5}{IntNumberTheoryFnsXmpPageEmpty5}
\pastebutton{IntNumberTheoryFnsXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{sumOfDivisors(144)}
\indentrel{3}\begin{verbatim}
   (5)  403
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPageEmpty5}
\begin{paste}{IntNumberTheoryFnsXmpPageEmpty5}{IntNumberTheoryFnsXmpPagePatch5}
\pastebutton{IntNumberTheoryFnsXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{sumOfDivisors(144)}
\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPagePatch6}
\begin{paste}{IntNumberTheoryFnsXmpPageFull6}{IntNumberTheoryFnsXmpPageEmpty6}
\pastebutton{IntNumberTheoryFnsXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{f1(n) == reduce(+,[moebiusMu(d) * numberOfDivisors(quo(n,d)) for d in divisors(n)])\bound{f1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPageEmpty6}
\begin{paste}{IntNumberTheoryFnsXmpPageEmpty6}{IntNumberTheoryFnsXmpPagePatch6}
\pastebutton{IntNumberTheoryFnsXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{f1(n) == reduce(+,[moebiusMu(d) * numberOfDivisors(quo(n,d)) for d in divisors(n)])\bound{f1 }}
\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPagePatch7}
\begin{paste}{IntNumberTheoryFnsXmpPageFull7}{IntNumberTheoryFnsXmpPageEmpty7}
\pastebutton{IntNumberTheoryFnsXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{f1(200)\free{f1 }}
\indentrel{3}\begin{verbatim}
   (7)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPageEmpty7}
\begin{paste}{IntNumberTheoryFnsXmpPageEmpty7}{IntNumberTheoryFnsXmpPagePatch7}
\pastebutton{IntNumberTheoryFnsXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{f1(200)\free{f1 }}
\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPagePatch8}
\begin{paste}{IntNumberTheoryFnsXmpPageFull8}{IntNumberTheoryFnsXmpPageEmpty8}
\pastebutton{IntNumberTheoryFnsXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{f1(846)\free{f1 }}
\indentrel{3}\begin{verbatim}
   (8)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPageEmpty8}
\begin{paste}{IntNumberTheoryFnsXmpPageEmpty8}{IntNumberTheoryFnsXmpPagePatch8}
\pastebutton{IntNumberTheoryFnsXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{f1(846)\free{f1 }}
\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPagePatch9}
\begin{paste}{IntNumberTheoryFnsXmpPageFull9}{IntNumberTheoryFnsXmpPageEmpty9}
\pastebutton{IntNumberTheoryFnsXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{f2(n) == reduce(+,[moebiusMu(d) * sumOfDivisors(quo(n,d)) for d in divisors(n)])\bound{f2 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPageEmpty9}
\begin{paste}{IntNumberTheoryFnsXmpPageEmpty9}{IntNumberTheoryFnsXmpPagePatch9}
\pastebutton{IntNumberTheoryFnsXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{f2(n) == reduce(+,[moebiusMu(d) * sumOfDivisors(quo(n,d)) for d in divisors(n)])\bound{f2 }}
\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPagePatch10}
\begin{paste}{IntNumberTheoryFnsXmpPageFull10}{IntNumberTheoryFnsXmpPageEmpty10}
\pastebutton{IntNumberTheoryFnsXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{f2(200)\free{f2 }}
\indentrel{3}\begin{verbatim}
   (10)  200
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPageEmpty10}
\begin{paste}{IntNumberTheoryFnsXmpPageEmpty10}{IntNumberTheoryFnsXmpPagePatch10}
\pastebutton{IntNumberTheoryFnsXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{f2(200)\free{f2 }}
\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPagePatch11}
\begin{paste}{IntNumberTheoryFnsXmpPageFull11}{IntNumberTheoryFnsXmpPageEmpty11}
\pastebutton{IntNumberTheoryFnsXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{f2(846)\free{f2 }}
\indentrel{3}\begin{verbatim}
   (11)  846
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPageEmpty11}
\begin{paste}{IntNumberTheoryFnsXmpPageEmpty11}{IntNumberTheoryFnsXmpPagePatch11}
\pastebutton{IntNumberTheoryFnsXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{f2(846)\free{f2 }}
\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPagePatch12}
\begin{paste}{IntNumberTheoryFnsXmpPageFull12}{IntNumberTheoryFnsXmpPageEmpty12}
\pastebutton{IntNumberTheoryFnsXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{fibonacci(25)}
\indentrel{3}\begin{verbatim}
   (12)  75025
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPageEmpty12}
\begin{paste}{IntNumberTheoryFnsXmpPageEmpty12}{IntNumberTheoryFnsXmpPagePatch12}
\pastebutton{IntNumberTheoryFnsXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{fibonacci(25)}
\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPagePatch13}
\begin{paste}{IntNumberTheoryFnsXmpPageFull13}{IntNumberTheoryFnsXmpPageEmpty13}
\pastebutton{IntNumberTheoryFnsXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{[fibonacci(n) for n in 1..15]}
\indentrel{3}\begin{verbatim}
   (13)  [1,1,2,3,5,8,13,21,34,55,89,144,233,377,610]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPageEmpty13}
\begin{paste}{IntNumberTheoryFnsXmpPageEmpty13}{IntNumberTheoryFnsXmpPagePatch13}
\pastebutton{IntNumberTheoryFnsXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{[fibonacci(n) for n in 1..15]}
\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPagePatch14}
\begin{paste}{IntNumberTheoryFnsXmpPageFull14}{IntNumberTheoryFnsXmpPageEmpty14}
\pastebutton{IntNumberTheoryFnsXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{fib(n) == reduce(+,[binomial(n-1-k,k) for k in 0..quo(n-1,2)])\bound{fib }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPageEmpty14}
\begin{paste}{IntNumberTheoryFnsXmpPageEmpty14}{IntNumberTheoryFnsXmpPagePatch14}
\pastebutton{IntNumberTheoryFnsXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{fib(n) == reduce(+,[binomial(n-1-k,k) for k in 0..quo(n-1,2)])\bound{fib }}
\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPagePatch15}
\begin{paste}{IntNumberTheoryFnsXmpPageFull15}{IntNumberTheoryFnsXmpPageEmpty15}
\pastebutton{IntNumberTheoryFnsXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{fib(25)\free{fib }}
\indentrel{3}\begin{verbatim}
   (15)  75025
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPageEmpty15}
\begin{paste}{IntNumberTheoryFnsXmpPageEmpty15}{IntNumberTheoryFnsXmpPagePatch15}
\pastebutton{IntNumberTheoryFnsXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{fib(25)\free{fib }}
\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPagePatch16}
\begin{paste}{IntNumberTheoryFnsXmpPageFull16}{IntNumberTheoryFnsXmpPageEmpty16}
\pastebutton{IntNumberTheoryFnsXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{[fib(n) for n in 1..15]\free{fib }}
\indentrel{3}\begin{verbatim}
   (16)  [1,1,2,3,5,8,13,21,34,55,89,144,233,377,610]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPageEmpty16}
\begin{paste}{IntNumberTheoryFnsXmpPageEmpty16}{IntNumberTheoryFnsXmpPagePatch16}
\pastebutton{IntNumberTheoryFnsXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{[fib(n) for n in 1..15]\free{fib }}
\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPagePatch17}
\begin{paste}{IntNumberTheoryFnsXmpPageFull17}{IntNumberTheoryFnsXmpPageEmpty17}
\pastebutton{IntNumberTheoryFnsXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{legendre(3,5)}
\indentrel{3}\begin{verbatim}
   (17)  - 1
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPageEmpty17}
\begin{paste}{IntNumberTheoryFnsXmpPageEmpty17}{IntNumberTheoryFnsXmpPagePatch17}
\pastebutton{IntNumberTheoryFnsXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{legendre(3,5)}
\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPagePatch18}
\begin{paste}{IntNumberTheoryFnsXmpPageFull18}{IntNumberTheoryFnsXmpPageEmpty18}
\pastebutton{IntNumberTheoryFnsXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{legendre(23,691)}
\indentrel{3}\begin{verbatim}
   (18)  - 1
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPageEmpty18}
\begin{paste}{IntNumberTheoryFnsXmpPageEmpty18}{IntNumberTheoryFnsXmpPagePatch18}
\pastebutton{IntNumberTheoryFnsXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{legendre(23,691)}
\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPagePatch19}
\begin{paste}{IntNumberTheoryFnsXmpPageFull19}{IntNumberTheoryFnsXmpPageEmpty19}
\pastebutton{IntNumberTheoryFnsXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{h(d) == quo(reduce(+, [jacobi(d,k) for k in 1..quo(-d, 2)]), 2 - jacobi(d,2))\bound{h }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPageEmpty19}
\begin{paste}{IntNumberTheoryFnsXmpPageEmpty19}{IntNumberTheoryFnsXmpPagePatch19}
\pastebutton{IntNumberTheoryFnsXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{h(d) == quo(reduce(+, [jacobi(d,k) for k in 1..quo(-d, 2)]), 2 - jacobi(d,2))\bound{h }}
\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPagePatch20}
\begin{paste}{IntNumberTheoryFnsXmpPageFull20}{IntNumberTheoryFnsXmpPageEmpty20}
\pastebutton{IntNumberTheoryFnsXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{h(-163)\free{h }}
\indentrel{3}\begin{verbatim}
   (20)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPageEmpty20}
\begin{paste}{IntNumberTheoryFnsXmpPageEmpty20}{IntNumberTheoryFnsXmpPagePatch20}
\pastebutton{IntNumberTheoryFnsXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{h(-163)\free{h }}
\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPagePatch21}
\begin{paste}{IntNumberTheoryFnsXmpPageFull21}{IntNumberTheoryFnsXmpPageEmpty21}
\pastebutton{IntNumberTheoryFnsXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{h(-499)\free{h }}
\indentrel{3}\begin{verbatim}
   (21)  3
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPageEmpty21}
\begin{paste}{IntNumberTheoryFnsXmpPageEmpty21}{IntNumberTheoryFnsXmpPagePatch21}
\pastebutton{IntNumberTheoryFnsXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{h(-499)\free{h }}
\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPagePatch22}
\begin{paste}{IntNumberTheoryFnsXmpPageFull22}{IntNumberTheoryFnsXmpPageEmpty22}
\pastebutton{IntNumberTheoryFnsXmpPageFull22}{\hidepaste}
\tab{5}\spadcommand{h(-1832)\free{h }}
\indentrel{3}\begin{verbatim}
   (22)  26
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntNumberTheoryFnsXmpPageEmpty22}
\begin{paste}{IntNumberTheoryFnsXmpPageEmpty22}{IntNumberTheoryFnsXmpPagePatch22}
\pastebutton{IntNumberTheoryFnsXmpPageEmpty22}{\showpaste}
\tab{5}\spadcommand{h(-1832)\free{h }}
\end{paste}\end{patch}

\end{chunk}
\section{kafile.ht}
\pagetitle{KeyedAccessFileXmpPage}{kafile.ht}{KeyedAccessFile}
\pageto{notitle}{FileXmpPage}
\pageto{notitle}{TextFileXmpPage}
\pageto{notitle}{LibraryXmpPage}
\begin{chunk}{kafile.ht}
\begin{page}{KeyedAccessFileXmpPage}{KeyedAccessFile}
\beginscroll

The domain \spadtype{KeyedAccessFile(S)} provides files which can be
used as associative tables.  Data values are stored in these files and
can be retrieved according to their keys.  The keys must be strings so
this type behaves very much like the \spadtype{StringTable(S)} domain.
The difference is that keyed access files reside in secondary storage
while string tables are kept in memory.  For more information on
table-oriented operations, see the description of \spadtype{Table}.

\xtc{
Before a keyed access file can be used, it must first be opened.
A new file can be created by opening it for output.
}{
\spadpaste{ey: KeyedAccessFile(Integer) := 
open("/tmp/editor.year", "output")  \bound{ey}}
}
\xtc{
Just as for vectors, tables or lists, values are saved in a keyed
access file by setting elements.
}{
\spadpaste{ey."Char"     := 1986 \free{ey}\bound{eya}}
}
\xtc{
}{
\spadpaste{ey."Caviness" := 1985 \free{ey}\bound{eyb}}
}
\xtc{
}{
\spadpaste{ey."Fitch"    := 1984 \free{ey}\bound{eyc}}
}
\xtc{
Values are retrieved using application, in any of its syntactic forms.
}{
\spadpaste{ey."Char"     \free{eya}}
}
\xtc{
}{
\spadpaste{ey("Char")    \free{eya}}
}
\xtc{
}{
\spadpaste{ey "Char"     \free{eya}}
}
\xtc{
Attempting to retrieve a non-existent element in this way causes an
error.  If it is not known whether a key exists, you should use the
\spadfunFrom{search}{KeyedAccessFile} operation.
}{
\spadpaste{search("Char", ey)   \free{eya,eyb,eyc}\bound{eyaa}}
}
\xtc{
}{
\spadpaste{search("Smith", ey)  \free{eyaa}}
}
\xtc{
When an entry is no longer needed, it can be removed from the file.
}{
\spadpaste{remove!("Char", ey)  \free{eyaa}\bound{eybb}}
}
\xtc{
The \spadfunFrom{keys}{KeyedAccessFile} operation returns a list of
all the keys for a given file.
}{
\spadpaste{keys ey  \free{eybb}}
}
\xtc{
The \spadfunFrom{\#}{KeyedAccessFile} operation gives the
number of entries.
}{
\spadpaste{\#ey     \free{eybb}}
}

The table view of keyed access files provides safe operations.
That is, if the Axiom program is terminated between file operations,
the file is left in a consistent, current state.
This means, however, that the operations are somewhat costly.
For example, after each update the file is closed.
\xtc{
Here we add several more items to the file, then check its contents.
}{
\spadpaste{KE := Record(key: String, entry: Integer)  \bound{KE}}
}
\xtc{
}{
\spadpaste{reopen!(ey, "output")  \free{eybb,KE}\bound{eycc}}
}
\xtc{
If many items are to be added to a file at the same time, then
it is more efficient to use the 
\spadfunFromX{write}{KeyedAccessFile} operation.
}{
\spadpaste{write!(ey, ["van Hulzen", 1983]\$KE) \bound{eyccA}\free{eycc}}
}
\xtc{
}{
\spadpaste{write!(ey, ["Calmet", 1982]\$KE) \bound{eyccB}\free{eycc}}
}
\xtc{
}{
\spadpaste{write!(ey, ["Wang", 1981]\$KE) \bound{eyccC}\free{eycc}}
}
\xtc{
}{
\spadpaste{close! ey   \free{eyccA,eyccB,eyccC}\bound{eydd}}
}
\xtc{
The \spadfunFromX{read}{KeyedAccessFile} operation is also available
from the file view, but it returns elements in a random order.  It is
generally clearer and more efficient to use the
\spadfunFrom{keys}{KeyedAccessFile} operation and to extract elements
by key.
}{
\spadpaste{keys ey     \free{eydd}}
}
\xtc{
}{
\spadpaste{members ey  \free{eydd}}
}
\noOutputXtc{
}{
\spadpaste{)system rm -r /tmp/editor.year  \free{ey}}
}

For more information on related topics,  see
\downlink{`File'}{FileXmpPage}\ignore{File},
\downlink{`TextFile'}{TextFileXmpPage}\ignore{TextFile}, and
\downlink{`Library'}{LibraryXmpPage}\ignore{Library}.
%
\showBlurb{KeyedAccessFile}
\endscroll
\autobuttons
\end{page}

\begin{patch}{KeyedAccessFileXmpPagePatch1}
\begin{paste}{KeyedAccessFileXmpPageFull1}{KeyedAccessFileXmpPageEmpty1}
\pastebutton{KeyedAccessFileXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{ey: KeyedAccessFile(Integer) := open("/tmp/editor.year", "output")\bound{ey }}
\indentrel{3}\begin{verbatim}
   (1)  "/tmp/editor.year"
                          Type: KeyedAccessFile Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPageEmpty1}
\begin{paste}{KeyedAccessFileXmpPageEmpty1}{KeyedAccessFileXmpPagePatch1}
\pastebutton{KeyedAccessFileXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{ey: KeyedAccessFile(Integer) := open("/tmp/editor.year", "output")\bound{ey }}
\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPagePatch2}
\begin{paste}{KeyedAccessFileXmpPageFull2}{KeyedAccessFileXmpPageEmpty2}
\pastebutton{KeyedAccessFileXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{ey."Char" := 1986\free{ey }\bound{eya }}
\indentrel{3}\begin{verbatim}
   (2)  1986
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPageEmpty2}
\begin{paste}{KeyedAccessFileXmpPageEmpty2}{KeyedAccessFileXmpPagePatch2}
\pastebutton{KeyedAccessFileXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{ey."Char" := 1986\free{ey }\bound{eya }}
\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPagePatch3}
\begin{paste}{KeyedAccessFileXmpPageFull3}{KeyedAccessFileXmpPageEmpty3}
\pastebutton{KeyedAccessFileXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{ey."Caviness" := 1985\free{ey }\bound{eyb }}
\indentrel{3}\begin{verbatim}
   (3)  1985
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPageEmpty3}
\begin{paste}{KeyedAccessFileXmpPageEmpty3}{KeyedAccessFileXmpPagePatch3}
\pastebutton{KeyedAccessFileXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{ey."Caviness" := 1985\free{ey }\bound{eyb }}
\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPagePatch4}
\begin{paste}{KeyedAccessFileXmpPageFull4}{KeyedAccessFileXmpPageEmpty4}
\pastebutton{KeyedAccessFileXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{ey."Fitch" := 1984\free{ey }\bound{eyc }}
\indentrel{3}\begin{verbatim}
   (4)  1984
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPageEmpty4}
\begin{paste}{KeyedAccessFileXmpPageEmpty4}{KeyedAccessFileXmpPagePatch4}
\pastebutton{KeyedAccessFileXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{ey."Fitch" := 1984\free{ey }\bound{eyc }}
\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPagePatch5}
\begin{paste}{KeyedAccessFileXmpPageFull5}{KeyedAccessFileXmpPageEmpty5}
\pastebutton{KeyedAccessFileXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{ey."Char"\free{eya }}
\indentrel{3}\begin{verbatim}
   (5)  1986
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPageEmpty5}
\begin{paste}{KeyedAccessFileXmpPageEmpty5}{KeyedAccessFileXmpPagePatch5}
\pastebutton{KeyedAccessFileXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{ey."Char"\free{eya }}
\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPagePatch6}
\begin{paste}{KeyedAccessFileXmpPageFull6}{KeyedAccessFileXmpPageEmpty6}
\pastebutton{KeyedAccessFileXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{ey("Char")\free{eya }}
\indentrel{3}\begin{verbatim}
   (6)  1986
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPageEmpty6}
\begin{paste}{KeyedAccessFileXmpPageEmpty6}{KeyedAccessFileXmpPagePatch6}
\pastebutton{KeyedAccessFileXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{ey("Char")\free{eya }}
\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPagePatch7}
\begin{paste}{KeyedAccessFileXmpPageFull7}{KeyedAccessFileXmpPageEmpty7}
\pastebutton{KeyedAccessFileXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{ey "Char"\free{eya }}
\indentrel{3}\begin{verbatim}
   (7)  1986
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPageEmpty7}
\begin{paste}{KeyedAccessFileXmpPageEmpty7}{KeyedAccessFileXmpPagePatch7}
\pastebutton{KeyedAccessFileXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{ey "Char"\free{eya }}
\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPagePatch8}
\begin{paste}{KeyedAccessFileXmpPageFull8}{KeyedAccessFileXmpPageEmpty8}
\pastebutton{KeyedAccessFileXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{search("Char", ey)\free{eya eyb eyc }\bound{eyaa }}
\indentrel{3}\begin{verbatim}
   (8)  1986
                               Type: Union(Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPageEmpty8}
\begin{paste}{KeyedAccessFileXmpPageEmpty8}{KeyedAccessFileXmpPagePatch8}
\pastebutton{KeyedAccessFileXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{search("Char", ey)\free{eya eyb eyc }\bound{eyaa }}
\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPagePatch9}
\begin{paste}{KeyedAccessFileXmpPageFull9}{KeyedAccessFileXmpPageEmpty9}
\pastebutton{KeyedAccessFileXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{search("Smith", ey)\free{eyaa }}
\indentrel{3}\begin{verbatim}
   (9)  "failed"
                              Type: Union("failed",...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPageEmpty9}
\begin{paste}{KeyedAccessFileXmpPageEmpty9}{KeyedAccessFileXmpPagePatch9}
\pastebutton{KeyedAccessFileXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{search("Smith", ey)\free{eyaa }}
\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPagePatch10}
\begin{paste}{KeyedAccessFileXmpPageFull10}{KeyedAccessFileXmpPageEmpty10}
\pastebutton{KeyedAccessFileXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{remove!("Char", ey)\free{eyaa }\bound{eybb }}
\indentrel{3}\begin{verbatim}
   (10)  1986
                               Type: Union(Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPageEmpty10}
\begin{paste}{KeyedAccessFileXmpPageEmpty10}{KeyedAccessFileXmpPagePatch10}
\pastebutton{KeyedAccessFileXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{remove!("Char", ey)\free{eyaa }\bound{eybb }}
\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPagePatch11}
\begin{paste}{KeyedAccessFileXmpPageFull11}{KeyedAccessFileXmpPageEmpty11}
\pastebutton{KeyedAccessFileXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{keys ey\free{eybb }}
\indentrel{3}\begin{verbatim}
   (11)  ["Fitch","Caviness"]
                                      Type: List String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPageEmpty11}
\begin{paste}{KeyedAccessFileXmpPageEmpty11}{KeyedAccessFileXmpPagePatch11}
\pastebutton{KeyedAccessFileXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{keys ey\free{eybb }}
\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPagePatch12}
\begin{paste}{KeyedAccessFileXmpPageFull12}{KeyedAccessFileXmpPageEmpty12}
\pastebutton{KeyedAccessFileXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{\#ey\free{eybb }}
\indentrel{3}\begin{verbatim}
   (12)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPageEmpty12}
\begin{paste}{KeyedAccessFileXmpPageEmpty12}{KeyedAccessFileXmpPagePatch12}
\pastebutton{KeyedAccessFileXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{\#ey\free{eybb }}
\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPagePatch13}
\begin{paste}{KeyedAccessFileXmpPageFull13}{KeyedAccessFileXmpPageEmpty13}
\pastebutton{KeyedAccessFileXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{KE := Record(key: String, entry: Integer)\bound{KE }}
\indentrel{3}\begin{verbatim}
   (13)  Record(key: String,entry: Integer)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPageEmpty13}
\begin{paste}{KeyedAccessFileXmpPageEmpty13}{KeyedAccessFileXmpPagePatch13}
\pastebutton{KeyedAccessFileXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{KE := Record(key: String, entry: Integer)\bound{KE }}
\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPagePatch14}
\begin{paste}{KeyedAccessFileXmpPageFull14}{KeyedAccessFileXmpPageEmpty14}
\pastebutton{KeyedAccessFileXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{reopen!(ey, "output")\free{eybb KE }\bound{eycc }}
\indentrel{3}\begin{verbatim}
   (14)  "/tmp/editor.year"
                          Type: KeyedAccessFile Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPageEmpty14}
\begin{paste}{KeyedAccessFileXmpPageEmpty14}{KeyedAccessFileXmpPagePatch14}
\pastebutton{KeyedAccessFileXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{reopen!(ey, "output")\free{eybb KE }\bound{eycc }}
\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPagePatch15}
\begin{paste}{KeyedAccessFileXmpPageFull15}{KeyedAccessFileXmpPageEmpty15}
\pastebutton{KeyedAccessFileXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{write!(ey, ["van Hulzen", 1983]$KE)\bound{eyccA }\free{eycc }}
\indentrel{3}\begin{verbatim}
   (15)  [key= "van Hulzen",entry= 1983]
               Type: Record(key: String,entry: Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPageEmpty15}
\begin{paste}{KeyedAccessFileXmpPageEmpty15}{KeyedAccessFileXmpPagePatch15}
\pastebutton{KeyedAccessFileXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{write!(ey, ["van Hulzen", 1983]$KE)\bound{eyccA }\free{eycc }}
\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPagePatch16}
\begin{paste}{KeyedAccessFileXmpPageFull16}{KeyedAccessFileXmpPageEmpty16}
\pastebutton{KeyedAccessFileXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{write!(ey, ["Calmet", 1982]$KE)\bound{eyccB }\free{eycc }}
\indentrel{3}\begin{verbatim}
   (16)  [key= "Calmet",entry= 1982]
               Type: Record(key: String,entry: Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPageEmpty16}
\begin{paste}{KeyedAccessFileXmpPageEmpty16}{KeyedAccessFileXmpPagePatch16}
\pastebutton{KeyedAccessFileXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{write!(ey, ["Calmet", 1982]$KE)\bound{eyccB }\free{eycc }}
\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPagePatch17}
\begin{paste}{KeyedAccessFileXmpPageFull17}{KeyedAccessFileXmpPageEmpty17}
\pastebutton{KeyedAccessFileXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{write!(ey, ["Wang", 1981]$KE)\bound{eyccC }\free{eycc }}
\indentrel{3}\begin{verbatim}
   (17)  [key= "Wang",entry= 1981]
               Type: Record(key: String,entry: Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPageEmpty17}
\begin{paste}{KeyedAccessFileXmpPageEmpty17}{KeyedAccessFileXmpPagePatch17}
\pastebutton{KeyedAccessFileXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{write!(ey, ["Wang", 1981]$KE)\bound{eyccC }\free{eycc }}
\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPagePatch18}
\begin{paste}{KeyedAccessFileXmpPageFull18}{KeyedAccessFileXmpPageEmpty18}
\pastebutton{KeyedAccessFileXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{close! ey\free{eyccA eyccB eyccC }\bound{eydd }}
\indentrel{3}\begin{verbatim}
   (18)  "/tmp/editor.year"
                          Type: KeyedAccessFile Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPageEmpty18}
\begin{paste}{KeyedAccessFileXmpPageEmpty18}{KeyedAccessFileXmpPagePatch18}
\pastebutton{KeyedAccessFileXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{close! ey\free{eyccA eyccB eyccC }\bound{eydd }}
\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPagePatch19}
\begin{paste}{KeyedAccessFileXmpPageFull19}{KeyedAccessFileXmpPageEmpty19}
\pastebutton{KeyedAccessFileXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{keys ey\free{eydd }}
\indentrel{3}\begin{verbatim}
   (19)
   ["Wang","Calmet","van Hulzen","Fitch","Caviness"]
                                      Type: List String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPageEmpty19}
\begin{paste}{KeyedAccessFileXmpPageEmpty19}{KeyedAccessFileXmpPagePatch19}
\pastebutton{KeyedAccessFileXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{keys ey\free{eydd }}
\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPagePatch20}
\begin{paste}{KeyedAccessFileXmpPageFull20}{KeyedAccessFileXmpPageEmpty20}
\pastebutton{KeyedAccessFileXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{members ey\free{eydd }}
\indentrel{3}\begin{verbatim}
   (20)  [1981,1982,1983,1984,1985]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPageEmpty20}
\begin{paste}{KeyedAccessFileXmpPageEmpty20}{KeyedAccessFileXmpPagePatch20}
\pastebutton{KeyedAccessFileXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{members ey\free{eydd }}
\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPagePatch21}
\begin{paste}{KeyedAccessFileXmpPageFull21}{KeyedAccessFileXmpPageEmpty21}
\pastebutton{KeyedAccessFileXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{)system rm -r /tmp/editor.year\free{ey }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KeyedAccessFileXmpPageEmpty21}
\begin{paste}{KeyedAccessFileXmpPageEmpty21}{KeyedAccessFileXmpPagePatch21}
\pastebutton{KeyedAccessFileXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{)system rm -r /tmp/editor.year\free{ey }}
\end{paste}\end{patch}

\end{chunk}
\section{kernel.ht}
\pagetitle{KernelXmpPage}{kernel.ht}{Kernel}
\pageto{notitle}{BasicOperatorXmpPage}
\pageto{notitle}{ExpressionXmpPage}
\begin{chunk}{kernel.ht}
\begin{page}{KernelXmpPage}{Kernel}
\beginscroll

A {\it kernel} is a symbolic function application (such as 
\spad{sin(x + y)}) or a symbol (such as \spad{x}).  
More precisely, a non-symbol
kernel over a set {\it S} is an operator applied to a given list of
arguments from {\it S}.  The operator has type
\axiomType{BasicOperator} (see
\downlink{`BasicOperator'}{BasicOperatorXmpPage}\ignore{BasicOperator})
and the kernel object is usually part of an expression object (see
\downlink{`Expression'}{ExpressionXmpPage}\ignore{Expression}).

Kernels are created implicitly for you when you
create expressions.
\xtc{
}{
\spadpaste{x :: Expression Integer}
}
\xtc{
You can directly create a ``symbol'' kernel by using the
\axiomFunFrom{kernel}{Kernel} operation.
}{
\spadpaste{kernel x}
}
\xtc{
This expression has two different kernels.
}{
\spadpaste{sin(x) + cos(x) \bound{sincos}}
}
\xtc{
The operator \axiomFunFrom{kernels}{Expression} returns a list
of the kernels in an object of type \axiomType{Expression}.
}{
\spadpaste{kernels \% \free{sincos}}
}
\xtc{
This expression also has two different kernels.
}{
\spadpaste{sin(x)**2 + sin(x) + cos(x) \bound{sincos2}}
}
\xtc{
The \spad{sin(x)} kernel is used twice.
}{
\spadpaste{kernels \% \free{sincos2}}
}
\xtc{
An expression need not contain any kernels.
}{
\spadpaste{kernels(1 :: Expression Integer)}
}
\xtc{
If one or more kernels are present, one of them is
designated the {\it main} kernel.
}{
\spadpaste{mainKernel(cos(x) + tan(x))}
}
\xtc{
Kernels can be nested. Use \axiomFunFrom{height}{Kernel} to determine
the nesting depth.
}{
\spadpaste{height kernel x}
}
\xtc{
This has height 2 because the \spad{x} has height 1 and then we apply
an operator to that.
}{
\spadpaste{height mainKernel(sin x)}
}
\xtc{
}{
\spadpaste{height mainKernel(sin cos x)}
}
\xtc{
}{
\spadpaste{height mainKernel(sin cos (tan x + sin x))}
}
\xtc{
Use the \axiomFunFrom{operator}{Kernel} operation to extract the
operator component of the kernel.
The operator has type \axiomType{BasicOperator}.
}{
\spadpaste{operator mainKernel(sin cos (tan x + sin x))}
}
\xtc{
Use the \axiomFunFrom{name}{Kernel} operation to extract the name of
the operator component of the kernel.  The name has type
\axiomType{Symbol}.  This is really just a shortcut for a two-step
process of extracting the operator and then calling
\axiomFunFrom{name}{BasicOperator} on the operator.
}{
\spadpaste{name mainKernel(sin cos (tan x + sin x))}
}
Axiom knows about functions such as \axiomFun{sin}, \axiomFun{cos}
and so on and can make kernels and then expressions using them.
To create a kernel and expression using an arbitrary operator, use
\axiomFunFrom{operator}{BasicOperator}.
\xtc{
Now \spad{f} can be used to create symbolic function applications.
}{
\spadpaste{f := operator 'f \bound{f}}
}
\xtc{
}{
\spadpaste{e := f(x, y, 10) \free{f}\bound{e}}
}
\xtc{
Use the \axiomFunFrom{is?}{Kernel} operation to learn if the
operator component of a kernel is equal to a given operator.
}{
\spadpaste{is?(e, f) \free{f e}}
}
\xtc{
You can also use a symbol or a string as the second
argument to \axiomFunFrom{is?}{Kernel}.
}{
\spadpaste{is?(e, 'f) \free{e}}
}
\xtc{
Use the \axiomFunFrom{argument}{Kernel} operation to get a list containing
the argument component of a kernel.
}{
\spadpaste{argument mainKernel e \free{f}\free{e}}
}

Conceptually, an object of type \axiomType{Expression} can be thought
of a quotient of multivariate polynomials, where the ``variables''
are kernels.
The arguments of the kernels are again expressions and so the
structure recurses.
See 
\downlink{`Expression'}{ExpressionXmpPage}\ignore{Expression} 
for examples of using kernels to
take apart expression objects.
\endscroll
\autobuttons
\end{page}

\begin{patch}{KernelXmpPagePatch1}
\begin{paste}{KernelXmpPageFull1}{KernelXmpPageEmpty1}
\pastebutton{KernelXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{x :: Expression Integer}
\indentrel{3}\begin{verbatim}
   (1)  x
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KernelXmpPageEmpty1}
\begin{paste}{KernelXmpPageEmpty1}{KernelXmpPagePatch1}
\pastebutton{KernelXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{x :: Expression Integer}
\end{paste}\end{patch}

\begin{patch}{KernelXmpPagePatch2}
\begin{paste}{KernelXmpPageFull2}{KernelXmpPageEmpty2}
\pastebutton{KernelXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{kernel x}
\indentrel{3}\begin{verbatim}
   (2)  x
                        Type: Kernel Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KernelXmpPageEmpty2}
\begin{paste}{KernelXmpPageEmpty2}{KernelXmpPagePatch2}
\pastebutton{KernelXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{kernel x}
\end{paste}\end{patch}

\begin{patch}{KernelXmpPagePatch3}
\begin{paste}{KernelXmpPageFull3}{KernelXmpPageEmpty3}
\pastebutton{KernelXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{sin(x) + cos(x)\bound{sincos }}
\indentrel{3}\begin{verbatim}
   (3)  sin(x) + cos(x)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KernelXmpPageEmpty3}
\begin{paste}{KernelXmpPageEmpty3}{KernelXmpPagePatch3}
\pastebutton{KernelXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{sin(x) + cos(x)\bound{sincos }}
\end{paste}\end{patch}

\begin{patch}{KernelXmpPagePatch4}
\begin{paste}{KernelXmpPageFull4}{KernelXmpPageEmpty4}
\pastebutton{KernelXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{kernels \%\free{sincos }}
\indentrel{3}\begin{verbatim}
   (4)  [sin(x),cos(x)]
                   Type: List Kernel Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KernelXmpPageEmpty4}
\begin{paste}{KernelXmpPageEmpty4}{KernelXmpPagePatch4}
\pastebutton{KernelXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{kernels \%\free{sincos }}
\end{paste}\end{patch}

\begin{patch}{KernelXmpPagePatch5}
\begin{paste}{KernelXmpPageFull5}{KernelXmpPageEmpty5}
\pastebutton{KernelXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{sin(x)**2 + sin(x) + cos(x)\bound{sincos2 }}
\indentrel{3}\begin{verbatim}
              2
   (5)  sin(x)  + sin(x) + cos(x)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KernelXmpPageEmpty5}
\begin{paste}{KernelXmpPageEmpty5}{KernelXmpPagePatch5}
\pastebutton{KernelXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{sin(x)**2 + sin(x) + cos(x)\bound{sincos2 }}
\end{paste}\end{patch}

\begin{patch}{KernelXmpPagePatch6}
\begin{paste}{KernelXmpPageFull6}{KernelXmpPageEmpty6}
\pastebutton{KernelXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{kernels \%\free{sincos2 }}
\indentrel{3}\begin{verbatim}
   (6)  [sin(x),cos(x)]
                   Type: List Kernel Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KernelXmpPageEmpty6}
\begin{paste}{KernelXmpPageEmpty6}{KernelXmpPagePatch6}
\pastebutton{KernelXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{kernels \%\free{sincos2 }}
\end{paste}\end{patch}

\begin{patch}{KernelXmpPagePatch7}
\begin{paste}{KernelXmpPageFull7}{KernelXmpPageEmpty7}
\pastebutton{KernelXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{kernels(1 :: Expression Integer)}
\indentrel{3}\begin{verbatim}
   (7)  []
                   Type: List Kernel Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KernelXmpPageEmpty7}
\begin{paste}{KernelXmpPageEmpty7}{KernelXmpPagePatch7}
\pastebutton{KernelXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{kernels(1 :: Expression Integer)}
\end{paste}\end{patch}

\begin{patch}{KernelXmpPagePatch8}
\begin{paste}{KernelXmpPageFull8}{KernelXmpPageEmpty8}
\pastebutton{KernelXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{mainKernel(cos(x) + tan(x))}
\indentrel{3}\begin{verbatim}
   (8)  tan(x)
             Type: Union(Kernel Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KernelXmpPageEmpty8}
\begin{paste}{KernelXmpPageEmpty8}{KernelXmpPagePatch8}
\pastebutton{KernelXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{mainKernel(cos(x) + tan(x))}
\end{paste}\end{patch}

\begin{patch}{KernelXmpPagePatch9}
\begin{paste}{KernelXmpPageFull9}{KernelXmpPageEmpty9}
\pastebutton{KernelXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{height kernel x}
\indentrel{3}\begin{verbatim}
   (9)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KernelXmpPageEmpty9}
\begin{paste}{KernelXmpPageEmpty9}{KernelXmpPagePatch9}
\pastebutton{KernelXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{height kernel x}
\end{paste}\end{patch}

\begin{patch}{KernelXmpPagePatch10}
\begin{paste}{KernelXmpPageFull10}{KernelXmpPageEmpty10}
\pastebutton{KernelXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{height mainKernel(sin x)}
\indentrel{3}\begin{verbatim}
   (10)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KernelXmpPageEmpty10}
\begin{paste}{KernelXmpPageEmpty10}{KernelXmpPagePatch10}
\pastebutton{KernelXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{height mainKernel(sin x)}
\end{paste}\end{patch}

\begin{patch}{KernelXmpPagePatch11}
\begin{paste}{KernelXmpPageFull11}{KernelXmpPageEmpty11}
\pastebutton{KernelXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{height mainKernel(sin cos x)}
\indentrel{3}\begin{verbatim}
   (11)  3
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KernelXmpPageEmpty11}
\begin{paste}{KernelXmpPageEmpty11}{KernelXmpPagePatch11}
\pastebutton{KernelXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{height mainKernel(sin cos x)}
\end{paste}\end{patch}

\begin{patch}{KernelXmpPagePatch12}
\begin{paste}{KernelXmpPageFull12}{KernelXmpPageEmpty12}
\pastebutton{KernelXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{height mainKernel(sin cos (tan x + sin x))}
\indentrel{3}\begin{verbatim}
   (12)  4
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KernelXmpPageEmpty12}
\begin{paste}{KernelXmpPageEmpty12}{KernelXmpPagePatch12}
\pastebutton{KernelXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{height mainKernel(sin cos (tan x + sin x))}
\end{paste}\end{patch}

\begin{patch}{KernelXmpPagePatch13}
\begin{paste}{KernelXmpPageFull13}{KernelXmpPageEmpty13}
\pastebutton{KernelXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{operator mainKernel(sin cos (tan x + sin x))}
\indentrel{3}\begin{verbatim}
   (13)  sin
                                    Type: BasicOperator
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KernelXmpPageEmpty13}
\begin{paste}{KernelXmpPageEmpty13}{KernelXmpPagePatch13}
\pastebutton{KernelXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{operator mainKernel(sin cos (tan x + sin x))}
\end{paste}\end{patch}

\begin{patch}{KernelXmpPagePatch14}
\begin{paste}{KernelXmpPageFull14}{KernelXmpPageEmpty14}
\pastebutton{KernelXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{name mainKernel(sin cos (tan x + sin x))}
\indentrel{3}\begin{verbatim}
   (14)  sin
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KernelXmpPageEmpty14}
\begin{paste}{KernelXmpPageEmpty14}{KernelXmpPagePatch14}
\pastebutton{KernelXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{name mainKernel(sin cos (tan x + sin x))}
\end{paste}\end{patch}

\begin{patch}{KernelXmpPagePatch15}
\begin{paste}{KernelXmpPageFull15}{KernelXmpPageEmpty15}
\pastebutton{KernelXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{f := operator 'f\bound{f }}
\indentrel{3}\begin{verbatim}
   (15)  f
                                    Type: BasicOperator
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KernelXmpPageEmpty15}
\begin{paste}{KernelXmpPageEmpty15}{KernelXmpPagePatch15}
\pastebutton{KernelXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{f := operator 'f\bound{f }}
\end{paste}\end{patch}

\begin{patch}{KernelXmpPagePatch16}
\begin{paste}{KernelXmpPageFull16}{KernelXmpPageEmpty16}
\pastebutton{KernelXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{e := f(x, y, 10)\free{f }\bound{e }}
\indentrel{3}\begin{verbatim}
   (16)  f(x,y,10)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KernelXmpPageEmpty16}
\begin{paste}{KernelXmpPageEmpty16}{KernelXmpPagePatch16}
\pastebutton{KernelXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{e := f(x, y, 10)\free{f }\bound{e }}
\end{paste}\end{patch}

\begin{patch}{KernelXmpPagePatch17}
\begin{paste}{KernelXmpPageFull17}{KernelXmpPageEmpty17}
\pastebutton{KernelXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{is?(e, f)\free{f e }}
\indentrel{3}\begin{verbatim}
   (17)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KernelXmpPageEmpty17}
\begin{paste}{KernelXmpPageEmpty17}{KernelXmpPagePatch17}
\pastebutton{KernelXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{is?(e, f)\free{f e }}
\end{paste}\end{patch}

\begin{patch}{KernelXmpPagePatch18}
\begin{paste}{KernelXmpPageFull18}{KernelXmpPageEmpty18}
\pastebutton{KernelXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{is?(e, 'f)\free{e }}
\indentrel{3}\begin{verbatim}
   (18)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KernelXmpPageEmpty18}
\begin{paste}{KernelXmpPageEmpty18}{KernelXmpPagePatch18}
\pastebutton{KernelXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{is?(e, 'f)\free{e }}
\end{paste}\end{patch}

\begin{patch}{KernelXmpPagePatch19}
\begin{paste}{KernelXmpPageFull19}{KernelXmpPageEmpty19}
\pastebutton{KernelXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{argument mainKernel e\free{f }\free{e }}
\indentrel{3}\begin{verbatim}
   (19)  [x,y,10]
                          Type: List Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{KernelXmpPageEmpty19}
\begin{paste}{KernelXmpPageEmpty19}{KernelXmpPagePatch19}
\pastebutton{KernelXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{argument mainKernel e\free{f }\free{e }}
\end{paste}\end{patch}

\end{chunk}
\section{lazm3pk.ht}
\pagetitle{LazardSetSolvingPackageXmpPage}{lazm3pk.ht}
{LazardSetSolvingPackage}
\begin{chunk}{lazm3pk.ht}
\begin{page}{LazardSetSolvingPackageXmpPage}{LazardSetSolvingPackage}
\beginscroll
The \spadtype{LazardSetSolvingPackage} package constructor solves
polynomial systems by means of Lazard triangular sets.  However one
condition is relaxed: Regular triangular sets whose saturated ideals
have positive dimension are not necessarily normalized.

The decompositions are computed in two steps.  First the algorithm of
Moreno Maza (implemented in the \spadtype{RegularTriangularSet} domain
constructor) is called.  Then the resulting decompositions are
converted into lists of square-free regular triangular sets and the
redundant components are removed.  Moreover, zero-dimensional regular
triangular sets are normalized.

Note that the way of understanding triangular decompositions 
is detailed in the example of the \spadtype{RegularTriangularSet}
constructor.

The \spadtype{LazardSetSolvingPackage} constructor takes six arguments.
The first one, {\bf R}, is the coefficient ring of the polynomials;
it must belong to the category \spadtype{GcdDomain}.
The second one, {\bf E}, is the exponent monoid of the polynomials;
it must belong to the category \spadtype{OrderedAbelianMonoidSup}.
the third one, {\bf V}, is the ordered set of variables;
it must belong to the category \spadtype{OrderedSet}.
The fourth one is the polynomial ring;
it must belong to the category 
\spadtype{RecursivePolynomialCategory(R,E,V)}.
The fifth one is a domain of the category 
\spadtype{RegularTriangularSetCategory(R,E,V,P)}
and the last one is a domain of the category 
\spadtype{SquareFreeRegularTriangularSetCategory(R,E,V,P)}.
The abbreviation for \spadtype{LazardSetSolvingPackage} is 
\spad{LAZM3PK}.

{\bf N.B.} For the purpose of solving zero-dimensional algebraic 
systems, see also \spadtype{LexTriangularPackage} and 
\spadtype{ZeroDimensionalSolvePackage}.
These packages are easier to call than \spad{LAZM3PK}.
Moreover, the \spadtype{ZeroDimensionalSolvePackage} 
package  provides operations
to compute either the complex roots or the real roots.

We illustrate now the use of the \spadtype{LazardSetSolvingPackage} 
package constructor with two examples (Butcher and Vermeer).


\xtc{
Define the coefficient ring.
}{
\spadpaste{R := Integer \bound{R}}
}


\xtc{
Define the list of variables,
}{
\spadpaste{ls : List Symbol := [b1,x,y,z,t,v,u,w] \bound{ls}}
} 

\xtc{
and make it an ordered set;
}{
\spadpaste{V := OVAR(ls) \free{ls} \bound{V}}
}

\xtc{
then define the exponent monoid.
}{
\spadpaste{E := IndexedExponents V \free{V} \bound{E}}
}

\xtc{
Define the polynomial ring.
}{
\spadpaste{P := NSMP(R, V) \free{R} \free{V} \bound{P}}
}

\xtc{
Let the variables be polynomial.
}{
\spadpaste{b1: P := 'b1  \free{P} \bound{b1}}
}
\xtc{
}{
\spadpaste{x: P := 'x \free{P} \bound{x}}
}
\xtc{
}{
\spadpaste{y: P := 'y \free{P} \bound{y}}
}
\xtc{
}{
\spadpaste{z: P := 'z \free{P} \bound{z}}
}
\xtc{
}{
\spadpaste{t: P := 't \free{P} \bound{t}}
}
\xtc{
}{
\spadpaste{u: P := 'u  \free{P} \bound{u}}
}
\xtc{
}{
\spadpaste{v: P := 'v  \free{P} \bound{v}}
}
\xtc{
}{
\spadpaste{w: P := 'w  \free{P} \bound{w}}
}

\xtc{
Now call the \spadtype{RegularTriangularSet} domain constructor.
}{
\spadpaste{T := REGSET(R,E,V,P) \free{R} \free{E} \free{V} 
\free{P} \bound{T} }
}

\xtc{
Define a polynomial system (the Butcher example).
}{
\spadpaste{p0 := b1 + y + z - t - w \free{b1} \free{x} \free{y} 
\free{z} \free{t} \free{u} \free{v} \free{w} \bound{p0}}
}
\xtc{
}{
\spadpaste{p1 := 2*z*u + 2*y*v + 2*t*w - 2*w**2 - w - 1 \free{b1} 
\free{x} \free{y} \free{z} \free{t} \free{u} \free{v} \free{w} \bound{p1}}
}
\xtc{
}{
\spadpaste{p2 := 3*z*u**2 + 3*y*v**2 - 3*t*w**2 + 3*w**3 + 
3*w**2 - t + 4*w \free{b1} \free{x} \free{y} \free{z} \free{t} 
\free{u} \free{v} \free{w} \bound{p2}}
}
\xtc{
}{
\spadpaste{p3 := 6*x*z*v - 6*t*w**2 + 6*w**3 - 3*t*w + 
6*w**2 - t + 4*w \free{b1} \free{x} \free{y} \free{z} 
\free{t} \free{u} \free{v} \free{w} \bound{p3}}
}
\xtc{
}{
\spadpaste{p4 := 4*z*u**3+ 4*y*v**3+ 4*t*w**3- 4*w**4 - 
6*w**3+ 4*t*w- 10*w**2- w- 1 \free{b1} \free{x} \free{y} 
\free{z} \free{t} \free{u} \free{v} \free{w} \bound{p4}}
}
\xtc{
}{
\spadpaste{p5 := 8*x*z*u*v +8*t*w**3 -8*w**4 +4*t*w**2 -
12*w**3 +4*t*w -14*w**2 -3*w -1  \free{b1} \free{x} \free{y} 
\free{z} \free{t} \free{u} \free{v} \free{w} \bound{p5}}
}
\xtc{
}{
\spadpaste{p6 := 12*x*z*v**2+12*t*w**3 -12*w**4 +12*t*w**2 -
18*w**3 +8*t*w -14*w**2 -w -1 \free{b1} \free{x} \free{y} 
\free{z} \free{t} \free{u} \free{v} \free{w} \bound{p6}}
}
\xtc{
}{
\spadpaste{p7 := -24*t*w**3 + 24*w**4 - 24*t*w**2 + 36*w**3 - 
8*t*w + 26*w**2 + 7*w + 1 \free{b1} \free{x} \free{y} \free{z} 
\free{t} \free{u} \free{v} \free{w} \bound{p7}}
}
\xtc{
}{
\spadpaste{lp := [p0, p1, p2, p3, p4, p5, p6, p7] \free{p0} 
\free{p1} \free{p2} \free{p3} \free{p4} \free{p5} \free{p6} 
\free{p7} \bound{lp}}
}

\xtc{
First of all, let us solve this system in the sense of Lazard 
by means of the \spadtype{REGSET} constructor:
}{
\spadpaste{lts := zeroSetSplit(lp,false)$T\free{lp}\free{T}\bound{lts}}
}

\xtc{
We can get the dimensions of each component
of a decomposition as follows.
}{
\spadpaste{[coHeight(ts) for ts in lts] \free{lts}}
}

The first five sets have a simple shape.
However, the last one, which has dimension zero, can be simplified
by using Lazard triangular sets.

\xtc{
Thus we call the \spadtype{SquareFreeRegularTriangularSet} domain 
constructor,
}{
\spadpaste{ST := SREGSET(R,E,V,P) \free{R} \free{E} \free{V} 
\free{P} \bound{ST} }
}

\xtc{
and set the \spadtype{LAZM3PK} package constructor to our situation.
}{
\spadpaste{pack := LAZM3PK(R,E,V,P,T,ST) \free{R} \free{E} 
\free{V} \free{P} \free{T} \free{ST} \bound{pack} }
}

\xtc{
We are ready to solve the system by means of Lazard triangular sets:
}{
\spadpaste{zeroSetSplit(lp,false)$pack \free{lp} \free{pack}}
}

We see the sixth triangular set is {\em nicer} now: 
each one of its polynomials has a constant initial.

We follow with the Vermeer example. The ordering is the usual one
for this system.

\xtc{
Define the polynomial system.
}{
\spadpaste{f0 := (w - v) ** 2 + (u - t) ** 2 - 1 \free{b1} \free{x} 
\free{y} \free{z} \free{t} \free{u} \free{v} \free{w} \bound{f0}}
}
\xtc{
}{
\spadpaste{f1 := t ** 2 - v ** 3 \free{b1} \free{x} \free{y} \free{z} 
\free{t} \free{u} \free{v} \free{w} \bound{f1}}
}
\xtc{
}{
\spadpaste{f2 := 2 * t * (w - v) + 3 * v ** 2 * (u - t) \free{b1} 
\free{x} \free{y} \free{z} \free{t} \free{u} \free{v} \free{w} 
\bound{f2}}
}
\xtc{
}{
\spadpaste{f3 := (3 * z * v ** 2 - 1) * (2 * z * t - 1) \free{b1} 
\free{x} \free{y} \free{z} \free{t} \free{u} \free{v} \free{w} 
\bound{f3}}
}
\xtc{
}{
\spadpaste{lf := [f0, f1, f2, f3] \free{f0} \free{f1} \free{f2} 
\free{f3} \bound{lf}}
}


\xtc{
First of all, let us solve this system in the sense of Kalkbrener by 
means of the \spadtype{REGSET}
constructor:
}{
\spadpaste{zeroSetSplit(lf,true)$T \free{lf} \free{T}}
}

We have obtained one regular chain (i.e. regular triangular set) with
dimension 1.  This set is in fact a characterist set of the (radical
of) of the ideal generated by the input system {\bf lf}.  Thus we have
only the {\em generic points} of the variety associated with {\bf lf}
(for the elimination ordering given by {\bf ls}).

So let us get now a full description of this variety.
\xtc{
Hence, we solve this system in the sense of Lazard by means of the 
\spadtype{REGSET}
constructor:
}{
\spadpaste{zeroSetSplit(lf,false)$T \free{lf} \free{T}}
}

We retrieve our regular chain of dimension 1 and we get three regular
chains of dimension 0 corresponding to the {\em degenerated cases}.
We want now to simplify these zero-dimensional regular chains by using
Lazard triangular sets.  Moreover, this will allow us to prove that
the above decomposition has no redundant component.  {\bf N.B.}
Generally, decompositions computed by the \spadtype{REGSET}
constructor do not have redundant components.  However, to be sure
that no redundant component occurs one needs to use the
\spadtype{SREGSET} or \spadtype{LAZM3PK} constructors.

\xtc{
So let us solve the input system  in the sense of Lazard by means of 
the \spadtype{LAZM3PK} constructor:
}{
\spadpaste{zeroSetSplit(lf,false)$pack \free{lf} \free{pack}}
}

Due to square-free factorization, we obtained now four
zero-dimensional regular chains.  Moreover, each of them is normalized
(the initials are constant).  Note that these zero-dimensional
components may be investigated further with the
\spadtype{ZeroDimensionalSolvePackage} package constructor.

\endscroll
\autobuttons
\end{page}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch1}
\begin{paste}{LazardSetSolvingPackageXmpPageFull1}{LazardSetSolvingPackageXmpPageEmpty1}
\pastebutton{LazardSetSolvingPackageXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{R := Integer\bound{R }}
\indentrel{3}\begin{verbatim}
   (1)  Integer
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty1}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty1}{LazardSetSolvingPackageXmpPagePatch1}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{R := Integer\bound{R }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch2}
\begin{paste}{LazardSetSolvingPackageXmpPageFull2}{LazardSetSolvingPackageXmpPageEmpty2}
\pastebutton{LazardSetSolvingPackageXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{ls : List Symbol := [b1,x,y,z,t,v,u,w]\bound{ls }}
\indentrel{3}\begin{verbatim}
   (2)  [b1,x,y,z,t,v,u,w]
                                      Type: List Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty2}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty2}{LazardSetSolvingPackageXmpPagePatch2}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{ls : List Symbol := [b1,x,y,z,t,v,u,w]\bound{ls }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch3}
\begin{paste}{LazardSetSolvingPackageXmpPageFull3}{LazardSetSolvingPackageXmpPageEmpty3}
\pastebutton{LazardSetSolvingPackageXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{V := OVAR(ls)\free{ls }\bound{V }}
\indentrel{3}\begin{verbatim}
   (3)  OrderedVariableList [b1,x,y,z,t,v,u,w]
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty3}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty3}{LazardSetSolvingPackageXmpPagePatch3}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{V := OVAR(ls)\free{ls }\bound{V }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch4}
\begin{paste}{LazardSetSolvingPackageXmpPageFull4}{LazardSetSolvingPackageXmpPageEmpty4}
\pastebutton{LazardSetSolvingPackageXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{E := IndexedExponents V\free{V }\bound{E }}
\indentrel{3}\begin{verbatim}
   (4)
   IndexedExponents OrderedVariableList [b1,x,y,z,t,v,u,w]
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty4}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty4}{LazardSetSolvingPackageXmpPagePatch4}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{E := IndexedExponents V\free{V }\bound{E }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch5}
\begin{paste}{LazardSetSolvingPackageXmpPageFull5}{LazardSetSolvingPackageXmpPageEmpty5}
\pastebutton{LazardSetSolvingPackageXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{P := NSMP(R, V)\free{R }\free{V }\bound{P }}
\indentrel{3}\begin{verbatim}
   (5)
  NewSparseMultivariatePolynomial(Integer,OrderedVariable
  List [b1,x,y,z,t,v,u,w])
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty5}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty5}{LazardSetSolvingPackageXmpPagePatch5}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{P := NSMP(R, V)\free{R }\free{V }\bound{P }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch6}
\begin{paste}{LazardSetSolvingPackageXmpPageFull6}{LazardSetSolvingPackageXmpPageEmpty6}
\pastebutton{LazardSetSolvingPackageXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{b1: P := 'b1\free{P }\bound{b1 }}
\indentrel{3}\begin{verbatim}
   (6)  b1
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty6}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty6}{LazardSetSolvingPackageXmpPagePatch6}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{b1: P := 'b1\free{P }\bound{b1 }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch7}
\begin{paste}{LazardSetSolvingPackageXmpPageFull7}{LazardSetSolvingPackageXmpPageEmpty7}
\pastebutton{LazardSetSolvingPackageXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{x: P := 'x\free{P }\bound{x }}
\indentrel{3}\begin{verbatim}
   (7)  x
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty7}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty7}{LazardSetSolvingPackageXmpPagePatch7}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{x: P := 'x\free{P }\bound{x }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch8}
\begin{paste}{LazardSetSolvingPackageXmpPageFull8}{LazardSetSolvingPackageXmpPageEmpty8}
\pastebutton{LazardSetSolvingPackageXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{y: P := 'y\free{P }\bound{y }}
\indentrel{3}\begin{verbatim}
   (8)  y
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty8}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty8}{LazardSetSolvingPackageXmpPagePatch8}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{y: P := 'y\free{P }\bound{y }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch9}
\begin{paste}{LazardSetSolvingPackageXmpPageFull9}{LazardSetSolvingPackageXmpPageEmpty9}
\pastebutton{LazardSetSolvingPackageXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{z: P := 'z\free{P }\bound{z }}
\indentrel{3}\begin{verbatim}
   (9)  z
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty9}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty9}{LazardSetSolvingPackageXmpPagePatch9}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{z: P := 'z\free{P }\bound{z }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch10}
\begin{paste}{LazardSetSolvingPackageXmpPageFull10}{LazardSetSolvingPackageXmpPageEmpty10}
\pastebutton{LazardSetSolvingPackageXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{t: P := 't\free{P }\bound{t }}
\indentrel{3}\begin{verbatim}
   (10)  t
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty10}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty10}{LazardSetSolvingPackageXmpPagePatch10}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{t: P := 't\free{P }\bound{t }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch11}
\begin{paste}{LazardSetSolvingPackageXmpPageFull11}{LazardSetSolvingPackageXmpPageEmpty11}
\pastebutton{LazardSetSolvingPackageXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{u: P := 'u\free{P }\bound{u }}
\indentrel{3}\begin{verbatim}
   (11)  u
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty11}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty11}{LazardSetSolvingPackageXmpPagePatch11}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{u: P := 'u\free{P }\bound{u }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch12}
\begin{paste}{LazardSetSolvingPackageXmpPageFull12}{LazardSetSolvingPackageXmpPageEmpty12}
\pastebutton{LazardSetSolvingPackageXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{v: P := 'v\free{P }\bound{v }}
\indentrel{3}\begin{verbatim}
   (12)  v
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty12}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty12}{LazardSetSolvingPackageXmpPagePatch12}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{v: P := 'v\free{P }\bound{v }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch13}
\begin{paste}{LazardSetSolvingPackageXmpPageFull13}{LazardSetSolvingPackageXmpPageEmpty13}
\pastebutton{LazardSetSolvingPackageXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{w: P := 'w\free{P }\bound{w }}
\indentrel{3}\begin{verbatim}
   (13)  w
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty13}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty13}{LazardSetSolvingPackageXmpPagePatch13}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{w: P := 'w\free{P }\bound{w }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch14}
\begin{paste}{LazardSetSolvingPackageXmpPageFull14}{LazardSetSolvingPackageXmpPageEmpty14}
\pastebutton{LazardSetSolvingPackageXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{T := REGSET(R,E,V,P)\free{R }\free{E }\free{V }\free{P }\bound{T }}
\indentrel{3}\begin{verbatim}
   (14)
  RegularTriangularSet(Integer,IndexedExponents OrderedVa
  riableList [b1,x,y,z,t,v,u,w],OrderedVariableList [b1,x
  ,y,z,t,v,u,w],NewSparseMultivariatePolynomial(Integer,O
  rderedVariableList [b1,x,y,z,t,v,u,w]))
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty14}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty14}{LazardSetSolvingPackageXmpPagePatch14}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{T := REGSET(R,E,V,P)\free{R }\free{E }\free{V }\free{P }\bound{T }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch15}
\begin{paste}{LazardSetSolvingPackageXmpPageFull15}{LazardSetSolvingPackageXmpPageEmpty15}
\pastebutton{LazardSetSolvingPackageXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{p0 := b1 + y + z - t - w\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{p0 }}
\indentrel{3}\begin{verbatim}
   (15)  b1 + y + z - t - w
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty15}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty15}{LazardSetSolvingPackageXmpPagePatch15}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{p0 := b1 + y + z - t - w\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{p0 }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch16}
\begin{paste}{LazardSetSolvingPackageXmpPageFull16}{LazardSetSolvingPackageXmpPageEmpty16}
\pastebutton{LazardSetSolvingPackageXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{p1 := 2*z*u + 2*y*v + 2*t*w - 2*w**2 - w - 1\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{p1 }}
\indentrel{3}\begin{verbatim}
                                2
   (16)  2v y + 2u z + 2w t - 2w  - w - 1
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty16}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty16}{LazardSetSolvingPackageXmpPagePatch16}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{p1 := 2*z*u + 2*y*v + 2*t*w - 2*w**2 - w - 1\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{p1 }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch17}
\begin{paste}{LazardSetSolvingPackageXmpPageFull17}{LazardSetSolvingPackageXmpPageEmpty17}
\pastebutton{LazardSetSolvingPackageXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{p2 := 3*z*u**2 + 3*y*v**2 - 3*t*w**2 + 3*w**3 + 3*w**2 - t + 4*w\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{p2 }}
\indentrel{3}\begin{verbatim}
           2      2         2           3     2
   (17)  3v y + 3u z + (- 3w  - 1)t + 3w  + 3w  + 4w
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty17}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty17}{LazardSetSolvingPackageXmpPagePatch17}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{p2 := 3*z*u**2 + 3*y*v**2 - 3*t*w**2 + 3*w**3 + 3*w**2 - t + 4*w\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{p2 }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch18}
\begin{paste}{LazardSetSolvingPackageXmpPageFull18}{LazardSetSolvingPackageXmpPageEmpty18}
\pastebutton{LazardSetSolvingPackageXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{p3 := 6*x*z*v - 6*t*w**2 + 6*w**3 - 3*t*w + 6*w**2 - t + 4*w\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{p3 }}
\indentrel{3}\begin{verbatim}
                       2                3     2
   (18)  6v z x + (- 6w  - 3w - 1)t + 6w  + 6w  + 4w
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty18}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty18}{LazardSetSolvingPackageXmpPagePatch18}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{p3 := 6*x*z*v - 6*t*w**2 + 6*w**3 - 3*t*w + 6*w**2 - t + 4*w\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{p3 }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch19}
\begin{paste}{LazardSetSolvingPackageXmpPageFull19}{LazardSetSolvingPackageXmpPageEmpty19}
\pastebutton{LazardSetSolvingPackageXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{p4 := 4*z*u**3+ 4*y*v**3+ 4*t*w**3- 4*w**4 - 6*w**3+ 4*t*w- 10*w**2- w- 1\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{p4 }}
\indentrel{3}\begin{verbatim}
   (19)
     3      3       3            4     3      2
   4v y + 4u z + (4w  + 4w)t - 4w  - 6w  - 10w  - w - 1
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty19}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty19}{LazardSetSolvingPackageXmpPagePatch19}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{p4 := 4*z*u**3+ 4*y*v**3+ 4*t*w**3- 4*w**4 - 6*w**3+ 4*t*w- 10*w**2- w- 1\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{p4 }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch20}
\begin{paste}{LazardSetSolvingPackageXmpPageFull20}{LazardSetSolvingPackageXmpPageEmpty20}
\pastebutton{LazardSetSolvingPackageXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{p5 := 8*x*z*u*v +8*t*w**3 -8*w**4 +4*t*w**2 -12*w**3 +4*t*w -14*w**2 -3*w -1\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{p5 }}
\indentrel{3}\begin{verbatim}
   (20)
                   3     2            4      3      2
     8u v z x + (8w  + 4w  + 4w)t - 8w  - 12w  - 14w  - 3w
   + 
     - 1
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty20}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty20}{LazardSetSolvingPackageXmpPagePatch20}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{p5 := 8*x*z*u*v +8*t*w**3 -8*w**4 +4*t*w**2 -12*w**3 +4*t*w -14*w**2 -3*w -1\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{p5 }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch21}
\begin{paste}{LazardSetSolvingPackageXmpPageFull21}{LazardSetSolvingPackageXmpPageEmpty21}
\pastebutton{LazardSetSolvingPackageXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{p6 := 12*x*z*v**2+12*t*w**3 -12*w**4 +12*t*w**2 -18*w**3 +8*t*w -14*w**2 -w -1\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{p6 }}
\indentrel{3}\begin{verbatim}
   (21)
        2          3      2             4      3      2
     12v z x + (12w  + 12w  + 8w)t - 12w  - 18w  - 14w
   + 
     - w - 1
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty21}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty21}{LazardSetSolvingPackageXmpPagePatch21}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{p6 := 12*x*z*v**2+12*t*w**3 -12*w**4 +12*t*w**2 -18*w**3 +8*t*w -14*w**2 -w -1\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{p6 }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch22}
\begin{paste}{LazardSetSolvingPackageXmpPageFull22}{LazardSetSolvingPackageXmpPageEmpty22}
\pastebutton{LazardSetSolvingPackageXmpPageFull22}{\hidepaste}
\tab{5}\spadcommand{p7 := -24*t*w**3 + 24*w**4 - 24*t*w**2 + 36*w**3 - 8*t*w + 26*w**2 + 7*w + 1\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{p7 }}
\indentrel{3}\begin{verbatim}
   (22)
         3      2             4      3      2
   (- 24w  - 24w  - 8w)t + 24w  + 36w  + 26w  + 7w + 1
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty22}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty22}{LazardSetSolvingPackageXmpPagePatch22}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty22}{\showpaste}
\tab{5}\spadcommand{p7 := -24*t*w**3 + 24*w**4 - 24*t*w**2 + 36*w**3 - 8*t*w + 26*w**2 + 7*w + 1\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{p7 }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch23}
\begin{paste}{LazardSetSolvingPackageXmpPageFull23}{LazardSetSolvingPackageXmpPageEmpty23}
\pastebutton{LazardSetSolvingPackageXmpPageFull23}{\hidepaste}
\tab{5}\spadcommand{lp := [p0, p1, p2, p3, p4, p5, p6, p7]\free{p0 }\free{p1 }\free{p2 }\free{p3 }\free{p4 }\free{p5 }\free{p6 }\free{p7 }\bound{lp }}
\indentrel{3}\begin{verbatim}
   (23)
                                               2
   [b1 + y + z - t - w, 2v y + 2u z + 2w t - 2w  - w - 1,
      2      2         2           3     2
    3v y + 3u z + (- 3w  - 1)t + 3w  + 3w  + 4w,
                  2                3     2
    6v z x + (- 6w  - 3w - 1)t + 6w  + 6w  + 4w,
      3      3       3            4     3      2
    4v y + 4u z + (4w  + 4w)t - 4w  - 6w  - 10w  - w - 1,

                     3     2            4      3      2
       8u v z x + (8w  + 4w  + 4w)t - 8w  - 12w  - 14w
     + 
       - 3w - 1
     ,

          2          3      2             4      3      2
       12v z x + (12w  + 12w  + 8w)t - 12w  - 18w  - 14w
     + 
       - w - 1
     ,
          3      2             4      3      2
    (- 24w  - 24w  - 8w)t + 24w  + 36w  + 26w  + 7w + 1]
Type: List NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty23}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty23}{LazardSetSolvingPackageXmpPagePatch23}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty23}{\showpaste}
\tab{5}\spadcommand{lp := [p0, p1, p2, p3, p4, p5, p6, p7]\free{p0 }\free{p1 }\free{p2 }\free{p3 }\free{p4 }\free{p5 }\free{p6 }\free{p7 }\bound{lp }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch24}
\begin{paste}{LazardSetSolvingPackageXmpPageFull24}{LazardSetSolvingPackageXmpPageEmpty24}
\pastebutton{LazardSetSolvingPackageXmpPageFull24}{\hidepaste}
\tab{5}\spadcommand{lts := zeroSetSplit(lp,false)$T\free{lp }\free{T }\bound{lts }}
\indentrel{3}\begin{verbatim}
   (24)
   [{w + 1,u,v,t + 1,b1 + y + z + 2},
    {w + 1,v,t + 1,z,b1 + y + 2},
    {w + 1,t + 1,z,y,b1 + 2},
    {w + 1,v - u,t + 1,y + z,x,b1 + 2},
    {w + 1,u,t + 1,y,x,b1 + z + 2},

          5       4      3     2
     {144w  + 216w  + 96w  + 6w  - 11w - 1,
          2                 5       4      3     2
      (12w  + 9w + 1)u - 72w  - 108w  - 42w  - 9w  - 3w,
          2                 4      3      2
      (12w  + 9w + 1)v + 36w  + 54w  + 18w ,
          3      2             4      3      2
      (24w  + 24w  + 8w)t - 24w  - 36w  - 26w  - 7w - 1,

                     2                 2
         (12u v - 12u )z + (12w v + 12w  + 4)t + (3w - 5)v
       + 
            4      3     2
         36w  + 42w  + 6w  - 16w
       ,
                             2
      2v y + 2u z + 2w t - 2w  - w - 1,
                    2                3     2
      6v z x + (- 6w  - 3w - 1)t + 6w  + 6w  + 4w,
      b1 + y + z - t - w}
     ]
Type: List RegularTriangularSet(Integer,IndexedExponents OrderedVariableList [b1,x,y,z,t,v,u,w],OrderedVariableList [b1,x,y,z,t,v,u,w],NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w]))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty24}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty24}{LazardSetSolvingPackageXmpPagePatch24}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty24}{\showpaste}
\tab{5}\spadcommand{lts := zeroSetSplit(lp,false)$T\free{lp }\free{T }\bound{lts }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch25}
\begin{paste}{LazardSetSolvingPackageXmpPageFull25}{LazardSetSolvingPackageXmpPageEmpty25}
\pastebutton{LazardSetSolvingPackageXmpPageFull25}{\hidepaste}
\tab{5}\spadcommand{[coHeight(ts) for ts in lts]\free{lts }}
\indentrel{3}\begin{verbatim}
   (25)  [3,3,3,2,2,0]
                          Type: List NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty25}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty25}{LazardSetSolvingPackageXmpPagePatch25}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty25}{\showpaste}
\tab{5}\spadcommand{[coHeight(ts) for ts in lts]\free{lts }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch26}
\begin{paste}{LazardSetSolvingPackageXmpPageFull26}{LazardSetSolvingPackageXmpPageEmpty26}
\pastebutton{LazardSetSolvingPackageXmpPageFull26}{\hidepaste}
\tab{5}\spadcommand{ST := SREGSET(R,E,V,P)\free{R }\free{E }\free{V }\free{P }\bound{ST }}
\indentrel{3}\begin{verbatim}
   (26)
  SquareFreeRegularTriangularSet(Integer,IndexedExponents
   OrderedVariableList [b1,x,y,z,t,v,u,w],OrderedVariable
  List [b1,x,y,z,t,v,u,w],NewSparseMultivariatePolynomial
  (Integer,OrderedVariableList [b1,x,y,z,t,v,u,w]))
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty26}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty26}{LazardSetSolvingPackageXmpPagePatch26}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty26}{\showpaste}
\tab{5}\spadcommand{ST := SREGSET(R,E,V,P)\free{R }\free{E }\free{V }\free{P }\bound{ST }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch27}
\begin{paste}{LazardSetSolvingPackageXmpPageFull27}{LazardSetSolvingPackageXmpPageEmpty27}
\pastebutton{LazardSetSolvingPackageXmpPageFull27}{\hidepaste}
\tab{5}\spadcommand{pack := LAZM3PK(R,E,V,P,T,ST)\free{R }\free{E }\free{V }\free{P }\free{T }\free{ST }\bound{pack }}
\indentrel{3}\begin{verbatim}
   (27)
  LazardSetSolvingPackage(Integer,IndexedExponents Ordere
  dVariableList [b1,x,y,z,t,v,u,w],OrderedVariableList [b
  1,x,y,z,t,v,u,w],NewSparseMultivariatePolynomial(Intege
  r,OrderedVariableList [b1,x,y,z,t,v,u,w]),RegularTriang
  ularSet(Integer,IndexedExponents OrderedVariableList [b
  1,x,y,z,t,v,u,w],OrderedVariableList [b1,x,y,z,t,v,u,w]
  ,NewSparseMultivariatePolynomial(Integer,OrderedVariabl
  eList [b1,x,y,z,t,v,u,w])),SquareFreeRegularTriangularS
  et(Integer,IndexedExponents OrderedVariableList [b1,x,y
  ,z,t,v,u,w],OrderedVariableList [b1,x,y,z,t,v,u,w],NewS
  parseMultivariatePolynomial(Integer,OrderedVariableList
   [b1,x,y,z,t,v,u,w])))
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty27}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty27}{LazardSetSolvingPackageXmpPagePatch27}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty27}{\showpaste}
\tab{5}\spadcommand{pack := LAZM3PK(R,E,V,P,T,ST)\free{R }\free{E }\free{V }\free{P }\free{T }\free{ST }\bound{pack }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch28}
\begin{paste}{LazardSetSolvingPackageXmpPageFull28}{LazardSetSolvingPackageXmpPageEmpty28}
\pastebutton{LazardSetSolvingPackageXmpPageFull28}{\hidepaste}
\tab{5}\spadcommand{zeroSetSplit(lp,false)$pack\free{lp }\free{pack }}
\indentrel{3}\begin{verbatim}
   (28)
   [{w + 1,t + 1,z,y,b1 + 2},
    {w + 1,v,t + 1,z,b1 + y + 2},
    {w + 1,u,v,t + 1,b1 + y + z + 2},
    {w + 1,v - u,t + 1,y + z,x,b1 + 2},
    {w + 1,u,t + 1,y,x,b1 + z + 2},

          5       4      3     2
     {144w  + 216w  + 96w  + 6w  - 11w - 1,
             4      3      2
      u - 24w  - 36w  - 14w  + w + 1,
              4      3      2
      3v - 48w  - 60w  - 10w  + 8w + 2,
             4      3      2
      t - 24w  - 36w  - 14w  - w + 1,
                  4        3        2
      486z - 2772w  - 4662w  - 2055w  + 30w + 127,
                    4         3        2
      2916y - 22752w  - 30312w  - 8220w  + 2064w + 1561,
                  4        3       2
      356x - 3696w  - 4536w  - 968w  + 822w + 371,
                     4         3         2
      2916b1 - 30600w  - 46692w  - 20274w  - 8076w + 593}
     ]
Type: List SquareFreeRegularTriangularSet(Integer,IndexedExponents OrderedVariableList [b1,x,y,z,t,v,u,w],OrderedVariableList [b1,x,y,z,t,v,u,w],NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w]))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty28}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty28}{LazardSetSolvingPackageXmpPagePatch28}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty28}{\showpaste}
\tab{5}\spadcommand{zeroSetSplit(lp,false)$pack\free{lp }\free{pack }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch29}
\begin{paste}{LazardSetSolvingPackageXmpPageFull29}{LazardSetSolvingPackageXmpPageEmpty29}
\pastebutton{LazardSetSolvingPackageXmpPageFull29}{\hidepaste}
\tab{5}\spadcommand{f0 := (w - v) ** 2 + (u - t) ** 2 - 1\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{f0 }}
\indentrel{3}\begin{verbatim}
          2           2           2    2
   (29)  t  - 2u t + v  - 2w v + u  + w  - 1
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty29}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty29}{LazardSetSolvingPackageXmpPagePatch29}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty29}{\showpaste}
\tab{5}\spadcommand{f0 := (w - v) ** 2 + (u - t) ** 2 - 1\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{f0 }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch30}
\begin{paste}{LazardSetSolvingPackageXmpPageFull30}{LazardSetSolvingPackageXmpPageEmpty30}
\pastebutton{LazardSetSolvingPackageXmpPageFull30}{\hidepaste}
\tab{5}\spadcommand{f1 := t ** 2 - v ** 3\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{f1 }}
\indentrel{3}\begin{verbatim}
          2    3
   (30)  t  - v
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty30}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty30}{LazardSetSolvingPackageXmpPagePatch30}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty30}{\showpaste}
\tab{5}\spadcommand{f1 := t ** 2 - v ** 3\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{f1 }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch31}
\begin{paste}{LazardSetSolvingPackageXmpPageFull31}{LazardSetSolvingPackageXmpPageEmpty31}
\pastebutton{LazardSetSolvingPackageXmpPageFull31}{\hidepaste}
\tab{5}\spadcommand{f2 := 2 * t * (w - v) + 3 * v ** 2 * (u - t)\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{f2 }}
\indentrel{3}\begin{verbatim}
              2                   2
   (31)  (- 3v  - 2v + 2w)t + 3u v
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty31}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty31}{LazardSetSolvingPackageXmpPagePatch31}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty31}{\showpaste}
\tab{5}\spadcommand{f2 := 2 * t * (w - v) + 3 * v ** 2 * (u - t)\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{f2 }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch32}
\begin{paste}{LazardSetSolvingPackageXmpPageFull32}{LazardSetSolvingPackageXmpPageEmpty32}
\pastebutton{LazardSetSolvingPackageXmpPageFull32}{\hidepaste}
\tab{5}\spadcommand{f3 := (3 * z * v ** 2 - 1) * (2 * z * t - 1)\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{f3 }}
\indentrel{3}\begin{verbatim}
           2   2             2
   (32)  6v t z  + (- 2t - 3v )z + 1
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty32}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty32}{LazardSetSolvingPackageXmpPagePatch32}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty32}{\showpaste}
\tab{5}\spadcommand{f3 := (3 * z * v ** 2 - 1) * (2 * z * t - 1)\free{b1 }\free{x }\free{y }\free{z }\free{t }\free{u }\free{v }\free{w }\bound{f3 }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch33}
\begin{paste}{LazardSetSolvingPackageXmpPageFull33}{LazardSetSolvingPackageXmpPageEmpty33}
\pastebutton{LazardSetSolvingPackageXmpPageFull33}{\hidepaste}
\tab{5}\spadcommand{lf := [f0, f1, f2, f3]\free{f0 }\free{f1 }\free{f2 }\free{f3 }\bound{lf }}
\indentrel{3}\begin{verbatim}
   (33)
     2           2           2    2       2    3
   [t  - 2u t + v  - 2w v + u  + w  - 1, t  - v ,
         2                   2
    (- 3v  - 2v + 2w)t + 3u v ,
      2   2             2
    6v t z  + (- 2t - 3v )z + 1]
Type: List NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty33}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty33}{LazardSetSolvingPackageXmpPagePatch33}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty33}{\showpaste}
\tab{5}\spadcommand{lf := [f0, f1, f2, f3]\free{f0 }\free{f1 }\free{f2 }\free{f3 }\bound{lf }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch34}
\begin{paste}{LazardSetSolvingPackageXmpPageFull34}{LazardSetSolvingPackageXmpPageEmpty34}
\pastebutton{LazardSetSolvingPackageXmpPageFull34}{\hidepaste}
\tab{5}\spadcommand{zeroSetSplit(lf,true)$T\free{lf }\free{T }}
\indentrel{3}\begin{verbatim}
   (34)
   [
     {
             6           3       2                 4
         729u  + (- 1458w  + 729w  - 4158w - 1685)u
       + 
                 6        5        4        3       2
             729w  - 1458w  - 2619w  - 4892w  - 297w
           + 
             5814w + 427
        *
            2
           u
       + 
             8       7        6        5        4        3
         729w  + 216w  - 2900w  - 2376w  + 3870w  + 4072w
       + 
                2
         - 1188w  - 1656w + 529
       ,

                  4           3       2                  2
             2187u  + (- 4374w  - 972w  - 12474w - 2868)u
           + 
                  6        5         4        3        2
             2187w  - 1944w  - 10125w  - 4800w  + 2501w
           + 
             4968w - 1587
        *
           v
       + 
               3       2  2       6        5        4
         (1944w  - 108w )u  + 972w  + 3024w  - 1080w
       + 
             3        2
         496w  + 1116w
       ,
         2                   2
      (3v  + 2v - 2w)t - 3u v ,
                        2  2           2
      ((4v - 4w)t - 6u v )z  + (2t + 3v )z - 1}
     ]
Type: List RegularTriangularSet(Integer,IndexedExponents OrderedVariableList [b1,x,y,z,t,v,u,w],OrderedVariableList [b1,x,y,z,t,v,u,w],NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w]))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty34}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty34}{LazardSetSolvingPackageXmpPagePatch34}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty34}{\showpaste}
\tab{5}\spadcommand{zeroSetSplit(lf,true)$T\free{lf }\free{T }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch35}
\begin{paste}{LazardSetSolvingPackageXmpPageFull35}{LazardSetSolvingPackageXmpPageEmpty35}
\pastebutton{LazardSetSolvingPackageXmpPageFull35}{\hidepaste}
\tab{5}\spadcommand{zeroSetSplit(lf,false)$T\free{lf }\free{T }}
\indentrel{3}\begin{verbatim}
   (35)
   [
     {
             6           3       2                 4
         729u  + (- 1458w  + 729w  - 4158w - 1685)u
       + 
                 6        5        4        3       2
             729w  - 1458w  - 2619w  - 4892w  - 297w
           + 
             5814w + 427
        *
            2
           u
       + 
             8       7        6        5        4        3
         729w  + 216w  - 2900w  - 2376w  + 3870w  + 4072w
       + 
                2
         - 1188w  - 1656w + 529
       ,

                  4           3       2                  2
             2187u  + (- 4374w  - 972w  - 12474w - 2868)u
           + 
                  6        5         4        3        2
             2187w  - 1944w  - 10125w  - 4800w  + 2501w
           + 
             4968w - 1587
        *
           v
       + 
               3       2  2       6        5        4
         (1944w  - 108w )u  + 972w  + 3024w  - 1080w
       + 
             3        2
         496w  + 1116w
       ,
         2                   2
      (3v  + 2v - 2w)t - 3u v ,
                        2  2           2
      ((4v - 4w)t - 6u v )z  + (2t + 3v )z - 1}
     ,

         4     3      2
     {27w  + 4w  - 54w  - 36w + 23, u,
                     2             2          2
      (12w + 2)v - 9w  - 2w + 9, 6t  - 2v - 3w  + 2w + 3,
      2t z - 1}
     ,

     {
               6         5         4          3         2
         59049w  + 91854w  - 45198w  + 145152w  + 63549w
       + 
         60922w + 21420
       ,

                            5                  4
             31484448266904w  - 18316865522574w
           + 
                            3                 2
             23676995746098w  + 6657857188965w
           + 
             8904703998546w + 3890631403260
        *
            2
           u
       + 
                        5                  4
         94262810316408w  - 82887296576616w
       + 
                        3                  2
         89801831438784w  + 28141734167208w
       + 
         38070359425432w + 16003865949120
       ,

              2             2
         (243w  + 36w + 85)v
       + 
             2       3      2                    3     2
       (- 81u  - 162w  + 36w  + 154w + 72)v - 72w  + 4w
       ,
         2                   2
      (3v  + 2v - 2w)t - 3u v ,
                        2  2           2
      ((4v - 4w)t - 6u v )z  + (2t + 3v )z - 1}
     ,

         4     3      2
     {27w  + 4w  - 54w  - 36w + 23, u,
                     2             2          2
      (12w + 2)v - 9w  - 2w + 9, 6t  - 2v - 3w  + 2w + 3,
        2
      3v z - 1}
     ]
Type: List RegularTriangularSet(Integer,IndexedExponents OrderedVariableList [b1,x,y,z,t,v,u,w],OrderedVariableList [b1,x,y,z,t,v,u,w],NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w]))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty35}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty35}{LazardSetSolvingPackageXmpPagePatch35}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty35}{\showpaste}
\tab{5}\spadcommand{zeroSetSplit(lf,false)$T\free{lf }\free{T }}
\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPagePatch36}
\begin{paste}{LazardSetSolvingPackageXmpPageFull36}{LazardSetSolvingPackageXmpPageEmpty36}
\pastebutton{LazardSetSolvingPackageXmpPageFull36}{\hidepaste}
\tab{5}\spadcommand{zeroSetSplit(lf,false)$pack\free{lf }\free{pack }}
\indentrel{3}\begin{verbatim}
   (36)
   [
     {
             6           3       2                 4
         729u  + (- 1458w  + 729w  - 4158w - 1685)u
       + 
                 6        5        4        3       2
             729w  - 1458w  - 2619w  - 4892w  - 297w
           + 
             5814w + 427
        *
            2
           u
       + 
             8       7        6        5        4        3
         729w  + 216w  - 2900w  - 2376w  + 3870w  + 4072w
       + 
                2
         - 1188w  - 1656w + 529
       ,

                  4           3       2                  2
             2187u  + (- 4374w  - 972w  - 12474w - 2868)u
           + 
                  6        5         4        3        2
             2187w  - 1944w  - 10125w  - 4800w  + 2501w
           + 
             4968w - 1587
        *
           v
       + 
               3       2  2       6        5        4
         (1944w  - 108w )u  + 972w  + 3024w  - 1080w
       + 
             3        2
         496w  + 1116w
       ,
         2                   2
      (3v  + 2v - 2w)t - 3u v ,
                        2  2           2
      ((4v - 4w)t - 6u v )z  + (2t + 3v )z - 1}
     ,

         2                 2
     {81w  + 18w + 28, 729u  - 1890w - 533,
         2
      81v  + (- 162w + 27)v - 72w - 112,
      11881t + (972w + 2997)u v + (- 11448w - 11536)u,

                         2
         641237934604288z
       + 
                 (78614584763904w + 26785578742272)u
               + 
                 236143618655616w + 70221988585728
            *
               v
           + 
             (358520253138432w + 101922133759488)u
           + 
             142598803536000w + 54166419595008
        *
           z
       + 
         (32655103844499w - 44224572465882)u v
       + 
         (43213900115457w - 32432039102070)u
       }
     ,

         4     3      2
     {27w  + 4w  - 54w  - 36w + 23, u,
                 3     2
      218v - 162w  + 3w  + 160w + 153,
          2      3      2
      109t  - 27w  - 54w  + 63w + 80,
                      3      2
      1744z + (- 1458w  + 27w  + 1440w + 505)t}
     ,

         4     3      2
     {27w  + 4w  - 54w  - 36w + 23, u,
                 3     2
      218v - 162w  + 3w  + 160w + 153,
          2      3      2
      109t  - 27w  - 54w  + 63w + 80,
                  3     2
      1308z + 162w  - 3w  - 814w - 153}
     ,

          4       3        2
     {729w  + 972w  - 1026w  + 1684w + 765,
         2      2
      81u  + 72w  + 16w - 72,
                 3       2
      702v - 162w  - 225w  + 40w - 99,
                    3       2
      11336t + (324w  - 603w  - 1718w - 1557)u,

                   2
         595003968z
       + 
                             3             2
                 - 963325386w  - 898607682w  + 1516286466w
               + 
                 - 3239166186
            *
               u
           + 
                          3              2
             - 1579048992w  - 1796454288w  + 2428328160w
           + 
             - 4368495024
        *
           z
       + 
                        3              2
             9713133306w  + 9678670317w  - 16726834476w
           + 
             28144233593
        *
           u
       }
     ]
Type: List SquareFreeRegularTriangularSet(Integer,IndexedExponents OrderedVariableList [b1,x,y,z,t,v,u,w],OrderedVariableList [b1,x,y,z,t,v,u,w],NewSparseMultivariatePolynomial(Integer,OrderedVariableList [b1,x,y,z,t,v,u,w]))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LazardSetSolvingPackageXmpPageEmpty36}
\begin{paste}{LazardSetSolvingPackageXmpPageEmpty36}{LazardSetSolvingPackageXmpPagePatch36}
\pastebutton{LazardSetSolvingPackageXmpPageEmpty36}{\showpaste}
\tab{5}\spadcommand{zeroSetSplit(lf,false)$pack\free{lf }\free{pack }}
\end{paste}\end{patch}

\end{chunk}
\section{lexp.ht}
\pagetitle{LieExponentialsXmpPage}{lexp.ht}{LieExponentials}
\begin{chunk}{lexp.ht}
\begin{page}{LieExponentialsXmpPage}{LieExponentials}
\beginscroll
\xtc{
}{
\spadpaste{ a: Symbol := 'a \bound{a}}
}
\xtc{
}{
\spadpaste{ b: Symbol := 'b \bound{b}}
}

Declarations of domains
\xtc{
}{
\spadpaste{ coef     := Fraction(Integer) \bound{coef}}
}
\xtc{
}{
\spadpaste{ group    := LieExponentials(Symbol, coef, 3) 
\free{coef} \bound{group}}
}
\xtc{
}{
\spadpaste{ lpoly    := LiePolynomial(Symbol, coef) 
\free{coef} \bound{lpoly}}
}
\xtc{
}{
\spadpaste{ poly     := XPBWPolynomial(Symbol, coef) 
\free{coef} \bound{poly}}
}

Calculations
\xtc{
}{
\spadpaste{ ea := exp(a::lpoly)$group \free{a} \free{lpoly} 
\free{group} \bound{ea}}
}
\xtc{
}{
\spadpaste{ eb := exp(b::lpoly)$group \free{b} \free{lpoly} 
\free{group}  \bound{eb}}
}
\xtc{
}{
\spadpaste{ g: group := ea*eb \free{ea} \free{eb} \bound{g}}
}
\xtc{
}{
\spadpaste{ g :: poly \free{g} \free{poly}}
}
\xtc{
}{
\spadpaste{ log(g)$group \free{g} \free{group}}
}
\xtc{
}{
\spadpaste{ g1: group := inv(g) \free{g} \free{group} \bound{g1}}
}
\xtc{
}{
\spadpaste{ g*g1 \free{g} \free{g1}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{LieExponentialsXmpPagePatch1}
\begin{paste}{LieExponentialsXmpPageFull1}{LieExponentialsXmpPageEmpty1}
\pastebutton{LieExponentialsXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{ a: Symbol := 'a\bound{a }}
\indentrel{3}\begin{verbatim}
   (1)  a
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPageEmpty1}
\begin{paste}{LieExponentialsXmpPageEmpty1}{LieExponentialsXmpPagePatch1}
\pastebutton{LieExponentialsXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{ a: Symbol := 'a\bound{a }}
\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPagePatch2}
\begin{paste}{LieExponentialsXmpPageFull2}{LieExponentialsXmpPageEmpty2}
\pastebutton{LieExponentialsXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{ b: Symbol := 'b\bound{b }}
\indentrel{3}\begin{verbatim}
   (2)  b
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPageEmpty2}
\begin{paste}{LieExponentialsXmpPageEmpty2}{LieExponentialsXmpPagePatch2}
\pastebutton{LieExponentialsXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{ b: Symbol := 'b\bound{b }}
\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPagePatch3}
\begin{paste}{LieExponentialsXmpPageFull3}{LieExponentialsXmpPageEmpty3}
\pastebutton{LieExponentialsXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{ coef := Fraction(Integer)\bound{coef }}
\indentrel{3}\begin{verbatim}
   (3)  Fraction Integer
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPageEmpty3}
\begin{paste}{LieExponentialsXmpPageEmpty3}{LieExponentialsXmpPagePatch3}
\pastebutton{LieExponentialsXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{ coef := Fraction(Integer)\bound{coef }}
\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPagePatch4}
\begin{paste}{LieExponentialsXmpPageFull4}{LieExponentialsXmpPageEmpty4}
\pastebutton{LieExponentialsXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{ group := LieExponentials(Symbol, coef, 3)\free{coef }\bound{group }}
\indentrel{3}\begin{verbatim}
   (4)  LieExponentials(Symbol,Fraction Integer,3)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPageEmpty4}
\begin{paste}{LieExponentialsXmpPageEmpty4}{LieExponentialsXmpPagePatch4}
\pastebutton{LieExponentialsXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{ group := LieExponentials(Symbol, coef, 3)\free{coef }\bound{group }}
\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPagePatch5}
\begin{paste}{LieExponentialsXmpPageFull5}{LieExponentialsXmpPageEmpty5}
\pastebutton{LieExponentialsXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{ lpoly := LiePolynomial(Symbol, coef)\free{coef }\bound{lpoly }}
\indentrel{3}\begin{verbatim}
   (5)  LiePolynomial(Symbol,Fraction Integer)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPageEmpty5}
\begin{paste}{LieExponentialsXmpPageEmpty5}{LieExponentialsXmpPagePatch5}
\pastebutton{LieExponentialsXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{ lpoly := LiePolynomial(Symbol, coef)\free{coef }\bound{lpoly }}
\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPagePatch6}
\begin{paste}{LieExponentialsXmpPageFull6}{LieExponentialsXmpPageEmpty6}
\pastebutton{LieExponentialsXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{ poly := XPBWPolynomial(Symbol, coef)\free{coef }\bound{poly }}
\indentrel{3}\begin{verbatim}
   (6)  XPBWPolynomial(Symbol,Fraction Integer)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPageEmpty6}
\begin{paste}{LieExponentialsXmpPageEmpty6}{LieExponentialsXmpPagePatch6}
\pastebutton{LieExponentialsXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{ poly := XPBWPolynomial(Symbol, coef)\free{coef }\bound{poly }}
\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPagePatch7}
\begin{paste}{LieExponentialsXmpPageFull7}{LieExponentialsXmpPageEmpty7}
\pastebutton{LieExponentialsXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{ ea := exp(a::lpoly)$group\free{a }\free{lpoly }\free{group }\bound{ea }}
\indentrel{3}\begin{verbatim}
         [a]
   (7)  e
       Type: LieExponentials(Symbol,Fraction Integer,3)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPageEmpty7}
\begin{paste}{LieExponentialsXmpPageEmpty7}{LieExponentialsXmpPagePatch7}
\pastebutton{LieExponentialsXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{ ea := exp(a::lpoly)$group\free{a }\free{lpoly }\free{group }\bound{ea }}
\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPagePatch8}
\begin{paste}{LieExponentialsXmpPageFull8}{LieExponentialsXmpPageEmpty8}
\pastebutton{LieExponentialsXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{ eb := exp(b::lpoly)$group\free{b }\free{lpoly }\free{group }\bound{eb }}
\indentrel{3}\begin{verbatim}
         [b]
   (8)  e
       Type: LieExponentials(Symbol,Fraction Integer,3)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPageEmpty8}
\begin{paste}{LieExponentialsXmpPageEmpty8}{LieExponentialsXmpPagePatch8}
\pastebutton{LieExponentialsXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{ eb := exp(b::lpoly)$group\free{b }\free{lpoly }\free{group }\bound{eb }}
\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPagePatch9}
\begin{paste}{LieExponentialsXmpPageFull9}{LieExponentialsXmpPageEmpty9}
\pastebutton{LieExponentialsXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{ g: group := ea*eb\free{ea }\free{eb }\bound{g }}
\indentrel{3}\begin{verbatim}
             1     2        1   2
             Ä [a b ]       Ä [a b]
         [b] 2        [a b] 2       [a]
   (9)  e   e        e     e       e
       Type: LieExponentials(Symbol,Fraction Integer,3)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPageEmpty9}
\begin{paste}{LieExponentialsXmpPageEmpty9}{LieExponentialsXmpPagePatch9}
\pastebutton{LieExponentialsXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{ g: group := ea*eb\free{ea }\free{eb }\bound{g }}
\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPagePatch10}
\begin{paste}{LieExponentialsXmpPageFull10}{LieExponentialsXmpPageEmpty10}
\pastebutton{LieExponentialsXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{ g :: poly\free{g }\free{poly }}
\indentrel{3}\begin{verbatim}
   (10)
                     1                           1
     1 + [a] + [b] + Ä [a][a] + [a b] + [b][a] + Ä [b][b]
                     2                           2
   + 
     1             1   2                1     2
     Ä [a][a][a] + Ä [a b] + [a b][a] + Ä [a b ]
     6             2                    2
   + 
     1                        1             1
     Ä [b][a][a] + [b][a b] + Ä [b][b][a] + Ä [b][b][b]
     2                        2             6
          Type: XPBWPolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPageEmpty10}
\begin{paste}{LieExponentialsXmpPageEmpty10}{LieExponentialsXmpPagePatch10}
\pastebutton{LieExponentialsXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{ g :: poly\free{g }\free{poly }}
\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPagePatch11}
\begin{paste}{LieExponentialsXmpPageFull11}{LieExponentialsXmpPageEmpty11}
\pastebutton{LieExponentialsXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{ log(g)$group\free{g }\free{group }}
\indentrel{3}\begin{verbatim}
                     1          1   2      1     2
   (11)  [a] + [b] + Ä [a b] + ÄÄ [a b] + ÄÄ [a b ]
                     2         12         12
           Type: LiePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPageEmpty11}
\begin{paste}{LieExponentialsXmpPageEmpty11}{LieExponentialsXmpPagePatch11}
\pastebutton{LieExponentialsXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{ log(g)$group\free{g }\free{group }}
\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPagePatch12}
\begin{paste}{LieExponentialsXmpPageFull12}{LieExponentialsXmpPageEmpty12}
\pastebutton{LieExponentialsXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{ g1: group := inv(g)\free{g }\free{group }\bound{g1 }}
\indentrel{3}\begin{verbatim}
          - [b] - [a]
   (12)  e     e
       Type: LieExponentials(Symbol,Fraction Integer,3)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPageEmpty12}
\begin{paste}{LieExponentialsXmpPageEmpty12}{LieExponentialsXmpPagePatch12}
\pastebutton{LieExponentialsXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{ g1: group := inv(g)\free{g }\free{group }\bound{g1 }}
\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPagePatch13}
\begin{paste}{LieExponentialsXmpPageFull13}{LieExponentialsXmpPageEmpty13}
\pastebutton{LieExponentialsXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{ g*g1\free{g }\free{g1 }}
\indentrel{3}\begin{verbatim}
   (13)  1
       Type: LieExponentials(Symbol,Fraction Integer,3)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LieExponentialsXmpPageEmpty13}
\begin{paste}{LieExponentialsXmpPageEmpty13}{LieExponentialsXmpPagePatch13}
\pastebutton{LieExponentialsXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{ g*g1\free{g }\free{g1 }}
\end{paste}\end{patch}

\end{chunk}
\section{lextripk.ht}
\pagetitle{LexTriangularPkgXmpPage}{lextripk.ht}{LexTriangularPackage}
\begin{chunk}{lextripk.ht}
\begin{page}{LexTriangularPkgXmpPage}{LexTriangularPackage}
\beginscroll
The \spadtype{LexTriangularPackage} package constructor provides 
an implementation of the {\em lexTriangular} algorithm 
(D. Lazard "Solving Zero-dimensional Algebraic Systems", 
J. of Symbol. Comput., 1992).
This algorithm decomposes a zero-dimensional variety into zero-sets of
regular triangular sets.  Thus the input system must have a finite
number of complex solutions.  Moreover, this system needs to be a
lexicographical Groebner basis.

This package takes two arguments: the coefficient-ring {\bf R} of the
polynomials, which must be a \spadtype{GcdDomain} and their set of
variables given by {\bf ls} a \spadtype{List Symbol}.  The type of the
input polynomials must be
\spadtype{NewSparseMultivariatePolynomial(R,V)} where {\bf V} is
\spadtype{OrderedVariableList(ls)}.  The abbreviation for
\spadtype{LexTriangularPackage} is \spadtype{LEXTRIPK}.  The main
operations are \axiomOpFrom{lexTriangular}{LexTriangularPackage} and
\axiomOpFrom{squareFreeLexTriangular}{LexTriangularPackage}.  The
later provide decompositions by means of square-free regular
triangular sets, built with the \spadtype{SREGSET} constructor,
whereas the former uses the \spadtype{REGSET} constructor.  Note that
these constructors also implement another algorithm for solving
algebraic systems by means of regular triangular sets; in that case no
computations of Groebner bases are needed and the input system may
have any dimension (i.e. it may have an infinite number of solutions).

The implementation of the {\em lexTriangular} algorithm provided in
the \spadtype{LexTriangularPackage} constructor differs from that
reported in "Computations of gcd over algebraic towers of simple
extensions" by M. Moreno Maza and R. Rioboo (in proceedings of
AAECC11, Paris, 1995).  Indeed, the
\axiomOpFrom{squareFreeLexTriangular}{LexTriangularPackage} operation
removes all multiplicities of the solutions (i.e. the computed
solutions are pairwise different) and the
\axiomOpFrom{lexTriangular}{LexTriangularPackage} operation may keep
some multiplicities; this latter operation runs generally faster than
the former.

The interest of the {\em lexTriangular} algorithm is due to the
following experimental remark.  For some examples, a triangular
decomposition of a zero-dimensional variety can be computed faster via
a lexicographical Groebner basis computation than by using a direct
method (like that of \spadtype{SREGSET} and \spadtype{REGSET}).  This
happens typically when the total degree of the system relies
essentially on its smallest variable (like in the {\em Katsura}
systems).  When this is not the case, the direct method may give
better timings (like in the {\em Rose} system).

Of course, the direct method can also be applied to a lexicographical
Groebner basis.  However, the {\em lexTriangular} algorithm takes
advantage of the structure of this basis and avoids many unnecessary
computations which are performed by the direct method.

For this purpose of solving algebraic systems with a finite number of
solutions, see also the \spadtype{ZeroDimensionalSolvePackage}.  It
allows to use both strategies (the lexTriangular algorithm and the
direct method) for computing either the complex or real roots of a
system.

Note that the way of understanding triangular decompositions 
is detailed in the example of the \spadtype{RegularTriangularSet}
constructor.

Since the \spadtype{LEXTRIPK} package constructor is limited to
zero-dimensional systems, it provides a
\axiomOpFrom{zeroDimensional?}{LexTriangularPackage} operation to
check whether this requirement holds.  There is also a
\axiomOpFrom{groebner}{LexTriangularPackage} operation to compute the
lexicographical Groebner basis of a set of polynomials with type
\spadtype{NewSparseMultivariatePolynomial(R,V)}.  The elimination
ordering is that given by {\bf ls} (the greatest variable being the
first element of {\bf ls}).  This basis is computed by the {\em FLGM}
algorithm (Faugere et al. "Efficient Computation of Zero-Dimensional
Groebner Bases by Change of Ordering" , J. of Symbol. Comput., 1993)
implemented in the \spadtype{LinGroebnerPackage} package constructor.
Once a lexicographical Groebner basis is computed,
then one can call the operations 
\axiomOpFrom{lexTriangular}{LexTriangularPackage}
and \axiomOpFrom{squareFreeLexTriangular}{LexTriangularPackage}.
Note that these operations admit an optional argument
to produce normalized triangular sets.
There is also a \axiomOpFrom{zeroSetSplit}{LexTriangularPackage} 
operation which does all the job from the input system;
an error is produced if this system is not zero-dimensional.

Let us illustrate the facilities of the \spadtype{LEXTRIPK} constructor
by a famous example, the {\em cyclic-6 root} system.
\xtc{
Define the coefficient ring.
}{
\spadpaste{R := Integer \bound{R}}
}
\xtc{
Define the list of variables,
}{
\spadpaste{ls : List Symbol := [a,b,c,d,e,f] \bound{ls}}
}
\xtc{
and make it an ordered set.
}{
\spadpaste{V := OVAR(ls) \free{ls} \bound{V}}
}
\xtc{
Define the polynomial ring.
}{
\spadpaste{P := NSMP(R, V) \free{R} \free{V} \bound{P}}
}
\xtc{
Define the polynomials.
}{
\spadpaste{p1: P :=  a*b*c*d*e*f - 1 \free{P} \bound{p1}}
}
\xtc{
}{
\spadpaste{p2: P := a*b*c*d*e +a*b*c*d*f +a*b*c*e*f +a*b*d*e*f +
a*c*d*e*f +b*c*d*e*f  \free{P} \bound{p2}}
}
\xtc{
}{
\spadpaste{p3: P :=  a*b*c*d + a*b*c*f + a*b*e*f + a*d*e*f + 
b*c*d*e + c*d*e*f \free{P} \bound{p3}}
}
\xtc{
}{
\spadpaste{p4: P := a*b*c + a*b*f + a*e*f + b*c*d + c*d*e + d*e*f
\free{P} \bound{p4}}
}
\xtc{
}{
\spadpaste{p5: P := a*b + a*f + b*c + c*d + d*e + e*f \free{P} 
\bound{p5}}
}
\xtc{
}{
\spadpaste{p6: P := a + b + c + d + e + f  \free{P} \bound{p6}}
}
\xtc{
}{
\spadpaste{lp := [p1, p2, p3, p4, p5, p6] \free{p1} \free{p2} 
\free{p3} \free{p4} \free{p5} \free{p6} \bound{lp}}
}
\xtc{
Now call \spadtype{LEXTRIPK} .
}{
\spadpaste{lextripack :=  LEXTRIPK(R,ls) \free{R} \free{ls} 
\bound{lextripack}}
}
\xtc{
Compute the lexicographical Groebner basis of the system.
This may take between 5 minutes and one hour, depending on your machine.
}{
\spadpaste{lg := groebner(lp)$lextripack \free{lp} 
\free{lextripack} \bound{lg}}
}
\xtc{
Apply lexTriangular to compute a decomposition into regular triangular sets.
This should not take more than 5 seconds.
}{
\spadpaste{lexTriangular(lg,false)$lextripack \free{lg} 
\free{lextripack}}
}
Note that the first set of the decomposition is normalized
(all initials are integer numbers) but not the second one
(normalized triangular sets are defined in the
description of the \spadtype{NormalizedTriangularSetCategory} 
constructor).
\xtc{
So apply now lexTriangular to produce normalized triangular sets.
}{
\spadpaste{lts := lexTriangular(lg,true)$lextripack \free{lg} 
\free{lextripack} \bound{lts}}
}
\xtc{
We check that all initials are constant.
}{
\spadpaste{[[init(p) for p in (ts :: List(P))] for ts in lts]  
\free{lts}}
}
Note that each triangular set in {\bf lts} is a lexicographical 
Groebner basis.
Recall that a point belongs to the variety 
associated with {\bf lp} if and only if
it belongs to that associated with one triangular set {\bf ts} 
in {\bf lts}.

By running the 
\axiomOpFrom{squareFreeLexTriangular}{LexTriangularPackage} operation,
we retrieve the above decomposition.
\xtc{
}{
\spadpaste{squareFreeLexTriangular(lg,true)$lextripack \free{lg} 
\free{lextripack}}
}
Thus the solutions given by {\bf lts} are pairwise different.
\xtc{
We count them as follows.
}{
\spadpaste{reduce(+,[degree(ts) for ts in lts]) \free{lts}}
}

We can investigate the triangular decomposition {\bf lts} by
using the \spadtype{ZeroDimensionalSolvePackage}.
\xtc{
This requires to add an extra variable (smaller than the others) as follows.
}{
\spadpaste{ls2 : List Symbol := concat(ls,new()$Symbol) \free{ls} 
\bound{ls2}}
}

\xtc{
Then we call the package.
}{
\spadpaste{zdpack := ZDSOLVE(R,ls,ls2) \free{R} \free{ls} 
\free{ls2} \bound{zdpack}}
}


\xtc{
We compute a univariate representation of the variety associated with
the input system as follows.
}{
\spadpaste{concat [univariateSolve(ts)$zdpack for ts in lts] 
\free{lts} \free{zdpack}}
}
Since the 
\axiomOpFrom{univariateSolve}{ZeroDimensionalSolvePackage} operation may
split a regular set, it returns a list. This explains the use
of \axiomOpFrom{concat}{List}.

Look at the last item of the result. It consists of two parts.  For
any complex root {\bf ?} of the univariate polynomial in the first
part, we get a tuple of univariate polynomials (in {\bf a}, ..., 
{\bf f} respectively) by replacing {\bf \%A} by {\bf ?} in the second 
part. Each of these tuples {\bf t} describes a point of the variety
associated with {\bf lp} by equaling to zero the polynomials in 
{\bf t}.

Note that the way of reading these univariate representations is
explained also in the example illustrating the
\spadtype{ZeroDimensionalSolvePackage} constructor.

\xtc{
Now, we compute the points of the variety with real coordinates.
}{
\spadpaste{concat [realSolve(ts)$zdpack for ts in lts] \free{lts}
\free{zdpack}}
}
We obtain 24 points given by lists of elements in the 
\spadtype{RealClosure} of \spadtype{Fraction} of {\bf R}.
In each list, the first value corresponds to the indeterminate {\bf f},
the second to {\bf e} and so on.
See \spadtype{ZeroDimensionalSolvePackage} to learn more about
the \axiomOpFrom{realSolve}{ZeroDimensionalSolvePackage} operation.

\endscroll
\autobuttons
\end{page}

\begin{patch}{LexTriangularPackageXmpPagePatch1}
\begin{paste}{LexTriangularPackageXmpPageFull1}{LexTriangularPackageXmpPageEmpty1}
\pastebutton{LexTriangularPackageXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{R := Integer\bound{R }}
\indentrel{3}\begin{verbatim}
   (1)  Integer
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPageEmpty1}
\begin{paste}{LexTriangularPackageXmpPageEmpty1}{LexTriangularPackageXmpPagePatch1}
\pastebutton{LexTriangularPackageXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{R := Integer\bound{R }}
\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPagePatch2}
\begin{paste}{LexTriangularPackageXmpPageFull2}{LexTriangularPackageXmpPageEmpty2}
\pastebutton{LexTriangularPackageXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{ls : List Symbol := [a,b,c,d,e,f]\bound{ls }}
\indentrel{3}\begin{verbatim}
   (2)  [a,b,c,d,e,f]
                                      Type: List Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPageEmpty2}
\begin{paste}{LexTriangularPackageXmpPageEmpty2}{LexTriangularPackageXmpPagePatch2}
\pastebutton{LexTriangularPackageXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{ls : List Symbol := [a,b,c,d,e,f]\bound{ls }}
\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPagePatch3}
\begin{paste}{LexTriangularPackageXmpPageFull3}{LexTriangularPackageXmpPageEmpty3}
\pastebutton{LexTriangularPackageXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{V := OVAR(ls)\free{ls }\bound{V }}
\indentrel{3}\begin{verbatim}
   (3)  OrderedVariableList [a,b,c,d,e,f]
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPageEmpty3}
\begin{paste}{LexTriangularPackageXmpPageEmpty3}{LexTriangularPackageXmpPagePatch3}
\pastebutton{LexTriangularPackageXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{V := OVAR(ls)\free{ls }\bound{V }}
\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPagePatch4}
\begin{paste}{LexTriangularPackageXmpPageFull4}{LexTriangularPackageXmpPageEmpty4}
\pastebutton{LexTriangularPackageXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{P := NSMP(R, V)\free{R }\free{V }\bound{P }}
\indentrel{3}\begin{verbatim}
   (4)
  NewSparseMultivariatePolynomial(Integer,OrderedVariable
  List [a,b,c,d,e,f])
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPageEmpty4}
\begin{paste}{LexTriangularPackageXmpPageEmpty4}{LexTriangularPackageXmpPagePatch4}
\pastebutton{LexTriangularPackageXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{P := NSMP(R, V)\free{R }\free{V }\bound{P }}
\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPagePatch5}
\begin{paste}{LexTriangularPackageXmpPageFull5}{LexTriangularPackageXmpPageEmpty5}
\pastebutton{LexTriangularPackageXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{p1: P := a*b*c*d*e*f - 1\free{P }\bound{p1 }}
\indentrel{3}\begin{verbatim}
   (5)  f e d c b a - 1
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [a,b,c,d,e,f])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPageEmpty5}
\begin{paste}{LexTriangularPackageXmpPageEmpty5}{LexTriangularPackageXmpPagePatch5}
\pastebutton{LexTriangularPackageXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{p1: P := a*b*c*d*e*f - 1\free{P }\bound{p1 }}
\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPagePatch6}
\begin{paste}{LexTriangularPackageXmpPageFull6}{LexTriangularPackageXmpPageEmpty6}
\pastebutton{LexTriangularPackageXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{p2: P := a*b*c*d*e +a*b*c*d*f +a*b*c*e*f +a*b*d*e*f +a*c*d*e*f +b*c*d*e*f\free{P }\bound{p2 }}
\indentrel{3}\begin{verbatim}
   (6)
   ((((e + f)d + f e)c + f e d)b + f e d c)a + f e d c b
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [a,b,c,d,e,f])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPageEmpty6}
\begin{paste}{LexTriangularPackageXmpPageEmpty6}{LexTriangularPackageXmpPagePatch6}
\pastebutton{LexTriangularPackageXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{p2: P := a*b*c*d*e +a*b*c*d*f +a*b*c*e*f +a*b*d*e*f +a*c*d*e*f +b*c*d*e*f\free{P }\bound{p2 }}
\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPagePatch7}
\begin{paste}{LexTriangularPackageXmpPageFull7}{LexTriangularPackageXmpPageEmpty7}
\pastebutton{LexTriangularPackageXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{p3: P := a*b*c*d + a*b*c*f + a*b*e*f + a*d*e*f + b*c*d*e + c*d*e*f\free{P }\bound{p3 }}
\indentrel{3}\begin{verbatim}
   (7)  (((d + f)c + f e)b + f e d)a + e d c b + f e d c
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [a,b,c,d,e,f])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPageEmpty7}
\begin{paste}{LexTriangularPackageXmpPageEmpty7}{LexTriangularPackageXmpPagePatch7}
\pastebutton{LexTriangularPackageXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{p3: P := a*b*c*d + a*b*c*f + a*b*e*f + a*d*e*f + b*c*d*e + c*d*e*f\free{P }\bound{p3 }}
\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPagePatch8}
\begin{paste}{LexTriangularPackageXmpPageFull8}{LexTriangularPackageXmpPageEmpty8}
\pastebutton{LexTriangularPackageXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{p4: P := a*b*c + a*b*f + a*e*f + b*c*d + c*d*e + d*e*f\free{P }\bound{p4 }}
\indentrel{3}\begin{verbatim}
   (8)  ((c + f)b + f e)a + d c b + e d c + f e d
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [a,b,c,d,e,f])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPageEmpty8}
\begin{paste}{LexTriangularPackageXmpPageEmpty8}{LexTriangularPackageXmpPagePatch8}
\pastebutton{LexTriangularPackageXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{p4: P := a*b*c + a*b*f + a*e*f + b*c*d + c*d*e + d*e*f\free{P }\bound{p4 }}
\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPagePatch9}
\begin{paste}{LexTriangularPackageXmpPageFull9}{LexTriangularPackageXmpPageEmpty9}
\pastebutton{LexTriangularPackageXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{p5: P := a*b + a*f + b*c + c*d + d*e + e*f\free{P }\bound{p5 }}
\indentrel{3}\begin{verbatim}
   (9)  (b + f)a + c b + d c + e d + f e
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [a,b,c,d,e,f])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPageEmpty9}
\begin{paste}{LexTriangularPackageXmpPageEmpty9}{LexTriangularPackageXmpPagePatch9}
\pastebutton{LexTriangularPackageXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{p5: P := a*b + a*f + b*c + c*d + d*e + e*f\free{P }\bound{p5 }}
\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPagePatch10}
\begin{paste}{LexTriangularPackageXmpPageFull10}{LexTriangularPackageXmpPageEmpty10}
\pastebutton{LexTriangularPackageXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{p6: P := a + b + c + d + e + f\free{P }\bound{p6 }}
\indentrel{3}\begin{verbatim}
   (10)  a + b + c + d + e + f
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [a,b,c,d,e,f])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPageEmpty10}
\begin{paste}{LexTriangularPackageXmpPageEmpty10}{LexTriangularPackageXmpPagePatch10}
\pastebutton{LexTriangularPackageXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{p6: P := a + b + c + d + e + f\free{P }\bound{p6 }}
\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPagePatch11}
\begin{paste}{LexTriangularPackageXmpPageFull11}{LexTriangularPackageXmpPageEmpty11}
\pastebutton{LexTriangularPackageXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{lp := [p1, p2, p3, p4, p5, p6]\free{p1 }\free{p2 }\free{p3 }\free{p4 }\free{p5 }\free{p6 }\bound{lp }}
\indentrel{3}\begin{verbatim}
   (11)
   [f e d c b a - 1,
    ((((e + f)d + f e)c + f e d)b + f e d c)a + f e d c b,
    (((d + f)c + f e)b + f e d)a + e d c b + f e d c,
    ((c + f)b + f e)a + d c b + e d c + f e d,
    (b + f)a + c b + d c + e d + f e,
    a + b + c + d + e + f]
Type: List NewSparseMultivariatePolynomial(Integer,OrderedVariableList [a,b,c,d,e,f])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPageEmpty11}
\begin{paste}{LexTriangularPackageXmpPageEmpty11}{LexTriangularPackageXmpPagePatch11}
\pastebutton{LexTriangularPackageXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{lp := [p1, p2, p3, p4, p5, p6]\free{p1 }\free{p2 }\free{p3 }\free{p4 }\free{p5 }\free{p6 }\bound{lp }}
\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPagePatch12}
\begin{paste}{LexTriangularPackageXmpPageFull12}{LexTriangularPackageXmpPageEmpty12}
\pastebutton{LexTriangularPackageXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{lextripack := LEXTRIPK(R,ls)\free{R }\free{ls }\bound{lextripack }}
\indentrel{3}\begin{verbatim}
   (12)  LexTriangularPackage(Integer,[a,b,c,d,e,f])
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPageEmpty12}
\begin{paste}{LexTriangularPackageXmpPageEmpty12}{LexTriangularPackageXmpPagePatch12}
\pastebutton{LexTriangularPackageXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{lextripack := LEXTRIPK(R,ls)\free{R }\free{ls }\bound{lextripack }}
\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPagePatch13}
\begin{paste}{LexTriangularPackageXmpPageFull13}{LexTriangularPackageXmpPageEmpty13}
\pastebutton{LexTriangularPackageXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{lg := groebner(lp)$lextripack\free{lp }\free{lextripack }\bound{lg }}
\indentrel{3}\begin{verbatim}
   (13)
   [a + b + c + d + e + f,

                        2
       3968379498283200b  + 15873517993132800f b
     + 
                        2
       3968379498283200d  + 15873517993132800f d
     + 
                        3 5                     4 4
       3968379498283200f e  - 15873517993132800f e
     + 
                         5 3
       23810276989699200f e
     + 
                           6                       2
       (206355733910726400f  + 230166010900425600)e
     + 
                             43                       37
           - 729705987316687f   + 1863667496867205421f
         + 
                                 31
           291674853771731104461f
         + 
                                 25
           365285994691106921745f
         + 
                              19
           549961185828911895f
         + 
                                   13
           - 365048404038768439269f
         + 
                                 7
         - 292382820431504027669f  - 2271898467631865497f
      *
         e
     + 
                          44                        38
       - 3988812642545399f   + 10187423878429609997f
     + 
                              32
       1594377523424314053637f
     + 
                              26                       20
       1994739308439916238065f   + 1596840088052642815f
     + 
                                14
       - 1993494118301162145413f
     + 
                              8                        2
     - 1596049742289689815053f  - 11488171330159667449f
     ,

       (23810276989699200c - 23810276989699200f)b
     + 
                         2
       23810276989699200c  + 71430830969097600f c
     + 
                           2
       - 23810276989699200d  - 95241107958796800f d
     + 
                           3 5                      4 4
       - 55557312975964800f e  + 174608697924460800f e
     + 
                            5 3
       - 174608697924460800f e
     + 
                              6                        2
       (- 2428648252949318400f  - 2611193709870345600)e
     + 
                            43                        37
           8305444561289527f   - 21212087151945459641f
         + 
                                    31
           - 3319815883093451385381f
         + 
                                    25
           - 4157691646261657136445f
         + 
                                 19
           - 6072721607510764095f
         + 
                                  13
           4154986709036460221649f
         + 
                                7
         3327761311138587096749f  + 25885340608290841637f
      *
         e
     + 
                         44                         38
       45815897629010329f   - 117013765582151891207f
     + 
                                 32
       - 18313166848970865074187f
     + 
                                 26
       - 22909971239649297438915f
     + 
                              20
       - 16133250761305157265f
     + 
                               14
       22897305857636178256623f
     + 
                             8                         2
     18329944781867242497923f  + 130258531002020420699f
     ,

       (7936758996566400d - 7936758996566400f)b
     + 
                                                3 5
       - 7936758996566400f d - 7936758996566400f e
     + 
                         4 4                     5 3
       23810276989699200f e  - 23810276989699200f e
     + 
                             6                       2
       (- 337312257354072000f  - 369059293340337600)e
     + 
                            43                       37
           1176345388640471f   - 3004383582891473073f
         + 
                                   31
           - 470203502707246105653f
         + 
                                   25
           - 588858183402644348085f
         + 
                                19
           - 856939308623513535f
         + 
                                 13
           588472674242340526377f
         + 
                                 7
           471313241958371103517f  + 3659742549078552381f
      *
         e
     + 
                        44                        38
       6423170513956901f   - 16404772137036480803f
     + 
                                32
       - 2567419165227528774463f
     + 
                                26
       - 3211938090825682172335f
     + 
                             20
       - 2330490332697587485f
     + 
                              14
       3210100109444754864587f
     + 
                              8                        2
       2569858315395162617847f  + 18326089487427735751f
     ,

       (11905138494849600e - 11905138494849600f)b
     + 
                          3 5                     4 4
       - 3968379498283200f e  + 15873517993132800f e
     + 
                           5 3
       - 27778656487982400f e
     + 
                             6                       2
       (- 208339923659868000f  - 240086959646133600)e
     + 
                           43                       37
           786029984751110f   - 2007519008182245250f
         + 
                                   31
           - 314188062908073807090f
         + 
                                   25
           - 393423667537929575250f
         + 
                                19
           - 550329120654394950f
         + 
                                 13
           393196408728889612770f
         + 
                                 7
           314892372799176495730f  + 2409386515146668530f
      *
         e
     + 
                        44                        38
       4177638546747827f   - 10669685294602576381f
     + 
                                32
       - 1669852980419949524601f
     + 
                                26
       - 2089077057287904170745f
     + 
                             20
       - 1569899763580278795f
     + 
                              14
       2087864026859015573349f
     + 
                              8                        2
       1671496085945199577969f  + 11940257226216280177f
     ,

                          6
       (11905138494849600f  - 11905138494849600)b
     + 
                           2 5                     3 4
       - 15873517993132800f e  + 39683794982832000f e
     + 
                           4 3
       - 39683794982832000f e
     + 
                             11                      5  2
       (- 686529653202993600f   - 607162063237329600f )e
     + 
                          42                      36
           65144531306704f   - 166381280901088652f
         + 
                                  30
           - 26033434502470283472f
         + 
                                  24
           - 31696259583860650140f
         + 
                              18                        12
           971492093167581360f   + 32220085033691389548f
         + 
                                6
           25526177666070529808f  + 138603268355749244
      *
         e
     + 
                       43                      37
       167620036074811f   - 428102417974791473f
     + 
                              31                        25
       - 66997243801231679313f   - 83426716722148750485f
     + 
                          19                        13
       203673895369980765f   + 83523056326010432457f
     + 
                            7
       66995789640238066937f  + 478592855549587901f
     ,

                    3                   2
       801692827936c  + 2405078483808f c
     + 
                       2                45
       - 2405078483808f c - 13752945467f
     + 
                      39                    33
       35125117815561f   + 5496946957826433f
     + 
                        27                  21
       6834659447749117f   - 44484880462461f
     + 
                          15                    9
       - 6873406230093057f   - 5450844938762633f
     + 
                     3
       1216586044571f
     ,

       (23810276989699200d - 23810276989699200f)c
     + 
                         2
       23810276989699200d  + 71430830969097600f d
     + 
                        3 5                     4 4
       7936758996566400f e  - 31747035986265600f e
     + 
                         5 3
       31747035986265600f e
     + 
                           6                       2
       (404774708824886400f  + 396837949828320000)e
     + 
                              43                       37
           - 1247372229446701f   + 3185785654596621203f
         + 
                                 31
           498594866849974751463f
         + 
                                 25
           624542545845791047935f
         + 
                              19
           931085755769682885f
         + 
                                   13
           - 624150663582417063387f
         + 
                                 7
         - 499881859388360475647f  - 3926885313819527351f
      *
         e
     + 
                          44                        38
       - 7026011547118141f   + 17944427051950691243f
     + 
                              32
       2808383522593986603543f
     + 
                              26                       20
       3513624142354807530135f   + 2860757006705537685f
     + 
                                14
       - 3511356735642190737267f
     + 
                              8                        2
     - 2811332494697103819887f  - 20315011631522847311f
     ,

       (7936758996566400e - 7936758996566400f)c
     + 
                           43                     37
           - 4418748183673f   + 11285568707456559f
         + 
                               31                       25
           1765998617294451019f   + 2173749283622606155f
         + 
                               19                       13
           - 55788292195402895f   - 2215291421788292951f
         + 
                                 7
           - 1718142665347430851f  + 30256569458230237f
      *
         e
     + 
                     44                     38
       4418748183673f   - 11285568707456559f
     + 
                             32                       26
       - 1765998617294451019f   - 2173749283622606155f
     + 
                         20                       14
       55788292195402895f   + 2215291421788292951f
     + 
                           8                     2
       1718142665347430851f  - 30256569458230237f
     ,

                       6
       (72152354514240f  - 72152354514240)c
     + 
                   43                   37
       40950859449f   - 104588980990367f
     + 
                           31                     25
       - 16367227395575307f   - 20268523416527355f
     + 
                       19                     13
       442205002259535f   + 20576059935789063f
     + 
                         7
       15997133796970563f  - 275099892785581f
     ,

                        3                      2
       1984189749141600d  + 5952569247424800f d
     + 
                          2                     4 5
       - 5952569247424800f d - 3968379498283200f e
     + 
                         5 4                     3
       15873517993132800f e  + 17857707742274400e
     + 
                             7                        2
       (- 148814231185620000f  - 162703559429611200f)e
     + 
                             44                      38
           - 390000914678878f   + 996062704593756434f
         + 
                                 32
           155886323972034823914f
         + 
                                 26                    20
           194745956143985421330f   + 6205077595574430f
         + 
                                   14
           - 194596512653299068786f
         + 
                                 8                       2
         - 155796897940756922666f  - 1036375759077320978f
      *
         e
     + 
                         45                      39
       - 374998630035991f   + 957747106595453993f
     + 
                             33                         27
       149889155566764891693f   + 187154171443494641685f
     + 
                            21                         15
       - 127129015426348065f   - 187241533243115040417f
     + 
                               9                      3
       - 149719983567976534037f  - 836654081239648061f
     ,

       (5952569247424800e - 5952569247424800f)d
     + 
                          3 5                    4 4
       - 3968379498283200f e  + 9920948745708000f e
     + 
                          5 3
       - 3968379498283200f e
     + 
                             6                       2
       (- 148814231185620000f  - 150798420934761600)e
     + 
                           43                       37
           492558110242553f   - 1257992359608074599f
         + 
                                   31
           - 196883094539368513959f
         + 
                                   25
           - 246562115745735428055f
         + 
                                19
           - 325698701993885505f
         + 
                                 13
           246417769883651808111f
         + 
                                 7
           197327352068200652911f  + 1523373796389332143f
      *
         e
     + 
                        44                       38
       2679481081803026f   - 6843392695421906608f
     + 
                                32
       - 1071020459642646913578f
     + 
                                26                      20
       - 1339789169692041240060f   - 852746750910750210f
     + 
                              14
       1339105101971878401312f
     + 
                              8                       2
       1071900289758712984762f  + 7555239072072727756f
     ,

                          6
       (11905138494849600f  - 11905138494849600)d
     + 
                          2 5                     3 4
       - 7936758996566400f e  + 31747035986265600f e
     + 
                           4 3
       - 31747035986265600f e
     + 
                             11                      5  2
       (- 420648226818019200f   - 404774708824886400f )e
     + 
                          42                     36
           15336187600889f   - 39169739565161107f
         + 
                                 30
           - 6127176127489690827f
         + 
                                 24
           - 7217708742310509615f
         + 
                              18                       12
           538628483890722735f   + 7506804353843507643f
         + 
                               6
           5886160769782607203f  + 63576108396535879
      *
         e
     + 
                      43                      37
       71737781777066f   - 183218856207557938f
     + 
                              31                        25
       - 28672874271132276078f   - 35625223686939812010f
     + 
                          19                        13
       164831339634084390f   + 35724160423073052642f
     + 
                            7
       28627022578664910622f  + 187459987029680506f
     ,

                        6                      5
       1322793166094400e  - 3968379498283200f e
     + 
                        2 4                    3 3
       3968379498283200f e  - 5291172664377600f e
     + 
                             10                      4  2
       (- 230166010900425600f   - 226197631402142400f )e
     + 
                                47
           - 152375364610443885f
         + 
                                 41
           389166626064854890415f
         + 
                                   35
           60906097841360558987335f
         + 
                                   29
           76167367934608798697275f
         + 
                                23
           27855066785995181125f
         + 
                                     17
           - 76144952817052723145495f
         + 
                                     11
           - 60933629892463517546975f
         + 
                                   5
           - 411415071682002547795f
      *
         e
     + 
                         42                      36
       - 209493533143822f   + 535045979490560586f
     + 
                            30                         24
       83737947964973553146f   + 104889507084213371570f
     + 
                          18                         12
       167117997269207870f   - 104793725781390615514f
     + 
                              6
       - 83842685189903180394f  - 569978796672974242
     ,

                       6                   3
       (25438330117200f  + 25438330117200)e
     + 
                       7                    2
       (76314990351600f  + 76314990351600f)e
     + 
                           44                    38
           - 1594966552735f   + 4073543370415745f
         + 
                              32                      26
           637527159231148925f   + 797521176113606525f
         + 
                           20                      14
           530440941097175f   - 797160527306433145f
         + 
                                8                    2
           - 638132320196044965f  - 4510507167940725f
      *
         e
     + 
                       45                     39
       - 6036376800443f   + 15416903421476909f
     + 
                           33                       27
       2412807646192304449f   + 3017679923028013705f
     + 
                        21                       15
       1422320037411955f   - 3016560402417843941f
     + 
                             9                     3
       - 2414249368183033161f  - 16561862361763873f
     ,

                      12                  2
       (1387545279120f   - 1387545279120)e
     + 
                      43                  37
           4321823003f   - 11037922310209f
         + 
                              31                    25
           - 1727510711947989f   - 2165150991154425f
         + 
                           19                    13
           - 5114342560755f   + 2162682824948601f
         + 
                            7
           1732620732685741f  + 13506088516033f
      *
         e
     + 
                   44                  38
       24177661775f   - 61749727185325f
     + 
                          32                     26
       - 9664106795754225f   - 12090487758628245f
     + 
                       20                     14
       - 8787672733575f   + 12083693383005045f
     + 
                        8                  2
       9672870290826025f  + 68544102808525f
     ,

        48        42          36          30          18
       f   - 2554f   - 399710f   - 499722f   + 499722f
     + 
              12        6
       399710f   + 2554f  - 1
     ]
Type: List NewSparseMultivariatePolynomial(Integer,OrderedVariableList [a,b,c,d,e,f])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPageEmpty13}
\begin{paste}{LexTriangularPackageXmpPageEmpty13}{LexTriangularPackageXmpPagePatch13}
\pastebutton{LexTriangularPackageXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{lg := groebner(lp)$lextripack\free{lp }\free{lextripack }\bound{lg }}
\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPagePatch14}
\begin{paste}{LexTriangularPackageXmpPageFull14}{LexTriangularPackageXmpPageEmpty14}
\pastebutton{LexTriangularPackageXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{lexTriangular(lg,false)$lextripack\free{lg }\free{lextripack }}
\indentrel{3}\begin{verbatim}
   (14)
   [
       6
     {f  + 1,
       6       5     2 4     3 3     4 2     5
      e  - 3f e  + 3f e  - 4f e  + 3f e  - 3f e - 1,
            2 5     3 4     4 3     5 2
      3d + f e  - 4f e  + 4f e  - 2f e  - 2e + 2f, c + f,
             2 5     3 4     4 3      5 2
      3b + 2f e  - 5f e  + 5f e  - 10f e  - 4e + 7f,
           2 5     3 4     4 3     5 2
      a - f e  + 3f e  - 3f e  + 4f e  + 3e - 3f}
     ,

       6                     2           2
     {f  - 1, e - f, d - f, c  + 4f c + f ,
                         2
      (c - f)b - f c - 5f , a + b + c + 3f}
     ,
      6                        2           2
    {f  - 1,e - f,d - f,c - f,b  + 4f b + f ,a + b + 4f},

       6              2           2
     {f  - 1, e - f, d  + 4f d + f ,
                         2
      (d - f)c - f d - 5f , b - f, a + c + d + 3f}
     ,

     {
          36        30          24          18          12
         f   - 2554f   - 399709f   - 502276f   - 399709f
       + 
                6
         - 2554f  + 1
       ,

                    12              2
         (161718564f   - 161718564)e
       + 
                      31              25                19
             - 504205f   + 1287737951f   + 201539391380f
           + 
                        13                7
           253982817368f   + 201940704665f  + 1574134601f
        *
           e
       + 
                   32              26                 20
         - 2818405f   + 7198203911f   + 1126548149060f
       + 
                     14                 8              2
       1416530563364f   + 1127377589345f  + 7988820725f
       ,

                       6
         (693772639560f  - 693772639560)d
       + 
                        2 5                 3 4
         - 462515093040f e  + 1850060372160f e
       + 
                         4 3
         - 1850060372160f e
       + 
                           11                  5  2
         (- 24513299931120f   - 23588269745040f )e
       + 
                         30                 24
             - 890810428f   + 2275181044754f
           + 
                             18                   12
             355937263869776f   + 413736880104344f
           + 
                             6
             342849304487996f  + 3704966481878
        *
           e
       + 
                      31                  25
         - 4163798003f   + 10634395752169f
       + 
                          19                    13
         1664161760192806f   + 2079424391370694f
       + 
                          7
         1668153650635921f  + 10924274392693f
       ,

                      6                           31
         (12614047992f  - 12614047992)c - 7246825f
       + 
                     25                 19
         18508536599f   + 2896249516034f
       + 
                     13                 7
       3581539649666f   + 2796477571739f  - 48094301893f
       ,

                       6
         (693772639560f  - 693772639560)b
       + 
                        2 5                 3 4
         - 925030186080f e  + 2312575465200f e
       + 
                         4 3
         - 2312575465200f e
       + 
                           11                  5  2
         (- 40007555547960f   - 35382404617560f )e
       + 
                          30                 24
             - 3781280823f   + 9657492291789f
           + 
                              18                    12
             1511158913397906f   + 1837290892286154f
           + 
                              6
             1487216006594361f  + 8077238712093
        *
           e
       + 
                      31                  25
         - 9736390478f   + 24866827916734f
       + 
                          19                    13
         3891495681905296f   + 4872556418871424f
       + 
                          7
         3904047887269606f  + 27890075838538f
       ,
      a + b + c + d + e + f}
     ,

       6       2           2                     2
     {f  - 1, e  + 4f e + f , (e - f)d - f e - 5f ,
      c - f, b - f, a + d + e + 3f}
     ]
         Type: List RegularChain(Integer,[a,b,c,d,e,f])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPageEmpty14}
\begin{paste}{LexTriangularPackageXmpPageEmpty14}{LexTriangularPackageXmpPagePatch14}
\pastebutton{LexTriangularPackageXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{lexTriangular(lg,false)$lextripack\free{lg }\free{lextripack }}
\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPagePatch15}
\begin{paste}{LexTriangularPackageXmpPageFull15}{LexTriangularPackageXmpPageEmpty15}
\pastebutton{LexTriangularPackageXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{lts := lexTriangular(lg,true)$lextripack\free{lg }\free{lextripack }\bound{lts }}
\indentrel{3}\begin{verbatim}
   (15)
   [
       6
     {f  + 1,
       6       5     2 4     3 3     4 2     5
      e  - 3f e  + 3f e  - 4f e  + 3f e  - 3f e - 1,
            2 5     3 4     4 3     5 2
      3d + f e  - 4f e  + 4f e  - 2f e  - 2e + 2f, c + f,
             2 5     3 4     4 3      5 2
      3b + 2f e  - 5f e  + 5f e  - 10f e  - 4e + 7f,
           2 5     3 4     4 3     5 2
      a - f e  + 3f e  - 3f e  + 4f e  + 3e - 3f}
     ,
      6                  2           2
    {f  - 1,e - f,d - f,c  + 4f c + f ,b + c + 4f,a - f},
      6                        2           2
    {f  - 1,e - f,d - f,c - f,b  + 4f b + f ,a + b + 4f},
      6            2           2
    {f  - 1,e - f,d  + 4f d + f ,c + d + 4f,b - f,a - f},

     {
          36        30          24          18          12
         f   - 2554f   - 399709f   - 502276f   - 399709f
       + 
                6
         - 2554f  + 1
       ,

                       2
         1387545279120e
       + 
                        31                  25
             4321823003f   - 11037922310209f
           + 
                                19                    13
             - 1727506390124986f   - 2176188913464634f
           + 
                                7
             - 1732620732685741f  - 13506088516033f
        *
           e
       + 
                     32                  26
         24177661775f   - 61749727185325f
       + 
                            20                     14
         - 9664082618092450f   - 12152237485813570f
       + 
                            8                  2
         - 9672870290826025f  - 68544102808525f
       ,

         1387545279120d
       + 
                          30                 24
             - 1128983050f   + 2883434331830f
           + 
                             18                   12
             451234998755840f   + 562426491685760f
           + 
                             6
             447129055314890f  - 165557857270
        *
           e
       + 
                      31                 25
         - 1816935351f   + 4640452214013f
       + 
                         19                   13
         726247129626942f   + 912871801716798f
       + 
                         7
         726583262666877f  + 4909358645961f
       ,

                                    31                 25
         1387545279120c + 778171189f   - 1987468196267f
       + 
                           19                   13
         - 310993556954378f   - 383262822316802f
       + 
                           7
         - 300335488637543f  + 5289595037041f
       ,

         1387545279120b
       + 
                        30                 24
             1128983050f   - 2883434331830f
           + 
                               18                   12
             - 451234998755840f   - 562426491685760f
           + 
                               6
             - 447129055314890f  + 165557857270
        *
           e
       + 
                      31                 25
         - 3283058841f   + 8384938292463f
       + 
                          19                    13
         1312252817452422f   + 1646579934064638f
       + 
                          7
         1306372958656407f  + 4694680112151f
       ,

                                                      31
         1387545279120a + 1387545279120e + 4321823003f
       + 
                          25                    19
         - 11037922310209f   - 1727506390124986f
       + 
                            13                    7
         - 2176188913464634f   - 1732620732685741f
       + 
         - 13506088516033f
       }
     ,
      6      2           2
    {f  - 1,e  + 4f e + f ,d + e + 4f,c - f,b - f,a - f}]
         Type: List RegularChain(Integer,[a,b,c,d,e,f])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPageEmpty15}
\begin{paste}{LexTriangularPackageXmpPageEmpty15}{LexTriangularPackageXmpPagePatch15}
\pastebutton{LexTriangularPackageXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{lts := lexTriangular(lg,true)$lextripack\free{lg }\free{lextripack }\bound{lts }}
\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPagePatch16}
\begin{paste}{LexTriangularPackageXmpPageFull16}{LexTriangularPackageXmpPageEmpty16}
\pastebutton{LexTriangularPackageXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{[[init(p) for p in (ts :: List(P))] for ts in lts]\free{lts }}
\indentrel{3}\begin{verbatim}
   (16)
   [[1,3,1,3,1,1], [1,1,1,1,1,1], [1,1,1,1,1,1],
    [1,1,1,1,1,1],

     [1387545279120, 1387545279120, 1387545279120,
      1387545279120, 1387545279120, 1]
     ,
    [1,1,1,1,1,1]]
Type: List List NewSparseMultivariatePolynomial(Integer,OrderedVariableList [a,b,c,d,e,f])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPageEmpty16}
\begin{paste}{LexTriangularPackageXmpPageEmpty16}{LexTriangularPackageXmpPagePatch16}
\pastebutton{LexTriangularPackageXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{[[init(p) for p in (ts :: List(P))] for ts in lts]\free{lts }}
\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPagePatch17}
\begin{paste}{LexTriangularPackageXmpPageFull17}{LexTriangularPackageXmpPageEmpty17}
\pastebutton{LexTriangularPackageXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{squareFreeLexTriangular(lg,true)$lextripack\free{lg }\free{lextripack }}
\indentrel{3}\begin{verbatim}
   (17)
   [
       6
     {f  + 1,
       6       5     2 4     3 3     4 2     5
      e  - 3f e  + 3f e  - 4f e  + 3f e  - 3f e - 1,
            2 5     3 4     4 3     5 2
      3d + f e  - 4f e  + 4f e  - 2f e  - 2e + 2f, c + f,
             2 5     3 4     4 3      5 2
      3b + 2f e  - 5f e  + 5f e  - 10f e  - 4e + 7f,
           2 5     3 4     4 3     5 2
      a - f e  + 3f e  - 3f e  + 4f e  + 3e - 3f}
     ,
      6                  2           2
    {f  - 1,e - f,d - f,c  + 4f c + f ,b + c + 4f,a - f},
      6                        2           2
    {f  - 1,e - f,d - f,c - f,b  + 4f b + f ,a + b + 4f},
      6            2           2
    {f  - 1,e - f,d  + 4f d + f ,c + d + 4f,b - f,a - f},

     {
          36        30          24          18          12
         f   - 2554f   - 399709f   - 502276f   - 399709f
       + 
                6
         - 2554f  + 1
       ,

                       2
         1387545279120e
       + 
                        31                  25
             4321823003f   - 11037922310209f
           + 
                                19                    13
             - 1727506390124986f   - 2176188913464634f
           + 
                                7
             - 1732620732685741f  - 13506088516033f
        *
           e
       + 
                     32                  26
         24177661775f   - 61749727185325f
       + 
                            20                     14
         - 9664082618092450f   - 12152237485813570f
       + 
                            8                  2
         - 9672870290826025f  - 68544102808525f
       ,

         1387545279120d
       + 
                          30                 24
             - 1128983050f   + 2883434331830f
           + 
                             18                   12
             451234998755840f   + 562426491685760f
           + 
                             6
             447129055314890f  - 165557857270
        *
           e
       + 
                      31                 25
         - 1816935351f   + 4640452214013f
       + 
                         19                   13
         726247129626942f   + 912871801716798f
       + 
                         7
         726583262666877f  + 4909358645961f
       ,

                                    31                 25
         1387545279120c + 778171189f   - 1987468196267f
       + 
                           19                   13
         - 310993556954378f   - 383262822316802f
       + 
                           7
         - 300335488637543f  + 5289595037041f
       ,

         1387545279120b
       + 
                        30                 24
             1128983050f   - 2883434331830f
           + 
                               18                   12
             - 451234998755840f   - 562426491685760f
           + 
                               6
             - 447129055314890f  + 165557857270
        *
           e
       + 
                      31                 25
         - 3283058841f   + 8384938292463f
       + 
                          19                    13
         1312252817452422f   + 1646579934064638f
       + 
                          7
         1306372958656407f  + 4694680112151f
       ,

                                                      31
         1387545279120a + 1387545279120e + 4321823003f
       + 
                          25                    19
         - 11037922310209f   - 1727506390124986f
       + 
                            13                    7
         - 2176188913464634f   - 1732620732685741f
       + 
         - 13506088516033f
       }
     ,
      6      2           2
    {f  - 1,e  + 4f e + f ,d + e + 4f,c - f,b - f,a - f}]
Type: List SquareFreeRegularTriangularSet(Integer,IndexedExponents OrderedVariableList [a,b,c,d,e,f],OrderedVariableList [a,b,c,d,e,f],NewSparseMultivariatePolynomial(Integer,OrderedVariableList [a,b,c,d,e,f]))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPageEmpty17}
\begin{paste}{LexTriangularPackageXmpPageEmpty17}{LexTriangularPackageXmpPagePatch17}
\pastebutton{LexTriangularPackageXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{squareFreeLexTriangular(lg,true)$lextripack\free{lg }\free{lextripack }}
\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPagePatch18}
\begin{paste}{LexTriangularPackageXmpPageFull18}{LexTriangularPackageXmpPageEmpty18}
\pastebutton{LexTriangularPackageXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{reduce(+,[degree(ts) for ts in lts])\free{lts }}
\indentrel{3}\begin{verbatim}
   (18)  156
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPageEmpty18}
\begin{paste}{LexTriangularPackageXmpPageEmpty18}{LexTriangularPackageXmpPagePatch18}
\pastebutton{LexTriangularPackageXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{reduce(+,[degree(ts) for ts in lts])\free{lts }}
\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPagePatch19}
\begin{paste}{LexTriangularPackageXmpPageFull19}{LexTriangularPackageXmpPageEmpty19}
\pastebutton{LexTriangularPackageXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{ls2 : List Symbol := concat(ls,new()$Symbol)\free{ls }\bound{ls2 }}
\indentrel{3}\begin{verbatim}
   (19)  [a,b,c,d,e,f,%A]
                                      Type: List Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPageEmpty19}
\begin{paste}{LexTriangularPackageXmpPageEmpty19}{LexTriangularPackageXmpPagePatch19}
\pastebutton{LexTriangularPackageXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{ls2 : List Symbol := concat(ls,new()$Symbol)\free{ls }\bound{ls2 }}
\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPagePatch20}
\begin{paste}{LexTriangularPackageXmpPageFull20}{LexTriangularPackageXmpPageEmpty20}
\pastebutton{LexTriangularPackageXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{zdpack := ZDSOLVE(R,ls,ls2)\free{R }\free{ls }\free{ls2 }\bound{zdpack }}
\indentrel{3}\begin{verbatim}
   (20)
  ZeroDimensionalSolvePackage(Integer,[a,b,c,d,e,f],[a,b,
  c,d,e,f,%A])
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPageEmpty20}
\begin{paste}{LexTriangularPackageXmpPageEmpty20}{LexTriangularPackageXmpPagePatch20}
\pastebutton{LexTriangularPackageXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{zdpack := ZDSOLVE(R,ls,ls2)\free{R }\free{ls }\free{ls2 }\bound{zdpack }}
\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPagePatch21}
\begin{paste}{LexTriangularPackageXmpPageFull21}{LexTriangularPackageXmpPageEmpty21}
\pastebutton{LexTriangularPackageXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{concat [univariateSolve(ts)$zdpack for ts in lts]\free{lts }\free{zdpack }}
\indentrel{3}\begin{verbatim}
   (21)
   [
                     4      2
     [complexRoots= ?  - 13?  + 49,

       coordinates =
                 3                3
         [7a + %A  - 6%A, 21b + %A  + %A,
                   3                3
          21c - 2%A  + 19%A, 7d - %A  + 6%A,
                  3                3
          21e - %A  - %A, 21f + 2%A  - 19%A]
       ]
     ,

                     4      2
     [complexRoots= ?  + 11?  + 49,

       coordinates =
                   3                 3
         [35a + 3%A  + 19%A, 35b + %A  + 18%A,
                   3                3
          35c - 2%A  - %A, 35d - 3%A  - 19%A,
                  3                  3
          35e - %A  - 18%A, 35f + 2%A  + %A]
       ]
     ,

     [
       complexRoots =
            8      7      6       5       4       3
           ?  - 12?  + 58?  - 120?  + 207?  - 360?
         + 
               2
           802?  - 1332? + 1369
       ,

       coordinates =
         [
                                7           6            5
             43054532a + 33782%A  - 546673%A  + 3127348%A
           + 
                        4            3             2
             - 6927123%A  + 4365212%A  - 25086957%A
           + 
             39582814%A - 107313172
           ,

                                7           6            5
             43054532b - 33782%A  + 546673%A  - 3127348%A
           + 
                      4            3             2
             6927123%A  - 4365212%A  + 25086957%A
           + 
             - 39582814%A + 107313172
           ,

                                7           6            5
             21527266c - 22306%A  + 263139%A  - 1166076%A
           + 
                      4            3             2
             1821805%A  - 2892788%A  + 10322663%A
           + 
             - 9026596%A + 12950740
           ,

                                7           6            5
             43054532d + 22306%A  - 263139%A  + 1166076%A
           + 
                        4            3             2
             - 1821805%A  + 2892788%A  - 10322663%A
           + 
             30553862%A - 12950740
           ,

                                7           6            5
             43054532e - 22306%A  + 263139%A  - 1166076%A
           + 
                      4            3             2
             1821805%A  - 2892788%A  + 10322663%A
           + 
             - 30553862%A + 12950740
           ,

                                7           6            5
             21527266f + 22306%A  - 263139%A  + 1166076%A
           + 
                        4            3             2
             - 1821805%A  + 2892788%A  - 10322663%A
           + 
             9026596%A - 12950740
           ]
       ]
     ,

     [
       complexRoots =
            8      7      6       5       4       3
           ?  + 12?  + 58?  + 120?  + 207?  + 360?
         + 
               2
           802?  + 1332? + 1369
       ,

       coordinates =
         [
                                7           6            5
             43054532a + 33782%A  + 546673%A  + 3127348%A
           + 
                      4            3             2
             6927123%A  + 4365212%A  + 25086957%A
           + 
             39582814%A + 107313172
           ,

                                7           6            5
             43054532b - 33782%A  - 546673%A  - 3127348%A
           + 
                        4            3             2
             - 6927123%A  - 4365212%A  - 25086957%A
           + 
             - 39582814%A - 107313172
           ,

                                7           6            5
             21527266c - 22306%A  - 263139%A  - 1166076%A
           + 
                        4            3             2
             - 1821805%A  - 2892788%A  - 10322663%A
           + 
             - 9026596%A - 12950740
           ,

                                7           6            5
             43054532d + 22306%A  + 263139%A  + 1166076%A
           + 
                      4            3             2
             1821805%A  + 2892788%A  + 10322663%A
           + 
             30553862%A + 12950740
           ,

                                7           6            5
             43054532e - 22306%A  - 263139%A  - 1166076%A
           + 
                        4            3             2
             - 1821805%A  - 2892788%A  - 10322663%A
           + 
             - 30553862%A - 12950740
           ,

                                7           6            5
             21527266f + 22306%A  + 263139%A  + 1166076%A
           + 
                      4            3             2
             1821805%A  + 2892788%A  + 10322663%A
           + 
             9026596%A + 12950740
           ]
       ]
     ,

                     4    2
     [complexRoots= ?  - ?  + 1,

       coordinates =
                        3             3
         [a - %A, b + %A  - %A, c + %A , d + %A,
                3             3
          e - %A  + %A, f - %A ]
       ]
     ,

                     8     6      4      2
     [complexRoots= ?  + 4?  + 12?  + 16?  + 4,

       coordinates =
                  7      5       3
         [4a - 2%A  - 7%A  - 20%A  - 22%A,
                  7      5       3
          4b + 2%A  + 7%A  + 20%A  + 22%A,
                 7      5       3
          4c + %A  + 3%A  + 10%A  + 10%A,
                 7      5       3
          4d + %A  + 3%A  + 10%A  + 6%A,
                 7      5       3
          4e - %A  - 3%A  - 10%A  - 6%A,
                 7      5       3
          4f - %A  - 3%A  - 10%A  - 10%A]
       ]
     ,

                     4     3      2
     [complexRoots= ?  + 6?  + 30?  + 36? + 36,

       coordinates =
                  3      2
         [30a - %A  - 5%A  - 30%A - 6,
                 3      2
          6b + %A  + 5%A  + 24%A + 6,
                  3      2
          30c - %A  - 5%A  - 6,
                  3      2
          30d - %A  - 5%A  - 30%A - 6,
                  3      2
          30e - %A  - 5%A  - 30%A - 6,
                  3      2
          30f - %A  - 5%A  - 30%A - 6]
       ]
     ,

                     4     3      2
     [complexRoots= ?  - 6?  + 30?  - 36? + 36,

       coordinates =
                  3      2
         [30a - %A  + 5%A  - 30%A + 6,
                 3      2
          6b + %A  - 5%A  + 24%A - 6,
                  3      2
          30c - %A  + 5%A  + 6,
                  3      2
          30d - %A  + 5%A  - 30%A + 6,
                  3      2
          30e - %A  + 5%A  - 30%A + 6,
                  3      2
          30f - %A  + 5%A  - 30%A + 6]
       ]
     ,

                     2
     [complexRoots= ?  + 6? + 6,

       coordinates =
         [a + 1,b - %A - 5,c + %A + 1,d + 1,e + 1,f + 1]
       ]
     ,

                     2
     [complexRoots= ?  - 6? + 6,

       coordinates =
         [a - 1,b - %A + 5,c + %A - 1,d - 1,e - 1,f - 1]
       ]
     ,

                     4     3      2
     [complexRoots= ?  + 6?  + 30?  + 36? + 36,

       coordinates =
                 3      2
         [6a + %A  + 5%A  + 24%A + 6,
                  3      2
          30b - %A  - 5%A  - 6,
                  3      2
          30c - %A  - 5%A  - 30%A - 6,
                  3      2
          30d - %A  - 5%A  - 30%A - 6,
                  3      2
          30e - %A  - 5%A  - 30%A - 6,
                  3      2
          30f - %A  - 5%A  - 30%A - 6]
       ]
     ,

                     4     3      2
     [complexRoots= ?  - 6?  + 30?  - 36? + 36,

       coordinates =
                 3      2
         [6a + %A  - 5%A  + 24%A - 6,
                  3      2
          30b - %A  + 5%A  + 6,
                  3      2
          30c - %A  + 5%A  - 30%A + 6,
                  3      2
          30d - %A  + 5%A  - 30%A + 6,
                  3      2
          30e - %A  + 5%A  - 30%A + 6,
                  3      2
          30f - %A  + 5%A  - 30%A + 6]
       ]
     ,

                     2
     [complexRoots= ?  + 6? + 6,

       coordinates =
         [a - %A - 5,b + %A + 1,c + 1,d + 1,e + 1,f + 1]
       ]
     ,

                     2
     [complexRoots= ?  - 6? + 6,

       coordinates =
         [a - %A + 5,b + %A - 1,c - 1,d - 1,e - 1,f - 1]
       ]
     ,

                     4     3      2
     [complexRoots= ?  + 6?  + 30?  + 36? + 36,

       coordinates =
                  3      2
         [30a - %A  - 5%A  - 30%A - 6,
                  3      2
          30b - %A  - 5%A  - 30%A - 6,
                 3      2
          6c + %A  + 5%A  + 24%A + 6,
                  3      2
          30d - %A  - 5%A  - 6,
                  3      2
          30e - %A  - 5%A  - 30%A - 6,
                  3      2
          30f - %A  - 5%A  - 30%A - 6]
       ]
     ,

                     4     3      2
     [complexRoots= ?  - 6?  + 30?  - 36? + 36,

       coordinates =
                  3      2
         [30a - %A  + 5%A  - 30%A + 6,
                  3      2
          30b - %A  + 5%A  - 30%A + 6,
                 3      2
          6c + %A  - 5%A  + 24%A - 6,
                  3      2
          30d - %A  + 5%A  + 6,
                  3      2
          30e - %A  + 5%A  - 30%A + 6,
                  3      2
          30f - %A  + 5%A  - 30%A + 6]
       ]
     ,

                     2
     [complexRoots= ?  + 6? + 6,

       coordinates =
         [a + 1,b + 1,c - %A - 5,d + %A + 1,e + 1,f + 1]
       ]
     ,

                     2
     [complexRoots= ?  - 6? + 6,

       coordinates =
         [a - 1,b - 1,c - %A + 5,d + %A - 1,e - 1,f - 1]
       ]
     ,

     [
       complexRoots =
          8     7      6      5      4     2
         ?  + 6?  + 16?  + 24?  + 18?  - 8?  + 4
       ,

       coordinates =
         [
                     7      6       5       4      3
             2a + 2%A  + 9%A  + 18%A  + 19%A  + 4%A
           + 
                   2
             - 10%A  - 2%A + 4
           ,

                     7      6       5       4      3
             2b + 2%A  + 9%A  + 18%A  + 19%A  + 4%A
           + 
                   2
             - 10%A  - 4%A + 4
           ,
                 7      6      5      4      3
          2c - %A  - 4%A  - 8%A  - 9%A  - 4%A  - 2%A - 4,
                 7      6      5      4      3
          2d + %A  + 4%A  + 8%A  + 9%A  + 4%A  + 2%A + 4,

                     7      6       5       4      3
             2e - 2%A  - 9%A  - 18%A  - 19%A  - 4%A
           + 
                 2
             10%A  + 4%A - 4
           ,

                     7      6       5       4      3
             2f - 2%A  - 9%A  - 18%A  - 19%A  - 4%A
           + 
                 2
             10%A  + 2%A - 4
           ]
       ]
     ,

     [
       complexRoots =
            8      7      6       5       4       3
           ?  + 12?  + 64?  + 192?  + 432?  + 768?
         + 
                2
           1024?  + 768? + 256
       ,

       coordinates =
         [
                         7        6        5         4
             1408a - 19%A  - 200%A  - 912%A  - 2216%A
           + 
                     3         2
             - 4544%A  - 6784%A  - 6976%A - 1792
           ,

                         7        6         5         4
             1408b - 37%A  - 408%A  - 1952%A  - 5024%A
           + 
                      3          2
             - 10368%A  - 16768%A  - 17920%A - 5120
           ,

                         7        6         5         4
             1408c + 37%A  + 408%A  + 1952%A  + 5024%A
           + 
                    3          2
             10368%A  + 16768%A  + 17920%A + 5120
           ,

                         7        6        5         4
             1408d + 19%A  + 200%A  + 912%A  + 2216%A
           + 
                   3         2
             4544%A  + 6784%A  + 6976%A + 1792
           ,
          2e + %A, 2f - %A]
       ]
     ,

                     8     6      4      2
     [complexRoots= ?  + 4?  + 12?  + 16?  + 4,

       coordinates =
                 7      5       3
         [4a - %A  - 3%A  - 10%A  - 6%A,
                 7      5       3
          4b - %A  - 3%A  - 10%A  - 10%A,
                  7      5       3
          4c - 2%A  - 7%A  - 20%A  - 22%A,
                  7      5       3
          4d + 2%A  + 7%A  + 20%A  + 22%A,
                 7      5       3
          4e + %A  + 3%A  + 10%A  + 10%A,
                 7      5       3
          4f + %A  + 3%A  + 10%A  + 6%A]
       ]
     ,

                     8      6      4       2
     [complexRoots= ?  + 16?  - 96?  + 256?  + 256,

       coordinates =
                   7       5        3
         [512a - %A  - 12%A  + 176%A  - 448%A,
                   7       5       3
          128b - %A  - 16%A  + 96%A  - 256%A,
                   7       5       3
          128c + %A  + 16%A  - 96%A  + 256%A,
                   7       5        3
          512d + %A  + 12%A  - 176%A  + 448%A, 2e + %A,
          2f - %A]
       ]
     ,

     [
       complexRoots =
            8      7      6       5       4       3
           ?  - 12?  + 64?  - 192?  + 432?  - 768?
         + 
                2
           1024?  - 768? + 256
       ,

       coordinates =
         [
                         7        6        5         4
             1408a - 19%A  + 200%A  - 912%A  + 2216%A
           + 
                     3         2
             - 4544%A  + 6784%A  - 6976%A + 1792
           ,

                         7        6         5         4
             1408b - 37%A  + 408%A  - 1952%A  + 5024%A
           + 
                      3          2
             - 10368%A  + 16768%A  - 17920%A + 5120
           ,

                         7        6         5         4
             1408c + 37%A  - 408%A  + 1952%A  - 5024%A
           + 
                    3          2
             10368%A  - 16768%A  + 17920%A - 5120
           ,

                         7        6        5         4
             1408d + 19%A  - 200%A  + 912%A  - 2216%A
           + 
                   3         2
             4544%A  - 6784%A  + 6976%A - 1792
           ,
          2e + %A, 2f - %A]
       ]
     ,

     [
       complexRoots =
          8     7      6      5      4     2
         ?  - 6?  + 16?  - 24?  + 18?  - 8?  + 4
       ,

       coordinates =
         [
                     7      6       5       4      3
             2a + 2%A  - 9%A  + 18%A  - 19%A  + 4%A
           + 
                 2
             10%A  - 2%A - 4
           ,

                     7      6       5       4      3
             2b + 2%A  - 9%A  + 18%A  - 19%A  + 4%A
           + 
                 2
             10%A  - 4%A - 4
           ,
                 7      6      5      4      3
          2c - %A  + 4%A  - 8%A  + 9%A  - 4%A  - 2%A + 4,
                 7      6      5      4      3
          2d + %A  - 4%A  + 8%A  - 9%A  + 4%A  + 2%A - 4,

                     7      6       5       4      3
             2e - 2%A  + 9%A  - 18%A  + 19%A  - 4%A
           + 
                   2
             - 10%A  + 4%A + 4
           ,

                     7      6       5       4      3
             2f - 2%A  + 9%A  - 18%A  + 19%A  - 4%A
           + 
                   2
             - 10%A  + 2%A + 4
           ]
       ]
     ,

                     4      2
     [complexRoots= ?  + 12?  + 144,

       coordinates =
                  2               2               2
         [12a - %A  - 12, 12b - %A  - 12, 12c - %A  - 12,
                  2              2
          12d - %A  - 12, 6e + %A  + 3%A + 12,
                 2
          6f + %A  - 3%A + 12]
       ]
     ,

                     4     3      2
     [complexRoots= ?  + 6?  + 30?  + 36? + 36,

       coordinates =
                 3      2
         [6a - %A  - 5%A  - 24%A - 6,
                  3      2
          30b + %A  + 5%A  + 30%A + 6,
                  3      2
          30c + %A  + 5%A  + 30%A + 6,
                  3      2
          30d + %A  + 5%A  + 30%A + 6,
                  3      2
          30e + %A  + 5%A  + 30%A + 6,
                  3      2
          30f + %A  + 5%A  + 6]
       ]
     ,

                     4     3      2
     [complexRoots= ?  - 6?  + 30?  - 36? + 36,

       coordinates =
                 3      2
         [6a - %A  + 5%A  - 24%A + 6,
                  3      2
          30b + %A  - 5%A  + 30%A - 6,
                  3      2
          30c + %A  - 5%A  + 30%A - 6,
                  3      2
          30d + %A  - 5%A  + 30%A - 6,
                  3      2
          30e + %A  - 5%A  + 30%A - 6,
                  3      2
          30f + %A  - 5%A  - 6]
       ]
     ,

                     4      2
     [complexRoots= ?  + 12?  + 144,

       coordinates =
                  2               2               2
         [12a + %A  + 12, 12b + %A  + 12, 12c + %A  + 12,
                  2              2
          12d + %A  + 12, 6e - %A  + 3%A - 12,
                 2
          6f - %A  - 3%A - 12]
       ]
     ,

                     2
     [complexRoots= ?  - 12,

       coordinates =
         [a - 1,b - 1,c - 1,d - 1,2e + %A + 4,2f - %A + 4]
       ]
     ,

                     2
     [complexRoots= ?  + 6? + 6,

       coordinates =
         [a + %A + 5,b - 1,c - 1,d - 1,e - 1,f - %A - 1]
       ]
     ,

                     2
     [complexRoots= ?  - 6? + 6,

       coordinates =
         [a + %A - 5,b + 1,c + 1,d + 1,e + 1,f - %A + 1]
       ]
     ,

                     2
     [complexRoots= ?  - 12,

       coordinates =
         [a + 1,b + 1,c + 1,d + 1,2e + %A - 4,2f - %A - 4]
       ]
     ,

                     4     3      2
     [complexRoots= ?  + 6?  + 30?  + 36? + 36,

       coordinates =
                  3      2
         [30a - %A  - 5%A  - 30%A - 6,
                  3      2
          30b - %A  - 5%A  - 30%A - 6,
                  3      2
          30c - %A  - 5%A  - 30%A - 6,
                 3      2
          6d + %A  + 5%A  + 24%A + 6,
                  3      2
          30e - %A  - 5%A  - 6,
                  3      2
          30f - %A  - 5%A  - 30%A - 6]
       ]
     ,

                     4     3      2
     [complexRoots= ?  - 6?  + 30?  - 36? + 36,

       coordinates =
                  3      2
         [30a - %A  + 5%A  - 30%A + 6,
                  3      2
          30b - %A  + 5%A  - 30%A + 6,
                  3      2
          30c - %A  + 5%A  - 30%A + 6,
                 3      2
          6d + %A  - 5%A  + 24%A - 6,
                  3      2
          30e - %A  + 5%A  + 6,
                  3      2
          30f - %A  + 5%A  - 30%A + 6]
       ]
     ,

                     2
     [complexRoots= ?  + 6? + 6,

       coordinates =
         [a + 1,b + 1,c + 1,d - %A - 5,e + %A + 1,f + 1]
       ]
     ,

                     2
     [complexRoots= ?  - 6? + 6,

       coordinates =
         [a - 1,b - 1,c - 1,d - %A + 5,e + %A - 1,f - 1]
       ]
     ]
Type: List Record(complexRoots: SparseUnivariatePolynomial Integer,coordinates: List Polynomial Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPageEmpty21}
\begin{paste}{LexTriangularPackageXmpPageEmpty21}{LexTriangularPackageXmpPagePatch21}
\pastebutton{LexTriangularPackageXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{concat [univariateSolve(ts)$zdpack for ts in lts]\free{lts }\free{zdpack }}
\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPagePatch22}
\begin{paste}{LexTriangularPackageXmpPageFull22}{LexTriangularPackageXmpPageEmpty22}
\pastebutton{LexTriangularPackageXmpPageFull22}{\hidepaste}
\tab{5}\spadcommand{concat [realSolve(ts)$zdpack for ts in lts]\free{lts }\free{zdpack }}
\indentrel{3}\begin{verbatim}
   (22)
   [[%R1,%R1,%R1,%R5,- %R5 - 4%R1,%R1],
    [%R1,%R1,%R1,%R6,- %R6 - 4%R1,%R1],
    [%R2,%R2,%R2,%R3,- %R3 - 4%R2,%R2],
    [%R2,%R2,%R2,%R4,- %R4 - 4%R2,%R2],
    [%R7,%R7,%R7,%R7,%R11,- %R11 - 4%R7],
    [%R7,%R7,%R7,%R7,%R12,- %R12 - 4%R7],
    [%R8,%R8,%R8,%R8,%R9,- %R9 - 4%R8],
    [%R8,%R8,%R8,%R8,%R10,- %R10 - 4%R8],
    [%R13,%R13,%R17,- %R17 - 4%R13,%R13,%R13],
    [%R13,%R13,%R18,- %R18 - 4%R13,%R13,%R13],
    [%R14,%R14,%R15,- %R15 - 4%R14,%R14,%R14],
    [%R14,%R14,%R16,- %R16 - 4%R14,%R14,%R14],

     [%R19, %R29,

           7865521      31   6696179241     25
         ÄÄÄÄÄÄÄÄÄÄ %R19   - ÄÄÄÄÄÄÄÄÄÄ %R19
         6006689520          2002229840
       + 
           25769893181     19   1975912990729     13
         - ÄÄÄÄÄÄÄÄÄÄÄ %R19   - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19
             49235160             3003344760
       + 
           1048460696489     7   21252634831
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19  - ÄÄÄÄÄÄÄÄÄÄÄ %R19
             2002229840           6006689520
       ,

             778171189       31   1987468196267     25
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19   + ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19
           1387545279120          1387545279120
       + 
         155496778477189     19   191631411158401     13
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19
           693772639560             693772639560
       + 
         300335488637543     7   755656433863
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19  - ÄÄÄÄÄÄÄÄÄÄÄÄ %R19
          1387545279120          198220754160
       ,

          1094352947      31   2794979430821     25
         ÄÄÄÄÄÄÄÄÄÄÄÄ %R19   - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19
         462515093040           462515093040
       + 
           218708802908737     19   91476663003591     13
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19   - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19
             231257546520             77085848840
       + 
           145152550961823     7   1564893370717
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19  - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19
             154171697680           462515093040
       ,

                    4321823003      31
         - %R29 - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19
                  1387545279120
       + 
         180949546069     25   863753195062493     19
         ÄÄÄÄÄÄÄÄÄÄÄÄ %R19   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19
          22746643920            693772639560
       + 
         1088094456732317     13   1732620732685741     7
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19
           693772639560              1387545279120
       + 
         13506088516033
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19
          1387545279120
       ]
     ,

     [%R19, %R30,

           7865521      31   6696179241     25
         ÄÄÄÄÄÄÄÄÄÄ %R19   - ÄÄÄÄÄÄÄÄÄÄ %R19
         6006689520          2002229840
       + 
           25769893181     19   1975912990729     13
         - ÄÄÄÄÄÄÄÄÄÄÄ %R19   - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19
             49235160             3003344760
       + 
           1048460696489     7   21252634831
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19  - ÄÄÄÄÄÄÄÄÄÄÄ %R19
             2002229840           6006689520
       ,

             778171189       31   1987468196267     25
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19   + ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19
           1387545279120          1387545279120
       + 
         155496778477189     19   191631411158401     13
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19
           693772639560             693772639560
       + 
         300335488637543     7   755656433863
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19  - ÄÄÄÄÄÄÄÄÄÄÄÄ %R19
          1387545279120          198220754160
       ,

          1094352947      31   2794979430821     25
         ÄÄÄÄÄÄÄÄÄÄÄÄ %R19   - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19
         462515093040           462515093040
       + 
           218708802908737     19   91476663003591     13
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19   - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19
             231257546520             77085848840
       + 
           145152550961823     7   1564893370717
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19  - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19
             154171697680           462515093040
       ,

                    4321823003      31
         - %R30 - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19
                  1387545279120
       + 
         180949546069     25   863753195062493     19
         ÄÄÄÄÄÄÄÄÄÄÄÄ %R19   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19
          22746643920            693772639560
       + 
         1088094456732317     13   1732620732685741     7
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19
           693772639560              1387545279120
       + 
         13506088516033
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R19
          1387545279120
       ]
     ,

     [%R20, %R27,

           7865521      31   6696179241     25
         ÄÄÄÄÄÄÄÄÄÄ %R20   - ÄÄÄÄÄÄÄÄÄÄ %R20
         6006689520          2002229840
       + 
           25769893181     19   1975912990729     13
         - ÄÄÄÄÄÄÄÄÄÄÄ %R20   - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20
             49235160             3003344760
       + 
           1048460696489     7   21252634831
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20  - ÄÄÄÄÄÄÄÄÄÄÄ %R20
             2002229840           6006689520
       ,

             778171189       31   1987468196267     25
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20   + ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20
           1387545279120          1387545279120
       + 
         155496778477189     19   191631411158401     13
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20
           693772639560             693772639560
       + 
         300335488637543     7   755656433863
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20  - ÄÄÄÄÄÄÄÄÄÄÄÄ %R20
          1387545279120          198220754160
       ,

          1094352947      31   2794979430821     25
         ÄÄÄÄÄÄÄÄÄÄÄÄ %R20   - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20
         462515093040           462515093040
       + 
           218708802908737     19   91476663003591     13
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20   - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20
             231257546520             77085848840
       + 
           145152550961823     7   1564893370717
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20  - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20
             154171697680           462515093040
       ,

                    4321823003      31
         - %R27 - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20
                  1387545279120
       + 
         180949546069     25   863753195062493     19
         ÄÄÄÄÄÄÄÄÄÄÄÄ %R20   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20
          22746643920            693772639560
       + 
         1088094456732317     13   1732620732685741     7
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20
           693772639560              1387545279120
       + 
         13506088516033
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20
          1387545279120
       ]
     ,

     [%R20, %R28,

           7865521      31   6696179241     25
         ÄÄÄÄÄÄÄÄÄÄ %R20   - ÄÄÄÄÄÄÄÄÄÄ %R20
         6006689520          2002229840
       + 
           25769893181     19   1975912990729     13
         - ÄÄÄÄÄÄÄÄÄÄÄ %R20   - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20
             49235160             3003344760
       + 
           1048460696489     7   21252634831
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20  - ÄÄÄÄÄÄÄÄÄÄÄ %R20
             2002229840           6006689520
       ,

             778171189       31   1987468196267     25
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20   + ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20
           1387545279120          1387545279120
       + 
         155496778477189     19   191631411158401     13
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20
           693772639560             693772639560
       + 
         300335488637543     7   755656433863
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20  - ÄÄÄÄÄÄÄÄÄÄÄÄ %R20
          1387545279120          198220754160
       ,

          1094352947      31   2794979430821     25
         ÄÄÄÄÄÄÄÄÄÄÄÄ %R20   - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20
         462515093040           462515093040
       + 
           218708802908737     19   91476663003591     13
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20   - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20
             231257546520             77085848840
       + 
           145152550961823     7   1564893370717
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20  - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20
             154171697680           462515093040
       ,

                    4321823003      31
         - %R28 - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20
                  1387545279120
       + 
         180949546069     25   863753195062493     19
         ÄÄÄÄÄÄÄÄÄÄÄÄ %R20   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20
          22746643920            693772639560
       + 
         1088094456732317     13   1732620732685741     7
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20
           693772639560              1387545279120
       + 
         13506088516033
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R20
          1387545279120
       ]
     ,

     [%R21, %R25,

           7865521      31   6696179241     25
         ÄÄÄÄÄÄÄÄÄÄ %R21   - ÄÄÄÄÄÄÄÄÄÄ %R21
         6006689520          2002229840
       + 
           25769893181     19   1975912990729     13
         - ÄÄÄÄÄÄÄÄÄÄÄ %R21   - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21
             49235160             3003344760
       + 
           1048460696489     7   21252634831
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21  - ÄÄÄÄÄÄÄÄÄÄÄ %R21
             2002229840           6006689520
       ,

             778171189       31   1987468196267     25
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21   + ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21
           1387545279120          1387545279120
       + 
         155496778477189     19   191631411158401     13
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21
           693772639560             693772639560
       + 
         300335488637543     7   755656433863
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21  - ÄÄÄÄÄÄÄÄÄÄÄÄ %R21
          1387545279120          198220754160
       ,

          1094352947      31   2794979430821     25
         ÄÄÄÄÄÄÄÄÄÄÄÄ %R21   - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21
         462515093040           462515093040
       + 
           218708802908737     19   91476663003591     13
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21   - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21
             231257546520             77085848840
       + 
           145152550961823     7   1564893370717
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21  - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21
             154171697680           462515093040
       ,

                    4321823003      31
         - %R25 - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21
                  1387545279120
       + 
         180949546069     25   863753195062493     19
         ÄÄÄÄÄÄÄÄÄÄÄÄ %R21   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21
          22746643920            693772639560
       + 
         1088094456732317     13   1732620732685741     7
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21
           693772639560              1387545279120
       + 
         13506088516033
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21
          1387545279120
       ]
     ,

     [%R21, %R26,

           7865521      31   6696179241     25
         ÄÄÄÄÄÄÄÄÄÄ %R21   - ÄÄÄÄÄÄÄÄÄÄ %R21
         6006689520          2002229840
       + 
           25769893181     19   1975912990729     13
         - ÄÄÄÄÄÄÄÄÄÄÄ %R21   - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21
             49235160             3003344760
       + 
           1048460696489     7   21252634831
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21  - ÄÄÄÄÄÄÄÄÄÄÄ %R21
             2002229840           6006689520
       ,

             778171189       31   1987468196267     25
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21   + ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21
           1387545279120          1387545279120
       + 
         155496778477189     19   191631411158401     13
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21
           693772639560             693772639560
       + 
         300335488637543     7   755656433863
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21  - ÄÄÄÄÄÄÄÄÄÄÄÄ %R21
          1387545279120          198220754160
       ,

          1094352947      31   2794979430821     25
         ÄÄÄÄÄÄÄÄÄÄÄÄ %R21   - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21
         462515093040           462515093040
       + 
           218708802908737     19   91476663003591     13
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21   - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21
             231257546520             77085848840
       + 
           145152550961823     7   1564893370717
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21  - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21
             154171697680           462515093040
       ,

                    4321823003      31
         - %R26 - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21
                  1387545279120
       + 
         180949546069     25   863753195062493     19
         ÄÄÄÄÄÄÄÄÄÄÄÄ %R21   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21
          22746643920            693772639560
       + 
         1088094456732317     13   1732620732685741     7
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21
           693772639560              1387545279120
       + 
         13506088516033
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R21
          1387545279120
       ]
     ,

     [%R22, %R23,

           7865521      31   6696179241     25
         ÄÄÄÄÄÄÄÄÄÄ %R22   - ÄÄÄÄÄÄÄÄÄÄ %R22
         6006689520          2002229840
       + 
           25769893181     19   1975912990729     13
         - ÄÄÄÄÄÄÄÄÄÄÄ %R22   - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22
             49235160             3003344760
       + 
           1048460696489     7   21252634831
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22  - ÄÄÄÄÄÄÄÄÄÄÄ %R22
             2002229840           6006689520
       ,

             778171189       31   1987468196267     25
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22   + ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22
           1387545279120          1387545279120
       + 
         155496778477189     19   191631411158401     13
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22
           693772639560             693772639560
       + 
         300335488637543     7   755656433863
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22  - ÄÄÄÄÄÄÄÄÄÄÄÄ %R22
          1387545279120          198220754160
       ,

          1094352947      31   2794979430821     25
         ÄÄÄÄÄÄÄÄÄÄÄÄ %R22   - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22
         462515093040           462515093040
       + 
           218708802908737     19   91476663003591     13
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22   - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22
             231257546520             77085848840
       + 
           145152550961823     7   1564893370717
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22  - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22
             154171697680           462515093040
       ,

                    4321823003      31
         - %R23 - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22
                  1387545279120
       + 
         180949546069     25   863753195062493     19
         ÄÄÄÄÄÄÄÄÄÄÄÄ %R22   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22
          22746643920            693772639560
       + 
         1088094456732317     13   1732620732685741     7
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22
           693772639560              1387545279120
       + 
         13506088516033
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22
          1387545279120
       ]
     ,

     [%R22, %R24,

           7865521      31   6696179241     25
         ÄÄÄÄÄÄÄÄÄÄ %R22   - ÄÄÄÄÄÄÄÄÄÄ %R22
         6006689520          2002229840
       + 
           25769893181     19   1975912990729     13
         - ÄÄÄÄÄÄÄÄÄÄÄ %R22   - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22
             49235160             3003344760
       + 
           1048460696489     7   21252634831
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22  - ÄÄÄÄÄÄÄÄÄÄÄ %R22
             2002229840           6006689520
       ,

             778171189       31   1987468196267     25
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22   + ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22
           1387545279120          1387545279120
       + 
         155496778477189     19   191631411158401     13
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22
           693772639560             693772639560
       + 
         300335488637543     7   755656433863
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22  - ÄÄÄÄÄÄÄÄÄÄÄÄ %R22
          1387545279120          198220754160
       ,

          1094352947      31   2794979430821     25
         ÄÄÄÄÄÄÄÄÄÄÄÄ %R22   - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22
         462515093040           462515093040
       + 
           218708802908737     19   91476663003591     13
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22   - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22
             231257546520             77085848840
       + 
           145152550961823     7   1564893370717
         - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22  - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22
             154171697680           462515093040
       ,

                    4321823003      31
         - %R24 - ÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22
                  1387545279120
       + 
         180949546069     25   863753195062493     19
         ÄÄÄÄÄÄÄÄÄÄÄÄ %R22   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22
          22746643920            693772639560
       + 
         1088094456732317     13   1732620732685741     7
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22   + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22
           693772639560              1387545279120
       + 
         13506088516033
         ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ %R22
          1387545279120
       ]
     ,
    [%R31,%R35,- %R35 - 4%R31,%R31,%R31,%R31],
    [%R31,%R36,- %R36 - 4%R31,%R31,%R31,%R31],
    [%R32,%R33,- %R33 - 4%R32,%R32,%R32,%R32],
    [%R32,%R34,- %R34 - 4%R32,%R32,%R32,%R32]]
           Type: List List RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LexTriangularPackageXmpPageEmpty22}
\begin{paste}{LexTriangularPackageXmpPageEmpty22}{LexTriangularPackageXmpPagePatch22}
\pastebutton{LexTriangularPackageXmpPageEmpty22}{\showpaste}
\tab{5}\spadcommand{concat [realSolve(ts)$zdpack for ts in lts]\free{lts }\free{zdpack }}
\end{paste}\end{patch}

\end{chunk}
\section{lib.ht}
\pagetitle{LibraryXmpPage}{lib.ht}{Library}
\pageto{notitle}{FileXmpPage}
\pageto{notitle}{TextFileXmpPage}
\pageto{notitle}{KeyedAccessFileXmpPage}
\begin{chunk}{lib.ht}
\begin{page}{LibraryXmpPage}{Library}
\beginscroll
 
The \spadtype{Library} domain provides a simple way to store Axiom
values in a file.  This domain is similar to
\spadtype{KeyedAccessFile} but fewer declarations are needed and items
of different types can be saved together in the same file.
 
\xtc{
To create a library, you supply a file name.
}{
\spadpaste{stuff := library "/tmp/Neat.stuff" \bound{stuff}}
}
\xtc{
Now values can be saved by key in the file.
The keys should be mnemonic, just as the field names are for records.
They can be given either as strings or symbols.
}{
\spadpaste{stuff.int    := 32**2     \free{stuff}\bound{stuffa}}
}
\xtc{
}{
\spadpaste{stuff."poly" := x**2 + 1  \free{stuffa}\bound{stuffb}}
}
\xtc{
}{
\spadpaste{stuff.str    := "Hello"   \free{stuffb}\bound{stuffc}}
}
\xtc{
You obtain
the set of available keys using the \spadfunFrom{keys}{Library} operation.
}{
\spadpaste{keys stuff \free{stuffa,stuffb,stuffc}\bound{stuffabc}}
}
\xtc{
You extract values  by giving the desired key in this way.
}{
\spadpaste{stuff.poly     \free{stuffb}}
}
\xtc{
}{
\spadpaste{stuff("poly")  \free{stuffb}}
}
\noOutputXtc{
When the file is no longer needed, you should remove it from the
file system.
}{
\spadpaste{)system rm -rf /tmp/Neat.stuff  \free{stuff}\bound{rmstuff}}
}
 
For more information on related topics, see
\downlink{`File'}{FileXmpPage}\ignore{File},
\downlink{`TextFile'}{TextFileXmpPage}\ignore{TextFile}, and
\downlink{`KeyedAccessFile'}{KeyedAccessFileXmpPage}
\ignore{KeyedAccessFile}.
\showBlurb{Library}
\endscroll
\autobuttons
\end{page}

\begin{patch}{LibraryXmpPagePatch1}
\begin{paste}{LibraryXmpPageFull1}{LibraryXmpPageEmpty1}
\pastebutton{LibraryXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{stuff := library "/tmp/Neat.stuff"\bound{stuff }}
\indentrel{3}\begin{verbatim}
   (1)  "/tmp/Neat.stuff"
                                          Type: Library
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LibraryXmpPageEmpty1}
\begin{paste}{LibraryXmpPageEmpty1}{LibraryXmpPagePatch1}
\pastebutton{LibraryXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{stuff := library "/tmp/Neat.stuff"\bound{stuff }}
\end{paste}\end{patch}

\begin{patch}{LibraryXmpPagePatch2}
\begin{paste}{LibraryXmpPageFull2}{LibraryXmpPageEmpty2}
\pastebutton{LibraryXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{stuff.int := 32**2\free{stuff }\bound{stuffa }}
\indentrel{3}\begin{verbatim}
   (2)  1024
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LibraryXmpPageEmpty2}
\begin{paste}{LibraryXmpPageEmpty2}{LibraryXmpPagePatch2}
\pastebutton{LibraryXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{stuff.int := 32**2\free{stuff }\bound{stuffa }}
\end{paste}\end{patch}

\begin{patch}{LibraryXmpPagePatch3}
\begin{paste}{LibraryXmpPageFull3}{LibraryXmpPageEmpty3}
\pastebutton{LibraryXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{stuff."poly" := x**2 + 1\free{stuffa }\bound{stuffb }}
\indentrel{3}\begin{verbatim}
         2
   (3)  x  + 1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LibraryXmpPageEmpty3}
\begin{paste}{LibraryXmpPageEmpty3}{LibraryXmpPagePatch3}
\pastebutton{LibraryXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{stuff."poly" := x**2 + 1\free{stuffa }\bound{stuffb }}
\end{paste}\end{patch}

\begin{patch}{LibraryXmpPagePatch4}
\begin{paste}{LibraryXmpPageFull4}{LibraryXmpPageEmpty4}
\pastebutton{LibraryXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{stuff.str := "Hello"\free{stuffb }\bound{stuffc }}
\indentrel{3}\begin{verbatim}
   (4)  "Hello"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LibraryXmpPageEmpty4}
\begin{paste}{LibraryXmpPageEmpty4}{LibraryXmpPagePatch4}
\pastebutton{LibraryXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{stuff.str := "Hello"\free{stuffb }\bound{stuffc }}
\end{paste}\end{patch}

\begin{patch}{LibraryXmpPagePatch5}
\begin{paste}{LibraryXmpPageFull5}{LibraryXmpPageEmpty5}
\pastebutton{LibraryXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{keys stuff\free{stuffa stuffb stuffc }\bound{stuffabc }}
\indentrel{3}\begin{verbatim}
   (5)  ["str","poly","int"]
                                      Type: List String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LibraryXmpPageEmpty5}
\begin{paste}{LibraryXmpPageEmpty5}{LibraryXmpPagePatch5}
\pastebutton{LibraryXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{keys stuff\free{stuffa stuffb stuffc }\bound{stuffabc }}
\end{paste}\end{patch}

\begin{patch}{LibraryXmpPagePatch6}
\begin{paste}{LibraryXmpPageFull6}{LibraryXmpPageEmpty6}
\pastebutton{LibraryXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{stuff.poly\free{stuffb }}
\indentrel{3}\begin{verbatim}
         2
   (6)  x  + 1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LibraryXmpPageEmpty6}
\begin{paste}{LibraryXmpPageEmpty6}{LibraryXmpPagePatch6}
\pastebutton{LibraryXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{stuff.poly\free{stuffb }}
\end{paste}\end{patch}

\begin{patch}{LibraryXmpPagePatch7}
\begin{paste}{LibraryXmpPageFull7}{LibraryXmpPageEmpty7}
\pastebutton{LibraryXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{stuff("poly")\free{stuffb }}
\indentrel{3}\begin{verbatim}
         2
   (7)  x  + 1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LibraryXmpPageEmpty7}
\begin{paste}{LibraryXmpPageEmpty7}{LibraryXmpPagePatch7}
\pastebutton{LibraryXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{stuff("poly")\free{stuffb }}
\end{paste}\end{patch}

\begin{patch}{LibraryXmpPagePatch8}
\begin{paste}{LibraryXmpPageFull8}{LibraryXmpPageEmpty8}
\pastebutton{LibraryXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{)system rm -rf /tmp/Neat.stuff\free{stuff }\bound{rmstuff }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LibraryXmpPageEmpty8}
\begin{paste}{LibraryXmpPageEmpty8}{LibraryXmpPagePatch8}
\pastebutton{LibraryXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{)system rm -rf /tmp/Neat.stuff\free{stuff }\bound{rmstuff }}
\end{paste}\end{patch}

\end{chunk}
\section{link.ht}
\pagetitle{htxl}{link.ht}{The Axiom Link to NAG Software}
\pageto{Introduction to the NAG Library Link}{nagLinkIntroPage}
\pageto{Access the Link from HyperDoc}{htxl1}
\pageto{Browser pages for individual routines}{LispFunctions}
\pageto{NAG Library Documentation}{FoundationLibraryDocPage}
\begin{chunk}{link.ht}
\begin{page}{htxl}{The Axiom Link to NAG Software}
\beginscroll
\beginmenu
\item \menumemolink{Introduction to the NAG Library Link}
{nagLinkIntroPage}
\menumemolink{Access the Link from HyperDoc}{htxl1}
\menulispmemolink{Browser pages for individual routines}
{(|kSearch| "Nag*")}
\menumemolink{NAG Library Documentation}{FoundationLibraryDocPage}
\endmenu
\endscroll
\end{page}

\end{chunk}
\pagetitle{htxl1}{link.ht}{Use of the Link from HyperDoc}
\pageto{notitle}{c02}
\pageto{notitle}{c05}
\pageto{notitle}{c06}
\pageto{notitle}{d01}
\pageto{notitle}{d02}
\pageto{notitle}{d03}
\pageto{notitle}{e01}
\pageto{notitle}{e02}
\pageto{notitle}{e04}
\pageto{notitle}{f01}
\pageto{notitle}{f02}
\pageto{notitle}{f04}
\pageto{notitle}{f07}
\pageto{notitle}{s}
\begin{chunk}{link.ht}
\begin{page}{htxl1}{Use of the Link from HyperDoc}
Click on the chapter of routines that you would like to use.
\beginscroll
\beginmenu
\menumemolink{C02}{c02}\tab{8} Zeros of Polynomials
\menumemolink{C05}{c05}\tab{8} 
Roots of One or More Transcendental Equations
\menumemolink{C06}{c06}\tab{8} Summation of Series
\menumemolink{D01}{d01}\tab{8} Quadrature
\menumemolink{D02}{d02}\tab{8} Ordinary Differential Equations
\menumemolink{D03}{d03}\tab{8} Partial Differential Equations
\menumemolink{E01}{e01}\tab{8} Interpolation
\menumemolink{E02}{e02}\tab{8} Curve and Surface Fitting
\menumemolink{E04}{e04}\tab{8} Minimizing or Maximizing a Function
\menumemolink{F01}{f01}\tab{8} Matrix Operations, Including Inversion
\menumemolink{F02}{f02}\tab{8} Eigenvalues and Eigenvectors
\menumemolink{F04}{f04}\tab{8} Simultaneous Linear Equations
\menumemolink{F07}{f07}\tab{8} Linear Equations (LAPACK)
\menumemolink{S}{s}\tab{8} Approximations of Special Functions
\endmenu
\endscroll
\end{page}

\end{chunk}
\pagetitle{c02}{link.ht}{C02 Zeros of Polynomials}
\pageto{Foundation Library Chapter c02 Manual Page}{manpageXXc02}
\pageto{Browse}{LispFunctions}
\pageto{C02AFF}{LispFunctions}
\pageto{C02AGF}{LispFunctions}
\begin{chunk}{link.ht}
\begin{page}{c02}{C02 Zeros of Polynomials}
\beginscroll
\centerline{What would you like to do?}
\newline
\beginmenu
\item Read
\menuwindowlink{Foundation Library Chapter c02 Manual Page}
{manpageXXc02}
\item or
\menulispwindowlink{Browse}{(|kSearch| "NagPolynomialRootsPackage")}
\tab{10} through this chapter
\item or use the routines:
\menulispdownlink{C02AFF}{(|c02aff|)}\space{}
\tab{10}  All zeros of a complex polynomial 
\menulispdownlink{C02AGF}{(|c02agf|)}\space{}
\tab{10}  All zeros of a real polynomial
\endmenu
\endscroll
\autobuttons 
\end{page}

\end{chunk}
\pagetitle{c05}{link.ht}
{C05 Roots of One or More Transcendental Equations}
\pageto{Foundation Library Chapter c05 Manual Page}{manpageXXc05}
\pageto{Browse}{LispFunctions}
\pageto{C05ADF}{LispFunctions}
\pageto{C05NBF}{LispFunctions}
\pageto{C05PBF}{LispFunctions}
\begin{chunk}{link.ht}
\begin{page}{c05}{C05 Roots of One or More Transcendental Equations}
\beginscroll
\centerline{What would you like to do?}
\newline
\beginmenu
\item Read
\menuwindowlink{Foundation Library Chapter c05 Manual Page}
{manpageXXc05}
\item or
\menulispwindowlink{Browse}{(|kSearch| "NagRootFindingPackage")}
\tab{10} through this chapter
\item or use the routines:
\menulispdownlink{C05ADF}{(|c05adf|)}\space{}
\tab{10}  Zero of continuous function in given interval, 
Bus and Dekker algorithm
\menulispdownlink{C05NBF}{(|c05nbf|)}\space{}
\tab{10}  Solution of system of nonlinear equations using 
function values only
\menulispdownlink{C05PBF}{(|c05pbf|)}\space{}
\tab{10}  Solution of system of nonlinear equations using 
1st derivatives
\endmenu
\endscroll
\autobuttons 
\end{page}

\end{chunk}
\pagetitle{c06}{link.ht}{C06 Summation of Series}
\pageto{Foundation Library Chapter c06 Manual Page}{manpageXXc06}
\pageto{Browse}{LispFunctions}
\pageto{C06EAF}{LispFunctions}
\pageto{C06EBF}{LispFunctions}
\pageto{C06ECF}{LispFunctions}
\pageto{C06EKF}{LispFunctions}
\pageto{C06FPF}{LispFunctions}
\pageto{C06FQF}{LispFunctions}
\pageto{C06FRF}{LispFunctions}
\pageto{C06FUF}{LispFunctions}
\pageto{C06GBF}{LispFunctions}
\pageto{C06GCF}{LispFunctions}
\pageto{C06GQF}{LispFunctions}
\pageto{C06GSF}{LispFunctions}
\begin{chunk}{link.ht}
\begin{page}{c06}{C06 Summation of Series}
\beginscroll
\centerline{What would you like to do?}
\newline
\beginmenu
\item Read
\menuwindowlink{Foundation Library Chapter c06 Manual Page}
{manpageXXc06}
\item or
\menulispwindowlink{Browse}{(|kSearch| "NagSeriesSummationPackage")}
\tab{10} through this chapter
\item or use the routines:
\menulispdownlink{C06EAF}{(|c06eaf|)}\space{}
\tab{10}  Single 1-D real discrete Fourier transform, no extra 
workspace
\menulispdownlink{C06EBF}{(|c06ebf|)}\space{}
\tab{10}  Single 1-D Hermitian discrete Fourier transform, no 
extra workspace
\menulispdownlink{C06ECF}{(|c06ecf|)}\space{}
\tab{10}  Single 1-D complex discrete Fourier transform, no 
extra workspace
\menulispdownlink{C06EKF}{(|c06ekf|)}\space{}
\tab{10}  Circular convolution or correlation of two real 
vectors, no extra
workspace
\menulispdownlink{C06FPF}{(|c06fpf|)}\space{}
\tab{10}  Multiple 1-D real discrete Fourier transforms
\menulispdownlink{C06FQF}{(|c06fqf|)}\space{}
\tab{10}  Multiple 1-D Hermitian discrete Fourier transforms
\menulispdownlink{C06FRF}{(|c06frf|)}\space{}
\tab{10}  Multiple 1-D complex discrete Fourier transforms
\menulispdownlink{C06FUF}{(|c06fuf|)}\space{}
\tab{10}  2-D complex discrete Fourier transforms
\menulispdownlink{C06GBF}{(|c06gbf|)}\space{}
\tab{10}  Complex conjugate of Hermitian sequence
\menulispdownlink{C06GCF}{(|c06gcf|)}\space{}
\tab{10}  Complex conjugate of complex sequence
\menulispdownlink{C06GQF}{(|c06gqf|)}\space{}
\tab{10}  Complex conjugate of multiple Hermitian sequences
\menulispdownlink{C06GSF}{(|c06gsf|)}\space{}
\tab{10}  Convert Hermitian sequences to general complex sequences
\endmenu
\endscroll
\autobuttons 
\end{page}

\end{chunk}
\pagetitle{d01}{link.ht}{D01 Quadrature}
\pageto{Foundation Library Chapter d01 Manual Page}{manpageXXd01}
\pageto{Browse}{LispFunctions}
\pageto{D01AJF}{LispFunctions}
\pageto{D01AKF}{LispFunctions}
\pageto{D01ALF}{LispFunctions}
\pageto{D01AMF}{LispFunctions}
\pageto{D01ANF}{LispFunctions}
\pageto{D01APF}{LispFunctions}
\pageto{D01AQF}{LispFunctions}
\pageto{D01ASF}{LispFunctions}
\pageto{D01BBF}{LispFunctions}
\pageto{D01FCF}{LispFunctions}
\pageto{D01GAF}{LispFunctions}
\pageto{D01GBF}{LispFunctions}
\begin{chunk}{link.ht}
\begin{page}{d01}{D01 Quadrature}
\beginscroll
\centerline{What would you like to do?}
\newline
\beginmenu
\item Read
\menuwindowlink{Foundation Library Chapter d01 Manual Page}
{manpageXXd01}
\item or
\menulispwindowlink{Browse}{(|kSearch| "NagIntegrationPackage")}
\tab{10} through this chapter
\item or use the routines:
\menulispdownlink{D01AJF}{(|d01ajf|)}\space{}
\tab{10}  1-D quadrature, adaptive, finite interval, strategy 
due to Plessens
and de Doncker, allowing for badly-behaved integrands
\menulispdownlink{D01AKF}{(|d01akf|)}\space{}
\tab{10}  1-D quadrature, adaptive, finite interval, method 
suitable for
oscillating functions
\menulispdownlink{D01ALF}{(|d01alf|)}\space{}
\tab{10}  1-D quadrature, adaptive, finite interval, allowing for 
singularities at user specified points
\menulispdownlink{D01AMF}{(|d01amf|)}\space{}
\tab{10}  1-D quadrature, adaptive, infinite or semi-finite interval
\menulispdownlink{D01ANF}{(|d01anf|)}\space{}
\tab{10}  1-D quadrature, adaptive, finite interval, weight function
 cos(\omega x) or sin(\omega x)
\menulispdownlink{D01APF}{(|d01apf|)}\space{}
\tab{10}  1-D quadrature, adaptive, finite interval, weight function
with end point singularities of algebraico-logarithmic type
\menulispdownlink{D01AQF}{(|d01aqf|)}\space{}
\tab{10}  1-D quadrature, adaptive, finite interval, weight function
1/(x-c), Cauchy principle value (Hilbert transform)
\menulispdownlink{D01ASF}{(|d01asf|)}\space{}
\tab{10}  1-D quadrature, adaptive, semi-infinite interval, 
weight function
cos(\omega x) or sin(\omega x)
\menulispdownlink{D01BBF}{(|d01bbf|)}\space{}
\tab{10} Pre-computed weights and abscissae for Gaussian 
quadrature rules,
restricted choice of rule
\menulispdownlink{D01FCF}{(|d01fcf|)}\space{}
\tab{10} Multi-dimensional adaptive quadrature over 
hyper-rectangle
\menulispdownlink{D01GAF}{(|d01gaf|)}\space{}
\tab{10} 1-D quadrature, integration of function defined 
by data values,
Gill-Miller method
\menulispdownlink{D01GBF}{(|d01gbf|)}\space{}
\tab{10} Multi-dimensional quadrature over hyper-rectangle, 
Monte Carlo method
\endmenu
\endscroll
\autobuttons 
\end{page}

\end{chunk}
\pagetitle{d02}{link.ht}{D02 Ordinary Differential Equations}
\pageto{notitle}{manpageXXd02}
\begin{chunk}{link.ht}
\begin{page}{d02}{D02 Ordinary Differential Equations}
\pageto{Foundation Library Chapter d02 Manual Page}{manpageXXd02}
\pageto{Browse}{LispFunctions}
\pageto{D02BBF}{LispFunctions}
\pageto{D02BHF}{LispFunctions}
\pageto{D02CJF}{LispFunctions}
\pageto{D02EJF}{LispFunctions}
\pageto{D02GAF}{LispFunctions}
\pageto{D02GBF}{LispFunctions}
\pageto{D02KEF}{LispFunctions}
\pageto{D02RAF}{LispFunctions}
\beginscroll
\centerline{What would you like to do?}
\newline
\beginmenu
\item Read
\menuwindowlink{Foundation Library Chapter d02 Manual Page}
{manpageXXd02}
\item or
\menulispwindowlink{Browse}
{(|kSearch| "NagOrdinaryDifferentialEquationsPackage")}
\tab{10} through this chapter
\item or use the routines:
\menulispdownlink{D02BBF}{(|d02bbf|)}\space{}
\tab{10}  ODEs, IVP, Runge-Kutta-Merson method, over a range, 
intermediate output
\menulispdownlink{D02BHF}{(|d02bhf|)}\space{}
\tab{10}  ODEs, IVP, Runge-Kutta-Merson method, until function of 
solution is zero
\menulispdownlink{D02CJF}{(|d02cjf|)}\space{}
\tab{10}  ODEs, IVP, Adams method, until function of solution 
is zero,
intermediate output
\menulispdownlink{D02EJF}{(|d02ejf|)}\space{}
\tab{10}  ODEs, stiff IVP, BDF method, until function of solution 
is zero,
intermediate output
\menulispdownlink{D02GAF}{(|d02gaf|)}\space{}
\tab{10}  ODEs, boundary value problem, finite difference technique 
with deferred correction, simple nonlinear problem
\menulispdownlink{D02GBF}{(|d02gbf|)}\space{}
\tab{10}  ODEs, boundary value problem, finite difference technique 
with deferred correction, general nonlinear problem
\menulispdownlink{D02KEF}{(|d02kef|)}\space{}
\tab{10}  2nd order Sturm-Liouville problem, regular/singular system,
finite/infinite range, eigenvalue and eigenfunction, user-specified 
break-points
\menulispdownlink{D02RAF}{(|d02raf|)}\space{}
\tab{10}  ODEs, general nonlinear boundary value problem, finite 
difference technique with deferred correction, continuation facility
\endmenu
\endscroll
\autobuttons 
\end{page}

\end{chunk}
\pagetitle{d03}{link.ht}{D03 Partial Differential Equations}
\pageto{Foundation Library Chapter d03 Manual Page}{manpageXXd03}
\pageto{Browse}{LispFunctions}
\pageto{D03EDF}{LispFunctions}
\pageto{D03EEF}{LispFunctions}
\pageto{D03FAF}{LispFunctions}
\begin{chunk}{link.ht}
\begin{page}{d03}{D03 Partial Differential Equations}
\beginscroll
\centerline{What would you like to do?}
\newline
\beginmenu
\item Read
\menuwindowlink{Foundation Library Chapter d03 Manual Page}
{manpageXXd03}
\item or
\menulispwindowlink{Browse}
{(|kSearch| "NagPartialDifferentialEquationsPackage")}
\tab{10} through this chapter
\item or use the routines:
\menulispdownlink{D03EDF}{(|d03edf|)}\space{}
\tab{10}  Elliptic PDE, solution of finite difference equations 
by a multigrid technique
\menulispdownlink{D03EEF}{(|d03eef|)}\space{}
\tab{10}  Discretize a 2nd order elliptic PDE on a rectangle
\menulispdownlink{D03FAF}{(|d03faf|)}\space{}
\tab{10}  Elliptic PDE, Helmholtz equation, 3-D Cartesian co-ordinates
\endmenu
\endscroll
\autobuttons 
\end{page}

\end{chunk}
\pagetitle{e01}{link.ht}{E01 Interpolation}
\pageto{Foundation Library Chapter e01 Manual Page}{manpageXXe01}
\pageto{Browse}{LispFunctions}
\pageto{E01BAF}{LispFunctions}
\pageto{E01BEF}{LispFunctions}
\pageto{E01BFF}{LispFunctions}
\pageto{E01BGF}{LispFunctions}
\pageto{E01BHF}{LispFunctions}
\pageto{E01DAF}{LispFunctions}
\pageto{E01SAF}{LispFunctions}
\pageto{E01SEF}{LispFunctions}
\begin{chunk}{link.ht}
\begin{page}{e01}{E01 Interpolation}
\beginscroll
\centerline{What would you like to do?}
\beginmenu
\item Read
\menuwindowlink{Foundation Library Chapter e01 Manual Page}
{manpageXXe01}
\item or
\menulispwindowlink{Browse}{(|kSearch| "NagInterpolationPackage")}
\tab{10} through this chapter
\item or use the routines:
\menulispdownlink{E01BAF}{(|e01baf|)}\space{}
\tab{10}  Interpolating functions, cubic spline interpolant, 
one variable
\menulispdownlink{E01BEF}{(|e01bef|)}\space{}
\tab{10}  Interpolating functions, monotonicity-preserving, piecewise
cubic Hermite, one variable
\menulispdownlink{E01BFF}{(|e01bff|)}\space{}
\tab{10}  Interpolated values, interpolant computed by E01BEF, function
only, one variable
\menulispdownlink{E01BGF}{(|e01bgf|)}\space{}
\tab{10}  Interpolated values, interpolant computed by E01BEF, function
and 1st derivative, one variable
\menulispdownlink{E01BHF}{(|e01bhf|)}\space{}
\tab{10}  Interpolated values, interpolant computed by E01BEF, definite
integral, one variable
\menulispdownlink{E01DAF}{(|e01daf|)}\space{}
\tab{10}  Interpolating functions, fitting bicubic spline, data on a 
rectangular grid
\menulispdownlink{E01SAF}{(|e01saf|)}\space{}
\tab{10}  Interpolating functions, method of Renka and Cline, 
two variables
\menulispdownlink{E01SEF}{(|e01sef|)}\space{}
\tab{10}  Interpolating functions, modified Shepherd's method, 
two variables
\endmenu
\endscroll
\autobuttons 
\end{page}

\end{chunk}
\pagetitle{e02}{link.ht}{E02 Curve and Surface Fitting}
\pageto{Foundation Library Chapter e02 Manual Page}{manpageXXe02}
\pageto{Browse}{LispFunctions}
\pageto{E02ADF}{LispFunctions}
\pageto{E02AEF}{LispFunctions}
\pageto{E02AGF}{LispFunctions}
\pageto{E02AHF}{LispFunctions}
\pageto{E02AJF}{LispFunctions}
\pageto{E02AKF}{LispFunctions}
\pageto{E02BAF}{LispFunctions}
\pageto{E02BBF}{LispFunctions}
\pageto{E02BCF}{LispFunctions}
\pageto{E02BDF}{LispFunctions}
\pageto{E02BEF}{LispFunctions}
\pageto{E02DAF}{LispFunctions}
\pageto{E02DCF}{LispFunctions}
\pageto{E02DDF}{LispFunctions}
\pageto{E02DEF}{LispFunctions}
\pageto{E02DFF}{LispFunctions}
\pageto{E02GAF}{LispFunctions}
\pageto{E02ZAF}{LispFunctions}
\begin{chunk}{link.ht}
\begin{page}{e02}{E02 Curve and Surface Fitting}
\beginscroll
\centerline{What would you like to do?}
\beginmenu
\item Read
\menuwindowlink{Foundation Library Chapter e02 Manual Page}
{manpageXXe02}
\item or
\menulispwindowlink{Browse}{(|kSearch| "NagFittingPackage")}
\tab{10} through this chapter
\item or use the routines:
\menulispdownlink{E02ADF}{(|e02adf|)}\space{}
\tab{10}  Least-squares curve fit, by polynomials, arbitrary 
data points
\menulispdownlink{E02AEF}{(|e02aef|)}\space{}
\tab{10}  Evaluation of fitted polynomial in one variable from 
Chebyshev series
form (simplified parameter list)
\menulispdownlink{E02AGF}{(|e02agf|)}\space{}
\tab{10}  Least-squares polynomial fit, values and derivatives 
may be
constrained, arbitrary data points
\menulispdownlink{E02AHF}{(|e02ahf|)}\space{}
\tab{10}  Derivative of fitted polynomial in Chebyshev series form
\menulispdownlink{E02AJF}{(|e02ajf|)}\space{}
\tab{10}  Integral of fitted polynomial in Chebyshev series form
\menulispdownlink{E02AKF}{(|e02akf|)}\space{}
\tab{10}  Evaluation of fitted polynomial in one variable, from 
Chebyshev 
series form
\menulispdownlink{E02BAF}{(|e02baf|)}\space{}
\tab{10}  Least-squares curve cubic spline fit (including 
interpolation)
\menulispdownlink{E02BBF}{(|e02bbf|)}\space{}
\tab{10}  Evaluation of fitted cubic spline, function only
\menulispdownlink{E02BCF}{(|e02bcf|)}\space{}
\tab{10}  Evaluation of fitted cubic spline, function and derivatives
\menulispdownlink{E02BDF}{(|e02bdf|)}\space{}
\tab{10}  Evaluation of fitted cubic spline, definite integral
\menulispdownlink{E02BEF}{(|e02bef|)}\space{}
\tab{10}  Least-squares curve cubic spline fit, automatic knot placement
\menulispdownlink{E02DAF}{(|e02daf|)}\space{}
\tab{10}  Least-squares surface fit, bicubic splines
\menulispdownlink{E02DCF}{(|e02dcf|)}\space{}
\tab{10}  Least-squares surface fit by bicubic splines with automatic 
knot placement, data on a rectangular grid
\menulispdownlink{E02DDF}{(|e02ddf|)}\space{}
\tab{10}  Least-squares surface fit by bicubic splines with automatic 
knot placement, scattered data
\menulispdownlink{E02DEF}{(|e02def|)}\space{}
\tab{10}  Evaluation of a fitted bicubic spline at a vector of points
\menulispdownlink{E02DFF}{(|e02dff|)}\space{}
\tab{10}  Evaluation of a fitted bicubic spline at a mesh of points
\menulispdownlink{E02GAF}{(|e02gaf|)}\space{}
\tab{10}  \htbitmap{l1}-approximation by general linear function
\menulispdownlink{E02ZAF}{(|e02zaf|)}\space{}
\tab{10}  Sort 2-D sata into panels for fitting bicubic splines
\endmenu
\endscroll
\autobuttons 
\end{page}

\end{chunk}
\pagetitle{e04}{link.ht}{E04 Minimizing or Maximizing a Function}
\pageto{Foundation Library Chapter e04 Manual Page}{manpageXXe04}
\pageto{Browse}{LispFunctions}
\pageto{E04DGF}{LispFunctions}
\pageto{E04FDF}{LispFunctions}
\pageto{E04GCF}{LispFunctions}
\pageto{E04JAF}{LispFunctions}
\pageto{E04MBF}{LispFunctions}
\pageto{E04NAF}{LispFunctions}
\pageto{E04UCF}{LispFunctions}
\pageto{E04YCF}{LispFunctions}
\begin{chunk}{link.ht}
\begin{page}{e04}{E04 Minimizing or Maximizing a Function}
\beginscroll
\centerline{What would you like to do?}
\newline
\beginmenu
\item Read
\menuwindowlink{Foundation Library Chapter e04 Manual Page}
{manpageXXe04}
\item or
\menulispwindowlink{Browse}{(|kSearch| "NagOptimisationPackage")}
\tab{10} through this chapter
\item or use the routines:
\menulispdownlink{E04DGF}{(|e04dgf|)}\space{}
\tab{10}  Unconstrained minimum, pre-conditioned conjugate gradient 
algorithm, function of several variables using 1st derivatives
\menulispdownlink{E04FDF}{(|e04fdf|)}\space{}
\tab{10}  Unconstrained minimum of a sum of squares, combined 
Gauss-Newton and modified Newton algorithm using function values only
\menulispdownlink{E04GCF}{(|e04gcf|)}\space{}
\tab{10}  Unconstrained minimum, of a sum of squares, combined 
Gauss-Newton and modified Newton algorithm using 1st derivatives
\menulispdownlink{E04JAF}{(|e04jaf|)}\space{}
\tab{10}  Minimum, function of several variables, quasi-Newton 
algorithm, simple bounds, using function values only
\menulispdownlink{E04MBF}{(|e04mbf|)}\space{}
\tab{10}  Linear programming problem
\menulispdownlink{E04NAF}{(|e04naf|)}\space{}
\tab{10}  Quadratic programming problem
\menulispdownlink{E04UCF}{(|e04ucf|)}\space{}
\tab{10}  Minimum, function of several variables, sequential QP method,
nonlinear constraints, using function values and optionally 1st 
derivatives 
\menulispdownlink{E04YCF}{(|e04ycf|)}\space{}
\tab{10}  Covariance matrix for non-linear least-squares problem
\endmenu
\endscroll
\autobuttons 
\end{page}

\end{chunk}
\pagetitle{f01}{link.ht}{F01 Matrix Operations - Including Inversion}
\pageto{Foundation Library Chapter f Manual Page}{manpageXXf}
\pageto{Foundation Library Chapter f01 Manual Page}{manpageXXf01}
\pageto{Browse}{LispFunctions}
\pageto{F01BRF}{LispFunctions}
\pageto{F01BSF}{LispFunctions}
\pageto{F01MAF}{LispFunctions}
\pageto{F01MCF}{LispFunctions}
\pageto{F01QCF}{LispFunctions}
\pageto{F01QDF}{LispFunctions}
\pageto{F01QEF}{LispFunctions}
\pageto{F01RCF}{LispFunctions}
\pageto{F01RDF}{LispFunctions}
\pageto{F01REF}{LispFunctions}
\begin{chunk}{link.ht}
\begin{page}{f01}{F01 Matrix Operations - Including Inversion}
\beginscroll
\centerline{What would you like to do?}
\beginmenu
\item Read
\menuwindowlink{Foundation Library Chapter f Manual Page}
{manpageXXf}
\menuwindowlink{Foundation Library Chapter f01 Manual Page}
{manpageXXf01}
\item or
\menulispwindowlink{Browse}{(|kSearch| "NagMatrixOperationsPackage")}
\tab{10} through this chapter
\item or use the routines:
\menulispdownlink{F01BRF}{(|f01brf|)}\space{}
\tab{10}  {\it LU} factorization of real sparse matrix
\menulispdownlink{F01BSF}{(|f01bsf|)}\space{}
\tab{10}  {\it LU} factorization of real sparse matrix with known 
sparsity pattern
\menulispdownlink{F01MAF}{(|f01maf|)}\space{}
\tab{10}  \htbitmap{llt} factorization of real sparse
symmetric positive-definite matrix
\menulispdownlink{F01MCF}{(|f01mcf|)}\space{}
\tab{10}  \htbitmap{ldlt} factorization of real 
symmetric positive-definite variable-bandwith matrix
\menulispdownlink{F01QCF}{(|f01qcf|)}\space{}
\tab{10}  {\it QR} factorization of real {\it m} by {\it n} matrix 
(m \htbitmap{great=} n)
\menulispdownlink{F01QDF}{(|f01qdf|)}\space{}
\tab{10} Operations with orthogonal matrices, compute {\it QB} or
\htbitmap{f01qdf} after factorization by F01QCF or F01QFF
\menulispdownlink{F01QEF}{(|f01qef|)}\space{}
\tab{10} Operations with orthogonal matrices, form columns of {\it Q}
after factorization by F01QCF or F01QFF 
\menulispdownlink{F01RCF}{(|f01rcf|)}\space{}
\tab{10} {\it QR} factorization of complex {\it m} by {\it n} matrix 
(m \htbitmap{great=} n) 
\menulispdownlink{F01RDF}{(|f01rdf|)}\space{}
\tab{10} Operations with unitary matrices, compute {\it QB} or
\htbitmap{f01rdf} after factorization by F01RCF
\menulispdownlink{F01REF}{(|f01ref|)}\space{}
\tab{10} Operations with unitary matrices, form columns of {\it Q}
after factorization by F01RCF
\endmenu
\endscroll
\autobuttons 
\end{page}

\end{chunk}
\pagetitle{f02}{link.ht}{F02 Eigenvalues and Eigenvectors}
\pageto{Foundation Library Chapter f Manual Page}{manpageXXf}
\pageto{Foundation Library Chapter f02 Manual Page}{manpageXXf02}
\pageto{Browse}{LispFunctions}
\pageto{F02AAF}{LispFunctions}
\pageto{F02ABF}{LispFunctions}
\pageto{F02ADF}{LispFunctions}
\pageto{F02AEF}{LispFunctions}
\pageto{F02AFF}{LispFunctions}
\pageto{F02AGF}{LispFunctions}
\pageto{F02AJF}{LispFunctions}
\pageto{F02AKF}{LispFunctions}
\pageto{F02AWF}{LispFunctions}
\pageto{F02AXF}{LispFunctions}
\pageto{F02BBF}{LispFunctions}
\pageto{F02BJF}{LispFunctions}
\pageto{F02FJF}{LispFunctions}
\pageto{F02WEF}{LispFunctions}
\pageto{F02XEF}{LispFunctions}
\begin{chunk}{link.ht}
\begin{page}{f02}{F02 Eigenvalues and Eigenvectors}
\beginscroll
\centerline{What would you like to do?}
\beginmenu
\item Read
\menuwindowlink{Foundation Library Chapter f Manual Page}{manpageXXf}
\menuwindowlink{Foundation Library Chapter f02 Manual Page}
{manpageXXf02}
\item or
\menulispwindowlink{Browse}{(|kSearch| "NagEigenPackage")}
\tab{10} through this chapter
\item or use the routines:
\menulispdownlink{F02AAF}{(|f02aaf|)}\space{}
\tab{10}  All eigenvalues of real symmetric matrix (Black box)
\menulispdownlink{F02ABF}{(|f02abf|)}\space{}
\tab{10}  All eigenvalues and eigenvectors of real symmetric 
matrix (Black box)
\menulispdownlink{F02ADF}{(|f02adf|)}\space{}
\tab{10}  All eigenvalues of generalized real eigenproblem of the form
Ax = \lambda Bx where A and B are symmetric and B is positive definite
\menulispdownlink{F02AEF}{(|f02aef|)}\space{}
\tab{10}  All eigenvalues and eigenvectors of generalized real 
eigenproblem of the form Ax = \lambda Bx where A and B are symmetric 
and B is positive definite
\menulispdownlink{F02AFF}{(|f02aff|)}\space{}
\tab{10}  All eigenvalues of real matrix (Black box)
\menulispdownlink{F02AGF}{(|f02agf|)}\space{}
\tab{10}  All eigenvalues and eigenvectors of real matrix (Black box)
\menulispdownlink{F02AJF}{(|f02ajf|)}\space{}
\tab{10}  All eigenvalues of complex matrix (Black box)
\menulispdownlink{F02AKF}{(|f02akf|)}\space{}
\tab{10}  All eigenvalues and eigenvectors of complex matrix 
(Black box)
\menulispdownlink{F02AWF}{(|f02awf|)}\space{}
\tab{10}  All eigenvalues of complex Hermitian matrix (Black box)
\menulispdownlink{F02AXF}{(|f02axf|)}\space{}
\tab{10}  All eigenvalues and eigenvectors of complex Hermitian 
matrix (Black box)
\menulispdownlink{F02BBF}{(|f02bbf|)}\space{}
\tab{10}  Selected eigenvalues and eigenvectors of real symmetric
matrix (Black box)
\menulispdownlink{F02BJF}{(|f02bjf|)}\space{}
\tab{10}  All eigenvalues and optionally eigenvectors of generalized
eigenproblem by {\it QZ} algorithm, real matrices (Black box)
\menulispdownlink{F02FJF}{(|f02fjf|)}\space{}
\tab{10}  Selected eigenvalues and eigenvectors of sparse symmetric 
eigenproblem
\menulispdownlink{F02WEF}{(|f02wef|)}\space{}
\tab{10}  SVD of real matrix
\menulispdownlink{F02XEF}{(|f02xef|)}\space{}
\tab{10}  SVD of complex matrix
\endmenu
\endscroll
\autobuttons 
\end{page}

\end{chunk}
\pagetitle{f04}{link.ht}{F04 Simultaneous Linear Equations}
\pageto{Foundation Library Chapter f Manual Page}{manpageXXf}
\pageto{Foundation Library Chapter f04 Manual Page}{manpageXXf04}
\pageto{Browse}{LispFunctions}
\pageto{F04ADF}{LispFunctions}
\pageto{F04ARF}{LispFunctions}
\pageto{F04ASF}{LispFunctions}
\pageto{F04ATF}{LispFunctions}
\pageto{F04AXF}{LispFunctions}
\pageto{F04FAF}{LispFunctions}
\pageto{F04JGF}{LispFunctions}
\pageto{F04MAF}{LispFunctions}
\pageto{F04MBF}{LispFunctions}
\pageto{F04MCF}{LispFunctions}
\pageto{F04QAF}{LispFunctions}
\begin{chunk}{link.ht}
\begin{page}{f04}{F04 Simultaneous Linear Equations}
\beginscroll
\centerline{What would you like to do?}
\beginmenu
\item Read
\menuwindowlink{Foundation Library Chapter f Manual Page}
{manpageXXf}
\menuwindowlink{Foundation Library Chapter f04 Manual Page}
{manpageXXf04}
\item or
\menulispwindowlink{Browse}
{(|kSearch| "NagLinearEquationSolvingPackage")}\tab{10} through 
this chapter 
\item or use the routines:
\menulispdownlink{F04ADF}{(|f04adf|)}\space{}
\tab{10}  Solution of complex simultaneous linear equations, with 
multiple right-hand sides (Black box)
\menulispdownlink{F04ARF}{(|f04arf|)}\space{}
\tab{10}  Solution of real simultaneous linear equations, one 
right-hand side
(Black box)
\menulispdownlink{F04ASF}{(|f04asf|)}\space{}
\tab{10}  Solution of real symmetric positive-definite simultaneous 
linear equations, one right-hand side using iterative refinement 
(Black box)
\menulispdownlink{F04ATF}{(|f04atf|)}\space{}
\tab{10}  Solution of real simultaneous linear equations, one 
right-hand side 
using iterative refinement (Black box)
\menulispdownlink{F04AXF}{(|f04axf|)}\space{}
\tab{10}  Approximate solution of real sparse simultaneous linear 
equations (coefficient matrix already factorized by F01BRF or F01BSF)
\menulispdownlink{F04FAF}{(|f04faf|)}\space{}
\tab{10}  Solution of real symmetric positive-definite tridiagonal 
simultaneous linear equations, one right-hand side (Black box)
\menulispdownlink{F04JGF}{(|f04jgf|)}\space{}
\tab{10}  Least-squares (if rank = n) or minimal least-squares 
(if rank < n) solution of m real equations in n unknowns, rank 
\htbitmap{less=} n, m \htbitmap{great=} n
\menulispdownlink{F04MAF}{(|f04maf|)}\space{}
\tab{10}  Real sparse symmetric positive-definite simultaneous linear
equations(coefficient matrix already factorized)
\menulispdownlink{F04MBF}{(|f04mbf|)}\space{}
\tab{10}  Real sparse symmetric simultaneous linear equations
\menulispdownlink{F04MCF}{(|f04mcf|)}\space{}
\tab{10}  Approximate solution of real symmetric positive-definite 
variable-bandwidth simultaneous linear equations (coefficient matrix 
already factorized)
\menulispdownlink{F04QAF}{(|f04qaf|)}\space{}
\tab{10}  Sparse linear least-squares problem, {\it m} real equations
in {\it n} unknowns
\endmenu
\endscroll
\autobuttons 
\end{page}

\end{chunk}
\pagetitle{f07}{link.ht}{F07 Linear Equations (LAPACK)}
\pageto{Foundation Library Chapter f Manual Page}{manpageXXf}
\pageto{Foundation Library Chapter f07 Manual Page}{manpageXXf07}
\pageto{Browse}{LispFunctions}
\pageto{F07ADF}{LispFunctions}
\pageto{F07AEF}{LispFunctions}
\pageto{F07FDF}{LispFunctions}
\pageto{F07FEF}{LispFunctions}
\begin{chunk}{link.ht}
\begin{page}{f07}{F07 Linear Equations (LAPACK)}
\beginscroll
\centerline{What would you like to do?}
\beginmenu
\item Read
\menuwindowlink{Foundation Library Chapter f Manual Page}{manpageXXf}
\menuwindowlink{Foundation Library Chapter f07 Manual Page}{manpageXXf07}
\item or
\menulispwindowlink{Browse}
{(|kSearch| "NagLapack")}\tab{10} through this chapter
\item or use the routines:
\menulispdownlink{F07ADF}{(|f07adf|)}\space{}
\tab{10}  (DGETRF) {\it LU} factorization of real 
{\it m} by {\it n} matrix
\menulispdownlink{F07AEF}{(|f07aef|)}\space{}
\tab{10}  (DGETRS) Solution of real system of linear equations, 
multiple right hand sides, matrix factorized by F07ADF
\menulispdownlink{F07FDF}{(|f07fdf|)}\space{}
\tab{10}  (DPOTRF) Cholesky factorization of real symmetric 
positive-definite matrix
\menulispdownlink{F07FEF}{(|f07fef|)}\space{}
\tab{10}  (DPOTRS) Solution of real symmetric positive-definite 
system of linear equations, multiple right-hand sides, matrix 
already factorized by F07FDF
\endmenu
\endscroll
\autobuttons 
\end{page}

\end{chunk}
\pagetitle{s}{link.ht}{S -- Approximations of Special Functions}
\pageto{Foundation Library Chapter s Manual Page}{manpageXXs}
\pageto{Browse}{LispFunctions}
\pageto{S01EAF}{LispFunctions}
\pageto{S13AAF}{LispFunctions}
\pageto{S13ACF}{LispFunctions}
\pageto{S13ADF}{LispFunctions}
\pageto{S14AAF}{LispFunctions}
\pageto{S14ABF}{LispFunctions}
\pageto{S14BAF}{LispFunctions}
\pageto{S15ADF}{LispFunctions}
\pageto{S15AEF}{LispFunctions}
\pageto{S17ACF}{LispFunctions}
\pageto{S17ADF}{LispFunctions}
\pageto{S17AEF}{LispFunctions}
\pageto{S17AFF}{LispFunctions}
\pageto{S17AGF}{LispFunctions}
\pageto{S17AHF}{LispFunctions}
\pageto{S17AJF}{LispFunctions}
\pageto{S17AKF}{LispFunctions}
\pageto{S17DCF}{LispFunctions}
\pageto{S17DEF}{LispFunctions}
\pageto{S17DGF}{LispFunctions}
\pageto{S17DHF}{LispFunctions}
\pageto{S17DLF}{LispFunctions}
\pageto{S18ACF}{LispFunctions}
\pageto{S18ADF}{LispFunctions}
\pageto{S18AEF}{LispFunctions}
\pageto{S18AFF}{LispFunctions}
\pageto{S18DCF}{LispFunctions}
\pageto{S18DEF}{LispFunctions}
\pageto{S19AAF}{LispFunctions}
\pageto{S19ABF}{LispFunctions}
\pageto{S19ACF}{LispFunctions}
\pageto{S19ADF}{LispFunctions}
\pageto{S20ACF}{LispFunctions}
\pageto{S20ADF}{LispFunctions}
\pageto{S21BAF}{LispFunctions}
\pageto{S21BBF}{LispFunctions}
\pageto{S21BCF}{LispFunctions}
\pageto{S21BDF}{LispFunctions}

\begin{chunk}{link.ht}
\begin{page}{s}{S \space{2} Approximations of Special Functions}
\beginscroll
\centerline{What would you like to do?}
\beginmenu
\item Read
\menuwindowlink{Foundation Library Chapter s Manual Page}{manpageXXs}
\item or
\menulispwindowlink{Browse}{(|kSearch| "NagSpecialFunctionsPackage")}
\tab{10} through this chapter
\item or use the routines:
\menulispdownlink{S01EAF}{(|s01eaf|)}\space{}
\tab{10}  Complex exponential {\em exp(z)}
\menulispdownlink{S13AAF}{(|s13aaf|)}\space{}
\tab{10}  Exponential integral \htbitmap{s13aaf2}
\menulispdownlink{S13ACF}{(|s13acf|)}\space{}
\tab{10}  Cosine integral {\em Ci(x)}
\menulispdownlink{S13ADF}{(|s13adf|)}\space{}
\tab{10}  Sine integral {\em Si(x)}
\menulispdownlink{S14AAF}{(|s14aaf|)}\space{}
\tab{10}  Gamma function \Gamma
\menulispdownlink{S14ABF}{(|s14abf|)}\space{}
\tab{10}  Log Gamma function {\em ln \Gamma}
\menulispdownlink{S14BAF}{(|s14baf|)}\space{}
\tab{10}  Incomplete gamma functions P(a,x) and Q(a,x)
\menulispdownlink{S15ADF}{(|s15adf|)}\space{}
\tab{10}  Complement of error function {\em erfc x }
\menulispdownlink{S15AEF}{(|s15aef|)}\space{}
\tab{10}  Error function {\em erf x}
\menulispdownlink{S17ACF}{(|s17acf|)}\space{}
\tab{10}  Bessel function \space{1} \htbitmap{s17acf} 
\menulispdownlink{S17ADF}{(|s17adf|)}\space{}
\tab{10}  Bessel function \space{1} \htbitmap{s17adf} 
\menulispdownlink{S17AEF}{(|s17aef|)}\space{}
\tab{10}  Bessel function \space{1} \htbitmap{s17aef1} 
\menulispdownlink{S17AFF}{(|s17aff|)}\space{}
\tab{10}  Bessel function \space{1} \htbitmap{s17aff1} 
\menulispdownlink{S17AGF}{(|s17agf|)}
\tab{10}  Airy function {\em Ai(x)}
\menulispdownlink{S17AHF}{(|s17ahf|)}
\tab{10}  Airy function {\em Bi(x)}
\menulispdownlink{S17AJF}{(|s17ajf|)}
\tab{10}  Airy function {\em Ai'(x)}
\menulispdownlink{S17AKF}{(|s17akf|)}
\tab{10}  Airy function {\em Bi'(x)}
\menulispdownlink{S17DCF}{(|s17dcf|)}
\tab{10} Bessel function \htbitmap{s17dcf}, real a \space{1}
\htbitmap{great=} 0, complex z, v = 0,1,2,...
\menulispdownlink{S17DEF}{(|s17def|)}
\tab{10} Bessel function \htbitmap{s17def}, real a \space{1}
\htbitmap{great=} 0, complex z, v = 0,1,2,...
\menulispdownlink{S17DGF}{(|s17dgf|)}
\tab{10} Airy function {\em Ai(z)} and {\em Ai'(z)}, complex z
\menulispdownlink{S17DHF}{(|s17dhf|)}
\tab{10} Airy function {\em Bi(z)} and {\em Bi'(z)}, complex z
\menulispdownlink{S17DLF}{(|s17dlf|)}
\tab{10} Hankel function \vspace{-32} \htbitmap{s17dlf}
\vspace{-37}, j = 1,2, real a \space{1} \htbitmap{great=} 0, 
complex z, v = 0,1,2,... \newline
\menulispdownlink{S18ACF}{(|s18acf|)}
\tab{10} Modified Bessel function \space{1} \htbitmap{s18acf1} 
\menulispdownlink{S18ADF}{(|s18adf|)}
\tab{10} Modified Bessel function \space{1} \htbitmap{s18adf1}
\menulispdownlink{S18AEF}{(|s18aef|)}
\tab{10} Modified Bessel function \space{1} \htbitmap{s18aef1} 
\menulispdownlink{S18AFF}{(|s18aff|)}
\tab{10} Modified Bessel function \space{1} \htbitmap{s18aff1} 
\menulispdownlink{S18DCF}{(|s18dcf|)}
\tab{10} Modified bessel function \htbitmap{s18dcf}, real a \space{1}
\htbitmap{great=} 0, complex z, v = 0,1,2,...
\menulispdownlink{S18DEF}{(|s18def|)}
\tab{10} Modified bessel function \htbitmap{s18def}, real a \space{1}
\htbitmap{great=} 0, complex z, v = 0,1,2,...
\menulispdownlink{S19AAF}{(|s19aaf|)}
\tab{10} Kelvin function {\em ber x}
\menulispdownlink{S19ABF}{(|s19abf|)}
\tab{10} Kelvin function {\em bei x}
\menulispdownlink{S19ACF}{(|s19acf|)}
\tab{10} Kelvin function {\em ker x}
\menulispdownlink{S19ADF}{(|s19adf|)}
\tab{10} Kelvin function {\em kei x}
\menulispdownlink{S20ACF}{(|s20acf|)}
\tab{10} Fresnel integral {\em S(x)}
\menulispdownlink{S20ADF}{(|s20adf|)}
\tab{10} Fresnel integral {\em C(x)}
\menulispdownlink{S21BAF}{(|s21baf|)}
\tab{10} Degenerate symmetrised elliptic integral of 1st kind 
\space{1} \htbitmap{s21baf1} 
\menulispdownlink{S21BBF}{(|s21bbf|)}
\tab{10} Symmetrised elliptic integral of 1st kind \space{1} 
\vspace{-28} \htbitmap{s21bbf1} \vspace{-40} 
\menulispdownlink{S21BCF}{(|s21bcf|)}
\tab{10} Symmetrised elliptic integral of 2nd kind \space{1} 
\vspace{-28} \htbitmap{s21bcf1} \vspace{-40} 
\menulispdownlink{S21BDF}{(|s21bdf|)}
\tab{10} Symmetrised elliptic integral of 3rd kind \space{1} 
\vspace{-26} \htbitmap{s21bdf1} \vspace{-40} 
\endmenu
\endscroll
\autobuttons 
\end{page}

\end{chunk}
\section{list.ht}
\pagetitle{ListXmpPage}{list.ht}{List}
\pageto{notitle}{ugxListCreatePage}
\pageto{notitle}{ugxListAccessPage}
\pageto{notitle}{ugxListChangePage}
\pageto{notitle}{ugxListOtherPage}
\pageto{notitle}{ugxListDotPage}
\begin{chunk}{list.ht}
\begin{page}{ListXmpPage}{List}
\beginscroll
A \spadgloss{list} is a finite collection of elements in a specified
order that can contain duplicates.
A list is a convenient structure to work with because it is easy
to add or remove elements and the length need not be constant.
There are many different kinds of lists in Axiom, but the
default types (and those used most often) are created by the
\spadtype{List} constructor.
For example, there are objects of type \spadtype{List Integer},
\spadtype{List Float} and \spadtype{List Polynomial Fraction Integer}.
Indeed, you can even have \spadtype{List List List Boolean}
(that is, lists of lists of lists of Boolean values).
You can have lists of any type of Axiom object.

\beginmenu
    \menudownlink{{9.47.1. Creating Lists}}{ugxListCreatePage}
    \menudownlink{{9.47.2. Accessing List Elements}}{ugxListAccessPage}
    \menudownlink{{9.47.3. Changing List Elements}}{ugxListChangePage}
    \menudownlink{{9.47.4. Other Functions}}{ugxListOtherPage}
    \menudownlink{{9.47.5. Dot, Dot}}{ugxListDotPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugxListCreatePage}{list.ht}{Creating Lists}
\begin{chunk}{list.ht}
\begin{page}{ugxListCreatePage}{Creating Lists}
\beginscroll

The easiest way to create a list with, for example, the elements
\spad{2, 4, 5, 6} is to enclose the elements with square
brackets and separate the elements with commas.
\xtc{
The spaces after the commas are optional, but they do improve the
readability.
}{
\spadpaste{[2, 4, 5, 6]}
}
\xtc{
To create a list with the single element \spad{1}, you can use
either \spad{[1]} or the operation \spadfunFrom{list}{List}.
}{
\spadpaste{[1]}
}
\xtc{
}{
\spadpaste{list(1)}
}
\xtc{
Once created, two lists \spad{k} and \spad{m} can be
concatenated by issuing \spad{append(k,m)}.
\spadfunFrom{append}{List} does {\it not} physically join the lists,
but rather produces a new list with the elements coming from the two
arguments.
}{
\spadpaste{append([1,2,3],[5,6,7])}
}
\xtc{
Use \spadfunFrom{cons}{List} to append an element onto the front of a
list.
}{
\spadpaste{cons(10,[9,8,7])}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxListCreatePagePatch1}
\begin{paste}{ugxListCreatePageFull1}{ugxListCreatePageEmpty1}
\pastebutton{ugxListCreatePageFull1}{\hidepaste}
\tab{5}\spadcommand{[2, 4, 5, 6]}
\indentrel{3}\begin{verbatim}
   (1)  [2,4,5,6]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListCreatePageEmpty1}
\begin{paste}{ugxListCreatePageEmpty1}{ugxListCreatePagePatch1}
\pastebutton{ugxListCreatePageEmpty1}{\showpaste}
\tab{5}\spadcommand{[2, 4, 5, 6]}
\end{paste}\end{patch}

\begin{patch}{ugxListCreatePagePatch2}
\begin{paste}{ugxListCreatePageFull2}{ugxListCreatePageEmpty2}
\pastebutton{ugxListCreatePageFull2}{\hidepaste}
\tab{5}\spadcommand{[1]}
\indentrel{3}\begin{verbatim}
   (2)  [1]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListCreatePageEmpty2}
\begin{paste}{ugxListCreatePageEmpty2}{ugxListCreatePagePatch2}
\pastebutton{ugxListCreatePageEmpty2}{\showpaste}
\tab{5}\spadcommand{[1]}
\end{paste}\end{patch}

\begin{patch}{ugxListCreatePagePatch3}
\begin{paste}{ugxListCreatePageFull3}{ugxListCreatePageEmpty3}
\pastebutton{ugxListCreatePageFull3}{\hidepaste}
\tab{5}\spadcommand{list(1)}
\indentrel{3}\begin{verbatim}
   (3)  [1]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListCreatePageEmpty3}
\begin{paste}{ugxListCreatePageEmpty3}{ugxListCreatePagePatch3}
\pastebutton{ugxListCreatePageEmpty3}{\showpaste}
\tab{5}\spadcommand{list(1)}
\end{paste}\end{patch}

\begin{patch}{ugxListCreatePagePatch4}
\begin{paste}{ugxListCreatePageFull4}{ugxListCreatePageEmpty4}
\pastebutton{ugxListCreatePageFull4}{\hidepaste}
\tab{5}\spadcommand{append([1,2,3],[5,6,7])}
\indentrel{3}\begin{verbatim}
   (4)  [1,2,3,5,6,7]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListCreatePageEmpty4}
\begin{paste}{ugxListCreatePageEmpty4}{ugxListCreatePagePatch4}
\pastebutton{ugxListCreatePageEmpty4}{\showpaste}
\tab{5}\spadcommand{append([1,2,3],[5,6,7])}
\end{paste}\end{patch}

\begin{patch}{ugxListCreatePagePatch5}
\begin{paste}{ugxListCreatePageFull5}{ugxListCreatePageEmpty5}
\pastebutton{ugxListCreatePageFull5}{\hidepaste}
\tab{5}\spadcommand{cons(10,[9,8,7])}
\indentrel{3}\begin{verbatim}
   (5)  [10,9,8,7]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListCreatePageEmpty5}
\begin{paste}{ugxListCreatePageEmpty5}{ugxListCreatePagePatch5}
\pastebutton{ugxListCreatePageEmpty5}{\showpaste}
\tab{5}\spadcommand{cons(10,[9,8,7])}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxListAccessPage}{list.ht}{Accessing List Elements}
\begin{chunk}{list.ht}
\begin{page}{ugxListAccessPage}{Accessing List Elements}
\beginscroll

\labelSpace{4pc}
\xtc{
To determine whether a list has any elements, use the operation
\spadfunFrom{empty?}{List}.
}{
\spadpaste{empty? [x+1]}
}
\xtc{
Alternatively, equality with the list constant \spadfunFrom{nil}{List} 
can be tested.
}{
\spadpaste{([] = nil)@Boolean}
}

\xtc{
We'll use this in some of the following examples.
}{
\spadpaste{k := [4,3,7,3,8,5,9,2] \bound{k}}
}
\xtc{
Each of the next four expressions extracts the \spadfunFrom{first}{List}
element of \spad{k}.
}{
\spadpaste{first k \free{k}}
}
\xtc{
}{
\spadpaste{k.first \free{k}}
}
\xtc{
}{
\spadpaste{k.1 \free{k}}
}
\xtc{
}{
\spadpaste{k(1) \free{k}}
}
The last two forms generalize to \spad{k.i} and \spad{k(i)},
respectively, where
\texht{$ 1 \leq i \leq n$}{\spad{1 <= i <= n}}
and
\spad{n} equals the length of \spad{k}.
\xtc{
This length is calculated by \spadopFrom{\#}{List}.
}{
\spadpaste{n := \#k \free{k}}
}
Performing an operation such as \spad{k.i} is sometimes
referred to as {\it indexing into k} or
{\it elting into k}.
The latter phrase comes about because the name of the operation
that extracts elements is called \spadfunFrom{elt}{List}.
That is, \spad{k.3} is just alternative syntax for \spad{elt(k,3)}.
It is important to remember that list indices
begin with 1.
If we issue \spad{k := [1,3,2,9,5]} then \spad{k.4}
returns \spad{9}.
It is an error to use an index that is not in the range from
\spad{1} to the length of the list.

\xtc{
The last element of a list is extracted by any of the
following three expressions.
}{
\spadpaste{last k \free{k}}
}
\xtc{
}{
\spadpaste{k.last \free{k}}
}
\xtc{
This form computes the index of the last element and then
extracts the element from the list.
}{
\spadpaste{k.(\#k) \free{k}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxListAccessPagePatch1}
\begin{paste}{ugxListAccessPageFull1}{ugxListAccessPageEmpty1}
\pastebutton{ugxListAccessPageFull1}{\hidepaste}
\tab{5}\spadcommand{empty? [x+1]}
\indentrel{3}\begin{verbatim}
   (1)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListAccessPageEmpty1}
\begin{paste}{ugxListAccessPageEmpty1}{ugxListAccessPagePatch1}
\pastebutton{ugxListAccessPageEmpty1}{\showpaste}
\tab{5}\spadcommand{empty? [x+1]}
\end{paste}\end{patch}

\begin{patch}{ugxListAccessPagePatch2}
\begin{paste}{ugxListAccessPageFull2}{ugxListAccessPageEmpty2}
\pastebutton{ugxListAccessPageFull2}{\hidepaste}
\tab{5}\spadcommand{([] = nil)@Boolean}
\indentrel{3}\begin{verbatim}
   (2)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListAccessPageEmpty2}
\begin{paste}{ugxListAccessPageEmpty2}{ugxListAccessPagePatch2}
\pastebutton{ugxListAccessPageEmpty2}{\showpaste}
\tab{5}\spadcommand{([] = nil)@Boolean}
\end{paste}\end{patch}

\begin{patch}{ugxListAccessPagePatch3}
\begin{paste}{ugxListAccessPageFull3}{ugxListAccessPageEmpty3}
\pastebutton{ugxListAccessPageFull3}{\hidepaste}
\tab{5}\spadcommand{k := [4,3,7,3,8,5,9,2]\bound{k }}
\indentrel{3}\begin{verbatim}
   (3)  [4,3,7,3,8,5,9,2]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListAccessPageEmpty3}
\begin{paste}{ugxListAccessPageEmpty3}{ugxListAccessPagePatch3}
\pastebutton{ugxListAccessPageEmpty3}{\showpaste}
\tab{5}\spadcommand{k := [4,3,7,3,8,5,9,2]\bound{k }}
\end{paste}\end{patch}

\begin{patch}{ugxListAccessPagePatch4}
\begin{paste}{ugxListAccessPageFull4}{ugxListAccessPageEmpty4}
\pastebutton{ugxListAccessPageFull4}{\hidepaste}
\tab{5}\spadcommand{first k\free{k }}
\indentrel{3}\begin{verbatim}
   (4)  4
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListAccessPageEmpty4}
\begin{paste}{ugxListAccessPageEmpty4}{ugxListAccessPagePatch4}
\pastebutton{ugxListAccessPageEmpty4}{\showpaste}
\tab{5}\spadcommand{first k\free{k }}
\end{paste}\end{patch}

\begin{patch}{ugxListAccessPagePatch5}
\begin{paste}{ugxListAccessPageFull5}{ugxListAccessPageEmpty5}
\pastebutton{ugxListAccessPageFull5}{\hidepaste}
\tab{5}\spadcommand{k.first\free{k }}
\indentrel{3}\begin{verbatim}
   (5)  4
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListAccessPageEmpty5}
\begin{paste}{ugxListAccessPageEmpty5}{ugxListAccessPagePatch5}
\pastebutton{ugxListAccessPageEmpty5}{\showpaste}
\tab{5}\spadcommand{k.first\free{k }}
\end{paste}\end{patch}

\begin{patch}{ugxListAccessPagePatch6}
\begin{paste}{ugxListAccessPageFull6}{ugxListAccessPageEmpty6}
\pastebutton{ugxListAccessPageFull6}{\hidepaste}
\tab{5}\spadcommand{k.1\free{k }}
\indentrel{3}\begin{verbatim}
   (6)  4
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListAccessPageEmpty6}
\begin{paste}{ugxListAccessPageEmpty6}{ugxListAccessPagePatch6}
\pastebutton{ugxListAccessPageEmpty6}{\showpaste}
\tab{5}\spadcommand{k.1\free{k }}
\end{paste}\end{patch}

\begin{patch}{ugxListAccessPagePatch7}
\begin{paste}{ugxListAccessPageFull7}{ugxListAccessPageEmpty7}
\pastebutton{ugxListAccessPageFull7}{\hidepaste}
\tab{5}\spadcommand{k(1)\free{k }}
\indentrel{3}\begin{verbatim}
   (7)  4
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListAccessPageEmpty7}
\begin{paste}{ugxListAccessPageEmpty7}{ugxListAccessPagePatch7}
\pastebutton{ugxListAccessPageEmpty7}{\showpaste}
\tab{5}\spadcommand{k(1)\free{k }}
\end{paste}\end{patch}

\begin{patch}{ugxListAccessPagePatch8}
\begin{paste}{ugxListAccessPageFull8}{ugxListAccessPageEmpty8}
\pastebutton{ugxListAccessPageFull8}{\hidepaste}
\tab{5}\spadcommand{n := \#k\free{k }}
\indentrel{3}\begin{verbatim}
   (8)  8
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListAccessPageEmpty8}
\begin{paste}{ugxListAccessPageEmpty8}{ugxListAccessPagePatch8}
\pastebutton{ugxListAccessPageEmpty8}{\showpaste}
\tab{5}\spadcommand{n := \#k\free{k }}
\end{paste}\end{patch}

\begin{patch}{ugxListAccessPagePatch9}
\begin{paste}{ugxListAccessPageFull9}{ugxListAccessPageEmpty9}
\pastebutton{ugxListAccessPageFull9}{\hidepaste}
\tab{5}\spadcommand{last k\free{k }}
\indentrel{3}\begin{verbatim}
   (9)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListAccessPageEmpty9}
\begin{paste}{ugxListAccessPageEmpty9}{ugxListAccessPagePatch9}
\pastebutton{ugxListAccessPageEmpty9}{\showpaste}
\tab{5}\spadcommand{last k\free{k }}
\end{paste}\end{patch}

\begin{patch}{ugxListAccessPagePatch10}
\begin{paste}{ugxListAccessPageFull10}{ugxListAccessPageEmpty10}
\pastebutton{ugxListAccessPageFull10}{\hidepaste}
\tab{5}\spadcommand{k.last\free{k }}
\indentrel{3}\begin{verbatim}
   (10)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListAccessPageEmpty10}
\begin{paste}{ugxListAccessPageEmpty10}{ugxListAccessPagePatch10}
\pastebutton{ugxListAccessPageEmpty10}{\showpaste}
\tab{5}\spadcommand{k.last\free{k }}
\end{paste}\end{patch}

\begin{patch}{ugxListAccessPagePatch11}
\begin{paste}{ugxListAccessPageFull11}{ugxListAccessPageEmpty11}
\pastebutton{ugxListAccessPageFull11}{\hidepaste}
\tab{5}\spadcommand{k.(\#k)\free{k }}
\indentrel{3}\begin{verbatim}
   (11)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListAccessPageEmpty11}
\begin{paste}{ugxListAccessPageEmpty11}{ugxListAccessPagePatch11}
\pastebutton{ugxListAccessPageEmpty11}{\showpaste}
\tab{5}\spadcommand{k.(\#k)\free{k }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxListChangePage}{list.ht}{Changing List Elements}
\begin{chunk}{list.ht}
\begin{page}{ugxListChangePage}{Changing List Elements}
\beginscroll

\labelSpace{4pc}
\xtc{
We'll use this in some of the following examples.
}{
\spadpaste{k := [4,3,7,3,8,5,9,2] \bound{k}}
}
\xtc{
List elements are reset by using the \spad{k.i} form on
the left-hand side of an assignment.
This expression resets the first element of \spad{k} to \spad{999}.
}{
\spadpaste{k.1 := 999 \free{k}\bound{k1}}
}
\xtc{
As with indexing into a list, it is an error to use an index
that is not within the proper bounds.
Here you see that \spad{k} was modified.
}{
\spadpaste{k \free{k1}}
}

The operation that performs the assignment of an element to a particular
position in a list is called \spadfunFrom{setelt}{List}.
This operation is {\it destructive} in that it changes the list.
In the above example, the assignment returned the value \spad{999} and
\spad{k} was modified.
For this reason, lists are called \spadglos{mutable} objects: it is
possible to change part of a list (mutate it) rather than always returning
a new list reflecting the intended modifications.
\xtc{
Moreover, since lists can share structure, changes to one list can
sometimes affect others.
}{
\spadpaste{k := [1,2] \bound{k2}}
}
\xtc{
}{
\spadpaste{m := cons(0,k) \free{k2}\bound{m}}
}
\xtc{
Change the second element of \spad{m}.
}{
\spadpaste{m.2 := 99 \free{m}\bound{m2}}
}
\xtc{
See, \spad{m} was altered.
}{
\spadpaste{m \free{m2}}
}
\xtc{
But what about \spad{k}?
It changed too!
}{
\spadpaste{k  \free{m2 k2}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxListChangePagePatch1}
\begin{paste}{ugxListChangePageFull1}{ugxListChangePageEmpty1}
\pastebutton{ugxListChangePageFull1}{\hidepaste}
\tab{5}\spadcommand{k := [4,3,7,3,8,5,9,2]\bound{k }}
\indentrel{3}\begin{verbatim}
   (1)  [4,3,7,3,8,5,9,2]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListChangePageEmpty1}
\begin{paste}{ugxListChangePageEmpty1}{ugxListChangePagePatch1}
\pastebutton{ugxListChangePageEmpty1}{\showpaste}
\tab{5}\spadcommand{k := [4,3,7,3,8,5,9,2]\bound{k }}
\end{paste}\end{patch}

\begin{patch}{ugxListChangePagePatch2}
\begin{paste}{ugxListChangePageFull2}{ugxListChangePageEmpty2}
\pastebutton{ugxListChangePageFull2}{\hidepaste}
\tab{5}\spadcommand{k.1 := 999\free{k }\bound{k1 }}
\indentrel{3}\begin{verbatim}
   (2)  999
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListChangePageEmpty2}
\begin{paste}{ugxListChangePageEmpty2}{ugxListChangePagePatch2}
\pastebutton{ugxListChangePageEmpty2}{\showpaste}
\tab{5}\spadcommand{k.1 := 999\free{k }\bound{k1 }}
\end{paste}\end{patch}

\begin{patch}{ugxListChangePagePatch3}
\begin{paste}{ugxListChangePageFull3}{ugxListChangePageEmpty3}
\pastebutton{ugxListChangePageFull3}{\hidepaste}
\tab{5}\spadcommand{k\free{k1 }}
\indentrel{3}\begin{verbatim}
   (3)  [999,3,7,3,8,5,9,2]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListChangePageEmpty3}
\begin{paste}{ugxListChangePageEmpty3}{ugxListChangePagePatch3}
\pastebutton{ugxListChangePageEmpty3}{\showpaste}
\tab{5}\spadcommand{k\free{k1 }}
\end{paste}\end{patch}

\begin{patch}{ugxListChangePagePatch4}
\begin{paste}{ugxListChangePageFull4}{ugxListChangePageEmpty4}
\pastebutton{ugxListChangePageFull4}{\hidepaste}
\tab{5}\spadcommand{k := [1,2]\bound{k2 }}
\indentrel{3}\begin{verbatim}
   (4)  [1,2]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListChangePageEmpty4}
\begin{paste}{ugxListChangePageEmpty4}{ugxListChangePagePatch4}
\pastebutton{ugxListChangePageEmpty4}{\showpaste}
\tab{5}\spadcommand{k := [1,2]\bound{k2 }}
\end{paste}\end{patch}

\begin{patch}{ugxListChangePagePatch5}
\begin{paste}{ugxListChangePageFull5}{ugxListChangePageEmpty5}
\pastebutton{ugxListChangePageFull5}{\hidepaste}
\tab{5}\spadcommand{m := cons(0,k)\free{k2 }\bound{m }}
\indentrel{3}\begin{verbatim}
   (5)  [0,1,2]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListChangePageEmpty5}
\begin{paste}{ugxListChangePageEmpty5}{ugxListChangePagePatch5}
\pastebutton{ugxListChangePageEmpty5}{\showpaste}
\tab{5}\spadcommand{m := cons(0,k)\free{k2 }\bound{m }}
\end{paste}\end{patch}

\begin{patch}{ugxListChangePagePatch6}
\begin{paste}{ugxListChangePageFull6}{ugxListChangePageEmpty6}
\pastebutton{ugxListChangePageFull6}{\hidepaste}
\tab{5}\spadcommand{m.2 := 99\free{m }\bound{m2 }}
\indentrel{3}\begin{verbatim}
   (6)  99
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListChangePageEmpty6}
\begin{paste}{ugxListChangePageEmpty6}{ugxListChangePagePatch6}
\pastebutton{ugxListChangePageEmpty6}{\showpaste}
\tab{5}\spadcommand{m.2 := 99\free{m }\bound{m2 }}
\end{paste}\end{patch}

\begin{patch}{ugxListChangePagePatch7}
\begin{paste}{ugxListChangePageFull7}{ugxListChangePageEmpty7}
\pastebutton{ugxListChangePageFull7}{\hidepaste}
\tab{5}\spadcommand{m\free{m2 }}
\indentrel{3}\begin{verbatim}
   (7)  [0,99,2]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListChangePageEmpty7}
\begin{paste}{ugxListChangePageEmpty7}{ugxListChangePagePatch7}
\pastebutton{ugxListChangePageEmpty7}{\showpaste}
\tab{5}\spadcommand{m\free{m2 }}
\end{paste}\end{patch}

\begin{patch}{ugxListChangePagePatch8}
\begin{paste}{ugxListChangePageFull8}{ugxListChangePageEmpty8}
\pastebutton{ugxListChangePageFull8}{\hidepaste}
\tab{5}\spadcommand{k\free{m2 k2 }}
\indentrel{3}\begin{verbatim}
   (8)  [99,2]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListChangePageEmpty8}
\begin{paste}{ugxListChangePageEmpty8}{ugxListChangePagePatch8}
\pastebutton{ugxListChangePageEmpty8}{\showpaste}
\tab{5}\spadcommand{k\free{m2 k2 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxListOtherPage}{list.ht}{Other Functions}
\begin{chunk}{list.ht}
\begin{page}{ugxListOtherPage}{Other Functions}
\beginscroll

\labelSpace{3pc}
\xtc{
An operation that is used frequently in list processing is that
which returns all elements in a list after the first element.
}{
\spadpaste{k := [1,2,3] \bound{k}}
}
\xtc{
Use the \spadfunFrom{rest}{List} operation to do this.
}{
\spadpaste{rest k \free{k}}
}

\xtc{
To remove duplicate elements in a list \spad{k}, use
\spadfunFrom{removeDuplicates}{List}.
}{
\spadpaste{removeDuplicates [4,3,4,3,5,3,4]}
}
\xtc{
To get a list with elements in the order opposite to those in
a list \spad{k}, use \spadfunFrom{reverse}{List}.
}{
\spadpaste{reverse [1,2,3,4,5,6]}
}
\xtc{
To test whether an element is in a list, use \spadfunFrom{member?}{List}:
\spad{member?(a,k)} returns \spad{true} or \spad{false}
depending on whether \spad{a} is in \spad{k} or not.
}{
\spadpaste{member?(1/2,[3/4,5/6,1/2])}
}
\xtc{
}{
\spadpaste{member?(1/12,[3/4,5/6,1/2])}
}

As an exercise, the reader should determine how to get a
list containing all but the last of the elements in a given non-empty
list \spad{k}.\footnote{\spad{reverse(rest(reverse(k)))} works.}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxListOtherPagePatch1}
\begin{paste}{ugxListOtherPageFull1}{ugxListOtherPageEmpty1}
\pastebutton{ugxListOtherPageFull1}{\hidepaste}
\tab{5}\spadcommand{k := [1,2,3]\bound{k }}
\indentrel{3}\begin{verbatim}
   (1)  [1,2,3]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListOtherPageEmpty1}
\begin{paste}{ugxListOtherPageEmpty1}{ugxListOtherPagePatch1}
\pastebutton{ugxListOtherPageEmpty1}{\showpaste}
\tab{5}\spadcommand{k := [1,2,3]\bound{k }}
\end{paste}\end{patch}

\begin{patch}{ugxListOtherPagePatch2}
\begin{paste}{ugxListOtherPageFull2}{ugxListOtherPageEmpty2}
\pastebutton{ugxListOtherPageFull2}{\hidepaste}
\tab{5}\spadcommand{rest k\free{k }}
\indentrel{3}\begin{verbatim}
   (2)  [2,3]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListOtherPageEmpty2}
\begin{paste}{ugxListOtherPageEmpty2}{ugxListOtherPagePatch2}
\pastebutton{ugxListOtherPageEmpty2}{\showpaste}
\tab{5}\spadcommand{rest k\free{k }}
\end{paste}\end{patch}

\begin{patch}{ugxListOtherPagePatch3}
\begin{paste}{ugxListOtherPageFull3}{ugxListOtherPageEmpty3}
\pastebutton{ugxListOtherPageFull3}{\hidepaste}
\tab{5}\spadcommand{removeDuplicates [4,3,4,3,5,3,4]}
\indentrel{3}\begin{verbatim}
   (3)  [4,3,5]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListOtherPageEmpty3}
\begin{paste}{ugxListOtherPageEmpty3}{ugxListOtherPagePatch3}
\pastebutton{ugxListOtherPageEmpty3}{\showpaste}
\tab{5}\spadcommand{removeDuplicates [4,3,4,3,5,3,4]}
\end{paste}\end{patch}

\begin{patch}{ugxListOtherPagePatch4}
\begin{paste}{ugxListOtherPageFull4}{ugxListOtherPageEmpty4}
\pastebutton{ugxListOtherPageFull4}{\hidepaste}
\tab{5}\spadcommand{reverse [1,2,3,4,5,6]}
\indentrel{3}\begin{verbatim}
   (4)  [6,5,4,3,2,1]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListOtherPageEmpty4}
\begin{paste}{ugxListOtherPageEmpty4}{ugxListOtherPagePatch4}
\pastebutton{ugxListOtherPageEmpty4}{\showpaste}
\tab{5}\spadcommand{reverse [1,2,3,4,5,6]}
\end{paste}\end{patch}

\begin{patch}{ugxListOtherPagePatch5}
\begin{paste}{ugxListOtherPageFull5}{ugxListOtherPageEmpty5}
\pastebutton{ugxListOtherPageFull5}{\hidepaste}
\tab{5}\spadcommand{member?(1/2,[3/4,5/6,1/2])}
\indentrel{3}\begin{verbatim}
   (5)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListOtherPageEmpty5}
\begin{paste}{ugxListOtherPageEmpty5}{ugxListOtherPagePatch5}
\pastebutton{ugxListOtherPageEmpty5}{\showpaste}
\tab{5}\spadcommand{member?(1/2,[3/4,5/6,1/2])}
\end{paste}\end{patch}

\begin{patch}{ugxListOtherPagePatch6}
\begin{paste}{ugxListOtherPageFull6}{ugxListOtherPageEmpty6}
\pastebutton{ugxListOtherPageFull6}{\hidepaste}
\tab{5}\spadcommand{member?(1/12,[3/4,5/6,1/2])}
\indentrel{3}\begin{verbatim}
   (6)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListOtherPageEmpty6}
\begin{paste}{ugxListOtherPageEmpty6}{ugxListOtherPagePatch6}
\pastebutton{ugxListOtherPageEmpty6}{\showpaste}
\tab{5}\spadcommand{member?(1/12,[3/4,5/6,1/2])}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxListDotPage}{list.ht}{Dot, Dot}
\begin{chunk}{list.ht}
\begin{page}{ugxListDotPage}{Dot, Dot}
\beginscroll

Certain lists are used so often that Axiom provides an easy way
of constructing them.
If \spad{n} and \spad{m} are integers, then \spad{expand [n..m]}
creates a list containing \spad{n, n+1, ... m}.
If \spad{n > m} then the list is empty.
It is actually permissible to leave off the \spad{m} in the
dot-dot construction (see below).

\xtc{
The dot-dot notation can be used more than once in a list
construction and with specific elements being given.
Items separated by dots are called {\it segments.}
}{
\spadpaste{[1..3,10,20..23]}
}
\xtc{
Segments can be expanded into the range of items between the
endpoints by using \spadfunFrom{expand}{Segment}.
}{
\spadpaste{expand [1..3,10,20..23]}
}
\xtc{
What happens if we leave off a number on the right-hand side of
\spadopFrom{..}{UniversalSegment}?
}{
\spadpaste{expand [1..]}
}
What is created in this case is a \spadtype{Stream} which is a
generalization of a list.
See \downlink{`Stream'}{StreamXmpPage}\ignore{Stream} for more information.
\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxListDotPagePatch1}
\begin{paste}{ugxListDotPageFull1}{ugxListDotPageEmpty1}
\pastebutton{ugxListDotPageFull1}{\hidepaste}
\tab{5}\spadcommand{[1..3,10,20..23]}
\indentrel{3}\begin{verbatim}
   (1)  [1..3,10..10,20..23]
                     Type: List Segment PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListDotPageEmpty1}
\begin{paste}{ugxListDotPageEmpty1}{ugxListDotPagePatch1}
\pastebutton{ugxListDotPageEmpty1}{\showpaste}
\tab{5}\spadcommand{[1..3,10,20..23]}
\end{paste}\end{patch}

\begin{patch}{ugxListDotPagePatch2}
\begin{paste}{ugxListDotPageFull2}{ugxListDotPageEmpty2}
\pastebutton{ugxListDotPageFull2}{\hidepaste}
\tab{5}\spadcommand{expand [1..3,10,20..23]}
\indentrel{3}\begin{verbatim}
   (2)  [1,2,3,10,20,21,22,23]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListDotPageEmpty2}
\begin{paste}{ugxListDotPageEmpty2}{ugxListDotPagePatch2}
\pastebutton{ugxListDotPageEmpty2}{\showpaste}
\tab{5}\spadcommand{expand [1..3,10,20..23]}
\end{paste}\end{patch}

\begin{patch}{ugxListDotPagePatch3}
\begin{paste}{ugxListDotPageFull3}{ugxListDotPageEmpty3}
\pastebutton{ugxListDotPageFull3}{\hidepaste}
\tab{5}\spadcommand{expand [1..]}
\indentrel{3}\begin{verbatim}
   (3)  [1,2,3,4,5,6,7,8,9,10,...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxListDotPageEmpty3}
\begin{paste}{ugxListDotPageEmpty3}{ugxListDotPagePatch3}
\pastebutton{ugxListDotPageEmpty3}{\showpaste}
\tab{5}\spadcommand{expand [1..]}
\end{paste}\end{patch}

\end{chunk}
\section{lodo.ht}
\pagetitle{LinearOrdinaryDifferentialOperatorXmpPage}{lodo.ht}
{LinearOrdinaryDifferentialOperator}
\pageto{notitle}{ugxLinearOrdinaryDifferentialOperatorSeriesPage}
\begin{chunk}{lodo.ht}
\begin{page}{LinearOrdinaryDifferentialOperatorXmpPage}
{LinearOrdinaryDifferentialOperator}
\beginscroll

\spadtype{LinearOrdinaryDifferentialOperator(A, diff)} is the 
domain of linear ordinary differential operators with coefficients 
in a ring \spad{A} with a given derivation.
%This includes the cases of operators which are polynomials in \spad{D}
%acting upon scalar or vector expressions of a single variable.
%The coefficients of the operator polynomials can be integers, rational
%functions, matrices or elements of other domains.
\showBlurb{LinearOrdinaryDifferentialOperator}

\beginmenu
menudownlink{{9.44.1. Differential Operators with Series Coefficients}}
{ugxLinearOrdinaryDifferentialOperatorSeriesPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugxLinearOrdinaryDifferentialOperatorSeriesPage}{lodo.ht}
{Differential Operators with Series Coefficients}
\begin{chunk}{lodo.ht}
\begin{page}{ugxLinearOrdinaryDifferentialOperatorSeriesPage}
{Differential Operators with Series Coefficients}
\beginscroll

\noindent
{\bf Problem:}
Find the first few coefficients of \spad{exp(x)/x**i} of \spad{Dop phi} 
where
\begin{verbatim}
Dop := D**3 + G/x**2 * D + H/x**3 - 1
phi := sum(s[i]*exp(x)/x**i, i = 0..)
\end{verbatim}

\noindent
{\bf Solution:}
\xtc{
Define the differential.
}{
\spadpaste{Dx: LODO(EXPR INT, f +-> D(f, x)) \bound{Dxd}}
}
\xtc{
}{
\spadpaste{Dx := D() \free{Dxd}\bound{Dx}}
}
\xtc{
Now define the differential operator \spad{Dop}.
}{
\spadpaste{Dop:= Dx**3 + G/x**2*Dx + H/x**3 - 1 \free{Dx}\bound{Dop}}
}
\xtc{
}{
\spadpaste{n == 3 \bound{n3}}
}
\xtc{
}{
\spadpaste{phi == reduce(+,[subscript(s,[i])*exp(x)/x**i for i in 0..n]) 
\bound{phi}}
}
\xtc{
}{
\spadpaste{phi1 ==  Dop(phi) / exp x \bound{phi1}\free{Dop phi}}
}
\xtc{
}{
\spadpaste{phi2 == phi1 *x**(n+3) \bound{phi2}\free{phi1}}
}
\xtc{
}{
\spadpaste{phi3 == retract(phi2)@(POLY INT) \bound{phi3}\free{phi2}}
}
\xtc{
}{
\spadpaste{pans == phi3 ::UP(x,POLY INT) \free{phi3}\bound{pans}}
}
\xtc{
}{
\spadpaste{pans1 == [coefficient(pans, (n+3-i) :: NNI) for i in 2..n+1] 
\bound{pans1}\free{pans}}
}
\xtc{
}{
\spadpaste{leq == solve(pans1,[subscript(s,[i]) for i in 1..n]) 
\bound{leq}\free{pans1}}
}
\xtc{
Evaluate this for several values of \spad{n}.
}{
\spadpaste{leq \free{n3 leq}}
}
\xtc{
}{
\spadpaste{n==4 \bound{n4}}
}
\xtc{
}{
\spadpaste{leq \free{n4 leq}}
}
\xtc{
}{
\spadpaste{n==7 \bound{n7}}
}
\xtc{
}{
\spadpaste{leq \free{n7 leq}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch1}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull1}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty1}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull1}{\hidepaste}
\tab{5}\spadcommand{Dx: LODO(EXPR INT, f +-> D(f, x))\bound{Dxd }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty1}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty1}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch1}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty1}{\showpaste}
\tab{5}\spadcommand{Dx: LODO(EXPR INT, f +-> D(f, x))\bound{Dxd }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch2}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull2}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty2}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull2}{\hidepaste}
\tab{5}\spadcommand{Dx := D()\free{Dxd }\bound{Dx }}
\indentrel{3}\begin{verbatim}
   (2)  D
Type: LinearOrdinaryDifferentialOperator(Expression Integer,theMap NIL)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty2}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty2}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch2}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty2}{\showpaste}
\tab{5}\spadcommand{Dx := D()\free{Dxd }\bound{Dx }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch3}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull3}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty3}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull3}{\hidepaste}
\tab{5}\spadcommand{Dop:= Dx**3 + G/x**2*Dx + H/x**3 - 1\free{Dx }\bound{Dop }}
\indentrel{3}\begin{verbatim}
                       3
         3    G     - x  + H
   (3)  D  + ÄÄ D + ÄÄÄÄÄÄÄÄ
              2         3
             x         x
Type: LinearOrdinaryDifferentialOperator(Expression Integer,theMap NIL)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty3}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty3}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch3}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty3}{\showpaste}
\tab{5}\spadcommand{Dop:= Dx**3 + G/x**2*Dx + H/x**3 - 1\free{Dx }\bound{Dop }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch4}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull4}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty4}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull4}{\hidepaste}
\tab{5}\spadcommand{n == 3\bound{n3 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty4}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty4}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch4}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty4}{\showpaste}
\tab{5}\spadcommand{n == 3\bound{n3 }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch5}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull5}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty5}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull5}{\hidepaste}
\tab{5}\spadcommand{phi == reduce(+,[subscript(s,[i])*exp(x)/x**i for i in 0..n])\bound{phi }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty5}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty5}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch5}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty5}{\showpaste}
\tab{5}\spadcommand{phi == reduce(+,[subscript(s,[i])*exp(x)/x**i for i in 0..n])\bound{phi }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch6}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull6}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty6}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull6}{\hidepaste}
\tab{5}\spadcommand{phi1 == Dop(phi) / exp x\bound{phi1 }\free{Dop phi }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty6}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty6}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch6}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty6}{\showpaste}
\tab{5}\spadcommand{phi1 == Dop(phi) / exp x\bound{phi1 }\free{Dop phi }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch7}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull7}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty7}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull7}{\hidepaste}
\tab{5}\spadcommand{phi2 == phi1 *x**(n+3)\bound{phi2 }\free{phi1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty7}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty7}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch7}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty7}{\showpaste}
\tab{5}\spadcommand{phi2 == phi1 *x**(n+3)\bound{phi2 }\free{phi1 }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch8}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull8}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty8}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull8}{\hidepaste}
\tab{5}\spadcommand{phi3 == retract(phi2)@(POLY INT)\bound{phi3 }\free{phi2 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty8}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty8}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch8}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty8}{\showpaste}
\tab{5}\spadcommand{phi3 == retract(phi2)@(POLY INT)\bound{phi3 }\free{phi2 }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch9}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull9}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty9}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull9}{\hidepaste}
\tab{5}\spadcommand{pans == phi3 ::UP(x,POLY INT)\free{phi3 }\bound{pans }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty9}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty9}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch9}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty9}{\showpaste}
\tab{5}\spadcommand{pans == phi3 ::UP(x,POLY INT)\free{phi3 }\bound{pans }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch10}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull10}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty10}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull10}{\hidepaste}
\tab{5}\spadcommand{pans1 == [coefficient(pans, (n+3-i) :: NNI) for i in 2..n+1]\bound{pans1 }\free{pans }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty10}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty10}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch10}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty10}{\showpaste}
\tab{5}\spadcommand{pans1 == [coefficient(pans, (n+3-i) :: NNI) for i in 2..n+1]\bound{pans1 }\free{pans }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch11}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull11}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty11}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull11}{\hidepaste}
\tab{5}\spadcommand{leq == solve(pans1,[subscript(s,[i]) for i in 1..n])\bound{leq }\free{pans1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty11}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty11}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch11}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty11}{\showpaste}
\tab{5}\spadcommand{leq == solve(pans1,[subscript(s,[i]) for i in 1..n])\bound{leq }\free{pans1 }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch12}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull12}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty12}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull12}{\hidepaste}
\tab{5}\spadcommand{leq\free{n3 leq }}
\indentrel{3}\begin{verbatim}
   (12)
   [
                             2
          s G      3s H + s G  + 6s G
           0         0     0       0
     [s = ÄÄÄ, s = ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ,
       1   3    2          18
                              3        2
          (9s G + 54s )H + s G  + 18s G  + 72s G
             0       0      0        0        0
      s = ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ]
       3                    162
     ]
   Type: List List Equation Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty12}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty12}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch12}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty12}{\showpaste}
\tab{5}\spadcommand{leq\free{n3 leq }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch13}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull13}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty13}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull13}{\hidepaste}
\tab{5}\spadcommand{n==4\bound{n4 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty13}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty13}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch13}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty13}{\showpaste}
\tab{5}\spadcommand{n==4\bound{n4 }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch14}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull14}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty14}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull14}{\hidepaste}
\tab{5}\spadcommand{leq\free{n4 leq }}
\indentrel{3}\begin{verbatim}
   (14)
   [
                             2
          s G      3s H + s G  + 6s G
           0         0     0       0
     [s = ÄÄÄ, s = ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ,
       1   3    2          18
                              3        2
          (9s G + 54s )H + s G  + 18s G  + 72s G
             0       0      0        0        0
      s = ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ,
       3                    162

       s  =
        4
                  2         2                          4
             27s H  + (18s G  + 378s G + 1296s )H + s G
                0         0         0         0      0
           + 
                  3         2
             36s G  + 396s G  + 1296s G
                0         0          0
        /
           1944
       ]
     ]
   Type: List List Equation Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty14}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty14}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch14}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty14}{\showpaste}
\tab{5}\spadcommand{leq\free{n4 leq }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch15}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull15}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty15}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull15}{\hidepaste}
\tab{5}\spadcommand{n==7\bound{n7 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty15}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty15}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch15}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty15}{\showpaste}
\tab{5}\spadcommand{n==7\bound{n7 }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch16}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull16}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty16}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageFull16}{\hidepaste}
\tab{5}\spadcommand{leq\free{n7 leq }}
\indentrel{3}\begin{verbatim}
   (16)
   [
                             2
          s G      3s H + s G  + 6s G
           0         0     0       0
     [s = ÄÄÄ, s = ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ,
       1   3    2          18
                              3        2
          (9s G + 54s )H + s G  + 18s G  + 72s G
             0       0      0        0        0
      s = ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ,
       3                    162

       s  =
        4
                  2         2                          4
             27s H  + (18s G  + 378s G + 1296s )H + s G
                0         0         0         0      0
           + 
                  3         2
             36s G  + 396s G  + 1296s G
                0         0          0
        /
           1944
       ,

       s  =
        5
                               2
             (135s G + 2268s )H
                  0         0
           + 
                   3          2
             (30s G  + 1350s G  + 16416s G + 38880s )H
                 0          0           0          0
           + 
              5        4          3          2
           s G  + 60s G  + 1188s G  + 9504s G  + 25920s G
            0        0          0          0           0
        /
           29160
       ,

       s  =
        6
                   3          2                        2
             405s H  + (405s G  + 18468s G + 174960s )H
                 0          0           0           0
           + 
                      4          3           2
                 45s G  + 3510s G  + 88776s G  + 777600s G
                    0          0           0            0
               + 
                 1166400s
                         0
            *
               H
           + 
                6        5          4           3
             s G  + 90s G  + 2628s G  + 27864s G
              0        0          0           0
           + 
                     2
             90720s G
                   0
        /
           524880
       ,

       s  =
        7
                                 3
             (2835s G + 91854s )H
                   0          0
           + 
                       3           2
                 945s G  + 81648s G  + 2082996s G
                     0           0             0
               + 
                 14171760s
                          0
            *
                2
               H
           + 
                      5          4            3
                 63s G  + 7560s G  + 317520s G
                    0          0            0
               + 
                           2
                 5554008s G  + 34058880s G
                         0              0
            *
               H
           + 
                7         6          5           4
             s G  + 126s G  + 4788s G  + 25272s G
              0         0          0           0
           + 
                         3              2
             - 1744416s G  - 26827200s G  - 97977600s G
                       0              0              0
        /
           11022480
       ]
     ]
   Type: List List Equation Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty16}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty16}{ugxLinearOrdinaryDifferentialOperatorSeriesPagePatch16}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorSeriesPageEmpty16}{\showpaste}
\tab{5}\spadcommand{leq\free{n7 leq }}
\end{paste}\end{patch}

\end{chunk}
\section{lodo1.ht}
\pagetitle{LinearOrdinaryDifferentialOperatorOneXmpPage}{lodo1.ht}
{LinearOrdinaryDifferentialOperator1}
\pageto{notitle}{ugxLinearOrdinaryDifferentialOperatorOneRatPage}
\begin{chunk}{lodo1.ht}
\begin{page}{LinearOrdinaryDifferentialOperatorOneXmpPage}
{LinearOrdinaryDifferentialOperator1}
\beginscroll

\spadtype{LinearOrdinaryDifferentialOperator1(A)} is the domain of 
linear ordinary differential operators with coefficients in the 
differential ring \spad{A}.
%This includes the cases of operators which are polynomials in \spad{D}
%acting upon scalar or vector expressions of a single variable.
%The coefficients of the operator polynomials can be integers, rational
%functions, matrices or elements of other domains.
\showBlurb{LinearOrdinaryDifferentialOperator1}

\beginmenu
    \menudownlink{
{9.45.1. Differential Operators with Rational Function Coefficients}}
{ugxLinearOrdinaryDifferentialOperatorOneRatPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugxLinearOrdinaryDifferentialOperatorOneRatPage}{lodo1.ht}
{Differential Operators with Rational Function Coefficients}
\begin{chunk}{lodo1.ht}
\begin{page}{ugxLinearOrdinaryDifferentialOperatorOneRatPage}
{Differential Operators with Rational Function Coefficients}
\beginscroll

This example shows differential operators with rational function
coefficients.  In this case operator multiplication is non-commutative and,
since the coefficients form a field, an operator division algorithm exists.

\labelSpace{2pc}
\xtc{
We begin by defining \spad{RFZ} to be the rational functions in
\spad{x} with integer coefficients and \spad{Dx} to be the differential
operator for \spad{d/dx}.
}{
\spadpaste{RFZ := Fraction UnivariatePolynomial('x, Integer) \bound{RFZ0}}
}
\xtc{
}{
\spadpaste{x : RFZ := 'x \free{RFZ0}\bound{RFZ}}
}
\xtc{
}{
\spadpaste{Dx : LODO1 RFZ := D()\bound{Dx}\free{RFZ}}
}
\xtc{
Operators are created using the usual arithmetic operations.
}{
\spadpaste{b : LODO1 RFZ := 3*x**2*Dx**2 + 2*Dx + 1/x  \free{Dx}\bound{b}}
}
\xtc{
}{
\spadpaste{a : LODO1 RFZ := b*(5*x*Dx + 7)             \free{b Dx}\bound{a}}
}
\xtc{
Operator multiplication corresponds to functional composition.
}{
\spadpaste{p := x**2 + 1/x**2 \bound{p}\free{RFZ}}
}
\xtc{
Since operator coefficients depend on \spad{x}, the multiplication is
not commutative.
}{
\spadpaste{(a*b - b*a) p \free{a b p}}
}

When the coefficients of operator polynomials come from a field, as in
this case, it is possible to define operator division.  Division on
the left and division on the right yield different results when the
multiplication is non-commutative.

The results of 
\spadfunFrom{leftDivide}{LinearOrdinaryDifferentialOperator1} and
\spadfunFrom{rightDivide}{LinearOrdinaryDifferentialOperator1} are
quotient-remainder pairs satisfying: \newline
%
\spad{leftDivide(a,b) = [q, r]} such that  \spad{a = b*q + r} \newline
\spad{rightDivide(a,b) = [q, r]} such that  \spad{a = q*b + r} \newline
%
\xtc{
In both cases, the 
\spadfunFrom{degree}{LinearOrdinaryDifferentialOperator1}
of the remainder, \spad{r}, is less than
the degree of \spad{b}.
}{
\spadpaste{ld := leftDivide(a,b) \bound{ld}\free{a b}}
}
\xtc{
}{
\spadpaste{a = b * ld.quotient + ld.remainder \free{a b ld}}
}
\xtc{
The operations of left and right division
are so-called because the quotient is obtained by dividing
\spad{a} on that side by \spad{b}.
}{
\spadpaste{rd := rightDivide(a,b) \bound{rd}\free{a b}}
}
\xtc{
}{
\spadpaste{a = rd.quotient * b + rd.remainder \free{a b rd}}
}

\xtc{
Operations \spadfunFrom{rightQuotient}{LinearOrdinaryDifferentialOperator1}
and \spadfunFrom{rightRemainder}{LinearOrdinaryDifferentialOperator1}
are available if only one of the quotient or remainder are of
interest to you.
This is the quotient from right division.
}{
\spadpaste{rightQuotient(a,b) \free{a b}}
}
\xtc{
This is the remainder from right division.
The corresponding ``left'' functions
\spadfunFrom{leftQuotient}{LinearOrdinaryDifferentialOperator1} and
\spadfunFrom{leftRemainder}{LinearOrdinaryDifferentialOperator1}
are also available.
}{
\spadpaste{rightRemainder(a,b) \free{a b}}
}

\xtc{
For exact division, the operations
\spadfunFrom{leftExactQuotient}{LinearOrdinaryDifferentialOperator1} and
\spadfunFrom{rightExactQuotient}{LinearOrdinaryDifferentialOperator1} 
are supplied.
These return the quotient but only if the remainder is zero.
The call \spad{rightExactQuotient(a,b)} would yield an error.
}{
\spadpaste{leftExactQuotient(a,b) \free{a b}}
}

\xtc{
The division operations allow the computation of left and right 
greatest common divisors 
(\spadfunFrom{leftGcd}{LinearOrdinaryDifferentialOperator1} and
\spadfunFrom{rightGcd}{LinearOrdinaryDifferentialOperator1}) via 
remainder sequences, and consequently the computation of left and 
right least common
multiples (\spadfunFrom{rightLcm}{LinearOrdinaryDifferentialOperator1} 
and 
\spadfunFrom{leftLcm}{LinearOrdinaryDifferentialOperator1}).
}{
\spadpaste{e := leftGcd(a,b) \bound{e}\free{a b}}
}
\xtc{
Note that a greatest common divisor doesn't necessarily divide \spad{a} and
{9.45.1.}{Differential Operators with Rational Function Coefficients}
\spad{b} on both sides.
Here the left greatest common divisor does not divide \spad{a} on the right.
}{
\spadpaste{leftRemainder(a, e) \free{a e}}
}
\xtc{
}{
\spadpaste{rightRemainder(a, e) \free{a e}}
}

\xtc{
Similarly, a least common multiple
is not necessarily divisible from both sides.
}{
\spadpaste{f := rightLcm(a,b) \bound{f}\free{a b}}
}
\xtc{
}{
\spadpaste{rightRemainder(f, b) \free{f b}}
}
\xtc{
}{
\spadpaste{leftRemainder(f, b) \free{f b}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch1}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull1}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty1}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull1}{\hidepaste}
\tab{5}\spadcommand{RFZ := Fraction UnivariatePolynomial('x, Integer)\bound{RFZ0 }}
\indentrel{3}\begin{verbatim}
   (1)  Fraction UnivariatePolynomial(x,Integer)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty1}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty1}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch1}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty1}{\showpaste}
\tab{5}\spadcommand{RFZ := Fraction UnivariatePolynomial('x, Integer)\bound{RFZ0 }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch2}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull2}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty2}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull2}{\hidepaste}
\tab{5}\spadcommand{x : RFZ := 'x\free{RFZ0 }\bound{RFZ }}
\indentrel{3}\begin{verbatim}
   (2)  x
         Type: Fraction UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty2}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty2}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch2}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty2}{\showpaste}
\tab{5}\spadcommand{x : RFZ := 'x\free{RFZ0 }\bound{RFZ }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch3}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull3}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty3}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull3}{\hidepaste}
\tab{5}\spadcommand{Dx : LODO1 RFZ := D()\bound{Dx }\free{RFZ }}
\indentrel{3}\begin{verbatim}
   (3)  D
Type: LinearOrdinaryDifferentialOperator1 Fraction UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty3}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty3}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch3}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty3}{\showpaste}
\tab{5}\spadcommand{Dx : LODO1 RFZ := D()\bound{Dx }\free{RFZ }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch4}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull4}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty4}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull4}{\hidepaste}
\tab{5}\spadcommand{b : LODO1 RFZ := 3*x**2*Dx**2 + 2*Dx + 1/x\free{Dx }\bound{b }}
\indentrel{3}\begin{verbatim}
          2 2        1
   (4)  3x D  + 2D + Ä
                     x
Type: LinearOrdinaryDifferentialOperator1 Fraction UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty4}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty4}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch4}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty4}{\showpaste}
\tab{5}\spadcommand{b : LODO1 RFZ := 3*x**2*Dx**2 + 2*Dx + 1/x\free{Dx }\bound{b }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch5}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull5}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty5}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull5}{\hidepaste}
\tab{5}\spadcommand{a : LODO1 RFZ := b*(5*x*Dx + 7)\free{b Dx }\bound{a }}
\indentrel{3}\begin{verbatim}
           3 3       2        2         7
   (5)  15x D  + (51x  + 10x)D  + 29D + Ä
                                        x
Type: LinearOrdinaryDifferentialOperator1 Fraction UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty5}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty5}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch5}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty5}{\showpaste}
\tab{5}\spadcommand{a : LODO1 RFZ := b*(5*x*Dx + 7)\free{b Dx }\bound{a }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch6}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull6}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty6}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull6}{\hidepaste}
\tab{5}\spadcommand{p := x**2 + 1/x**2\bound{p }\free{RFZ }}
\indentrel{3}\begin{verbatim}
         4
        x  + 1
   (6)  ÄÄÄÄÄÄ
           2
          x
         Type: Fraction UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty6}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty6}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch6}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty6}{\showpaste}
\tab{5}\spadcommand{p := x**2 + 1/x**2\bound{p }\free{RFZ }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch7}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull7}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty7}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull7}{\hidepaste}
\tab{5}\spadcommand{(a*b - b*a) p\free{a b p }}
\indentrel{3}\begin{verbatim}
             4
        - 75x  + 540x - 75
   (7)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                 4
                x
         Type: Fraction UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty7}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty7}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch7}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty7}{\showpaste}
\tab{5}\spadcommand{(a*b - b*a) p\free{a b p }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch8}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull8}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty8}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull8}{\hidepaste}
\tab{5}\spadcommand{ld := leftDivide(a,b)\bound{ld }\free{a b }}
\indentrel{3}\begin{verbatim}
   (8)  [quotient= 5x D + 7,remainder= 0]
Type: Record(quotient: LinearOrdinaryDifferentialOperator1 Fraction UnivariatePolynomial(x,Integer),remainder: LinearOrdinaryDifferentialOperator1 Fraction UnivariatePolynomial(x,Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty8}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty8}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch8}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty8}{\showpaste}
\tab{5}\spadcommand{ld := leftDivide(a,b)\bound{ld }\free{a b }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch9}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull9}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty9}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull9}{\hidepaste}
\tab{5}\spadcommand{a = b * ld.quotient + ld.remainder\free{a b ld }}
\indentrel{3}\begin{verbatim}
   (9)
      3 3       2        2         7
   15x D  + (51x  + 10x)D  + 29D + Ä =
                                   x
        3 3       2        2         7
     15x D  + (51x  + 10x)D  + 29D + Ä
                                     x
Type: Equation LinearOrdinaryDifferentialOperator1 Fraction UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty9}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty9}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch9}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty9}{\showpaste}
\tab{5}\spadcommand{a = b * ld.quotient + ld.remainder\free{a b ld }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch10}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull10}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty10}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull10}{\hidepaste}
\tab{5}\spadcommand{rd := rightDivide(a,b)\bound{rd }\free{a b }}
\indentrel{3}\begin{verbatim}
                                              5
   (10)  [quotient= 5x D + 7,remainder= 10D + Ä]
                                              x
Type: Record(quotient: LinearOrdinaryDifferentialOperator1 Fraction UnivariatePolynomial(x,Integer),remainder: LinearOrdinaryDifferentialOperator1 Fraction UnivariatePolynomial(x,Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty10}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty10}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch10}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty10}{\showpaste}
\tab{5}\spadcommand{rd := rightDivide(a,b)\bound{rd }\free{a b }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch11}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull11}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty11}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull11}{\hidepaste}
\tab{5}\spadcommand{a = rd.quotient * b + rd.remainder\free{a b rd }}
\indentrel{3}\begin{verbatim}
   (11)
      3 3       2        2         7
   15x D  + (51x  + 10x)D  + 29D + Ä =
                                   x
        3 3       2        2         7
     15x D  + (51x  + 10x)D  + 29D + Ä
                                     x
Type: Equation LinearOrdinaryDifferentialOperator1 Fraction UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty11}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty11}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch11}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty11}{\showpaste}
\tab{5}\spadcommand{a = rd.quotient * b + rd.remainder\free{a b rd }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch12}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull12}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty12}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull12}{\hidepaste}
\tab{5}\spadcommand{rightQuotient(a,b)\free{a b }}
\indentrel{3}\begin{verbatim}
   (12)  5x D + 7
Type: LinearOrdinaryDifferentialOperator1 Fraction UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty12}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty12}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch12}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty12}{\showpaste}
\tab{5}\spadcommand{rightQuotient(a,b)\free{a b }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch13}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull13}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty13}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull13}{\hidepaste}
\tab{5}\spadcommand{rightRemainder(a,b)\free{a b }}
\indentrel{3}\begin{verbatim}
               5
   (13)  10D + Ä
               x
Type: LinearOrdinaryDifferentialOperator1 Fraction UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty13}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty13}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch13}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty13}{\showpaste}
\tab{5}\spadcommand{rightRemainder(a,b)\free{a b }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch14}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull14}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty14}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull14}{\hidepaste}
\tab{5}\spadcommand{leftExactQuotient(a,b)\free{a b }}
\indentrel{3}\begin{verbatim}
   (14)  5x D + 7
Type: Union(LinearOrdinaryDifferentialOperator1 Fraction UnivariatePolynomial(x,Integer),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty14}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty14}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch14}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty14}{\showpaste}
\tab{5}\spadcommand{leftExactQuotient(a,b)\free{a b }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch15}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull15}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty15}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull15}{\hidepaste}
\tab{5}\spadcommand{e := leftGcd(a,b)\bound{e }\free{a b }}
\indentrel{3}\begin{verbatim}
           2 2        1
   (15)  3x D  + 2D + Ä
                      x
Type: LinearOrdinaryDifferentialOperator1 Fraction UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty15}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty15}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch15}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty15}{\showpaste}
\tab{5}\spadcommand{e := leftGcd(a,b)\bound{e }\free{a b }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch16}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull16}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty16}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull16}{\hidepaste}
\tab{5}\spadcommand{leftRemainder(a, e)\free{a e }}
\indentrel{3}\begin{verbatim}
   (16)  0
Type: LinearOrdinaryDifferentialOperator1 Fraction UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty16}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty16}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch16}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty16}{\showpaste}
\tab{5}\spadcommand{leftRemainder(a, e)\free{a e }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch17}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull17}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty17}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull17}{\hidepaste}
\tab{5}\spadcommand{rightRemainder(a, e)\free{a e }}
\indentrel{3}\begin{verbatim}
               5
   (17)  10D + Ä
               x
Type: LinearOrdinaryDifferentialOperator1 Fraction UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty17}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty17}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch17}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty17}{\showpaste}
\tab{5}\spadcommand{rightRemainder(a, e)\free{a e }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch18}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull18}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty18}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull18}{\hidepaste}
\tab{5}\spadcommand{f := rightLcm(a,b)\bound{f }\free{a b }}
\indentrel{3}\begin{verbatim}
            3 3       2        2         7
   (18)  15x D  + (51x  + 10x)D  + 29D + Ä
                                         x
Type: LinearOrdinaryDifferentialOperator1 Fraction UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty18}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty18}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch18}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty18}{\showpaste}
\tab{5}\spadcommand{f := rightLcm(a,b)\bound{f }\free{a b }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch19}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull19}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty19}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull19}{\hidepaste}
\tab{5}\spadcommand{rightRemainder(f, b)\free{f b }}
\indentrel{3}\begin{verbatim}
               5
   (19)  10D + Ä
               x
Type: LinearOrdinaryDifferentialOperator1 Fraction UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty19}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty19}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch19}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty19}{\showpaste}
\tab{5}\spadcommand{rightRemainder(f, b)\free{f b }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch20}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull20}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty20}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageFull20}{\hidepaste}
\tab{5}\spadcommand{leftRemainder(f, b)\free{f b }}
\indentrel{3}\begin{verbatim}
   (20)  0
Type: LinearOrdinaryDifferentialOperator1 Fraction UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty20}
\begin{paste}{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty20}{ugxLinearOrdinaryDifferentialOperatorOneRatPagePatch20}
\pastebutton{ugxLinearOrdinaryDifferentialOperatorOneRatPageEmpty20}{\showpaste}
\tab{5}\spadcommand{leftRemainder(f, b)\free{f b }}
\end{paste}\end{patch}

\end{chunk}
\section{lodo2.ht}
\pagetitle{LinearODEOperatorTwoXmpPage}{lodo2.ht}
{LinearOrdinaryDifferentialOperator2}
\pageto{notitle}{ugxLinearODEOperatorTwoConstPage}
\pageto{notitle}{ugxLinearODEOperatorTwoMatrixPage}
\begin{chunk}{lodo2.ht}
\begin{page}{LinearODEOperatorTwoXmpPage}
{LinearOrdinaryDifferentialOperator2}
\beginscroll

\spadtype{LinearOrdinaryDifferentialOperator2(A, M)} is the domain of
linear ordinary differential operators with coefficients in the
differential ring \spad{A} and operating on \spad{M}, an
\spad{A}-module.  This includes the cases of operators which are
polynomials in \spad{D} acting upon scalar or vector expressions of a
single variable.  The coefficients of the operator polynomials can be
integers, rational functions, matrices or elements of other domains.
\showBlurb{LinearOrdinaryDifferentialOperator2}

\beginmenu
    \menudownlink{
{9.46.1. Differential Operators with Constant Coefficients}}
{ugxLinearODEOperatorTwoConstPage}
    \menudownlink{
{9.46.2. 
Differential Operators with Matrix Coefficients Operating on Vectors}}
{ugxLinearODEOperatorTwoMatrixPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugxLinearODEOperatorTwoConstPage}{lodo2.ht}
{Differential Operators with Constant Coefficients}
\begin{chunk}{lodo2.ht}
\begin{page}{ugxLinearODEOperatorTwoConstPage}
{Differential Operators with Constant Coefficients}
\beginscroll

This example shows differential operators with rational
number coefficients operating on univariate polynomials.

\labelSpace{3pc}
\xtc{
We begin by making type assignments so we can conveniently refer
to univariate polynomials in \spad{x} over the rationals.
}{
\spadpaste{Q  := Fraction Integer \bound{Q}}
}
\xtc{
}{
\spadpaste{PQ := UnivariatePolynomial('x, Q) \free{Q}\bound{PQ0}}
}
\xtc{
}{
\spadpaste{x: PQ := 'x \free{PQ0}\bound{x}}
}
\xtc{
Now we assign \spad{Dx} to be the differential operator
\spadfunFrom{D}{LinearOrdinaryDifferentialOperator2}
corresponding to \spad{d/dx}.
}{
\spadpaste{Dx: LODO2(Q, PQ) := D() \free{Q PQ0}\bound{Dx}}
}
\xtc{
New operators are created as polynomials in \spad{D()}.
}{
\spadpaste{a := Dx  + 1 \bound{a}\free{Dx}}
}
\xtc{
}{
\spadpaste{b := a + 1/2*Dx**2 - 1/2 \bound{b}\free{Dx}}
}
\xtc{
To apply the operator \spad{a} to the value \spad{p} the usual function
call syntax is used.
}{
\spadpaste{p := 4*x**2 + 2/3 \free{x}\bound{p}}
}
\xtc{
}{
\spadpaste{a p \free{a p}}
}
\xtc{
Operator multiplication is defined by the identity \spad{(a*b) p = a(b(p))}
}{
\spadpaste{(a * b) p = a b p \free{a b p}}
}
\xtc{
Exponentiation follows from multiplication.
}{
\spadpaste{c := (1/9)*b*(a + b)**2 \free{a b}\bound{c}}
}
\xtc{
Finally, note that operator expressions may be applied directly.
}{
\spadpaste{(a**2 - 3/4*b + c) (p + 1) \free{a b c p}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxLinearODEOperatorTwoConstPagePatch1}
\begin{paste}{ugxLinearODEOperatorTwoConstPageFull1}{ugxLinearODEOperatorTwoConstPageEmpty1}
\pastebutton{ugxLinearODEOperatorTwoConstPageFull1}{\hidepaste}
\tab{5}\spadcommand{Q := Fraction Integer\bound{Q }}
\indentrel{3}\begin{verbatim}
   (1)  Fraction Integer
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoConstPageEmpty1}
\begin{paste}{ugxLinearODEOperatorTwoConstPageEmpty1}{ugxLinearODEOperatorTwoConstPagePatch1}
\pastebutton{ugxLinearODEOperatorTwoConstPageEmpty1}{\showpaste}
\tab{5}\spadcommand{Q := Fraction Integer\bound{Q }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoConstPagePatch2}
\begin{paste}{ugxLinearODEOperatorTwoConstPageFull2}{ugxLinearODEOperatorTwoConstPageEmpty2}
\pastebutton{ugxLinearODEOperatorTwoConstPageFull2}{\hidepaste}
\tab{5}\spadcommand{PQ := UnivariatePolynomial('x, Q)\free{Q }\bound{PQ0 }}
\indentrel{3}\begin{verbatim}
   (2)  UnivariatePolynomial(x,Fraction Integer)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoConstPageEmpty2}
\begin{paste}{ugxLinearODEOperatorTwoConstPageEmpty2}{ugxLinearODEOperatorTwoConstPagePatch2}
\pastebutton{ugxLinearODEOperatorTwoConstPageEmpty2}{\showpaste}
\tab{5}\spadcommand{PQ := UnivariatePolynomial('x, Q)\free{Q }\bound{PQ0 }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoConstPagePatch3}
\begin{paste}{ugxLinearODEOperatorTwoConstPageFull3}{ugxLinearODEOperatorTwoConstPageEmpty3}
\pastebutton{ugxLinearODEOperatorTwoConstPageFull3}{\hidepaste}
\tab{5}\spadcommand{x: PQ := 'x\free{PQ0 }\bound{x }}
\indentrel{3}\begin{verbatim}
   (3)  x
         Type: UnivariatePolynomial(x,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoConstPageEmpty3}
\begin{paste}{ugxLinearODEOperatorTwoConstPageEmpty3}{ugxLinearODEOperatorTwoConstPagePatch3}
\pastebutton{ugxLinearODEOperatorTwoConstPageEmpty3}{\showpaste}
\tab{5}\spadcommand{x: PQ := 'x\free{PQ0 }\bound{x }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoConstPagePatch4}
\begin{paste}{ugxLinearODEOperatorTwoConstPageFull4}{ugxLinearODEOperatorTwoConstPageEmpty4}
\pastebutton{ugxLinearODEOperatorTwoConstPageFull4}{\hidepaste}
\tab{5}\spadcommand{Dx: LODO2(Q, PQ) := D()\free{Q PQ0 }\bound{Dx }}
\indentrel{3}\begin{verbatim}
   (4)  D
Type: LinearOrdinaryDifferentialOperator2(Fraction Integer,UnivariatePolynomial(x,Fraction Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoConstPageEmpty4}
\begin{paste}{ugxLinearODEOperatorTwoConstPageEmpty4}{ugxLinearODEOperatorTwoConstPagePatch4}
\pastebutton{ugxLinearODEOperatorTwoConstPageEmpty4}{\showpaste}
\tab{5}\spadcommand{Dx: LODO2(Q, PQ) := D()\free{Q PQ0 }\bound{Dx }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoConstPagePatch5}
\begin{paste}{ugxLinearODEOperatorTwoConstPageFull5}{ugxLinearODEOperatorTwoConstPageEmpty5}
\pastebutton{ugxLinearODEOperatorTwoConstPageFull5}{\hidepaste}
\tab{5}\spadcommand{a := Dx + 1\bound{a }\free{Dx }}
\indentrel{3}\begin{verbatim}
   (5)  D + 1
Type: LinearOrdinaryDifferentialOperator2(Fraction Integer,UnivariatePolynomial(x,Fraction Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoConstPageEmpty5}
\begin{paste}{ugxLinearODEOperatorTwoConstPageEmpty5}{ugxLinearODEOperatorTwoConstPagePatch5}
\pastebutton{ugxLinearODEOperatorTwoConstPageEmpty5}{\showpaste}
\tab{5}\spadcommand{a := Dx + 1\bound{a }\free{Dx }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoConstPagePatch6}
\begin{paste}{ugxLinearODEOperatorTwoConstPageFull6}{ugxLinearODEOperatorTwoConstPageEmpty6}
\pastebutton{ugxLinearODEOperatorTwoConstPageFull6}{\hidepaste}
\tab{5}\spadcommand{b := a + 1/2*Dx**2 - 1/2\bound{b }\free{Dx }}
\indentrel{3}\begin{verbatim}
        1  2       1
   (6)  Ä D  + D + Ä
        2          2
Type: LinearOrdinaryDifferentialOperator2(Fraction Integer,UnivariatePolynomial(x,Fraction Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoConstPageEmpty6}
\begin{paste}{ugxLinearODEOperatorTwoConstPageEmpty6}{ugxLinearODEOperatorTwoConstPagePatch6}
\pastebutton{ugxLinearODEOperatorTwoConstPageEmpty6}{\showpaste}
\tab{5}\spadcommand{b := a + 1/2*Dx**2 - 1/2\bound{b }\free{Dx }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoConstPagePatch7}
\begin{paste}{ugxLinearODEOperatorTwoConstPageFull7}{ugxLinearODEOperatorTwoConstPageEmpty7}
\pastebutton{ugxLinearODEOperatorTwoConstPageFull7}{\hidepaste}
\tab{5}\spadcommand{p := 4*x**2 + 2/3\free{x }\bound{p }}
\indentrel{3}\begin{verbatim}
          2   2
   (7)  4x  + Ä
              3
         Type: UnivariatePolynomial(x,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoConstPageEmpty7}
\begin{paste}{ugxLinearODEOperatorTwoConstPageEmpty7}{ugxLinearODEOperatorTwoConstPagePatch7}
\pastebutton{ugxLinearODEOperatorTwoConstPageEmpty7}{\showpaste}
\tab{5}\spadcommand{p := 4*x**2 + 2/3\free{x }\bound{p }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoConstPagePatch8}
\begin{paste}{ugxLinearODEOperatorTwoConstPageFull8}{ugxLinearODEOperatorTwoConstPageEmpty8}
\pastebutton{ugxLinearODEOperatorTwoConstPageFull8}{\hidepaste}
\tab{5}\spadcommand{a p\free{a p }}
\indentrel{3}\begin{verbatim}
          2        2
   (8)  4x  + 8x + Ä
                   3
         Type: UnivariatePolynomial(x,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoConstPageEmpty8}
\begin{paste}{ugxLinearODEOperatorTwoConstPageEmpty8}{ugxLinearODEOperatorTwoConstPagePatch8}
\pastebutton{ugxLinearODEOperatorTwoConstPageEmpty8}{\showpaste}
\tab{5}\spadcommand{a p\free{a p }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoConstPagePatch9}
\begin{paste}{ugxLinearODEOperatorTwoConstPageFull9}{ugxLinearODEOperatorTwoConstPageEmpty9}
\pastebutton{ugxLinearODEOperatorTwoConstPageFull9}{\hidepaste}
\tab{5}\spadcommand{(a * b) p = a b p\free{a b p }}
\indentrel{3}\begin{verbatim}
          2         37    2         37
   (9)  2x  + 12x + ÄÄ= 2x  + 12x + ÄÄ
                     3               3
Type: Equation UnivariatePolynomial(x,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoConstPageEmpty9}
\begin{paste}{ugxLinearODEOperatorTwoConstPageEmpty9}{ugxLinearODEOperatorTwoConstPagePatch9}
\pastebutton{ugxLinearODEOperatorTwoConstPageEmpty9}{\showpaste}
\tab{5}\spadcommand{(a * b) p = a b p\free{a b p }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoConstPagePatch10}
\begin{paste}{ugxLinearODEOperatorTwoConstPageFull10}{ugxLinearODEOperatorTwoConstPageEmpty10}
\pastebutton{ugxLinearODEOperatorTwoConstPageFull10}{\hidepaste}
\tab{5}\spadcommand{c := (1/9)*b*(a + b)**2\free{a b }\bound{c }}
\indentrel{3}\begin{verbatim}
   (10)
    1  6    5  5   13  4   19  3   79  2    7     1
   ÄÄ D  + ÄÄ D  + ÄÄ D  + ÄÄ D  + ÄÄ D  + ÄÄ D + Ä
   72      36      24      18      72      12     8
Type: LinearOrdinaryDifferentialOperator2(Fraction Integer,UnivariatePolynomial(x,Fraction Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoConstPageEmpty10}
\begin{paste}{ugxLinearODEOperatorTwoConstPageEmpty10}{ugxLinearODEOperatorTwoConstPagePatch10}
\pastebutton{ugxLinearODEOperatorTwoConstPageEmpty10}{\showpaste}
\tab{5}\spadcommand{c := (1/9)*b*(a + b)**2\free{a b }\bound{c }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoConstPagePatch11}
\begin{paste}{ugxLinearODEOperatorTwoConstPageFull11}{ugxLinearODEOperatorTwoConstPageEmpty11}
\pastebutton{ugxLinearODEOperatorTwoConstPageFull11}{\hidepaste}
\tab{5}\spadcommand{(a**2 - 3/4*b + c) (p + 1)\free{a b c p }}
\indentrel{3}\begin{verbatim}
           2   44     541
   (11)  3x  + ÄÄ x + ÄÄÄ
                3      36
         Type: UnivariatePolynomial(x,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoConstPageEmpty11}
\begin{paste}{ugxLinearODEOperatorTwoConstPageEmpty11}{ugxLinearODEOperatorTwoConstPagePatch11}
\pastebutton{ugxLinearODEOperatorTwoConstPageEmpty11}{\showpaste}
\tab{5}\spadcommand{(a**2 - 3/4*b + c) (p + 1)\free{a b c p }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxLinearODEOperatorTwoMatrixPage}{lodo2.ht}
{Differential Operators with Matrix Coefficients Operating on Vectors}
\begin{chunk}{lodo2.ht}
\begin{page}{ugxLinearODEOperatorTwoMatrixPage}
{Differential Operators with Matrix Coefficients Operating on Vectors}
\beginscroll

This is another example of linear ordinary differential
operators with non-commutative multiplication.
Unlike the rational function case, the differential ring of
square matrices (of a given dimension) with univariate
polynomial entries does not form a field.
Thus the number of operations available is more limited.

\labelSpace{1pc}
\xtc{
In this section, the operators have three by three
matrix coefficients with polynomial entries.
}{
\spadpaste{PZ   := UnivariatePolynomial(x,Integer)\bound{PZ0}}
}
\xtc{
}{
\spadpaste{x:PZ := 'x \free{PZ0}\bound{PZ}}
}
\xtc{
}{
\spadpaste{Mat  := SquareMatrix(3,PZ)\free{PZ}\bound{Mat}}
}
\xtc{
The operators act on the vectors considered as a \spad{Mat}-module.
}{
\spadpaste{Vect := DPMM(3, PZ, Mat, PZ);\free{PZ,Mat}\bound{Vect}}
}
\xtc{
}{
\spadpaste{Modo := LODO2(Mat, Vect);\free{Mat Vect}\bound{Modo}}
}
\xtc{
The matrix \spad{m} is used as a coefficient and the vectors \spad{p}
and \spad{q} are operated upon.
}{
\spadpaste{m:Mat := matrix [[x**2,1,0],[1,x**4,0],[0,0,4*x**2]]
\free{Mat}\bound{m}}
}
\xtc{
}{
\spadpaste{p:Vect := directProduct [3*x**2+1,2*x,7*x**3+2*x]
\free{Vect}\bound{p}}
}
\xtc{
}{
\spadpaste{q: Vect := m * p\free{m p Vect}\bound{q}}
}
\xtc{
Now form a few operators.
}{
\spadpaste{Dx : Modo := D()\bound{Dx}\free{Modo}}
}
\xtc{
}{
\spadpaste{a : Modo := Dx  + m\bound{a}\free{m Dx}}
}
\xtc{
}{
\spadpaste{b : Modo := m*Dx  + 1\bound{b}\free{m Dx}}
}
\xtc{
}{
\spadpaste{c := a*b \bound{c}\free{a b}}
}
\xtc{
These operators can be applied to vector values.
}{
\spadpaste{a p \free{p a}}
}
\xtc{
}{
\spadpaste{b p \free{p b}}
}
\xtc{
}{
\spadpaste{(a + b + c) (p + q) \free{a b c p q}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPagePatch1}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageFull1}{ugxLinearODEOperatorTwoMatrixPageEmpty1}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageFull1}{\hidepaste}
\tab{5}\spadcommand{PZ := UnivariatePolynomial(x,Integer)\bound{PZ0 }}
\indentrel{3}\begin{verbatim}
   (1)  UnivariatePolynomial(x,Integer)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPageEmpty1}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageEmpty1}{ugxLinearODEOperatorTwoMatrixPagePatch1}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageEmpty1}{\showpaste}
\tab{5}\spadcommand{PZ := UnivariatePolynomial(x,Integer)\bound{PZ0 }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPagePatch2}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageFull2}{ugxLinearODEOperatorTwoMatrixPageEmpty2}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageFull2}{\hidepaste}
\tab{5}\spadcommand{x:PZ := 'x\free{PZ0 }\bound{PZ }}
\indentrel{3}\begin{verbatim}
   (2)  x
                  Type: UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPageEmpty2}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageEmpty2}{ugxLinearODEOperatorTwoMatrixPagePatch2}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageEmpty2}{\showpaste}
\tab{5}\spadcommand{x:PZ := 'x\free{PZ0 }\bound{PZ }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPagePatch3}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageFull3}{ugxLinearODEOperatorTwoMatrixPageEmpty3}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageFull3}{\hidepaste}
\tab{5}\spadcommand{Mat := SquareMatrix(3,PZ)\free{PZ }\bound{Mat }}
\indentrel{3}\begin{verbatim}
   (3)  SquareMatrix(3,UnivariatePolynomial(x,Integer))
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPageEmpty3}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageEmpty3}{ugxLinearODEOperatorTwoMatrixPagePatch3}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageEmpty3}{\showpaste}
\tab{5}\spadcommand{Mat := SquareMatrix(3,PZ)\free{PZ }\bound{Mat }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPagePatch4}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageFull4}{ugxLinearODEOperatorTwoMatrixPageEmpty4}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageFull4}{\hidepaste}
\tab{5}\spadcommand{Vect := DPMM(3, PZ, Mat, PZ);\free{PZ Mat }\bound{Vect }}
\indentrel{3}\begin{verbatim}
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPageEmpty4}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageEmpty4}{ugxLinearODEOperatorTwoMatrixPagePatch4}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageEmpty4}{\showpaste}
\tab{5}\spadcommand{Vect := DPMM(3, PZ, Mat, PZ);\free{PZ Mat }\bound{Vect }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPagePatch5}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageFull5}{ugxLinearODEOperatorTwoMatrixPageEmpty5}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageFull5}{\hidepaste}
\tab{5}\spadcommand{Modo := LODO2(Mat, Vect);\free{Mat Vect }\bound{Modo }}
\indentrel{3}\begin{verbatim}
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPageEmpty5}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageEmpty5}{ugxLinearODEOperatorTwoMatrixPagePatch5}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageEmpty5}{\showpaste}
\tab{5}\spadcommand{Modo := LODO2(Mat, Vect);\free{Mat Vect }\bound{Modo }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPagePatch6}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageFull6}{ugxLinearODEOperatorTwoMatrixPageEmpty6}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageFull6}{\hidepaste}
\tab{5}\spadcommand{m:Mat := matrix [[x**2,1,0],[1,x**4,0],[0,0,4*x**2]]\free{Mat }\bound{m }}
\indentrel{3}\begin{verbatim}
        Ú 2         ¿
        ³x   1    0 ³
        ³           ³
   (6)  ³     4     ³
        ³1   x    0 ³
        ³           ³
        ³          2³
        À0   0   4x Ù
  Type: SquareMatrix(3,UnivariatePolynomial(x,Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPageEmpty6}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageEmpty6}{ugxLinearODEOperatorTwoMatrixPagePatch6}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageEmpty6}{\showpaste}
\tab{5}\spadcommand{m:Mat := matrix [[x**2,1,0],[1,x**4,0],[0,0,4*x**2]]\free{Mat }\bound{m }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPagePatch7}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageFull7}{ugxLinearODEOperatorTwoMatrixPageEmpty7}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageFull7}{\hidepaste}
\tab{5}\spadcommand{p:Vect := directProduct [3*x**2+1,2*x,7*x**3+2*x]\free{Vect }\bound{p }}
\indentrel{3}\begin{verbatim}
           2          3
   (7)  [3x  + 1,2x,7x  + 2x]
Type: DirectProductMatrixModule(3,UnivariatePolynomial(x,Integer),SquareMatrix(3,UnivariatePolynomial(x,Integer)),UnivariatePolynomial(x,Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPageEmpty7}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageEmpty7}{ugxLinearODEOperatorTwoMatrixPagePatch7}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageEmpty7}{\showpaste}
\tab{5}\spadcommand{p:Vect := directProduct [3*x**2+1,2*x,7*x**3+2*x]\free{Vect }\bound{p }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPagePatch8}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageFull8}{ugxLinearODEOperatorTwoMatrixPageEmpty8}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageFull8}{\hidepaste}
\tab{5}\spadcommand{q: Vect := m * p\free{m p Vect }\bound{q }}
\indentrel{3}\begin{verbatim}
           4    2        5     2        5     3
   (8)  [3x  + x  + 2x,2x  + 3x  + 1,28x  + 8x ]
Type: DirectProductMatrixModule(3,UnivariatePolynomial(x,Integer),SquareMatrix(3,UnivariatePolynomial(x,Integer)),UnivariatePolynomial(x,Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPageEmpty8}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageEmpty8}{ugxLinearODEOperatorTwoMatrixPagePatch8}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageEmpty8}{\showpaste}
\tab{5}\spadcommand{q: Vect := m * p\free{m p Vect }\bound{q }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPagePatch9}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageFull9}{ugxLinearODEOperatorTwoMatrixPageEmpty9}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageFull9}{\hidepaste}
\tab{5}\spadcommand{Dx : Modo := D()\bound{Dx }\free{Modo }}
\indentrel{3}\begin{verbatim}
   (9)  D
Type: LinearOrdinaryDifferentialOperator2(SquareMatrix(3,UnivariatePolynomial(x,Integer)),DirectProductMatrixModule(3,UnivariatePolynomial(x,Integer),SquareMatrix(3,UnivariatePolynomial(x,Integer)),UnivariatePolynomial(x,Integer)))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPageEmpty9}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageEmpty9}{ugxLinearODEOperatorTwoMatrixPagePatch9}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageEmpty9}{\showpaste}
\tab{5}\spadcommand{Dx : Modo := D()\bound{Dx }\free{Modo }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPagePatch10}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageFull10}{ugxLinearODEOperatorTwoMatrixPageEmpty10}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageFull10}{\hidepaste}
\tab{5}\spadcommand{a : Modo := Dx + m\bound{a }\free{m Dx }}
\indentrel{3}\begin{verbatim}
             Ú 2         ¿
             ³x   1    0 ³
             ³           ³
   (10)  D + ³     4     ³
             ³1   x    0 ³
             ³           ³
             ³          2³
             À0   0   4x Ù
Type: LinearOrdinaryDifferentialOperator2(SquareMatrix(3,UnivariatePolynomial(x,Integer)),DirectProductMatrixModule(3,UnivariatePolynomial(x,Integer),SquareMatrix(3,UnivariatePolynomial(x,Integer)),UnivariatePolynomial(x,Integer)))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPageEmpty10}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageEmpty10}{ugxLinearODEOperatorTwoMatrixPagePatch10}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageEmpty10}{\showpaste}
\tab{5}\spadcommand{a : Modo := Dx + m\bound{a }\free{m Dx }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPagePatch11}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageFull11}{ugxLinearODEOperatorTwoMatrixPageEmpty11}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageFull11}{\hidepaste}
\tab{5}\spadcommand{b : Modo := m*Dx + 1\bound{b }\free{m Dx }}
\indentrel{3}\begin{verbatim}
         Ú 2         ¿
         ³x   1    0 ³    Ú1  0  0¿
         ³           ³    ³       ³
   (11)  ³     4     ³D + ³0  1  0³
         ³1   x    0 ³    ³       ³
         ³           ³    À0  0  1Ù
         ³          2³
         À0   0   4x Ù
Type: LinearOrdinaryDifferentialOperator2(SquareMatrix(3,UnivariatePolynomial(x,Integer)),DirectProductMatrixModule(3,UnivariatePolynomial(x,Integer),SquareMatrix(3,UnivariatePolynomial(x,Integer)),UnivariatePolynomial(x,Integer)))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPageEmpty11}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageEmpty11}{ugxLinearODEOperatorTwoMatrixPagePatch11}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageEmpty11}{\showpaste}
\tab{5}\spadcommand{b : Modo := m*Dx + 1\bound{b }\free{m Dx }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPagePatch12}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageFull12}{ugxLinearODEOperatorTwoMatrixPageEmpty12}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageFull12}{\hidepaste}
\tab{5}\spadcommand{c := a*b\bound{c }\free{a b }}
\indentrel{3}\begin{verbatim}
   (12)
     Ú 2         ¿
     ³x   1    0 ³
     ³           ³ 2
     ³     4     ³D
     ³1   x    0 ³
     ³           ³
     ³          2³
     À0   0   4x Ù
   + 
     Ú 4              4    2                  ¿
     ³x  + 2x + 2    x  + x            0      ³
     ³                                        ³
     ³   4    2     8     3                   ³D
     ³  x  + x     x  + 4x  + 2        0      ³
     ³                                        ³
     ³                              4         ³
     À     0            0        16x  + 8x + 1Ù
   + 
     Ú 2         ¿
     ³x   1    0 ³
     ³           ³
     ³     4     ³
     ³1   x    0 ³
     ³           ³
     ³          2³
     À0   0   4x Ù
Type: LinearOrdinaryDifferentialOperator2(SquareMatrix(3,UnivariatePolynomial(x,Integer)),DirectProductMatrixModule(3,UnivariatePolynomial(x,Integer),SquareMatrix(3,UnivariatePolynomial(x,Integer)),UnivariatePolynomial(x,Integer)))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPageEmpty12}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageEmpty12}{ugxLinearODEOperatorTwoMatrixPagePatch12}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageEmpty12}{\showpaste}
\tab{5}\spadcommand{c := a*b\bound{c }\free{a b }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPagePatch13}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageFull13}{ugxLinearODEOperatorTwoMatrixPageEmpty13}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageFull13}{\hidepaste}
\tab{5}\spadcommand{a p\free{p a }}
\indentrel{3}\begin{verbatim}
   (13)
      4    2        5     2        5     3      2
   [3x  + x  + 8x,2x  + 3x  + 3,28x  + 8x  + 21x  + 2]
Type: DirectProductMatrixModule(3,UnivariatePolynomial(x,Integer),SquareMatrix(3,UnivariatePolynomial(x,Integer)),UnivariatePolynomial(x,Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPageEmpty13}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageEmpty13}{ugxLinearODEOperatorTwoMatrixPagePatch13}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageEmpty13}{\showpaste}
\tab{5}\spadcommand{a p\free{p a }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPagePatch14}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageFull14}{ugxLinearODEOperatorTwoMatrixPageEmpty14}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageFull14}{\hidepaste}
\tab{5}\spadcommand{b p\free{p b }}
\indentrel{3}\begin{verbatim}
            3     2       4         4     3     2
   (14)  [6x  + 3x  + 3,2x  + 8x,84x  + 7x  + 8x  + 2x]
Type: DirectProductMatrixModule(3,UnivariatePolynomial(x,Integer),SquareMatrix(3,UnivariatePolynomial(x,Integer)),UnivariatePolynomial(x,Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPageEmpty14}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageEmpty14}{ugxLinearODEOperatorTwoMatrixPagePatch14}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageEmpty14}{\showpaste}
\tab{5}\spadcommand{b p\free{p b }}
\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPagePatch15}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageFull15}{ugxLinearODEOperatorTwoMatrixPageEmpty15}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageFull15}{\hidepaste}
\tab{5}\spadcommand{(a + b + c) (p + q)\free{a b c p q }}
\indentrel{3}\begin{verbatim}
   (15)
   [
          8      7      6      5      4      3      2
       10x  + 12x  + 16x  + 30x  + 85x  + 94x  + 40x
     + 
       40x + 17
     ,

          12      9      8      7     6      5      4
       10x   + 10x  + 12x  + 92x  + 6x  + 32x  + 72x
     + 
          3      2
       28x  + 49x  + 32x + 19
     ,

            8       7        6        5       4       3
       2240x  + 224x  + 1280x  + 3508x  + 492x  + 751x
     + 
          2
       98x  + 18x + 4
     ]
Type: DirectProductMatrixModule(3,UnivariatePolynomial(x,Integer),SquareMatrix(3,UnivariatePolynomial(x,Integer)),UnivariatePolynomial(x,Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxLinearODEOperatorTwoMatrixPageEmpty15}
\begin{paste}{ugxLinearODEOperatorTwoMatrixPageEmpty15}{ugxLinearODEOperatorTwoMatrixPagePatch15}
\pastebutton{ugxLinearODEOperatorTwoMatrixPageEmpty15}{\showpaste}
\tab{5}\spadcommand{(a + b + c) (p + q)\free{a b c p q }}
\end{paste}\end{patch}

\end{chunk}
\section{lpoly.ht}
\pagetitle{LiePolynomialXmpPage}{lpoly.ht}{LiePolynomial}
\begin{chunk}{lpoly.ht}
\begin{page}{LiePolynomialXmpPage}{LiePolynomial}
\beginscroll
Declaration of domains
\xtc{
}{
\spadpaste{RN    := Fraction Integer \bound{RN}}
}
\xtc{
}{
\spadpaste{Lpoly := LiePolynomial(Symbol,RN) \bound{Lpoly} \free{RN}}
}
\xtc{
}{
\spadpaste{Dpoly := XDPOLY(Symbol,RN) \bound{Dpoly} \free{RN}}
}
\xtc{
}{
\spadpaste{Lword := LyndonWord Symbol \bound{Lword}}
}

Initialisation
\xtc{
}{
\spadpaste{a:Symbol := 'a \bound{a}}
}
\xtc{
}{
\spadpaste{b:Symbol := 'b \bound{b}}
}
\xtc{
}{
\spadpaste{c:Symbol := 'c \bound{c}}
}
\xtc{
}{
\spadpaste{aa: Lpoly := a \bound{aa} \free{Lpoly} \free{a}}
}
\xtc{
}{
\spadpaste{bb: Lpoly := b \bound{bb} \free{Lpoly} \free{b}}
}
\xtc{
}{
\spadpaste{cc: Lpoly := c \bound{cc} \free{Lpoly} \free{c}}
}
\xtc{
}{
\spadpaste{p : Lpoly := [aa,bb] \bound{p} \free{aa} \free{bb} \free{Lpoly}}
}
\xtc{
}{
\spadpaste{q : Lpoly := [p,bb] \bound{q} \free{p} \free{bb} \free{Lpoly}}
}
\xtc{
All the Lyndon words of order 4
}{
\spadpaste{liste : List Lword := LyndonWordsList([a,b], 4) \free{a} 
\free{b} \free{Lword} \bound{liste}}
}
\xtc{
}{
\spadpaste{r: Lpoly := p + q + 3*LiePoly(liste.4)$Lpoly \bound{r} 
\free{Lpoly} \free{p} \free{q} \free{liste}}
}
\xtc{
}{
\spadpaste{s:Lpoly := [p,r] \bound{s} \free{Lpoly} \free{p} \free{r}}
}
\xtc{
}{
\spadpaste{t:Lpoly  := s  + 2*LiePoly(liste.3) - 5*LiePoly(liste.5) 
\bound{t} \free{Lpoly} \free{s} \free{liste} }
}
\xtc{
}{
\spadpaste{degree t \free{t}}
}
\xtc{
}{
\spadpaste{mirror t \free{t}}
}

Jacobi Relation
\xtc{
}{
\spadpaste{Jacobi(p: Lpoly, q: Lpoly, r: Lpoly): 
Lpoly == [[p,q]$Lpoly, r] + [[q,r]$Lpoly, p] + 
[[r,p]$Lpoly, q] \free{Lpoly} \bound{J}}
}

Tests
\xtc{
}{
\spadpaste{test: Lpoly := Jacobi(a,b,b) \free{J Lpoly a b} \bound{test1}}
}
\xtc{
}{
\spadpaste{test: Lpoly := Jacobi(p,q,r) \free{J p q r Lpoly} \bound{test2}}
}
\xtc{
}{
\spadpaste{test: Lpoly := Jacobi(r,s,t) \free{J r s t Lpoly} \bound{test3}}
}

Evaluation
\xtc{
}{
\spadpaste{eval(p, a, p)$Lpoly}
}
\xtc{
}{
\spadpaste{eval(p, [a,b], [2*bb, 3*aa])$Lpoly \free{p a b bb aa Lpoly}}
}
\xtc{
}{
\spadpaste{r: Lpoly := [p,c] \free{p c Lpoly} \bound{rr}}
}
\xtc{
}{
\spadpaste{r1: Lpoly := eval(r, [a,b,c], [bb, cc, aa])$Lpoly 
\free{rr a b c aa bb cc Lpoly} \bound{r1}}
}
\xtc{
}{
\spadpaste{r2: Lpoly := eval(r, [a,b,c], [cc, aa, bb])$Lpoly 
\free{rr a b c cc bb aa Lpoly} \bound{r2}}
}
\xtc{
}{
\spadpaste{r + r1 + r2 \free{rr r1 r2}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{LiePolynomialXmpPagePatch1}
\begin{paste}{LiePolynomialXmpPageFull1}{LiePolynomialXmpPageEmpty1}
\pastebutton{LiePolynomialXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{RN := Fraction Integer\bound{RN }}
\indentrel{3}\begin{verbatim}
   (1)  Fraction Integer
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty1}
\begin{paste}{LiePolynomialXmpPageEmpty1}{LiePolynomialXmpPagePatch1}
\pastebutton{LiePolynomialXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{RN := Fraction Integer\bound{RN }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch2}
\begin{paste}{LiePolynomialXmpPageFull2}{LiePolynomialXmpPageEmpty2}
\pastebutton{LiePolynomialXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{Lpoly := LiePolynomial(Symbol,RN)\bound{Lpoly }\free{RN }}
\indentrel{3}\begin{verbatim}
   (2)  LiePolynomial(Symbol,Fraction Integer)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty2}
\begin{paste}{LiePolynomialXmpPageEmpty2}{LiePolynomialXmpPagePatch2}
\pastebutton{LiePolynomialXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{Lpoly := LiePolynomial(Symbol,RN)\bound{Lpoly }\free{RN }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch3}
\begin{paste}{LiePolynomialXmpPageFull3}{LiePolynomialXmpPageEmpty3}
\pastebutton{LiePolynomialXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{Dpoly := XDPOLY(Symbol,RN)\bound{Dpoly }\free{RN }}
\indentrel{3}\begin{verbatim}
   (3)  XDistributedPolynomial(Symbol,Fraction Integer)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty3}
\begin{paste}{LiePolynomialXmpPageEmpty3}{LiePolynomialXmpPagePatch3}
\pastebutton{LiePolynomialXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{Dpoly := XDPOLY(Symbol,RN)\bound{Dpoly }\free{RN }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch4}
\begin{paste}{LiePolynomialXmpPageFull4}{LiePolynomialXmpPageEmpty4}
\pastebutton{LiePolynomialXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{Lword := LyndonWord Symbol\bound{Lword }}
\indentrel{3}\begin{verbatim}
   (4)  LyndonWord Symbol
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty4}
\begin{paste}{LiePolynomialXmpPageEmpty4}{LiePolynomialXmpPagePatch4}
\pastebutton{LiePolynomialXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{Lword := LyndonWord Symbol\bound{Lword }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch5}
\begin{paste}{LiePolynomialXmpPageFull5}{LiePolynomialXmpPageEmpty5}
\pastebutton{LiePolynomialXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{a:Symbol := 'a\bound{a }}
\indentrel{3}\begin{verbatim}
   (5)  a
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty5}
\begin{paste}{LiePolynomialXmpPageEmpty5}{LiePolynomialXmpPagePatch5}
\pastebutton{LiePolynomialXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{a:Symbol := 'a\bound{a }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch6}
\begin{paste}{LiePolynomialXmpPageFull6}{LiePolynomialXmpPageEmpty6}
\pastebutton{LiePolynomialXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{b:Symbol := 'b\bound{b }}
\indentrel{3}\begin{verbatim}
   (6)  b
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty6}
\begin{paste}{LiePolynomialXmpPageEmpty6}{LiePolynomialXmpPagePatch6}
\pastebutton{LiePolynomialXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{b:Symbol := 'b\bound{b }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch7}
\begin{paste}{LiePolynomialXmpPageFull7}{LiePolynomialXmpPageEmpty7}
\pastebutton{LiePolynomialXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{c:Symbol := 'c\bound{c }}
\indentrel{3}\begin{verbatim}
   (7)  c
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty7}
\begin{paste}{LiePolynomialXmpPageEmpty7}{LiePolynomialXmpPagePatch7}
\pastebutton{LiePolynomialXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{c:Symbol := 'c\bound{c }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch8}
\begin{paste}{LiePolynomialXmpPageFull8}{LiePolynomialXmpPageEmpty8}
\pastebutton{LiePolynomialXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{aa: Lpoly := a\bound{aa }\free{Lpoly }\free{a }}
\indentrel{3}\begin{verbatim}
   (8)  [a]
           Type: LiePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty8}
\begin{paste}{LiePolynomialXmpPageEmpty8}{LiePolynomialXmpPagePatch8}
\pastebutton{LiePolynomialXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{aa: Lpoly := a\bound{aa }\free{Lpoly }\free{a }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch9}
\begin{paste}{LiePolynomialXmpPageFull9}{LiePolynomialXmpPageEmpty9}
\pastebutton{LiePolynomialXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{bb: Lpoly := b\bound{bb }\free{Lpoly }\free{b }}
\indentrel{3}\begin{verbatim}
   (9)  [b]
           Type: LiePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty9}
\begin{paste}{LiePolynomialXmpPageEmpty9}{LiePolynomialXmpPagePatch9}
\pastebutton{LiePolynomialXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{bb: Lpoly := b\bound{bb }\free{Lpoly }\free{b }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch10}
\begin{paste}{LiePolynomialXmpPageFull10}{LiePolynomialXmpPageEmpty10}
\pastebutton{LiePolynomialXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{cc: Lpoly := c\bound{cc }\free{Lpoly }\free{c }}
\indentrel{3}\begin{verbatim}
   (10)  [c]
           Type: LiePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty10}
\begin{paste}{LiePolynomialXmpPageEmpty10}{LiePolynomialXmpPagePatch10}
\pastebutton{LiePolynomialXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{cc: Lpoly := c\bound{cc }\free{Lpoly }\free{c }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch11}
\begin{paste}{LiePolynomialXmpPageFull11}{LiePolynomialXmpPageEmpty11}
\pastebutton{LiePolynomialXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{p : Lpoly := [aa,bb]\bound{p }\free{aa }\free{bb }\free{Lpoly }}
\indentrel{3}\begin{verbatim}
   (11)  [a b]
           Type: LiePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty11}
\begin{paste}{LiePolynomialXmpPageEmpty11}{LiePolynomialXmpPagePatch11}
\pastebutton{LiePolynomialXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{p : Lpoly := [aa,bb]\bound{p }\free{aa }\free{bb }\free{Lpoly }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch12}
\begin{paste}{LiePolynomialXmpPageFull12}{LiePolynomialXmpPageEmpty12}
\pastebutton{LiePolynomialXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{q : Lpoly := [p,bb]\bound{q }\free{p }\free{bb }\free{Lpoly }}
\indentrel{3}\begin{verbatim}
             2
   (12)  [a b ]
           Type: LiePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty12}
\begin{paste}{LiePolynomialXmpPageEmpty12}{LiePolynomialXmpPagePatch12}
\pastebutton{LiePolynomialXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{q : Lpoly := [p,bb]\bound{q }\free{p }\free{bb }\free{Lpoly }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch13}
\begin{paste}{LiePolynomialXmpPageFull13}{LiePolynomialXmpPageEmpty13}
\pastebutton{LiePolynomialXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{liste : List Lword := LyndonWordsList([a,b], 4)\free{a }\free{b }\free{Lword }\bound{liste }}
\indentrel{3}\begin{verbatim}
   (13)
                    2       2    3     2 2      3
   [[a],[b],[a b],[a b],[a b ],[a b],[a b ],[a b ]]
                           Type: List LyndonWord Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty13}
\begin{paste}{LiePolynomialXmpPageEmpty13}{LiePolynomialXmpPagePatch13}
\pastebutton{LiePolynomialXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{liste : List Lword := LyndonWordsList([a,b], 4)\free{a }\free{b }\free{Lword }\bound{liste }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch14}
\begin{paste}{LiePolynomialXmpPageFull14}{LiePolynomialXmpPageEmpty14}
\pastebutton{LiePolynomialXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{r: Lpoly := p + q + 3*LiePoly(liste.4)$Lpoly\bound{r }\free{Lpoly }\free{p }\free{q }\free{liste }}
\indentrel{3}\begin{verbatim}
                    2         2
   (14)  [a b] + 3[a b] + [a b ]
           Type: LiePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty14}
\begin{paste}{LiePolynomialXmpPageEmpty14}{LiePolynomialXmpPagePatch14}
\pastebutton{LiePolynomialXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{r: Lpoly := p + q + 3*LiePoly(liste.4)$Lpoly\bound{r }\free{Lpoly }\free{p }\free{q }\free{liste }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch15}
\begin{paste}{LiePolynomialXmpPageFull15}{LiePolynomialXmpPageEmpty15}
\pastebutton{LiePolynomialXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{s:Lpoly := [p,r]\bound{s }\free{Lpoly }\free{p }\free{r }}
\indentrel{3}\begin{verbatim}
              2                 2
   (15)  - 3[a b a b] + [a b a b ]
           Type: LiePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty15}
\begin{paste}{LiePolynomialXmpPageEmpty15}{LiePolynomialXmpPagePatch15}
\pastebutton{LiePolynomialXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{s:Lpoly := [p,r]\bound{s }\free{Lpoly }\free{p }\free{r }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch16}
\begin{paste}{LiePolynomialXmpPageFull16}{LiePolynomialXmpPageEmpty16}
\pastebutton{LiePolynomialXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{t:Lpoly := s + 2*LiePoly(liste.3) - 5*LiePoly(liste.5)\bound{t }\free{Lpoly }\free{s }\free{liste }}
\indentrel{3}\begin{verbatim}
                       2       2                 2
   (16)  2[a b] - 5[a b ] - 3[a b a b] + [a b a b ]
           Type: LiePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty16}
\begin{paste}{LiePolynomialXmpPageEmpty16}{LiePolynomialXmpPagePatch16}
\pastebutton{LiePolynomialXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{t:Lpoly := s + 2*LiePoly(liste.3) - 5*LiePoly(liste.5)\bound{t }\free{Lpoly }\free{s }\free{liste }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch17}
\begin{paste}{LiePolynomialXmpPageFull17}{LiePolynomialXmpPageEmpty17}
\pastebutton{LiePolynomialXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{degree t\free{t }}
\indentrel{3}\begin{verbatim}
   (17)  5
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty17}
\begin{paste}{LiePolynomialXmpPageEmpty17}{LiePolynomialXmpPagePatch17}
\pastebutton{LiePolynomialXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{degree t\free{t }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch18}
\begin{paste}{LiePolynomialXmpPageFull18}{LiePolynomialXmpPageEmpty18}
\pastebutton{LiePolynomialXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{mirror t\free{t }}
\indentrel{3}\begin{verbatim}
                         2       2                 2
   (18)  - 2[a b] - 5[a b ] - 3[a b a b] + [a b a b ]
           Type: LiePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty18}
\begin{paste}{LiePolynomialXmpPageEmpty18}{LiePolynomialXmpPagePatch18}
\pastebutton{LiePolynomialXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{mirror t\free{t }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch19}
\begin{paste}{LiePolynomialXmpPageFull19}{LiePolynomialXmpPageEmpty19}
\pastebutton{LiePolynomialXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{Jacobi(p: Lpoly, q: Lpoly, r: Lpoly): Lpoly == [[p,q]$Lpoly, r] + [[q,r]$Lpoly, p] + [[r,p]$Lpoly, q]\free{Lpoly }\bound{J }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty19}
\begin{paste}{LiePolynomialXmpPageEmpty19}{LiePolynomialXmpPagePatch19}
\pastebutton{LiePolynomialXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{Jacobi(p: Lpoly, q: Lpoly, r: Lpoly): Lpoly == [[p,q]$Lpoly, r] + [[q,r]$Lpoly, p] + [[r,p]$Lpoly, q]\free{Lpoly }\bound{J }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch20}
\begin{paste}{LiePolynomialXmpPageFull20}{LiePolynomialXmpPageEmpty20}
\pastebutton{LiePolynomialXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{test: Lpoly := Jacobi(a,b,b)\free{J Lpoly a b }\bound{test1 }}
\indentrel{3}\begin{verbatim}
   (20)  0
           Type: LiePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty20}
\begin{paste}{LiePolynomialXmpPageEmpty20}{LiePolynomialXmpPagePatch20}
\pastebutton{LiePolynomialXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{test: Lpoly := Jacobi(a,b,b)\free{J Lpoly a b }\bound{test1 }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch21}
\begin{paste}{LiePolynomialXmpPageFull21}{LiePolynomialXmpPageEmpty21}
\pastebutton{LiePolynomialXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{test: Lpoly := Jacobi(p,q,r)\free{J p q r Lpoly }\bound{test2 }}
\indentrel{3}\begin{verbatim}
   (21)  0
           Type: LiePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty21}
\begin{paste}{LiePolynomialXmpPageEmpty21}{LiePolynomialXmpPagePatch21}
\pastebutton{LiePolynomialXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{test: Lpoly := Jacobi(p,q,r)\free{J p q r Lpoly }\bound{test2 }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch22}
\begin{paste}{LiePolynomialXmpPageFull22}{LiePolynomialXmpPageEmpty22}
\pastebutton{LiePolynomialXmpPageFull22}{\hidepaste}
\tab{5}\spadcommand{test: Lpoly := Jacobi(r,s,t)\free{J r s t Lpoly }\bound{test3 }}
\indentrel{3}\begin{verbatim}
   (22)  0
           Type: LiePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty22}
\begin{paste}{LiePolynomialXmpPageEmpty22}{LiePolynomialXmpPagePatch22}
\pastebutton{LiePolynomialXmpPageEmpty22}{\showpaste}
\tab{5}\spadcommand{test: Lpoly := Jacobi(r,s,t)\free{J r s t Lpoly }\bound{test3 }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch23}
\begin{paste}{LiePolynomialXmpPageFull23}{LiePolynomialXmpPageEmpty23}
\pastebutton{LiePolynomialXmpPageFull23}{\hidepaste}
\tab{5}\spadcommand{eval(p, a, p)$Lpoly}
\indentrel{3}\begin{verbatim}
             2
   (23)  [a b ]
           Type: LiePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty23}
\begin{paste}{LiePolynomialXmpPageEmpty23}{LiePolynomialXmpPagePatch23}
\pastebutton{LiePolynomialXmpPageEmpty23}{\showpaste}
\tab{5}\spadcommand{eval(p, a, p)$Lpoly}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch24}
\begin{paste}{LiePolynomialXmpPageFull24}{LiePolynomialXmpPageEmpty24}
\pastebutton{LiePolynomialXmpPageFull24}{\hidepaste}
\tab{5}\spadcommand{eval(p, [a,b], [2*bb, 3*aa])$Lpoly\free{p a b bb aa Lpoly }}
\indentrel{3}\begin{verbatim}
   (24)  - 6[a b]
           Type: LiePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty24}
\begin{paste}{LiePolynomialXmpPageEmpty24}{LiePolynomialXmpPagePatch24}
\pastebutton{LiePolynomialXmpPageEmpty24}{\showpaste}
\tab{5}\spadcommand{eval(p, [a,b], [2*bb, 3*aa])$Lpoly\free{p a b bb aa Lpoly }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch25}
\begin{paste}{LiePolynomialXmpPageFull25}{LiePolynomialXmpPageEmpty25}
\pastebutton{LiePolynomialXmpPageFull25}{\hidepaste}
\tab{5}\spadcommand{r: Lpoly := [p,c]\free{p c Lpoly }\bound{rr }}
\indentrel{3}\begin{verbatim}
   (25)  [a b c] + [a c b]
           Type: LiePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty25}
\begin{paste}{LiePolynomialXmpPageEmpty25}{LiePolynomialXmpPagePatch25}
\pastebutton{LiePolynomialXmpPageEmpty25}{\showpaste}
\tab{5}\spadcommand{r: Lpoly := [p,c]\free{p c Lpoly }\bound{rr }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch26}
\begin{paste}{LiePolynomialXmpPageFull26}{LiePolynomialXmpPageEmpty26}
\pastebutton{LiePolynomialXmpPageFull26}{\hidepaste}
\tab{5}\spadcommand{r1: Lpoly := eval(r, [a,b,c], [bb, cc, aa])$Lpoly\free{rr a b c aa bb cc Lpoly }\bound{r1 }}
\indentrel{3}\begin{verbatim}
   (26)  - [a b c]
           Type: LiePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty26}
\begin{paste}{LiePolynomialXmpPageEmpty26}{LiePolynomialXmpPagePatch26}
\pastebutton{LiePolynomialXmpPageEmpty26}{\showpaste}
\tab{5}\spadcommand{r1: Lpoly := eval(r, [a,b,c], [bb, cc, aa])$Lpoly\free{rr a b c aa bb cc Lpoly }\bound{r1 }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch27}
\begin{paste}{LiePolynomialXmpPageFull27}{LiePolynomialXmpPageEmpty27}
\pastebutton{LiePolynomialXmpPageFull27}{\hidepaste}
\tab{5}\spadcommand{r2: Lpoly := eval(r, [a,b,c], [cc, aa, bb])$Lpoly\free{rr a b c cc bb aa Lpoly }\bound{r2 }}
\indentrel{3}\begin{verbatim}
   (27)  - [a c b]
           Type: LiePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty27}
\begin{paste}{LiePolynomialXmpPageEmpty27}{LiePolynomialXmpPagePatch27}
\pastebutton{LiePolynomialXmpPageEmpty27}{\showpaste}
\tab{5}\spadcommand{r2: Lpoly := eval(r, [a,b,c], [cc, aa, bb])$Lpoly\free{rr a b c cc bb aa Lpoly }\bound{r2 }}
\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPagePatch28}
\begin{paste}{LiePolynomialXmpPageFull28}{LiePolynomialXmpPageEmpty28}
\pastebutton{LiePolynomialXmpPageFull28}{\hidepaste}
\tab{5}\spadcommand{r + r1 + r2\free{rr r1 r2 }}
\indentrel{3}\begin{verbatim}
   (28)  0
           Type: LiePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LiePolynomialXmpPageEmpty28}
\begin{paste}{LiePolynomialXmpPageEmpty28}{LiePolynomialXmpPagePatch28}
\pastebutton{LiePolynomialXmpPageEmpty28}{\showpaste}
\tab{5}\spadcommand{r + r1 + r2\free{rr r1 r2 }}
\end{paste}\end{patch}

\end{chunk}
\section{lword.ht}
\pagetitle{LyndonWordXmpPage}{lword.ht}{LyndonWord}
\begin{chunk}{lword.ht}
\begin{page}{LyndonWordXmpPage}{LyndonWord}
\beginscroll
Initialisations
\xtc{
}{
\spadpaste{a:Symbol :='a \bound{a}}
}
\xtc{
}{
\spadpaste{b:Symbol :='b \bound{b}}
}
\xtc{
}{
\spadpaste{c:Symbol :='c \bound{c}}
}
\xtc{
}{
\spadpaste{lword:= LyndonWord(Symbol) \bound{lword}}
}
\xtc{
}{
\spadpaste{magma := Magma(Symbol) \bound{magma}}
}
\xtc{
}{
\spadpaste{word   := OrderedFreeMonoid(Symbol) \bound{word}}
}
\xtc{
All Lyndon words of with a, b, c to order 3
}{
\spadpaste{LyndonWordsList1([a,b,c],3)$lword \free{lword} \free{a} 
\free{b} \free{c} }
}
\xtc{
All Lyndon words of with a, b, c to order 3 in flat list
}{
\spadpaste{LyndonWordsList([a,b,c],3)$lword \free{a} \free{b} 
\free{c} \free{lword}}
}
\xtc{
All Lyndon words of with a, b to order 5
}{
\spadpaste{lw := LyndonWordsList([a,b],5)$lword \free{a} \free{b} 
\free{lword} \bound{lw}}
}
\xtc{
}{
\spadpaste{w1 : word := lw.4 :: word \free{word} \free{lw} \bound{w1}}
}
\xtc{
}{
\spadpaste{w2 : word := lw.5 :: word \free{word} \free{lw} \bound{w2}}
}

Let's try factoring
\xtc{
}{
\spadpaste{factor(a::word)$lword \free{a word lword}}
}
\xtc{
}{
\spadpaste{factor(w1*w2)$lword \free{ w1 w2 lword}}
}
\xtc{
}{
\spadpaste{factor(w2*w2)$lword \free{w2 lword}}
}
\xtc{
}{
\spadpaste{factor(w2*w1)$lword \free{w1 w2 lword}}
}

Checks and coercions
\xtc{
}{
\spadpaste{lyndon?(w1)$lword \free{w1 lword}}
}
\xtc{
}{
\spadpaste{lyndon?(w1*w2)$lword \free{w1 w2 lword}}
}
\xtc{
}{
\spadpaste{lyndon?(w2*w1)$lword \free{w1 w2 lword}}
}
\xtc{
}{
\spadpaste{lyndonIfCan(w1)$lword \free{w1 lword}}
}
\xtc{
}{
\spadpaste{lyndonIfCan(w2*w1)$lword \free{w1 w2 lword}}
}
\xtc{
}{
\spadpaste{lyndon(w1)$lword \free{w1 lword}}
}
\xtc{
}{
\spadpaste{lyndon(w1*w2)$lword \free{w1 w2 lword}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{LyndonWordXmpPagePatch1}
\begin{paste}{LyndonWordXmpPageFull1}{LyndonWordXmpPageEmpty1}
\pastebutton{LyndonWordXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{a:Symbol :='a\bound{a }}
\indentrel{3}\begin{verbatim}
   (1)  a
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPageEmpty1}
\begin{paste}{LyndonWordXmpPageEmpty1}{LyndonWordXmpPagePatch1}
\pastebutton{LyndonWordXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{a:Symbol :='a\bound{a }}
\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPagePatch2}
\begin{paste}{LyndonWordXmpPageFull2}{LyndonWordXmpPageEmpty2}
\pastebutton{LyndonWordXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{b:Symbol :='b\bound{b }}
\indentrel{3}\begin{verbatim}
   (2)  b
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPageEmpty2}
\begin{paste}{LyndonWordXmpPageEmpty2}{LyndonWordXmpPagePatch2}
\pastebutton{LyndonWordXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{b:Symbol :='b\bound{b }}
\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPagePatch3}
\begin{paste}{LyndonWordXmpPageFull3}{LyndonWordXmpPageEmpty3}
\pastebutton{LyndonWordXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{c:Symbol :='c\bound{c }}
\indentrel{3}\begin{verbatim}
   (3)  c
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPageEmpty3}
\begin{paste}{LyndonWordXmpPageEmpty3}{LyndonWordXmpPagePatch3}
\pastebutton{LyndonWordXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{c:Symbol :='c\bound{c }}
\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPagePatch4}
\begin{paste}{LyndonWordXmpPageFull4}{LyndonWordXmpPageEmpty4}
\pastebutton{LyndonWordXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{lword:= LyndonWord(Symbol)\bound{lword }}
\indentrel{3}\begin{verbatim}
   (4)  LyndonWord Symbol
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPageEmpty4}
\begin{paste}{LyndonWordXmpPageEmpty4}{LyndonWordXmpPagePatch4}
\pastebutton{LyndonWordXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{lword:= LyndonWord(Symbol)\bound{lword }}
\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPagePatch5}
\begin{paste}{LyndonWordXmpPageFull5}{LyndonWordXmpPageEmpty5}
\pastebutton{LyndonWordXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{magma := Magma(Symbol)\bound{magma }}
\indentrel{3}\begin{verbatim}
   (5)  Magma Symbol
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPageEmpty5}
\begin{paste}{LyndonWordXmpPageEmpty5}{LyndonWordXmpPagePatch5}
\pastebutton{LyndonWordXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{magma := Magma(Symbol)\bound{magma }}
\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPagePatch6}
\begin{paste}{LyndonWordXmpPageFull6}{LyndonWordXmpPageEmpty6}
\pastebutton{LyndonWordXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{word := OrderedFreeMonoid(Symbol)\bound{word }}
\indentrel{3}\begin{verbatim}
   (6)  OrderedFreeMonoid Symbol
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPageEmpty6}
\begin{paste}{LyndonWordXmpPageEmpty6}{LyndonWordXmpPagePatch6}
\pastebutton{LyndonWordXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{word := OrderedFreeMonoid(Symbol)\bound{word }}
\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPagePatch7}
\begin{paste}{LyndonWordXmpPageFull7}{LyndonWordXmpPageEmpty7}
\pastebutton{LyndonWordXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{LyndonWordsList1([a,b,c],3)$lword\free{lword }\free{a }\free{b }\free{c }}
\indentrel{3}\begin{verbatim}
   (7)
   [[[a],[b],[c]], [[a b],[a c],[b c]],

        2      2        2                         2
     [[a b], [a c], [a b ], [a b c], [a c b], [a c ],
        2        2
      [b c], [b c ]]
     ]
       Type: OneDimensionalArray List LyndonWord Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPageEmpty7}
\begin{paste}{LyndonWordXmpPageEmpty7}{LyndonWordXmpPagePatch7}
\pastebutton{LyndonWordXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{LyndonWordsList1([a,b,c],3)$lword\free{lword }\free{a }\free{b }\free{c }}
\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPagePatch8}
\begin{paste}{LyndonWordXmpPageFull8}{LyndonWordXmpPageEmpty8}
\pastebutton{LyndonWordXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{LyndonWordsList([a,b,c],3)$lword\free{a }\free{b }\free{c }\free{lword }}
\indentrel{3}\begin{verbatim}
   (8)
                                          2      2
   [[a], [b], [c], [a b], [a c], [b c], [a b], [a c],
        2                         2     2        2
    [a b ], [a b c], [a c b], [a c ], [b c], [b c ]]
                           Type: List LyndonWord Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPageEmpty8}
\begin{paste}{LyndonWordXmpPageEmpty8}{LyndonWordXmpPagePatch8}
\pastebutton{LyndonWordXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{LyndonWordsList([a,b,c],3)$lword\free{a }\free{b }\free{c }\free{lword }}
\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPagePatch9}
\begin{paste}{LyndonWordXmpPageFull9}{LyndonWordXmpPageEmpty9}
\pastebutton{LyndonWordXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{lw := LyndonWordsList([a,b],5)$lword\free{a }\free{b }\free{lword }\bound{lw }}
\indentrel{3}\begin{verbatim}
   (9)
                       2        2     3      2 2
   [[a], [b], [a b], [a b], [a b ], [a b], [a b ],
        3     4      3 2     2          2 3           2
    [a b ], [a b], [a b ], [a b a b], [a b ], [a b a b ],
        4
    [a b ]]
                           Type: List LyndonWord Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPageEmpty9}
\begin{paste}{LyndonWordXmpPageEmpty9}{LyndonWordXmpPagePatch9}
\pastebutton{LyndonWordXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{lw := LyndonWordsList([a,b],5)$lword\free{a }\free{b }\free{lword }\bound{lw }}
\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPagePatch10}
\begin{paste}{LyndonWordXmpPageFull10}{LyndonWordXmpPageEmpty10}
\pastebutton{LyndonWordXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{w1 : word := lw.4 :: word\free{word }\free{lw }\bound{w1 }}
\indentrel{3}\begin{verbatim}
          2
   (10)  a b
                         Type: OrderedFreeMonoid Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPageEmpty10}
\begin{paste}{LyndonWordXmpPageEmpty10}{LyndonWordXmpPagePatch10}
\pastebutton{LyndonWordXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{w1 : word := lw.4 :: word\free{word }\free{lw }\bound{w1 }}
\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPagePatch11}
\begin{paste}{LyndonWordXmpPageFull11}{LyndonWordXmpPageEmpty11}
\pastebutton{LyndonWordXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{w2 : word := lw.5 :: word\free{word }\free{lw }\bound{w2 }}
\indentrel{3}\begin{verbatim}
            2
   (11)  a b
                         Type: OrderedFreeMonoid Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPageEmpty11}
\begin{paste}{LyndonWordXmpPageEmpty11}{LyndonWordXmpPagePatch11}
\pastebutton{LyndonWordXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{w2 : word := lw.5 :: word\free{word }\free{lw }\bound{w2 }}
\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPagePatch12}
\begin{paste}{LyndonWordXmpPageFull12}{LyndonWordXmpPageEmpty12}
\pastebutton{LyndonWordXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{factor(a::word)$lword\free{a word lword }}
\indentrel{3}\begin{verbatim}
   (12)  [[a]]
                           Type: List LyndonWord Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPageEmpty12}
\begin{paste}{LyndonWordXmpPageEmpty12}{LyndonWordXmpPagePatch12}
\pastebutton{LyndonWordXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{factor(a::word)$lword\free{a word lword }}
\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPagePatch13}
\begin{paste}{LyndonWordXmpPageFull13}{LyndonWordXmpPageEmpty13}
\pastebutton{LyndonWordXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{factor(w1*w2)$lword\free{w1 w2 lword }}
\indentrel{3}\begin{verbatim}
            2     2
   (13)  [[a b a b ]]
                           Type: List LyndonWord Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPageEmpty13}
\begin{paste}{LyndonWordXmpPageEmpty13}{LyndonWordXmpPagePatch13}
\pastebutton{LyndonWordXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{factor(w1*w2)$lword\free{w1 w2 lword }}
\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPagePatch14}
\begin{paste}{LyndonWordXmpPageFull14}{LyndonWordXmpPageEmpty14}
\pastebutton{LyndonWordXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{factor(w2*w2)$lword\free{w2 lword }}
\indentrel{3}\begin{verbatim}
              2      2
   (14)  [[a b ],[a b ]]
                           Type: List LyndonWord Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPageEmpty14}
\begin{paste}{LyndonWordXmpPageEmpty14}{LyndonWordXmpPagePatch14}
\pastebutton{LyndonWordXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{factor(w2*w2)$lword\free{w2 lword }}
\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPagePatch15}
\begin{paste}{LyndonWordXmpPageFull15}{LyndonWordXmpPageEmpty15}
\pastebutton{LyndonWordXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{factor(w2*w1)$lword\free{w1 w2 lword }}
\indentrel{3}\begin{verbatim}
              2    2
   (15)  [[a b ],[a b]]
                           Type: List LyndonWord Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPageEmpty15}
\begin{paste}{LyndonWordXmpPageEmpty15}{LyndonWordXmpPagePatch15}
\pastebutton{LyndonWordXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{factor(w2*w1)$lword\free{w1 w2 lword }}
\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPagePatch16}
\begin{paste}{LyndonWordXmpPageFull16}{LyndonWordXmpPageEmpty16}
\pastebutton{LyndonWordXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{lyndon?(w1)$lword\free{w1 lword }}
\indentrel{3}\begin{verbatim}
   (16)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPageEmpty16}
\begin{paste}{LyndonWordXmpPageEmpty16}{LyndonWordXmpPagePatch16}
\pastebutton{LyndonWordXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{lyndon?(w1)$lword\free{w1 lword }}
\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPagePatch17}
\begin{paste}{LyndonWordXmpPageFull17}{LyndonWordXmpPageEmpty17}
\pastebutton{LyndonWordXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{lyndon?(w1*w2)$lword\free{w1 w2 lword }}
\indentrel{3}\begin{verbatim}
   (17)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPageEmpty17}
\begin{paste}{LyndonWordXmpPageEmpty17}{LyndonWordXmpPagePatch17}
\pastebutton{LyndonWordXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{lyndon?(w1*w2)$lword\free{w1 w2 lword }}
\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPagePatch18}
\begin{paste}{LyndonWordXmpPageFull18}{LyndonWordXmpPageEmpty18}
\pastebutton{LyndonWordXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{lyndon?(w2*w1)$lword\free{w1 w2 lword }}
\indentrel{3}\begin{verbatim}
   (18)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPageEmpty18}
\begin{paste}{LyndonWordXmpPageEmpty18}{LyndonWordXmpPagePatch18}
\pastebutton{LyndonWordXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{lyndon?(w2*w1)$lword\free{w1 w2 lword }}
\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPagePatch19}
\begin{paste}{LyndonWordXmpPageFull19}{LyndonWordXmpPageEmpty19}
\pastebutton{LyndonWordXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{lyndonIfCan(w1)$lword\free{w1 lword }}
\indentrel{3}\begin{verbatim}
           2
   (19)  [a b]
                     Type: Union(LyndonWord Symbol,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPageEmpty19}
\begin{paste}{LyndonWordXmpPageEmpty19}{LyndonWordXmpPagePatch19}
\pastebutton{LyndonWordXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{lyndonIfCan(w1)$lword\free{w1 lword }}
\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPagePatch20}
\begin{paste}{LyndonWordXmpPageFull20}{LyndonWordXmpPageEmpty20}
\pastebutton{LyndonWordXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{lyndonIfCan(w2*w1)$lword\free{w1 w2 lword }}
\indentrel{3}\begin{verbatim}
   (20)  "failed"
                              Type: Union("failed",...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPageEmpty20}
\begin{paste}{LyndonWordXmpPageEmpty20}{LyndonWordXmpPagePatch20}
\pastebutton{LyndonWordXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{lyndonIfCan(w2*w1)$lword\free{w1 w2 lword }}
\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPagePatch21}
\begin{paste}{LyndonWordXmpPageFull21}{LyndonWordXmpPageEmpty21}
\pastebutton{LyndonWordXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{lyndon(w1)$lword\free{w1 lword }}
\indentrel{3}\begin{verbatim}
           2
   (21)  [a b]
                                Type: LyndonWord Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPageEmpty21}
\begin{paste}{LyndonWordXmpPageEmpty21}{LyndonWordXmpPagePatch21}
\pastebutton{LyndonWordXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{lyndon(w1)$lword\free{w1 lword }}
\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPagePatch22}
\begin{paste}{LyndonWordXmpPageFull22}{LyndonWordXmpPageEmpty22}
\pastebutton{LyndonWordXmpPageFull22}{\hidepaste}
\tab{5}\spadcommand{lyndon(w1*w2)$lword\free{w1 w2 lword }}
\indentrel{3}\begin{verbatim}
           2     2
   (22)  [a b a b ]
                                Type: LyndonWord Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{LyndonWordXmpPageEmpty22}
\begin{paste}{LyndonWordXmpPageEmpty22}{LyndonWordXmpPagePatch22}
\pastebutton{LyndonWordXmpPageEmpty22}{\showpaste}
\tab{5}\spadcommand{lyndon(w1*w2)$lword\free{w1 w2 lword }}
\end{paste}\end{patch}

\end{chunk}
\section{magma.ht}
\pagetitle{MagmaXmpPage}{magma.ht}{Magma}
\begin{chunk}{magma.ht}
\begin{page}{MagmaXmpPage}{Magma}
\beginscroll
Initialisations
\xtc{
}{
\spadpaste{x:Symbol :='x \bound{x}}
}
\xtc{
}{
\spadpaste{y:Symbol :='y \bound{y}}
}
\xtc{
}{
\spadpaste{z:Symbol :='z \bound{z}}
}
\xtc{
}{
\spadpaste{word := OrderedFreeMonoid(Symbol) \bound{word}}
}
\xtc{
}{
\spadpaste{tree := Magma(Symbol) \bound{tree}}
}

Let's make some trees
\xtc{
}{
\spadpaste{a:tree := x*x \free{x tree} \bound{a}}
}
\xtc{
}{
\spadpaste{b:tree := y*y \free{y tree} \bound{b}}
}
\xtc{
}{
\spadpaste{c:tree := a*b \free{a b tree} \bound{c}}
}

Query the trees
\xtc{
}{
\spadpaste{left c \free{c}}
}
\xtc{
}{
\spadpaste{right c \free{c}}
}
\xtc{
}{
\spadpaste{length c \free{c}}
}
\xtc{
Coerce to the monoid
}{
\spadpaste{c::word \free{c word}}
}

Check ordering
\xtc{
}{
\spadpaste{a < b \free{a b}}
}
\xtc{
}{
\spadpaste{a < c \free{a c}}
}
\xtc{
}{
\spadpaste{b < c \free{b c}}
}

Navigate the tree
\xtc{
}{
\spadpaste{first c \free{c}}
}
\xtc{
}{
\spadpaste{rest c \free{c}}
}
\xtc{
}{
\spadpaste{rest rest c  \free{c}}
}

Check ordering
\xtc{
}{
\spadpaste{ax:tree := a*x \free{a x tree} \bound{ax}}
}
\xtc{
}{
\spadpaste{xa:tree := x*a \free{a x tree} \bound{xa}}
}
\xtc{
}{
\spadpaste{xa < ax \free{ax xa}}
}
\xtc{
}{
\spadpaste{lexico(xa,ax) \free{ax xa}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{MagmaXmpPagePatch1}
\begin{paste}{MagmaXmpPageFull1}{MagmaXmpPageEmpty1}
\pastebutton{MagmaXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{x:Symbol :='x\bound{x }}
\indentrel{3}\begin{verbatim}
   (1)  x
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MagmaXmpPageEmpty1}
\begin{paste}{MagmaXmpPageEmpty1}{MagmaXmpPagePatch1}
\pastebutton{MagmaXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{x:Symbol :='x\bound{x }}
\end{paste}\end{patch}

\begin{patch}{MagmaXmpPagePatch2}
\begin{paste}{MagmaXmpPageFull2}{MagmaXmpPageEmpty2}
\pastebutton{MagmaXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{y:Symbol :='y\bound{y }}
\indentrel{3}\begin{verbatim}
   (2)  y
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MagmaXmpPageEmpty2}
\begin{paste}{MagmaXmpPageEmpty2}{MagmaXmpPagePatch2}
\pastebutton{MagmaXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{y:Symbol :='y\bound{y }}
\end{paste}\end{patch}

\begin{patch}{MagmaXmpPagePatch3}
\begin{paste}{MagmaXmpPageFull3}{MagmaXmpPageEmpty3}
\pastebutton{MagmaXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{z:Symbol :='z\bound{z }}
\indentrel{3}\begin{verbatim}
   (3)  z
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MagmaXmpPageEmpty3}
\begin{paste}{MagmaXmpPageEmpty3}{MagmaXmpPagePatch3}
\pastebutton{MagmaXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{z:Symbol :='z\bound{z }}
\end{paste}\end{patch}

\begin{patch}{MagmaXmpPagePatch4}
\begin{paste}{MagmaXmpPageFull4}{MagmaXmpPageEmpty4}
\pastebutton{MagmaXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{word := OrderedFreeMonoid(Symbol)\bound{word }}
\indentrel{3}\begin{verbatim}
   (4)  OrderedFreeMonoid Symbol
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MagmaXmpPageEmpty4}
\begin{paste}{MagmaXmpPageEmpty4}{MagmaXmpPagePatch4}
\pastebutton{MagmaXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{word := OrderedFreeMonoid(Symbol)\bound{word }}
\end{paste}\end{patch}

\begin{patch}{MagmaXmpPagePatch5}
\begin{paste}{MagmaXmpPageFull5}{MagmaXmpPageEmpty5}
\pastebutton{MagmaXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{tree := Magma(Symbol)\bound{tree }}
\indentrel{3}\begin{verbatim}
   (5)  Magma Symbol
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MagmaXmpPageEmpty5}
\begin{paste}{MagmaXmpPageEmpty5}{MagmaXmpPagePatch5}
\pastebutton{MagmaXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{tree := Magma(Symbol)\bound{tree }}
\end{paste}\end{patch}

\begin{patch}{MagmaXmpPagePatch6}
\begin{paste}{MagmaXmpPageFull6}{MagmaXmpPageEmpty6}
\pastebutton{MagmaXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{a:tree := x*x\free{x tree }\bound{a }}
\indentrel{3}\begin{verbatim}
   (6)  [x,x]
                                     Type: Magma Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MagmaXmpPageEmpty6}
\begin{paste}{MagmaXmpPageEmpty6}{MagmaXmpPagePatch6}
\pastebutton{MagmaXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{a:tree := x*x\free{x tree }\bound{a }}
\end{paste}\end{patch}

\begin{patch}{MagmaXmpPagePatch7}
\begin{paste}{MagmaXmpPageFull7}{MagmaXmpPageEmpty7}
\pastebutton{MagmaXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{b:tree := y*y\free{y tree }\bound{b }}
\indentrel{3}\begin{verbatim}
   (7)  [y,y]
                                     Type: Magma Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MagmaXmpPageEmpty7}
\begin{paste}{MagmaXmpPageEmpty7}{MagmaXmpPagePatch7}
\pastebutton{MagmaXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{b:tree := y*y\free{y tree }\bound{b }}
\end{paste}\end{patch}

\begin{patch}{MagmaXmpPagePatch8}
\begin{paste}{MagmaXmpPageFull8}{MagmaXmpPageEmpty8}
\pastebutton{MagmaXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{c:tree := a*b\free{a b tree }\bound{c }}
\indentrel{3}\begin{verbatim}
   (8)  [[x,x],[y,y]]
                                     Type: Magma Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MagmaXmpPageEmpty8}
\begin{paste}{MagmaXmpPageEmpty8}{MagmaXmpPagePatch8}
\pastebutton{MagmaXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{c:tree := a*b\free{a b tree }\bound{c }}
\end{paste}\end{patch}

\begin{patch}{MagmaXmpPagePatch9}
\begin{paste}{MagmaXmpPageFull9}{MagmaXmpPageEmpty9}
\pastebutton{MagmaXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{left c\free{c }}
\indentrel{3}\begin{verbatim}
   (9)  [x,x]
                                     Type: Magma Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MagmaXmpPageEmpty9}
\begin{paste}{MagmaXmpPageEmpty9}{MagmaXmpPagePatch9}
\pastebutton{MagmaXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{left c\free{c }}
\end{paste}\end{patch}

\begin{patch}{MagmaXmpPagePatch10}
\begin{paste}{MagmaXmpPageFull10}{MagmaXmpPageEmpty10}
\pastebutton{MagmaXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{right c\free{c }}
\indentrel{3}\begin{verbatim}
   (10)  [y,y]
                                     Type: Magma Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MagmaXmpPageEmpty10}
\begin{paste}{MagmaXmpPageEmpty10}{MagmaXmpPagePatch10}
\pastebutton{MagmaXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{right c\free{c }}
\end{paste}\end{patch}

\begin{patch}{MagmaXmpPagePatch11}
\begin{paste}{MagmaXmpPageFull11}{MagmaXmpPageEmpty11}
\pastebutton{MagmaXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{length c\free{c }}
\indentrel{3}\begin{verbatim}
   (11)  4
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MagmaXmpPageEmpty11}
\begin{paste}{MagmaXmpPageEmpty11}{MagmaXmpPagePatch11}
\pastebutton{MagmaXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{length c\free{c }}
\end{paste}\end{patch}

\begin{patch}{MagmaXmpPagePatch12}
\begin{paste}{MagmaXmpPageFull12}{MagmaXmpPageEmpty12}
\pastebutton{MagmaXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{c::word\free{c word }}
\indentrel{3}\begin{verbatim}
          2 2
   (12)  x y
                         Type: OrderedFreeMonoid Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MagmaXmpPageEmpty12}
\begin{paste}{MagmaXmpPageEmpty12}{MagmaXmpPagePatch12}
\pastebutton{MagmaXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{c::word\free{c word }}
\end{paste}\end{patch}

\begin{patch}{MagmaXmpPagePatch13}
\begin{paste}{MagmaXmpPageFull13}{MagmaXmpPageEmpty13}
\pastebutton{MagmaXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{a < b\free{a b }}
\indentrel{3}\begin{verbatim}
   (13)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MagmaXmpPageEmpty13}
\begin{paste}{MagmaXmpPageEmpty13}{MagmaXmpPagePatch13}
\pastebutton{MagmaXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{a < b\free{a b }}
\end{paste}\end{patch}

\begin{patch}{MagmaXmpPagePatch14}
\begin{paste}{MagmaXmpPageFull14}{MagmaXmpPageEmpty14}
\pastebutton{MagmaXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{a < c\free{a c }}
\indentrel{3}\begin{verbatim}
   (14)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MagmaXmpPageEmpty14}
\begin{paste}{MagmaXmpPageEmpty14}{MagmaXmpPagePatch14}
\pastebutton{MagmaXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{a < c\free{a c }}
\end{paste}\end{patch}

\begin{patch}{MagmaXmpPagePatch15}
\begin{paste}{MagmaXmpPageFull15}{MagmaXmpPageEmpty15}
\pastebutton{MagmaXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{b < c\free{b c }}
\indentrel{3}\begin{verbatim}
   (15)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MagmaXmpPageEmpty15}
\begin{paste}{MagmaXmpPageEmpty15}{MagmaXmpPagePatch15}
\pastebutton{MagmaXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{b < c\free{b c }}
\end{paste}\end{patch}

\begin{patch}{MagmaXmpPagePatch16}
\begin{paste}{MagmaXmpPageFull16}{MagmaXmpPageEmpty16}
\pastebutton{MagmaXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{first c\free{c }}
\indentrel{3}\begin{verbatim}
   (16)  x
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MagmaXmpPageEmpty16}
\begin{paste}{MagmaXmpPageEmpty16}{MagmaXmpPagePatch16}
\pastebutton{MagmaXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{first c\free{c }}
\end{paste}\end{patch}

\begin{patch}{MagmaXmpPagePatch17}
\begin{paste}{MagmaXmpPageFull17}{MagmaXmpPageEmpty17}
\pastebutton{MagmaXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{rest c\free{c }}
\indentrel{3}\begin{verbatim}
   (17)  [x,[y,y]]
                                     Type: Magma Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MagmaXmpPageEmpty17}
\begin{paste}{MagmaXmpPageEmpty17}{MagmaXmpPagePatch17}
\pastebutton{MagmaXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{rest c\free{c }}
\end{paste}\end{patch}

\begin{patch}{MagmaXmpPagePatch18}
\begin{paste}{MagmaXmpPageFull18}{MagmaXmpPageEmpty18}
\pastebutton{MagmaXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{rest rest c\free{c }}
\indentrel{3}\begin{verbatim}
   (18)  [y,y]
                                     Type: Magma Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MagmaXmpPageEmpty18}
\begin{paste}{MagmaXmpPageEmpty18}{MagmaXmpPagePatch18}
\pastebutton{MagmaXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{rest rest c\free{c }}
\end{paste}\end{patch}

\begin{patch}{MagmaXmpPagePatch19}
\begin{paste}{MagmaXmpPageFull19}{MagmaXmpPageEmpty19}
\pastebutton{MagmaXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{ax:tree := a*x\free{a x tree }\bound{ax }}
\indentrel{3}\begin{verbatim}
   (19)  [[x,x],x]
                                     Type: Magma Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MagmaXmpPageEmpty19}
\begin{paste}{MagmaXmpPageEmpty19}{MagmaXmpPagePatch19}
\pastebutton{MagmaXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{ax:tree := a*x\free{a x tree }\bound{ax }}
\end{paste}\end{patch}

\begin{patch}{MagmaXmpPagePatch20}
\begin{paste}{MagmaXmpPageFull20}{MagmaXmpPageEmpty20}
\pastebutton{MagmaXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{xa:tree := x*a\free{a x tree }\bound{xa }}
\indentrel{3}\begin{verbatim}
   (20)  [x,[x,x]]
                                     Type: Magma Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MagmaXmpPageEmpty20}
\begin{paste}{MagmaXmpPageEmpty20}{MagmaXmpPagePatch20}
\pastebutton{MagmaXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{xa:tree := x*a\free{a x tree }\bound{xa }}
\end{paste}\end{patch}

\begin{patch}{MagmaXmpPagePatch21}
\begin{paste}{MagmaXmpPageFull21}{MagmaXmpPageEmpty21}
\pastebutton{MagmaXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{xa < ax\free{ax xa }}
\indentrel{3}\begin{verbatim}
   (21)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MagmaXmpPageEmpty21}
\begin{paste}{MagmaXmpPageEmpty21}{MagmaXmpPagePatch21}
\pastebutton{MagmaXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{xa < ax\free{ax xa }}
\end{paste}\end{patch}

\begin{patch}{MagmaXmpPagePatch22}
\begin{paste}{MagmaXmpPageFull22}{MagmaXmpPageEmpty22}
\pastebutton{MagmaXmpPageFull22}{\hidepaste}
\tab{5}\spadcommand{lexico(xa,ax)\free{ax xa }}
\indentrel{3}\begin{verbatim}
   (22)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MagmaXmpPageEmpty22}
\begin{paste}{MagmaXmpPageEmpty22}{MagmaXmpPagePatch22}
\pastebutton{MagmaXmpPageEmpty22}{\showpaste}
\tab{5}\spadcommand{lexico(xa,ax)\free{ax xa }}
\end{paste}\end{patch}

\end{chunk}
\section{man0.ht}
\pagetitle{RefSearchPage}{man0.ht}{Reference Search}
\pagepic{ps/v71refsearchpage.eps}{refsearchpage}{0.50}
\pagefrom{Reference}{TopReferencePage}
\pageto{Search}{ugSysCmdPage}
\begin{chunk}{man0.ht}
\begin{page}{RefSearchPage}{Reference Search}
\beginscroll
Enter search string :
\inputstring{pattern}{40}{}
\newline
\beginmenu
\menuunixlink{Search}
  {htsearch "\stringvalue{pattern}"}
  \tab{15} Reference documentation ({\em *} wild card is not accepted).
\endmenu
\endscroll
\end{page}

\end{chunk}
\pagetitle{LispFunctions}{lisp.ht}{Lisp Functions}
\pagefrom{Root Page}{RootPage}
\pagefrom{System Commands}{TopSettingsPage}
\pagefrom{Axiom Browser}{Man0Page}
\pagefrom{Axiom Reference}{TopReferencePage}
\pagefrom{Basic Commands}{BasicCommand}
\pagefrom{Calculus}{Calculus}
\pagefrom{Glossary}{GlossaryPage}
\pagefrom{The Axiom Link to NAG Software}{htxl}
\pagefrom{C02 Zeros of Polynomials}{c02}
\pagefrom{C02 Roots of One or More TranscendentalEquations}{c05}
\pagefrom{C06 Summation of Series}{c06}
\pagefrom{D03 Partial Differential Equations}{d03}
\pagefrom{E01 Interpolation}{e01}
\pagefrom{E02 Curve and Surface Fitting}{e02}
\pagefrom{E04 Minimizing or Maximizing a Function}{e04}
\pagefrom{F01 Matrix Operations - Including Inversion}{f01}
\pagefrom{F02 Eigenvalues and Eigenvectors}{f02}
\pagefrom{F04 Simultaneous Linear Equations}{f04}
\pagefrom{F07 Linear Equations (LAPACK)}{f07}
\pagefrom{S -- Approximations of Special Functions}{s}
\pagefrom{Domain Mapping}{DomainMapping}
\pagefrom{Domain Record}{DomainRecord}
\pagefrom{Domain Union}{DomainUnion}
\pagefrom{HTXLinkPage4xPatch2}{HTXLinkPage4xPatch2}
\pagefrom{HTXLinkPage4xPatch4}{HTXLinkPage4xPatch4}
\pagefrom{Examples Using the Axiom/NAG Expert System}{UXANNAOdeEx}
\pagefrom{Examples Using the Axiom/NAG Expert System}{UXANNAIntEx}
\pagefrom{Examples Using the Axiom/NAG Expert System}{UXANNAOpt2Ex}
\pagefrom{Examples Using the Axiom/NAG Expert System}{UXANNAOptEx}
\pagefrom{Optimization}{UXANNAOpt}
\pagefrom{Ordinary Differential Equations}{UXANNAOde}
\pagefrom{Integration}{UXANNAInt}
\pagefrom{Axiom/NAG Expert System}{UXANNA}

There are lisp functions which exist behind certain pages and 
the page information is created dynamically by calling the function.

%syscomPage & syscom\\

This is a list of the macros which use lisp functions\\

\begin{tabular}{ll}
oPage & axiomFun\\
oPageFrom & axiomFunFrom\\
htGloss & gloss\\
htGloss & spadglos\\
htGloss & glossSee \\
conPage & aliascon\\
conPage & aliasdom\\
conPage & dom\\
conPage & con\\
conPage & conf\\
conOpPage & ops\\
htsn & keyword\\
htsn & op\\
\end{tabular}

%\item interp1 & Interpolation & Axiom/NAG Expert System\\
%\item bcExpand             & Operations        & Basic Commands\\
%\item bcProduct            & Compute a product & Calculus\\
%\item d03fafVars           & Helmholtz         & 
%Partial Differential Equations\\
%\item htHistory            & history           & Root Page \\
%\item htTutorialSearch     & Search            & Axiom Topics\\
%\item htUserVariables      & User Variables    & Root Page \\

This is a list of the lisp function, the link name, and the page name\\

\begin{itemize}
\item {\bf annaOde} -- Ordinary Differential Equations link from page 
Ordinary Differential Equations
\item {\bf annaOpt} -- Optimization of a Single Multivariate Function link from page
Optimization
\item {\bf annaOpt2} -- Optimization of a set of observations of a data set link from page
Optimization
\item {\bf annaPDESolve} -- Second Order Elliptic Partial Differential Equation link from page
Partial Differential Equations
\item {\bf annaOptDefaultSolve1} -- Example 1 link from page
Examples Using the Axiom/NAG Expert System
\item {\bf annaOptDefaultSolve2} -- Example 2 link from page
Examples Using the Axiom/NAG Expert System
\item {\bf annaOptDefaultSolve3} -- Example 3 link from page
Examples Using the Axiom/NAG Expert System
\item {\bf annaOptDefaultSolve4} -- Example 4 link from page
Examples Using the Axiom/NAG Expert System
\item {\bf annaOptDefaultSolve5} -- Example 5 link from page
Examples Using the Axiom/NAG Expert System
\item {\bf annaFoo} -- Example 1 link from page
Examples Using the Axiom/NAG Expert System
\item {\bf annaBar} -- Example 2 link from page
Examples Using the Axiom/NAG Expert System
\item {\bf annaJoe} -- Example 3 link from page
Examples Using the Axiom/NAG Expert System
\item {\bf annaSue} -- Example 4 link from page
Examples Using the Axiom/NAG Expert System
\item {\bf annaAnn} -- Example 5 link from page
Examples Using the Axiom/NAG Expert System
\item {\bf annaBab} -- Example 6 link from page
Examples Using the Axiom/NAG Expert System
\item {\bf annaFnar} -- Example 7 link from page
Examples Using the Axiom/NAG Expert System
\item {\bf annaDan} -- Example 8 link from page
Examples Using the Axiom/NAG Expert System
\item {\bf annaBlah} -- Example 9 link from page
Examples Using the Axiom/NAG Expert System
\item {\bf annaTub} -- Example 10 link from page
Examples Using the Axiom/NAG Expert System
\item {\bf annaRats} -- Example 11 link from page
Examples Using the Axiom/NAG Expert System
\item {\bf annaMInt} -- Example 12 link from page
Examples Using the Axiom/NAG Expert System
\item {\bf annaMInt} -- Multiple Integration link from page
Integration
\item {\bf annaInt} -- Integration link from page Integration
\item {\bf annaOdeDefaultSolve1} -- Example 1 link from page
Examples Using the Axiom/NAG Expert System
\item {\bf annaOdeDefaultSolve2} -- Example 2 link from page
Examples Using the Axiom/NAG Expert System
\item {\bf annaOpt2DefaultSolve} -- Example 1 link from page
Examples Using the Axiom/NAG Expert System
\end{itemize}
\begin{itemize}
\item {\bf aSearch} -- Attributes link from page
Axiom Browser
\item {\bf aokSearch} -- General link from page
Axiom Browser
\item {\bf bcDefiniteIntegrate} -- Do an Definite Integral 
link from page Calculus
\item {\bf bcDifferentiate} -- Differentiate link from page
Calculus
\item {\bf bcDraw} -- Draw link from page
Basic Commands
\item {\bf bcIndefiniteIntegrate} -- Do an Indefinite Integral 
link from page Calculus
\item {\bf bcLimit} -- Find a Limit link from page
Calculus
\item {\bf bcMatrix} -- Matrix link from page
Basic Commands
\item {\bf bcSeries} -- Series link from page
Basic Commands
\item {\bf bcSolve} -- Solve link from page
Basic Commands
\item {\bf bcSum} -- Sum link from page
Calculus
\item {\bf cSearch} -- categories link from page
Axiom Browser
\item {\bf dbSpecialDescription} -- Description link from page
Domain Mapping
\item {\bf dbSpecialDescription} -- Description link from page
Domain Record
\item {\bf dbSpecialDescription} -- Description link from page
Domain Union
\item {\bf dbSpecialDescription} -- Description link from page
Domain Untagged Union
\item {\bf dbSpecialExports} -- Exports link from page
Domain Union
\item {\bf dbSpecialOperations} -- Operations link from page
Domain Mapping
\item {\bf dbSpecialOperations} -- Operations link from page
Domain Record
\item {\bf dbSpecialOperations} -- Operations link from page
Domain Union
\item {\bf dbSpecialOperations} -- Operations link from page
Domain Untagged Union
\item {\bf dSearch} -- domains link from page
Axiom Browser
\item {\bf detailSearch} -- domains link from page
Axiom Browser
\item {\bf docSearch} -- Documentation link from page
Axiom Browser
\item {\bf genSearch} -- Complete link from page
Axiom Browser
\item {\bf htGloss} -- Search link from page
Glossary
\item {\bf HTSEARCH} -- Reference link from page
Axiom Browser
\item {\bf htsv} -- System Variables link from page
Axiom Reference
\item {\bf htSystemVariables} -- Settings link from page
System Commands
\item {\bf issueHT} -- Definition link from page
HTXLinkPage4xPatch2
\item {\bf kSearch} -- Constructors link from page
Axiom Browser
\item {\bf kSearch} -- Browser pages for individual routines 
link from page htxl
\item {\bf kSearch} -- C02 Zeros of Polynomials link from page
c02
\item {\bf kSearch} -- Browse link from page
c05 Roots of One or More Transcendental Equations
\item {\bf kSearch} -- Browse link from page
c06 Summation of Series
\item {\bf kSearch} -- Browse link from page
d01 Quadrature
\item {\bf kSearch} -- Browse link from page
d02 Ordinary Differential Equations
\item {\bf kSearch} -- Browse link from page
d03 Partial Differential Equations
\item {\bf kSearch} -- Browse link from page
e01 Interpolation
\item {\bf kSearch} -- Browse link from page
e02 Curve and Surface Fitting
\item {\bf kSearch} -- Browse link from page
e04 Minimizing or Maximizing a Function
\item {\bf kSearch} -- Browse link from page
F01 Matrix Operations - Including Inversion
\item {\bf kSearch} -- Browse link from page
F02 Eigenvalues and Eigenvectors
\item {\bf kSearch} -- Browse link from page
F04 Simultaneous Linear Equations
\item {\bf linkToHTPage} -- Interpret link from page
HTXLinkPage4xPatch3
\item {\bf oSearch} -- Operations link from page
Axiom Browser
\item {\bf pSearch} -- packages link from page
Axiom Browser
\item {\bf startHTPage}-- Interpret link from page
HTXLinkPage4xPatch4
\end{itemize}
\begin{itemize}
\item {\bf c02aff} -- C02AFF link from page
C02 Zeros of Polynomials
\item {\bf c02agf} -- C02AGF link from page
C02 Zeros of Polynomials
\end{itemize}
\begin{itemize}
\item {\bf c05adf} -- C05ADF link from page
C05 Roots of One or More Transcendental Equations
\item {\bf c05ndf} -- C05NDF link from page
C05 Roots of One or More Transcendental Equations
\item {\bf c05pbf} -- C05PBF link from page
C05 Roots of One or More Transcendental Equations
\end{itemize}
\begin{itemize}
\item {\bf c06eaf} -- C06EAF link from page
C06 Summation of Series
\item {\bf c06ebf} -- C06EBF link from page
C06 Summation of Series
\item {\bf c06ecf} -- C06ECF link from page
C06 Summation of Series
\item {\bf c06ekf} -- C06EKF link from page
C06 Summation of Series
\item {\bf c06fpf} -- C06FPF link from page
C06 Summation of Series
\item {\bf c06fqf} -- C06FQF link from page
C06 Summation of Series
\item {\bf c06frf} -- C06FRF link from page
C06 Summation of Series
\item {\bf c06fuf} -- C06FUF link from page
C06 Summation of Series
\item {\bf c06gbf} -- C06GBF link from page
C06 Summation of Series
\item {\bf c06gcf} -- C06GCF link from page
C06 Summation of Series
\item {\bf c06gqf} -- C06GQF link from page
C06 Summation of Series
\item {\bf c06gsf} -- C06GSF link from page
C06 Summation of Series
\end{itemize}
\begin{itemize}
\item {\bf d01ajf} -- D01AJF link from page
D01 Quadrature
\item {\bf d01akf} -- D01AKF link from page
D01 Quadrature
\item {\bf d01alf} -- D01ALF link from page
D01 Quadrature
\item {\bf d01amf} -- D01AMF link from page
D01 Quadrature
\item {\bf d01anf} -- D01ANF link from page
D01 Quadrature
\item {\bf d01apf} -- D01APF link from page
D01 Quadrature
\item {\bf d01aqf} -- D01AQF link from page
D01 Quadrature
\item {\bf d01asf} -- D01ASF link from page
D01 Quadrature
\item {\bf d01bbf} -- D01BBF link from page
D01 Quadrature
\item {\bf d01fcf} -- D01FCF link from page
D01 Quadrature
\item {\bf d01gaf} -- D01GAF link from page
D01 Quadrature
\item {\bf d01gbf} -- D01GBF link from page
D01 Quadrature
\end{itemize}
\begin{itemize}
\item {\bf d02bbf} -- D02BBF link from page
D02 Ordinary Differential Equations
\item {\bf d02bhf} -- D02BHF link from page
D02 Ordinary Differential Equations
\item {\bf d02cjf} -- D02CJF link from page
D02 Ordinary Differential Equations
\item {\bf d02ejf} -- D02EJF link from page
D02 Ordinary Differential Equations
\item {\bf d02gaf} -- D02GAF link from page
D02 Ordinary Differential Equations
\item {\bf d02gbf} -- D02GBF link from page
D02 Ordinary Differential Equations
\item {\bf d02kef} -- D02KEF link from page
D02 Ordinary Differential Equations
\item {\bf d02raf} -- D02RAF link from page
D02 Ordinary Differential Equations
\end{itemize}
\begin{itemize}
\item {\bf d03edf} -- D03EDF link from page
D03 Partial Differential Equations
\item {\bf d03eef} -- D03EEF link from page
D03 Partial Differential Equations
\item {\bf d03faf} -- D03FAF link from page
D03 Partial Differential Equations
\end{itemize}
\begin{itemize}
\item {\bf e01baf} -- E01BAF link from page
E01 Interpolation
\item {\bf e01bef} -- E01BEF link from page
E01 Interpolation
\item {\bf e01bff} -- E01BFF link from page
E01 Interpolation
\item {\bf e01bgf} -- E01BGF link from page
E01 Interpolation
\item {\bf e01bhf} -- E01BHF link from page
E01 Interpolation
\item {\bf e01daf} -- E01DAF link from page
E01 Interpolation
\item {\bf e01saf} -- E01SAF link from page
E01 Interpolation
\item {\bf e01sef} -- E01SEF link from page
E01 Interpolation
\end{itemize}
\begin{itemize}
\item {\bf e02adf} -- E02ADF link from page
E02 Curve and Surface Fitting
\item {\bf e02aef} -- E02AEF link from page
E02 Curve and Surface Fitting
\item {\bf e02agf} -- E02AGF link from page
E02 Curve and Surface Fitting
\item {\bf e02ahf} -- E02AHF link from page
E02 Curve and Surface Fitting
\item {\bf e02ajf} -- E02AJF link from page
E02 Curve and Surface Fitting
\item {\bf e02akf} -- E02AKF link from page
E02 Curve and Surface Fitting
\item {\bf e02baf} -- E02BAF link from page
E02 Curve and Surface Fitting
\item {\bf e02bbf} -- E02BBF link from page
E02 Curve and Surface Fitting
\item {\bf e02bcf} -- E02BCF link from page
E02 Curve and Surface Fitting
\item {\bf e02bdf} -- E02BDF link from page
E02 Curve and Surface Fitting
\item {\bf e02bef} -- E02BEF link from page
E02 Curve and Surface Fitting
\item {\bf e02daf} -- E02DAF link from page
E02 Curve and Surface Fitting
\item {\bf e02dcf} -- E02DCF link from page
E02 Curve and Surface Fitting
\item {\bf e02ddf} -- E02DDF link from page
E02 Curve and Surface Fitting
\item {\bf e02def} -- E02DEF link from page
E02 Curve and Surface Fitting
\item {\bf e02dff} -- E02DFF link from page
E02 Curve and Surface Fitting
\item {\bf e02gaf} -- E02GAF link from page
E02 Curve and Surface Fitting
\item {\bf e02zaf} -- E02ZAF link from page
E02 Curve and Surface Fitting
\end{itemize}
\begin{itemize}
\item {\bf e04dgf} -- E04DGF link from page
E04 Minimizing or Maximizing a Function
\item {\bf e04fdf} -- E04FDF link from page
E04 Minimizing or Maximizing a Function
\item {\bf e04gcf} -- E04GCF link from page
E04 Minimizing or Maximizing a Function
\item {\bf e04jaf} -- E04JAF link from page
E04 Minimizing or Maximizing a Function
\item {\bf e04mbf} -- E04MBF link from page
E04 Minimizing or Maximizing a Function
\item {\bf e04naf} -- E04NAF link from page
E04 Minimizing or Maximizing a Function
\item {\bf e04ucf} -- E04UCF link from page
E04 Minimizing or Maximizing a Function
\item {\bf e04ycf} -- E04YCF link from page
E04 Minimizing or Maximizing a Function
\end{itemize}
\begin{itemize}
\item {\bf f01brf} -- F01BRF link from page
F01 Matrix Operations - Including Inversion
\item {\bf f01bsf} -- F01BSF link from page
F01 Matrix Operations - Including Inversion
\item {\bf f01maf} -- F01MAF link from page
F01 Matrix Operations - Including Inversion
\item {\bf f01mcf} -- F01MCF link from page
F01 Matrix Operations - Including Inversion
\item {\bf f01qcf} -- F01QCF link from page
F01 Matrix Operations - Including Inversion
\item {\bf f01qdf} -- F01QDF link from page
F01 Matrix Operations - Including Inversion
\item {\bf f01qef} -- F01QEF link from page
F01 Matrix Operations - Including Inversion
\item {\bf f01rcf} -- F01RCF link from page
F01 Matrix Operations - Including Inversion
\item {\bf f01rdf} -- F01RDF link from page
F01 Matrix Operations - Including Inversion
\item {\bf f01ref} -- F01REF link from page
F01 Matrix Operations - Including Inversion
\end{itemize}
\begin{itemize}
\item {\bf f02aaf} -- F02AAF link from page
F02 Eigenvalues and Eigenvectors
\item {\bf f02abf} -- F02ABF link from page
F02 Eigenvalues and Eigenvectors
\item {\bf f02adf} -- F02ADF link from page
F02 Eigenvalues and Eigenvectors
\item {\bf f02aef} -- F02AEF link from page
F02 Eigenvalues and Eigenvectors
\item {\bf f02aff} -- F02AFF link from page
F02 Eigenvalues and Eigenvectors
\item {\bf f02agf} -- F02AGF link from page
F02 Eigenvalues and Eigenvectors
\item {\bf f02ajf} -- F02AJF link from page
F02 Eigenvalues and Eigenvectors
\item {\bf f02akf} -- F02AKF link from page
F02 Eigenvalues and Eigenvectors
\item {\bf f02awf} -- F02AWF link from page
F02 Eigenvalues and Eigenvectors
\item {\bf f02axf} -- F02AXF link from page
F02 Eigenvalues and Eigenvectors
\item {\bf f02bbf} -- F02BBF link from page
F02 Eigenvalues and Eigenvectors
\item {\bf f02bjf} -- F02BJF link from page
F02 Eigenvalues and Eigenvectors
\item {\bf f02fjf} -- F02FJF link from page
F02 Eigenvalues and Eigenvectors
\item {\bf f02wef} -- F02WEF link from page
F02 Eigenvalues and Eigenvectors
\item {\bf f02xef} -- F02XEF link from page
F02 Eigenvalues and Eigenvectors
\end{itemize}
\begin{itemize}
\item {\bf f04adf} -- F04ADF link from page
F04 Simultaneous Linear Equations
\item {\bf f04arf} -- F04ARF link from page
F04 Simultaneous Linear Equations
\item {\bf f04asf} -- F04ASF link from page
F04 Simultaneous Linear Equations
\item {\bf f04atf} -- F04ATF link from page
F04 Simultaneous Linear Equations
\item {\bf f04axf} -- F04AXF link from page
F04 Simultaneous Linear Equations
\item {\bf f04faf} -- F04FAF link from page
F04 Simultaneous Linear Equations
\item {\bf f04jgf} -- F04JGF link from page
F04 Simultaneous Linear Equations
\item {\bf f04maf} -- F04MAF link from page
F04 Simultaneous Linear Equations
\item {\bf f04mbf} -- F04MBF link from page
F04 Simultaneous Linear Equations
\item {\bf f04mcf} -- F04MCF link from page
F04 Simultaneous Linear Equations
\item {\bf f04qaf} -- F04QAF link from page
F04 Simultaneous Linear Equations
\end{itemize}
\begin{itemize}
\item {\bf f07adf} -- F07ADF link from page
F07 Linear Equations (LAPACK)
\item {\bf f07aef} -- F07AEF link from page
F07 Linear Equations (LAPACK)
\item {\bf f07fdf} -- F07FDF link from page
F07 Linear Equations (LAPACK)
\item {\bf f07fef} -- F07FEF link from page
F07 Linear Equations (LAPACK)
\end{itemize}
\begin{itemize}
\item {\bf s01eaf} -- S01EAF link from page
S -- Approximations of Special Functions
\item {\bf s13aaf} -- S13AAF link from page
S -- Approximations of Special Functions
\item {\bf s13acf} -- S13ACF link from page
S -- Approximations of Special Functions
\item {\bf s13adf} -- S13ADF link from page
S -- Approximations of Special Functions
\item {\bf s14aaf} -- S14AAF link from page
S -- Approximations of Special Functions
\item {\bf s14abf} -- S14ABF link from page
S -- Approximations of Special Functions
\item {\bf s14baf} -- S14BAF link from page
S -- Approximations of Special Functions
\item {\bf s15adf} -- S15ADF link from page
S -- Approximations of Special Functions
\item {\bf s15aef} -- S15AEF link from page
S -- Approximations of Special Functions
\item {\bf s17acf} -- S17ACF link from page
S -- Approximations of Special Functions
\item {\bf s17adf} -- S17ADF link from page
S -- Approximations of Special Functions
\item {\bf s17aef} -- S17AEF link from page
S -- Approximations of Special Functions
\item {\bf s17aff} -- S17AFF link from page
S -- Approximations of Special Functions
\item {\bf s17agf} -- S17AGF link from page
S -- Approximations of Special Functions
\item {\bf s17ahf} -- S17AHF link from page
S -- Approximations of Special Functions
\item {\bf s17ajf} -- S17AJF link from page
S -- Approximations of Special Functions
\item {\bf s17akf} -- S17AKF link from page
S -- Approximations of Special Functions
\item {\bf s17dcf} -- S17DCF link from page
S -- Approximations of Special Functions
\item {\bf s17def} -- S17DEF link from page
S -- Approximations of Special Functions
\item {\bf s17dgf} -- S17DGF link from page
S -- Approximations of Special Functions
\item {\bf s17dhf} -- S17DHF link from page
S -- Approximations of Special Functions
\item {\bf s17dlf} -- S17DLF link from page
S -- Approximations of Special Functions
\item {\bf s18acf} -- S18ACF link from page
S -- Approximations of Special Functions
\item {\bf s18adf} -- S18ADF link from page
S -- Approximations of Special Functions
\item {\bf s18aef} -- S18AEF link from page
S -- Approximations of Special Functions
\item {\bf s18aff} -- S18AFF link from page
S -- Approximations of Special Functions
\item {\bf s18dcf} -- S18DCF link from page
S -- Approximations of Special Functions
\item {\bf s18def} -- S18DEF link from page
S -- Approximations of Special Functions
\item {\bf s19aaf} -- S19AAF link from page
S -- Approximations of Special Functions
\item {\bf s19abf} -- S19ABF link from page
S -- Approximations of Special Functions
\item {\bf s19acf} -- S19ACF link from page
S -- Approximations of Special Functions
\item {\bf s19adf} -- S19ADF link from page
S -- Approximations of Special Functions
\item {\bf s20acf} -- S20ACF link from page
S -- Approximations of Special Functions
\item {\bf s20adf} -- S20ADF link from page
S -- Approximations of Special Functions
\item {\bf s21baf} -- S21BAF link from page
S -- Approximations of Special Functions
\item {\bf s21bbf} -- S21BBF link from page
S -- Approximations of Special Functions
\item {\bf s21bcf} -- S21BCF link from page
S -- Approximations of Special Functions
\item {\bf s21bdf} -- S21BDF link from page
S -- Approximations of Special Functions

\end{itemize}

\pagetitle{Man0Page}{man0.ht}{Axiom Browser}
\pagepic{ps/v71man0page.eps}{man0page}{0.50}
\pagefrom{Root Page}{RootPage}
\pageto{Commands}{ugSysCmdPage}
\pageto{Constructors}{LispFunctions}
\begin{chunk}{man0.ht}
\begin{page}{Man0Page}{A x i o m \   B r o w s e r}

\beginscroll
Enter search string (use {\em *} for wild card unless counter-indicated):
\inputstring{pattern}{40}{}
\newline
\beginmenu
\menulispmemolink{Constructors}
  { (|kSearch| '|\stringvalue{pattern}|) }
  \tab{15} Search for 
\lispmemolink{categories}{(|cSearch| '|\stringvalue{pattern}|)}, 
\lispmemolink{domains}{(|dSearch| '|\stringvalue{pattern}|)}, or 
\lispmemolink{packages}{(|pSearch| '|\stringvalue{pattern}|)}
\menulispmemolink{Operations}
  { (|oSearch| '|\stringvalue{pattern}|) }
  \tab{15} Search for operations.
\menulispmemolink{Attributes}
  { (|aSearch| '|\stringvalue{pattern}|) }
  \tab{15} Search for attributes.
\menulispmemolink{General}
  { (|aokSearch| '|\stringvalue{pattern}|) }
  \tab{15} Search for all three of the above.
\menulispmemolink{Documentation}
  { (|docSearch| '|\stringvalue{pattern}|) }
  \tab{15} Search library documentation.
\menulispmemolink{Complete}
  { (|genSearch| '|\stringvalue{pattern}|) }
  \tab{15} All of the above.
\menulispmemolink{Selectable}
  { (|detailedSearch| '|\stringvalue{pattern}|) }
  \tab{15} Detailed search with selectable options.
\horizontalline
\menuunixlink{Reference}
  {htsearch "\stringvalue{pattern}"}
  \tab{15} Search Reference documentation ({\em *} wild card 
is not accepted).
\menumemolink{Commands}{ugSysCmdPage}
\tab{15} View system command documentation.
\endmenu
\endscroll
\autobutt{BROWSEhelp}
\end{page}

\end{chunk}
\pagetitle{BROWSEhelp}{man0.ht}{The Hyperdoc Browse Facility}
\begin{chunk}{man0.ht}
\begin{page}{BROWSEhelp}{The Hyperdoc Browse Facility}

\beginscroll
\beginmenu
    \menudownlink{{The Front Page: Searching the Library}}
{ugBrowseStartPage}
    \menudownlink{{The Constructor Page}}{ugBrowseDomainPage}
    \menudownlink{{Miscellaneous Features of Browse}}
{ugBrowseMiscellaneousFeaturesPage}
\endmenu
\endscroll
\newline
\end{page}

\end{chunk}
\section{mapping.ht}
\pagetitle{DomainMapping}{mapping.ht}{Domain {\bf Mapping(T,S,...)}}
\pageto{Description}{LispFunctions}
\pageto{Operations}{LispFunctions}
\begin{chunk}{mapping.ht}
\begin{page}{DomainMapping}{Domain {\em Mapping(T,S,...)}}
\beginscroll
{\em Mapping} takes any number of arguments of the form:
\indentrel{2}
\newline \spad{T}, a domain of category \spadtype{SetCategory}
\newline \spad{S}, a domain of category \spadtype{SetCategory}
\newline\tab{10}...
\indentrel{-2}\newline
This constructor is a primitive in Axiom.
\newline
\beginmenu
\item\menulispdownlink{Description}
{(|dbSpecialDescription| '|Mapping|)}\tab{19}General description
\item\menulispdownlink{Operations} 
{(|dbSpecialOperations| '|Mapping|)}
\tab{19}All exported operations of \spad{Mapping(T,S)}
%\item\menudownlink{Examples}   {MappingExamples}   
\tab{19}Examples illustrating use
%\item\menudownlink{Exports}    {MappingExports}    
\tab{19}Explicit categories and operations
\endmenu
\endscroll\end{page}
 
\end{chunk}
\pagetitle{MappingDescription}{mapping.ht}
{Domain Constructor {\bf Mapping}}
\begin{chunk}{mapping.ht}
\begin{page}{MappingDescription}{Domain Constructor {\em Mapping}}	
\beginscroll
\newline\menuitemstyle{}\tab{2}Mapping({\em T},{\em S,...})
\newline\tab{2}{\em Arguments:}\indent{17}\tab{-2}
{\em T}, a domain of category \spadtype{SetCategory}
\newline\tab{-2}
{\em S}, a domain of category \spadtype{SetCategory}
\newline\tab{10}...
\indent{0}\newline\tab{2}{\em Returns:}\indent{15}\tab{0}
the class of mappings from domain ({\em S,...}) 
into domain {\em T} as described below.
\indent{0}\newline\tab{2}{\em Description:}\indent{15}\tab{0}
{\em Mapping(T,S,...)} denotes the class of objects which are
mappings from a source domain ({\em S,...}) into a target domain {\em T}.
The {\em Mapping} constructor can take any number of arguments.
All but the first argument is regarded as part of a source tuple
for the mapping. 
For example, {\em Mapping(T,A,B)} denotes the
class of mappings from {\em (A,B)} into {\em T}.
{\em Mapping} is a primitive domain of Axiom which cannot be
defined in the Axiom language. 
\endscroll
\end{page}

\end{chunk}
\section{mappkg1.ht}
\pagetitle{MappingPackageOneXmpPage}{mappkg1.ht}{MappingPackage1}
\begin{chunk}{mappkg1.ht}
\begin{page}{MappingPackageOneXmpPage}{MappingPackage1}
\beginscroll

Function are objects of type \pspadtype{Mapping}.
In this section we demonstrate some library operations from the
packages \spadtype{MappingPackage1}, \spadtype{MappingPackage2}, and
\spadtype{MappingPackage3} that manipulate and create functions.
Some terminology: a {\it nullary} function takes no arguments,
a {\it unary} function takes one argument, and
a {\it binary} function takes two arguments.

\xtc{
We begin by creating an example function that raises a
rational number to an integer exponent.
}{
\spadpaste{power(q: FRAC INT, n: INT): FRAC INT == q**n \bound{power}}
}
\xtc{
}{
\spadpaste{power(2,3) \free{power}}
}
\xtc{
The \spadfunFrom{twist}{MappingPackage3} operation
transposes the arguments of a binary function.
Here \spad{rewop(a, b)} is \spad{power(b, a)}.
}{
\spadpaste{rewop := twist power \free{power}\bound{rewop}}
}
\xtc{
This is \texht{$2^3.$}{\spad{2**3.}}
}{
\spadpaste{rewop(3, 2) \free{rewop}}
}
\xtc{
Now we define \userfun{square} in terms of \userfun{power}.
}{
\spadpaste{square: FRAC INT -> FRAC INT \bound{squaredec}}
}
\xtc{
The \spadfunFrom{curryRight}{MappingPackage3} operation creates a unary
function from a binary one by providing a constant
argument on the right.
}{
\spadpaste{square:= curryRight(power, 2) \free{squaredec poswer}
\bound{square}}
}
\xtc{
Likewise, the
\spadfunFrom{curryLeft}{MappingPackage3} operation provides a constant
argument on the left.
}{
\spadpaste{square 4 \free{square}}
}
\xtc{
The \spadfunFrom{constantRight}{MappingPackage3} operation creates
(in a trivial way) a binary function from a unary one:
\spad{constantRight(f)} is the function \spad{g} such that
\spad{g(a,b)= f(a).}
}{
\spadpaste{squirrel:= constantRight(square)\$MAPPKG3(FRAC INT,
FRAC INT,FRAC INT) \free{square}\bound{squirrel}}
}
\xtc{
Likewise,
\spad{constantLeft(f)} is the function \spad{g} such that 
\spad{g(a,b)= f(b).}
}{
\spadpaste{squirrel(1/2, 1/3) \free{squirrel}}
}
\xtc{
The \spadfunFrom{curry}{MappingPackage2} operation makes a 
unary function nullary.
}{
\spadpaste{sixteen := curry(square, 4/1) \free{square}\bound{sixteen}}
}
\xtc{
}{
\spadpaste{sixteen() \free{sixteen}}
}
\xtc{
The \spadopFrom{*}{MappingPackage3} operation
constructs composed functions.
}{
\spadpaste{square2:=square*square \free{square}\bound{square2}}
}
\xtc{
}{
\spadpaste{square2  3 \free{square2}}
}
\xtc{
Use the \spadopFrom{**}{MappingPackage1} operation to create
functions that are \spad{n}-fold iterations of other functions.
}{
\spadpaste{sc(x: FRAC INT): FRAC INT == x + 1 \bound{sc}}
}
\xtc{
This is a list of \pspadtype{Mapping} objects.
}{
\spadpaste{incfns := [sc**i for i in 0..10] \free{sc}\bound{incfns}}
}
\xtc{
This is a list of applications of those functions.
}{
\spadpaste{[f 4 for f in incfns] \free{incfns}}
}
\xtc{
Use the \spadfunFrom{recur}{MappingPackage1}
operation for recursion:
\spad{g := recur f} means \spad{g(n,x) == f(n,f(n-1,...f(1,x))).}
}{
\spadpaste{times(n:NNI, i:INT):INT == n*i \bound{rdec}}
}
\xtc{
}{
\spadpaste{r := recur(times) \free{rdec}\bound{r}}
}
\xtc{
This is a factorial function.
}{
\spadpaste{fact := curryRight(r, 1) \free{r}\bound{fact}}
}
\xtc{
}{
\spadpaste{fact 4 \free{fact}}
}
\xtc{
Constructed functions can be used within other functions.
}{
\begin{spadsrc}[\free{square}\bound{mto2ton}]
mto2ton(m, n) ==
  raiser := square**n
  raiser m
\end{spadsrc}
}
\xtc{
This is \texht{$3^{2^3}.$}{\spad{3**(2**3).}}
}{
\spadpaste{mto2ton(3, 3) \free{mto2ton}}
}
\xtc{
Here \userfun{shiftfib} is a unary function that modifies its argument.
}{
\begin{spadsrc}[\bound{shiftfib}]
shiftfib(r: List INT) : INT ==
  t := r.1
  r.1 := r.2
  r.2 := r.2 + t
  t
\end{spadsrc}
}
\xtc{
By currying over the argument we get a function with private state.
}{
\spadpaste{fibinit: List INT := [0, 1] \bound{fibinitdec}}
}
\xtc{
}{
\spadpaste{fibs := curry(shiftfib, fibinit) 
\free{shiftfib fibinit}\bound{fibs}}
}
\xtc{
}{
\spadpaste{[fibs() for i in 0..30] \free{fibs}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{MappingPackageOneXmpPagePatch1}
\begin{paste}{MappingPackageOneXmpPageFull1}{MappingPackageOneXmpPageEmpty1}
\pastebutton{MappingPackageOneXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{power(q: FRAC INT, n: INT): FRAC INT == q**n\bound{power }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty1}
\begin{paste}{MappingPackageOneXmpPageEmpty1}{MappingPackageOneXmpPagePatch1}
\pastebutton{MappingPackageOneXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{power(q: FRAC INT, n: INT): FRAC INT == q**n\bound{power }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch2}
\begin{paste}{MappingPackageOneXmpPageFull2}{MappingPackageOneXmpPageEmpty2}
\pastebutton{MappingPackageOneXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{power(2,3)\free{power }}
\indentrel{3}\begin{verbatim}
   (2)  8
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty2}
\begin{paste}{MappingPackageOneXmpPageEmpty2}{MappingPackageOneXmpPagePatch2}
\pastebutton{MappingPackageOneXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{power(2,3)\free{power }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch3}
\begin{paste}{MappingPackageOneXmpPageFull3}{MappingPackageOneXmpPageEmpty3}
\pastebutton{MappingPackageOneXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{rewop := twist power\free{power }\bound{rewop }}
\indentrel{3}\begin{verbatim}
   (3)  theMap(MAPPKG3;twist;MM;5!0)
 Type: ((Integer,Fraction Integer) -> Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty3}
\begin{paste}{MappingPackageOneXmpPageEmpty3}{MappingPackageOneXmpPagePatch3}
\pastebutton{MappingPackageOneXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{rewop := twist power\free{power }\bound{rewop }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch4}
\begin{paste}{MappingPackageOneXmpPageFull4}{MappingPackageOneXmpPageEmpty4}
\pastebutton{MappingPackageOneXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{rewop(3, 2)\free{rewop }}
\indentrel{3}\begin{verbatim}
   (4)  8
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty4}
\begin{paste}{MappingPackageOneXmpPageEmpty4}{MappingPackageOneXmpPagePatch4}
\pastebutton{MappingPackageOneXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{rewop(3, 2)\free{rewop }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch5}
\begin{paste}{MappingPackageOneXmpPageFull5}{MappingPackageOneXmpPageEmpty5}
\pastebutton{MappingPackageOneXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{square: FRAC INT -> FRAC INT\bound{squaredec }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty5}
\begin{paste}{MappingPackageOneXmpPageEmpty5}{MappingPackageOneXmpPagePatch5}
\pastebutton{MappingPackageOneXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{square: FRAC INT -> FRAC INT\bound{squaredec }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch6}
\begin{paste}{MappingPackageOneXmpPageFull6}{MappingPackageOneXmpPageEmpty6}
\pastebutton{MappingPackageOneXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{square:= curryRight(power, 2)\free{squaredec poswer }\bound{square }}
\indentrel{3}\begin{verbatim}
   (6)  theMap(MAPPKG3;curryRight;MBM;1!0,430)
           Type: (Fraction Integer -> Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty6}
\begin{paste}{MappingPackageOneXmpPageEmpty6}{MappingPackageOneXmpPagePatch6}
\pastebutton{MappingPackageOneXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{square:= curryRight(power, 2)\free{squaredec poswer }\bound{square }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch7}
\begin{paste}{MappingPackageOneXmpPageFull7}{MappingPackageOneXmpPageEmpty7}
\pastebutton{MappingPackageOneXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{square 4\free{square }}
\indentrel{3}\begin{verbatim}
   (7)  16
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty7}
\begin{paste}{MappingPackageOneXmpPageEmpty7}{MappingPackageOneXmpPagePatch7}
\pastebutton{MappingPackageOneXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{square 4\free{square }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch8}
\begin{paste}{MappingPackageOneXmpPageFull8}{MappingPackageOneXmpPageEmpty8}
\pastebutton{MappingPackageOneXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{squirrel:= constantRight(square)$MAPPKG3(FRAC INT,FRAC INT,FRAC INT)\free{square }\bound{squirrel }}
\indentrel{3}\begin{verbatim}
   (8)  theMap(MAPPKG3;constantRight;MM;3!0)
Type: ((Fraction Integer,Fraction Integer) -> Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty8}
\begin{paste}{MappingPackageOneXmpPageEmpty8}{MappingPackageOneXmpPagePatch8}
\pastebutton{MappingPackageOneXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{squirrel:= constantRight(square)$MAPPKG3(FRAC INT,FRAC INT,FRAC INT)\free{square }\bound{squirrel }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch9}
\begin{paste}{MappingPackageOneXmpPageFull9}{MappingPackageOneXmpPageEmpty9}
\pastebutton{MappingPackageOneXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{squirrel(1/2, 1/3)\free{squirrel }}
\indentrel{3}\begin{verbatim}
        1
   (9)  Ä
        4
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty9}
\begin{paste}{MappingPackageOneXmpPageEmpty9}{MappingPackageOneXmpPagePatch9}
\pastebutton{MappingPackageOneXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{squirrel(1/2, 1/3)\free{squirrel }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch10}
\begin{paste}{MappingPackageOneXmpPageFull10}{MappingPackageOneXmpPageEmpty10}
\pastebutton{MappingPackageOneXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{sixteen := curry(square, 4/1)\free{square }\bound{sixteen }}
\indentrel{3}\begin{verbatim}
   (10)  theMap(MAPPKG2;curry;MAM;2!0,488)
                         Type: (() -> Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty10}
\begin{paste}{MappingPackageOneXmpPageEmpty10}{MappingPackageOneXmpPagePatch10}
\pastebutton{MappingPackageOneXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{sixteen := curry(square, 4/1)\free{square }\bound{sixteen }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch11}
\begin{paste}{MappingPackageOneXmpPageFull11}{MappingPackageOneXmpPageEmpty11}
\pastebutton{MappingPackageOneXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{sixteen()\free{sixteen }}
\indentrel{3}\begin{verbatim}
   (11)  16
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty11}
\begin{paste}{MappingPackageOneXmpPageEmpty11}{MappingPackageOneXmpPagePatch11}
\pastebutton{MappingPackageOneXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{sixteen()\free{sixteen }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch12}
\begin{paste}{MappingPackageOneXmpPageFull12}{MappingPackageOneXmpPageEmpty12}
\pastebutton{MappingPackageOneXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{square2:=square*square\free{square }\bound{square2 }}
\indentrel{3}\begin{verbatim}
   (12)  theMap(MAPPKG3;*;MMM;6!0,589)
           Type: (Fraction Integer -> Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty12}
\begin{paste}{MappingPackageOneXmpPageEmpty12}{MappingPackageOneXmpPagePatch12}
\pastebutton{MappingPackageOneXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{square2:=square*square\free{square }\bound{square2 }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch13}
\begin{paste}{MappingPackageOneXmpPageFull13}{MappingPackageOneXmpPageEmpty13}
\pastebutton{MappingPackageOneXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{square2 3\free{square2 }}
\indentrel{3}\begin{verbatim}
   (13)  81
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty13}
\begin{paste}{MappingPackageOneXmpPageEmpty13}{MappingPackageOneXmpPagePatch13}
\pastebutton{MappingPackageOneXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{square2 3\free{square2 }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch14}
\begin{paste}{MappingPackageOneXmpPageFull14}{MappingPackageOneXmpPageEmpty14}
\pastebutton{MappingPackageOneXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{sc(x: FRAC INT): FRAC INT == x + 1\bound{sc }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty14}
\begin{paste}{MappingPackageOneXmpPageEmpty14}{MappingPackageOneXmpPagePatch14}
\pastebutton{MappingPackageOneXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{sc(x: FRAC INT): FRAC INT == x + 1\bound{sc }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch15}
\begin{paste}{MappingPackageOneXmpPageFull15}{MappingPackageOneXmpPageEmpty15}
\pastebutton{MappingPackageOneXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{incfns := [sc**i for i in 0..10]\free{sc }\bound{incfns }}
\indentrel{3}\begin{verbatim}
   (15)
   [theMap(MAPPKG1;**;MNniM;6!0,314),
    theMap(MAPPKG1;**;MNniM;6!0,963),
    theMap(MAPPKG1;**;MNniM;6!0,810),
    theMap(MAPPKG1;**;MNniM;6!0,546),
    theMap(MAPPKG1;**;MNniM;6!0,338),
    theMap(MAPPKG1;**;MNniM;6!0,989),
    theMap(MAPPKG1;**;MNniM;6!0,218),
    theMap(MAPPKG1;**;MNniM;6!0,20),
    theMap(MAPPKG1;**;MNniM;6!0,533),
    theMap(MAPPKG1;**;MNniM;6!0,437),
    theMap(MAPPKG1;**;MNniM;6!0,900)]
      Type: List (Fraction Integer -> Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty15}
\begin{paste}{MappingPackageOneXmpPageEmpty15}{MappingPackageOneXmpPagePatch15}
\pastebutton{MappingPackageOneXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{incfns := [sc**i for i in 0..10]\free{sc }\bound{incfns }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch16}
\begin{paste}{MappingPackageOneXmpPageFull16}{MappingPackageOneXmpPageEmpty16}
\pastebutton{MappingPackageOneXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{[f 4 for f in incfns]\free{incfns }}
\indentrel{3}\begin{verbatim}
   (16)  [4,5,6,7,8,9,10,11,12,13,14]
                            Type: List Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty16}
\begin{paste}{MappingPackageOneXmpPageEmpty16}{MappingPackageOneXmpPagePatch16}
\pastebutton{MappingPackageOneXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{[f 4 for f in incfns]\free{incfns }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch17}
\begin{paste}{MappingPackageOneXmpPageFull17}{MappingPackageOneXmpPageEmpty17}
\pastebutton{MappingPackageOneXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{times(n:NNI, i:INT):INT == n*i\bound{rdec }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty17}
\begin{paste}{MappingPackageOneXmpPageEmpty17}{MappingPackageOneXmpPagePatch17}
\pastebutton{MappingPackageOneXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{times(n:NNI, i:INT):INT == n*i\bound{rdec }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch18}
\begin{paste}{MappingPackageOneXmpPageFull18}{MappingPackageOneXmpPageEmpty18}
\pastebutton{MappingPackageOneXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{r := recur(times)\free{rdec }\bound{r }}
\indentrel{3}\begin{verbatim}
   (18)  theMap(MAPPKG1;recur;2M;7!0,161)
        Type: ((NonNegativeInteger,Integer) -> Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty18}
\begin{paste}{MappingPackageOneXmpPageEmpty18}{MappingPackageOneXmpPagePatch18}
\pastebutton{MappingPackageOneXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{r := recur(times)\free{rdec }\bound{r }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch19}
\begin{paste}{MappingPackageOneXmpPageFull19}{MappingPackageOneXmpPageEmpty19}
\pastebutton{MappingPackageOneXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{fact := curryRight(r, 1)\free{r }\bound{fact }}
\indentrel{3}\begin{verbatim}
   (19)  theMap(MAPPKG3;curryRight;MBM;1!0,541)
                  Type: (NonNegativeInteger -> Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty19}
\begin{paste}{MappingPackageOneXmpPageEmpty19}{MappingPackageOneXmpPagePatch19}
\pastebutton{MappingPackageOneXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{fact := curryRight(r, 1)\free{r }\bound{fact }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch20}
\begin{paste}{MappingPackageOneXmpPageFull20}{MappingPackageOneXmpPageEmpty20}
\pastebutton{MappingPackageOneXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{fact 4\free{fact }}
\indentrel{3}\begin{verbatim}
   (20)  24
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty20}
\begin{paste}{MappingPackageOneXmpPageEmpty20}{MappingPackageOneXmpPagePatch20}
\pastebutton{MappingPackageOneXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{fact 4\free{fact }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch21}
\begin{paste}{MappingPackageOneXmpPageFull21}{MappingPackageOneXmpPageEmpty21}
\pastebutton{MappingPackageOneXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{mto2ton(m, n) ==
  raiser := square**n
  raiser m
\free{square }\bound{mto2ton }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty21}
\begin{paste}{MappingPackageOneXmpPageEmpty21}{MappingPackageOneXmpPagePatch21}
\pastebutton{MappingPackageOneXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{mto2ton(m, n) ==
  raiser := square**n
  raiser m
\free{square }\bound{mto2ton }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch22}
\begin{paste}{MappingPackageOneXmpPageFull22}{MappingPackageOneXmpPageEmpty22}
\pastebutton{MappingPackageOneXmpPageFull22}{\hidepaste}
\tab{5}\spadcommand{mto2ton(3, 3)\free{mto2ton }}
\indentrel{3}\begin{verbatim}
   (22)  6561
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty22}
\begin{paste}{MappingPackageOneXmpPageEmpty22}{MappingPackageOneXmpPagePatch22}
\pastebutton{MappingPackageOneXmpPageEmpty22}{\showpaste}
\tab{5}\spadcommand{mto2ton(3, 3)\free{mto2ton }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch23}
\begin{paste}{MappingPackageOneXmpPageFull23}{MappingPackageOneXmpPageEmpty23}
\pastebutton{MappingPackageOneXmpPageFull23}{\hidepaste}
\tab{5}\spadcommand{shiftfib(r: List INT) : INT ==
  t := r.1
  r.1 := r.2
  r.2 := r.2 + t
  t
\bound{shiftfib }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty23}
\begin{paste}{MappingPackageOneXmpPageEmpty23}{MappingPackageOneXmpPagePatch23}
\pastebutton{MappingPackageOneXmpPageEmpty23}{\showpaste}
\tab{5}\spadcommand{shiftfib(r: List INT) : INT ==
  t := r.1
  r.1 := r.2
  r.2 := r.2 + t
  t
\bound{shiftfib }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch24}
\begin{paste}{MappingPackageOneXmpPageFull24}{MappingPackageOneXmpPageEmpty24}
\pastebutton{MappingPackageOneXmpPageFull24}{\hidepaste}
\tab{5}\spadcommand{fibinit: List INT := [0, 1]\bound{fibinitdec }}
\indentrel{3}\begin{verbatim}
   (24)  [0,1]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty24}
\begin{paste}{MappingPackageOneXmpPageEmpty24}{MappingPackageOneXmpPagePatch24}
\pastebutton{MappingPackageOneXmpPageEmpty24}{\showpaste}
\tab{5}\spadcommand{fibinit: List INT := [0, 1]\bound{fibinitdec }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch25}
\begin{paste}{MappingPackageOneXmpPageFull25}{MappingPackageOneXmpPageEmpty25}
\pastebutton{MappingPackageOneXmpPageFull25}{\hidepaste}
\tab{5}\spadcommand{fibs := curry(shiftfib, fibinit)\free{shiftfib fibinit }\bound{fibs }}
\indentrel{3}\begin{verbatim}
   (25)  theMap(MAPPKG2;curry;MAM;2!0,91)
                                  Type: (() -> Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty25}
\begin{paste}{MappingPackageOneXmpPageEmpty25}{MappingPackageOneXmpPagePatch25}
\pastebutton{MappingPackageOneXmpPageEmpty25}{\showpaste}
\tab{5}\spadcommand{fibs := curry(shiftfib, fibinit)\free{shiftfib fibinit }\bound{fibs }}
\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPagePatch26}
\begin{paste}{MappingPackageOneXmpPageFull26}{MappingPackageOneXmpPageEmpty26}
\pastebutton{MappingPackageOneXmpPageFull26}{\hidepaste}
\tab{5}\spadcommand{[fibs() for i in 0..30]\free{fibs }}
\indentrel{3}\begin{verbatim}
   (26)
   [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,
    377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711,
    28657, 46368, 75025, 121393, 196418, 317811, 514229,
    832040]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MappingPackageOneXmpPageEmpty26}
\begin{paste}{MappingPackageOneXmpPageEmpty26}{MappingPackageOneXmpPagePatch26}
\pastebutton{MappingPackageOneXmpPageEmpty26}{\showpaste}
\tab{5}\spadcommand{[fibs() for i in 0..30]\free{fibs }}
\end{paste}\end{patch}

\end{chunk}
\section{mset.ht}
\pagetitle{MultiSetXmpPage}{mset.ht}{MultiSet}
\begin{chunk}{mset.ht}
\begin{page}{MultiSetXmpPage}{MultiSet}
\beginscroll
The domain \spadtype{Multiset(R)} is similar to \spadtype{Set(R)}
except that multiplicities
(counts of duplications) are maintained and displayed.
Use the operation \spadfunFrom{multiset}{Multiset} to create
multisets from lists.
All the standard operations from sets are available for
multisets.
An element with multiplicity greater than one has the
multiplicity displayed first, then a colon, and then the element.

\xtc{
Create a multiset of integers.
}{
\spadpaste{s := multiset [1,2,3,4,5,4,3,2,3,4,5,6,7,4,10]\bound{s}}
}
\xtc{
The operation \spadfunX{insert} adds an element to a multiset.
}{
\spadpaste{insert!(3,s)\bound{s1}\free{s}}
}
\xtc{
Use \spadfunX{remove} to remove an element.
If a third argument is present, it specifies how many instances
to remove. Otherwise all instances of the element are removed.
Display the resulting multiset.
}{
\spadpaste{remove!(3,s,1); s\bound{s2}\free{s1}}
}
\xtc{
}{
\spadpaste{remove!(5,s); s\bound{s2}\free{s1}}
}
\xtc{
The operation \spadfun{count} returns the number of copies
of a given value.
}{
\spadpaste{count(5,s)\free{s2}}
}
\xtc{
A second multiset.
}{
\spadpaste{t := multiset [2,2,2,-9]\bound{t}}
}
\xtc{
The \spadfun{union} of two multisets is additive.
}{
\spadpaste{U := union(s,t)\bound{U}}
}
\xtc{
The \spadfun{intersect} operation gives the elements that are in
common, with additive multiplicity.
}{
\spadpaste{I := intersect(s,t)\bound{I}}
}
\xtc{
The \spadfun{difference} of \spad{s} and \spad{t} consists of
the elements that \spad{s} has but \spad{t} does not.
Elements are regarded as indistinguishable, so that if \spad{s}
and \spad{t} have any element in common, the \spadfun{difference}
does not contain that element.
}{
\spadpaste{difference(s,t)\free{s2 t}}
}
\xtc{
The \spadfun{symmetricDifference} is the \spadfun{union}
of \spad{difference(s, t)} and \spad{difference(t, s)}.
}{
\spadpaste{S := symmetricDifference(s,t)\bound{S}\free{s2 t}}
}
\xtc{
Check that the \spadfun{union} of the \spadfun{symmetricDifference} and
the \spadfun{intersect} equals the \spadfun{union} of the elements.
}{
\spadpaste{(U = union(S,I))@Boolean\free{S I U}}
}
\xtc{
Check some inclusion relations.
}{
\spadpaste{t1 := multiset [1,2,2,3]; [t1 < t, t1 < s, t < s, t1 <= s]
\free{t s2}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{MultiSetXmpPagePatch1}
\begin{paste}{MultiSetXmpPageFull1}{MultiSetXmpPageEmpty1}
\pastebutton{MultiSetXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{s := multiset [1,2,3,4,5,4,3,2,3,4,5,6,7,4,10]\bound{s }}
\indentrel{3}\begin{verbatim}
   (1)  {7,2: 5,3: 3,1,10,6,4: 4,2: 2}
                         Type: Multiset PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPageEmpty1}
\begin{paste}{MultiSetXmpPageEmpty1}{MultiSetXmpPagePatch1}
\pastebutton{MultiSetXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{s := multiset [1,2,3,4,5,4,3,2,3,4,5,6,7,4,10]\bound{s }}
\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPagePatch2}
\begin{paste}{MultiSetXmpPageFull2}{MultiSetXmpPageEmpty2}
\pastebutton{MultiSetXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{insert!(3,s)\bound{s1 }\free{s }}
\indentrel{3}\begin{verbatim}
   (2)  {7,2: 5,4: 3,1,10,6,4: 4,2: 2}
                         Type: Multiset PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPageEmpty2}
\begin{paste}{MultiSetXmpPageEmpty2}{MultiSetXmpPagePatch2}
\pastebutton{MultiSetXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{insert!(3,s)\bound{s1 }\free{s }}
\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPagePatch3}
\begin{paste}{MultiSetXmpPageFull3}{MultiSetXmpPageEmpty3}
\pastebutton{MultiSetXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{remove!(3,s,1); s\bound{s2 }\free{s1 }}
\indentrel{3}\begin{verbatim}
   (3)  {7,2: 5,3: 3,1,10,6,4: 4,2: 2}
                         Type: Multiset PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPageEmpty3}
\begin{paste}{MultiSetXmpPageEmpty3}{MultiSetXmpPagePatch3}
\pastebutton{MultiSetXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{remove!(3,s,1); s\bound{s2 }\free{s1 }}
\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPagePatch4}
\begin{paste}{MultiSetXmpPageFull4}{MultiSetXmpPageEmpty4}
\pastebutton{MultiSetXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{remove!(5,s); s\bound{s2 }\free{s1 }}
\indentrel{3}\begin{verbatim}
   (4)  {7,3: 3,1,10,6,4: 4,2: 2}
                         Type: Multiset PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPageEmpty4}
\begin{paste}{MultiSetXmpPageEmpty4}{MultiSetXmpPagePatch4}
\pastebutton{MultiSetXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{remove!(5,s); s\bound{s2 }\free{s1 }}
\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPagePatch5}
\begin{paste}{MultiSetXmpPageFull5}{MultiSetXmpPageEmpty5}
\pastebutton{MultiSetXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{count(5,s)\free{s2 }}
\indentrel{3}\begin{verbatim}
   (5)  0
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPageEmpty5}
\begin{paste}{MultiSetXmpPageEmpty5}{MultiSetXmpPagePatch5}
\pastebutton{MultiSetXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{count(5,s)\free{s2 }}
\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPagePatch6}
\begin{paste}{MultiSetXmpPageFull6}{MultiSetXmpPageEmpty6}
\pastebutton{MultiSetXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{t := multiset [2,2,2,-9]\bound{t }}
\indentrel{3}\begin{verbatim}
   (6)  {- 9,3: 2}
                                 Type: Multiset Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPageEmpty6}
\begin{paste}{MultiSetXmpPageEmpty6}{MultiSetXmpPagePatch6}
\pastebutton{MultiSetXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{t := multiset [2,2,2,-9]\bound{t }}
\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPagePatch7}
\begin{paste}{MultiSetXmpPageFull7}{MultiSetXmpPageEmpty7}
\pastebutton{MultiSetXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{U := union(s,t)\bound{U }}
\indentrel{3}\begin{verbatim}
   (7)  {7,3: 3,1,- 9,10,6,4: 4,5: 2}
                                 Type: Multiset Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPageEmpty7}
\begin{paste}{MultiSetXmpPageEmpty7}{MultiSetXmpPagePatch7}
\pastebutton{MultiSetXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{U := union(s,t)\bound{U }}
\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPagePatch8}
\begin{paste}{MultiSetXmpPageFull8}{MultiSetXmpPageEmpty8}
\pastebutton{MultiSetXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{I := intersect(s,t)\bound{I }}
\indentrel{3}\begin{verbatim}
   (8)  {5: 2}
                                 Type: Multiset Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPageEmpty8}
\begin{paste}{MultiSetXmpPageEmpty8}{MultiSetXmpPagePatch8}
\pastebutton{MultiSetXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{I := intersect(s,t)\bound{I }}
\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPagePatch9}
\begin{paste}{MultiSetXmpPageFull9}{MultiSetXmpPageEmpty9}
\pastebutton{MultiSetXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{difference(s,t)\free{s2 t }}
\indentrel{3}\begin{verbatim}
   (9)  {7,3: 3,1,10,6,4: 4}
                                 Type: Multiset Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPageEmpty9}
\begin{paste}{MultiSetXmpPageEmpty9}{MultiSetXmpPagePatch9}
\pastebutton{MultiSetXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{difference(s,t)\free{s2 t }}
\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPagePatch10}
\begin{paste}{MultiSetXmpPageFull10}{MultiSetXmpPageEmpty10}
\pastebutton{MultiSetXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{S := symmetricDifference(s,t)\bound{S }\free{s2 t }}
\indentrel{3}\begin{verbatim}
   (10)  {7,3: 3,1,- 9,10,6,4: 4}
                                 Type: Multiset Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPageEmpty10}
\begin{paste}{MultiSetXmpPageEmpty10}{MultiSetXmpPagePatch10}
\pastebutton{MultiSetXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{S := symmetricDifference(s,t)\bound{S }\free{s2 t }}
\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPagePatch11}
\begin{paste}{MultiSetXmpPageFull11}{MultiSetXmpPageEmpty11}
\pastebutton{MultiSetXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{(U = union(S,I))@Boolean\free{S I U }}
\indentrel{3}\begin{verbatim}
   (11)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPageEmpty11}
\begin{paste}{MultiSetXmpPageEmpty11}{MultiSetXmpPagePatch11}
\pastebutton{MultiSetXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{(U = union(S,I))@Boolean\free{S I U }}
\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPagePatch12}
\begin{paste}{MultiSetXmpPageFull12}{MultiSetXmpPageEmpty12}
\pastebutton{MultiSetXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{t1 := multiset [1,2,2,3]; [t1 < t, t1 < s, t < s, t1 <= s]\free{t s2 }}
\indentrel{3}\begin{verbatim}
   (12)  [false,true,false,true]
                                     Type: List Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MultiSetXmpPageEmpty12}
\begin{paste}{MultiSetXmpPageEmpty12}{MultiSetXmpPagePatch12}
\pastebutton{MultiSetXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{t1 := multiset [1,2,2,3]; [t1 < t, t1 < s, t < s, t1 <= s]\free{t s2 }}
\end{paste}\end{patch}

\end{chunk}
\section{matrix.ht}
\pagetitle{MatrixXmpPage}{matrix.ht}{Matrix}
\pageto{notitle}{ugxMatrixCreatePage}
\pageto{notitle}{ugxMatrixOpsPage}
\begin{chunk}{matrix.ht}
\begin{page}{MatrixXmpPage}{Matrix}
\beginscroll

The \spadtype{Matrix} domain provides arithmetic operations on matrices
and standard functions from linear algebra.
This domain is similar to the \spadtype{TwoDimensionalArray} domain, except
that the entries for \spadtype{Matrix} must belong to a \spadtype{Ring}.

\beginmenu
    \menudownlink{{9.52.1. Creating Matrices}}{ugxMatrixCreatePage}
    \menudownlink{{9.52.2. Operations on Matrices}}{ugxMatrixOpsPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugxMatrixCreatePage}{matrix.ht}{Creating Matrices}
\begin{chunk}{matrix.ht}
\begin{page}{ugxMatrixCreatePage}{Creating Matrices}
\beginscroll

There are many ways to create a matrix from a collection of
values or from existing matrices.

\xtc{
If the matrix has almost all items equal to the same value,
use \spadfunFrom{new}{Matrix} to create a matrix filled with that
value and then reset the entries that are different.
}{
\spadpaste{m : Matrix(Integer) := new(3,3,0) \bound{m}}
}
\xtc{
To change the entry in the second row, third column to \spad{5}, use
\spadfunFrom{setelt}{Matrix}.
}{
\spadpaste{setelt(m,2,3,5) \free{m}\bound{m1}}
}
\xtc{
An alternative syntax is to use assignment.
}{
\spadpaste{m(1,2) := 10 \free{m1}\bound{m2}}
}
\xtc{
The matrix was {\it destructively modified}.
}{
\spadpaste{m \free{m2}}
}

\xtc{
If you already have the matrix entries as a list of lists,
use \spadfunFrom{matrix}{Matrix}.
}{
\spadpaste{matrix [[1,2,3,4],[0,9,8,7]]}
}

\xtc{
If the matrix is diagonal, use
\spadfunFrom{diagonalMatrix}{Matrix}.
}{
\spadpaste{dm := diagonalMatrix [1,x**2,x**3,x**4,x**5] \bound{dm}}
}
\xtc{
Use \spadfunFromX{setRow}{Matrix} and
\spadfunFromX{setColumn}{Matrix} to change a row or column of a matrix.
}{
\spadpaste{setRow!(dm,5,vector [1,1,1,1,1]) \free{dm}\bound{dm1}}
}
\xtc{
}{
\spadpaste{setColumn!(dm,2,vector [y,y,y,y,y]) \free{dm1}\bound{dm2}}
}

%
\xtc{
Use \spadfunFrom{copy}{Matrix} to make a copy of a matrix.
}{
\spadpaste{cdm := copy(dm) \free{dm2}\bound{cdm}}
}
\xtc{
This is useful if you intend to modify a matrix destructively but
want a copy of the original.
}{
\spadpaste{setelt(dm,4,1,1-x**7) \free{dm2}\bound{setdm}}
}
\xtc{
}{
\spadpaste{[dm,cdm] \free{setdm cdm}}
}

%
\xtc{
Use \spadfunFrom{subMatrix}{Matrix} to extract part of an
existing matrix.
The syntax is \spad{subMatrix({\it m, firstrow, lastrow, firstcol,
lastcol})}.
}{
\spadpaste{subMatrix(dm,2,3,2,4) \free{setdm}}
}

%
\xtc{
To change a submatrix, use \spadfunFromX{setsubMatrix}{Matrix}.
}{
\spadpaste{d := diagonalMatrix [1.2,-1.3,1.4,-1.5] \bound{d}}
}
\xtc{
If \spad{e} is too big to fit where you specify, an error message
is displayed.
Use \spadfunFrom{subMatrix}{Matrix} to extract part of \spad{e}, if
necessary.
}{
\spadpaste{e := matrix [[6.7,9.11],[-31.33,67.19]] \bound{e}}
}
\xtc{
This changes the submatrix of \spad{d} whose upper left corner is
at the first row and second column and whose size is that of \spad{e}.
}{
\spadpaste{setsubMatrix!(d,1,2,e) \free{d e}\bound{d1}}
}
\xtc{
}{
\spadpaste{d \free{d1}}
}
%

%
\xtc{
Matrices can be joined either horizontally or vertically to make
new matrices.
}{
\spadpaste{a := matrix [[1/2,1/3,1/4],[1/5,1/6,1/7]] \bound{a}}
}
\xtc{
}{
\spadpaste{b := matrix [[3/5,3/7,3/11],[3/13,3/17,3/19]] \bound{b}}
}
\xtc{
Use \spadfunFrom{horizConcat}{Matrix} to append them side to side.
The two matrices must have the same number of rows.
}{
\spadpaste{horizConcat(a,b) \free{a b}}
}
\xtc{
Use \spadfunFrom{vertConcat}{Matrix} to stack one upon the other.
The two matrices must have the same number of columns.
}{
\spadpaste{vab := vertConcat(a,b) \free{a b}\bound{vab}}
}

%
\xtc{
The operation
\spadfunFrom{transpose}{Matrix} is used to create a new matrix by 
reflection across the main diagonal.
}{
\spadpaste{transpose vab \free{vab}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxMatrixCreatePagePatch1}
\begin{paste}{ugxMatrixCreatePageFull1}{ugxMatrixCreatePageEmpty1}
\pastebutton{ugxMatrixCreatePageFull1}{\hidepaste}
\tab{5}\spadcommand{m : Matrix(Integer) := new(3,3,0)\bound{m }}
\indentrel{3}\begin{verbatim}
        Ú0  0  0¿
        ³       ³
   (1)  ³0  0  0³
        ³       ³
        À0  0  0Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePageEmpty1}
\begin{paste}{ugxMatrixCreatePageEmpty1}{ugxMatrixCreatePagePatch1}
\pastebutton{ugxMatrixCreatePageEmpty1}{\showpaste}
\tab{5}\spadcommand{m : Matrix(Integer) := new(3,3,0)\bound{m }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePagePatch2}
\begin{paste}{ugxMatrixCreatePageFull2}{ugxMatrixCreatePageEmpty2}
\pastebutton{ugxMatrixCreatePageFull2}{\hidepaste}
\tab{5}\spadcommand{setelt(m,2,3,5)\free{m }\bound{m1 }}
\indentrel{3}\begin{verbatim}
   (2)  5
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePageEmpty2}
\begin{paste}{ugxMatrixCreatePageEmpty2}{ugxMatrixCreatePagePatch2}
\pastebutton{ugxMatrixCreatePageEmpty2}{\showpaste}
\tab{5}\spadcommand{setelt(m,2,3,5)\free{m }\bound{m1 }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePagePatch3}
\begin{paste}{ugxMatrixCreatePageFull3}{ugxMatrixCreatePageEmpty3}
\pastebutton{ugxMatrixCreatePageFull3}{\hidepaste}
\tab{5}\spadcommand{m(1,2) := 10\free{m1 }\bound{m2 }}
\indentrel{3}\begin{verbatim}
   (3)  10
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePageEmpty3}
\begin{paste}{ugxMatrixCreatePageEmpty3}{ugxMatrixCreatePagePatch3}
\pastebutton{ugxMatrixCreatePageEmpty3}{\showpaste}
\tab{5}\spadcommand{m(1,2) := 10\free{m1 }\bound{m2 }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePagePatch4}
\begin{paste}{ugxMatrixCreatePageFull4}{ugxMatrixCreatePageEmpty4}
\pastebutton{ugxMatrixCreatePageFull4}{\hidepaste}
\tab{5}\spadcommand{m\free{m2 }}
\indentrel{3}\begin{verbatim}
        Ú0  10  0¿
        ³        ³
   (4)  ³0  0   5³
        ³        ³
        À0  0   0Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePageEmpty4}
\begin{paste}{ugxMatrixCreatePageEmpty4}{ugxMatrixCreatePagePatch4}
\pastebutton{ugxMatrixCreatePageEmpty4}{\showpaste}
\tab{5}\spadcommand{m\free{m2 }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePagePatch5}
\begin{paste}{ugxMatrixCreatePageFull5}{ugxMatrixCreatePageEmpty5}
\pastebutton{ugxMatrixCreatePageFull5}{\hidepaste}
\tab{5}\spadcommand{matrix [[1,2,3,4],[0,9,8,7]]}
\indentrel{3}\begin{verbatim}
        Ú1  2  3  4¿
   (5)  ³          ³
        À0  9  8  7Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePageEmpty5}
\begin{paste}{ugxMatrixCreatePageEmpty5}{ugxMatrixCreatePagePatch5}
\pastebutton{ugxMatrixCreatePageEmpty5}{\showpaste}
\tab{5}\spadcommand{matrix [[1,2,3,4],[0,9,8,7]]}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePagePatch6}
\begin{paste}{ugxMatrixCreatePageFull6}{ugxMatrixCreatePageEmpty6}
\pastebutton{ugxMatrixCreatePageFull6}{\hidepaste}
\tab{5}\spadcommand{dm := diagonalMatrix [1,x**2,x**3,x**4,x**5]\bound{dm }}
\indentrel{3}\begin{verbatim}
        Ú1  0   0   0   0 ¿
        ³                 ³
        ³    2            ³
        ³0  x   0   0   0 ³
        ³                 ³
        ³        3        ³
   (6)  ³0  0   x   0   0 ³
        ³                 ³
        ³            4    ³
        ³0  0   0   x   0 ³
        ³                 ³
        ³                5³
        À0  0   0   0   x Ù
                        Type: Matrix Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePageEmpty6}
\begin{paste}{ugxMatrixCreatePageEmpty6}{ugxMatrixCreatePagePatch6}
\pastebutton{ugxMatrixCreatePageEmpty6}{\showpaste}
\tab{5}\spadcommand{dm := diagonalMatrix [1,x**2,x**3,x**4,x**5]\bound{dm }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePagePatch7}
\begin{paste}{ugxMatrixCreatePageFull7}{ugxMatrixCreatePageEmpty7}
\pastebutton{ugxMatrixCreatePageFull7}{\hidepaste}
\tab{5}\spadcommand{setRow!(dm,5,vector [1,1,1,1,1])\free{dm }\bound{dm1 }}
\indentrel{3}\begin{verbatim}
        Ú1  0   0   0   0¿
        ³                ³
        ³    2           ³
        ³0  x   0   0   0³
        ³                ³
   (7)  ³        3       ³
        ³0  0   x   0   0³
        ³                ³
        ³            4   ³
        ³0  0   0   x   0³
        ³                ³
        À1  1   1   1   1Ù
                        Type: Matrix Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePageEmpty7}
\begin{paste}{ugxMatrixCreatePageEmpty7}{ugxMatrixCreatePagePatch7}
\pastebutton{ugxMatrixCreatePageEmpty7}{\showpaste}
\tab{5}\spadcommand{setRow!(dm,5,vector [1,1,1,1,1])\free{dm }\bound{dm1 }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePagePatch8}
\begin{paste}{ugxMatrixCreatePageFull8}{ugxMatrixCreatePageEmpty8}
\pastebutton{ugxMatrixCreatePageFull8}{\hidepaste}
\tab{5}\spadcommand{setColumn!(dm,2,vector [y,y,y,y,y])\free{dm1 }\bound{dm2 }}
\indentrel{3}\begin{verbatim}
        Ú1  y  0   0   0¿
        ³               ³
        ³0  y  0   0   0³
        ³               ³
        ³       3       ³
   (8)  ³0  y  x   0   0³
        ³               ³
        ³           4   ³
        ³0  y  0   x   0³
        ³               ³
        À1  y  1   1   1Ù
                        Type: Matrix Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePageEmpty8}
\begin{paste}{ugxMatrixCreatePageEmpty8}{ugxMatrixCreatePagePatch8}
\pastebutton{ugxMatrixCreatePageEmpty8}{\showpaste}
\tab{5}\spadcommand{setColumn!(dm,2,vector [y,y,y,y,y])\free{dm1 }\bound{dm2 }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePagePatch9}
\begin{paste}{ugxMatrixCreatePageFull9}{ugxMatrixCreatePageEmpty9}
\pastebutton{ugxMatrixCreatePageFull9}{\hidepaste}
\tab{5}\spadcommand{cdm := copy(dm)\free{dm2 }\bound{cdm }}
\indentrel{3}\begin{verbatim}
        Ú1  y  0   0   0¿
        ³               ³
        ³0  y  0   0   0³
        ³               ³
        ³       3       ³
   (9)  ³0  y  x   0   0³
        ³               ³
        ³           4   ³
        ³0  y  0   x   0³
        ³               ³
        À1  y  1   1   1Ù
                        Type: Matrix Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePageEmpty9}
\begin{paste}{ugxMatrixCreatePageEmpty9}{ugxMatrixCreatePagePatch9}
\pastebutton{ugxMatrixCreatePageEmpty9}{\showpaste}
\tab{5}\spadcommand{cdm := copy(dm)\free{dm2 }\bound{cdm }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePagePatch10}
\begin{paste}{ugxMatrixCreatePageFull10}{ugxMatrixCreatePageEmpty10}
\pastebutton{ugxMatrixCreatePageFull10}{\hidepaste}
\tab{5}\spadcommand{setelt(dm,4,1,1-x**7)\free{dm2 }\bound{setdm }}
\indentrel{3}\begin{verbatim}
            7
   (10)  - x  + 1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePageEmpty10}
\begin{paste}{ugxMatrixCreatePageEmpty10}{ugxMatrixCreatePagePatch10}
\pastebutton{ugxMatrixCreatePageEmpty10}{\showpaste}
\tab{5}\spadcommand{setelt(dm,4,1,1-x**7)\free{dm2 }\bound{setdm }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePagePatch11}
\begin{paste}{ugxMatrixCreatePageFull11}{ugxMatrixCreatePageEmpty11}
\pastebutton{ugxMatrixCreatePageFull11}{\hidepaste}
\tab{5}\spadcommand{[dm,cdm]\free{setdm cdm }}
\indentrel{3}\begin{verbatim}
          Ú   1      y  0   0   0¿ Ú1  y  0   0   0¿
          ³                      ³ ³               ³
          ³   0      y  0   0   0³ ³0  y  0   0   0³
          ³                      ³ ³               ³
          ³              3       ³ ³       3       ³
   (11)  [³   0      y  x   0   0³,³0  y  x   0   0³]
          ³                      ³ ³               ³
          ³   7              4   ³ ³           4   ³
          ³- x  + 1  y  0   x   0³ ³0  y  0   x   0³
          ³                      ³ ³               ³
          À   1      y  1   1   1Ù À1  y  1   1   1Ù
                   Type: List Matrix Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePageEmpty11}
\begin{paste}{ugxMatrixCreatePageEmpty11}{ugxMatrixCreatePagePatch11}
\pastebutton{ugxMatrixCreatePageEmpty11}{\showpaste}
\tab{5}\spadcommand{[dm,cdm]\free{setdm cdm }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePagePatch12}
\begin{paste}{ugxMatrixCreatePageFull12}{ugxMatrixCreatePageEmpty12}
\pastebutton{ugxMatrixCreatePageFull12}{\hidepaste}
\tab{5}\spadcommand{subMatrix(dm,2,3,2,4)\free{setdm }}
\indentrel{3}\begin{verbatim}
         Úy  0   0¿
   (12)  ³        ³
         ³    3   ³
         Ày  x   0Ù
                        Type: Matrix Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePageEmpty12}
\begin{paste}{ugxMatrixCreatePageEmpty12}{ugxMatrixCreatePagePatch12}
\pastebutton{ugxMatrixCreatePageEmpty12}{\showpaste}
\tab{5}\spadcommand{subMatrix(dm,2,3,2,4)\free{setdm }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePagePatch13}
\begin{paste}{ugxMatrixCreatePageFull13}{ugxMatrixCreatePageEmpty13}
\pastebutton{ugxMatrixCreatePageFull13}{\hidepaste}
\tab{5}\spadcommand{d := diagonalMatrix [1.2,-1.3,1.4,-1.5]\bound{d }}
\indentrel{3}\begin{verbatim}
         Ú1.2   0.0   0.0   0.0 ¿
         ³                      ³
         ³0.0  - 1.3  0.0   0.0 ³
   (13)  ³                      ³
         ³0.0   0.0   1.4   0.0 ³
         ³                      ³
         À0.0   0.0   0.0  - 1.5Ù
                                     Type: Matrix Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePageEmpty13}
\begin{paste}{ugxMatrixCreatePageEmpty13}{ugxMatrixCreatePagePatch13}
\pastebutton{ugxMatrixCreatePageEmpty13}{\showpaste}
\tab{5}\spadcommand{d := diagonalMatrix [1.2,-1.3,1.4,-1.5]\bound{d }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePagePatch14}
\begin{paste}{ugxMatrixCreatePageFull14}{ugxMatrixCreatePageEmpty14}
\pastebutton{ugxMatrixCreatePageFull14}{\hidepaste}
\tab{5}\spadcommand{e := matrix [[6.7,9.11],[-31.33,67.19]]\bound{e }}
\indentrel{3}\begin{verbatim}
         Ú  6.7    9.11 ¿
   (14)  ³              ³
         À- 31.33  67.19Ù
                                     Type: Matrix Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePageEmpty14}
\begin{paste}{ugxMatrixCreatePageEmpty14}{ugxMatrixCreatePagePatch14}
\pastebutton{ugxMatrixCreatePageEmpty14}{\showpaste}
\tab{5}\spadcommand{e := matrix [[6.7,9.11],[-31.33,67.19]]\bound{e }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePagePatch15}
\begin{paste}{ugxMatrixCreatePageFull15}{ugxMatrixCreatePageEmpty15}
\pastebutton{ugxMatrixCreatePageFull15}{\hidepaste}
\tab{5}\spadcommand{setsubMatrix!(d,1,2,e)\free{d e }\bound{d1 }}
\indentrel{3}\begin{verbatim}
         Ú1.2    6.7    9.11    0.0 ¿
         ³                          ³
         ³0.0  - 31.33  67.19   0.0 ³
   (15)  ³                          ³
         ³0.0    0.0     1.4    0.0 ³
         ³                          ³
         À0.0    0.0     0.0   - 1.5Ù
                                     Type: Matrix Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePageEmpty15}
\begin{paste}{ugxMatrixCreatePageEmpty15}{ugxMatrixCreatePagePatch15}
\pastebutton{ugxMatrixCreatePageEmpty15}{\showpaste}
\tab{5}\spadcommand{setsubMatrix!(d,1,2,e)\free{d e }\bound{d1 }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePagePatch16}
\begin{paste}{ugxMatrixCreatePageFull16}{ugxMatrixCreatePageEmpty16}
\pastebutton{ugxMatrixCreatePageFull16}{\hidepaste}
\tab{5}\spadcommand{d\free{d1 }}
\indentrel{3}\begin{verbatim}
         Ú1.2    6.7    9.11    0.0 ¿
         ³                          ³
         ³0.0  - 31.33  67.19   0.0 ³
   (16)  ³                          ³
         ³0.0    0.0     1.4    0.0 ³
         ³                          ³
         À0.0    0.0     0.0   - 1.5Ù
                                     Type: Matrix Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePageEmpty16}
\begin{paste}{ugxMatrixCreatePageEmpty16}{ugxMatrixCreatePagePatch16}
\pastebutton{ugxMatrixCreatePageEmpty16}{\showpaste}
\tab{5}\spadcommand{d\free{d1 }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePagePatch17}
\begin{paste}{ugxMatrixCreatePageFull17}{ugxMatrixCreatePageEmpty17}
\pastebutton{ugxMatrixCreatePageFull17}{\hidepaste}
\tab{5}\spadcommand{a := matrix [[1/2,1/3,1/4],[1/5,1/6,1/7]]\bound{a }}
\indentrel{3}\begin{verbatim}
         Ú1  1  1¿
         ³Ä  Ä  Ä³
         ³2  3  4³
   (17)  ³       ³
         ³1  1  1³
         ³Ä  Ä  Ä³
         À5  6  7Ù
                          Type: Matrix Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePageEmpty17}
\begin{paste}{ugxMatrixCreatePageEmpty17}{ugxMatrixCreatePagePatch17}
\pastebutton{ugxMatrixCreatePageEmpty17}{\showpaste}
\tab{5}\spadcommand{a := matrix [[1/2,1/3,1/4],[1/5,1/6,1/7]]\bound{a }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePagePatch18}
\begin{paste}{ugxMatrixCreatePageFull18}{ugxMatrixCreatePageEmpty18}
\pastebutton{ugxMatrixCreatePageFull18}{\hidepaste}
\tab{5}\spadcommand{b := matrix [[3/5,3/7,3/11],[3/13,3/17,3/19]]\bound{b }}
\indentrel{3}\begin{verbatim}
         Ú3   3    3¿
         ³Ä   Ä   ÄÄ³
         ³5   7   11³
   (18)  ³          ³
         ³ 3   3   3³
         ³ÄÄ  ÄÄ  ÄÄ³
         À13  17  19Ù
                          Type: Matrix Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePageEmpty18}
\begin{paste}{ugxMatrixCreatePageEmpty18}{ugxMatrixCreatePagePatch18}
\pastebutton{ugxMatrixCreatePageEmpty18}{\showpaste}
\tab{5}\spadcommand{b := matrix [[3/5,3/7,3/11],[3/13,3/17,3/19]]\bound{b }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePagePatch19}
\begin{paste}{ugxMatrixCreatePageFull19}{ugxMatrixCreatePageEmpty19}
\pastebutton{ugxMatrixCreatePageFull19}{\hidepaste}
\tab{5}\spadcommand{horizConcat(a,b)\free{a b }}
\indentrel{3}\begin{verbatim}
         Ú1  1  1  3   3    3¿
         ³Ä  Ä  Ä  Ä   Ä   ÄÄ³
         ³2  3  4  5   7   11³
   (19)  ³                   ³
         ³1  1  1   3   3   3³
         ³Ä  Ä  Ä  ÄÄ  ÄÄ  ÄÄ³
         À5  6  7  13  17  19Ù
                          Type: Matrix Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePageEmpty19}
\begin{paste}{ugxMatrixCreatePageEmpty19}{ugxMatrixCreatePagePatch19}
\pastebutton{ugxMatrixCreatePageEmpty19}{\showpaste}
\tab{5}\spadcommand{horizConcat(a,b)\free{a b }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePagePatch20}
\begin{paste}{ugxMatrixCreatePageFull20}{ugxMatrixCreatePageEmpty20}
\pastebutton{ugxMatrixCreatePageFull20}{\hidepaste}
\tab{5}\spadcommand{vab := vertConcat(a,b)\free{a b }\bound{vab }}
\indentrel{3}\begin{verbatim}
         Ú1   1   1 ¿
         ³Ä   Ä   Ä ³
         ³2   3   4 ³
         ³          ³
         ³1   1   1 ³
         ³Ä   Ä   Ä ³
         ³5   6   7 ³
   (20)  ³          ³
         ³3   3    3³
         ³Ä   Ä   ÄÄ³
         ³5   7   11³
         ³          ³
         ³ 3   3   3³
         ³ÄÄ  ÄÄ  ÄÄ³
         À13  17  19Ù
                          Type: Matrix Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePageEmpty20}
\begin{paste}{ugxMatrixCreatePageEmpty20}{ugxMatrixCreatePagePatch20}
\pastebutton{ugxMatrixCreatePageEmpty20}{\showpaste}
\tab{5}\spadcommand{vab := vertConcat(a,b)\free{a b }\bound{vab }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePagePatch21}
\begin{paste}{ugxMatrixCreatePageFull21}{ugxMatrixCreatePageEmpty21}
\pastebutton{ugxMatrixCreatePageFull21}{\hidepaste}
\tab{5}\spadcommand{transpose vab\free{vab }}
\indentrel{3}\begin{verbatim}
         Ú1  1  3    3¿
         ³Ä  Ä  Ä   ÄÄ³
         ³2  5  5   13³
         ³            ³
         ³1  1  3    3³
   (21)  ³Ä  Ä  Ä   ÄÄ³
         ³3  6  7   17³
         ³            ³
         ³1  1   3   3³
         ³Ä  Ä  ÄÄ  ÄÄ³
         À4  7  11  19Ù
                          Type: Matrix Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixCreatePageEmpty21}
\begin{paste}{ugxMatrixCreatePageEmpty21}{ugxMatrixCreatePagePatch21}
\pastebutton{ugxMatrixCreatePageEmpty21}{\showpaste}
\tab{5}\spadcommand{transpose vab\free{vab }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxMatrixOpsPage}{matrix.ht}{Operations on Matrices}
\pageto{notitle}{ugIntroTwoDimPage}
\pageto{notitle}{ugProblemEigenPage}
\pageto{notitle}{ugxFloatHilbertPage}
\pageto{notitle}{PermanentXmpPage}
\pageto{notitle}{VectorXmpPage}
\pageto{notitle}{OneDimensionalArrayXmpPage}
\pageto{notitle}{TwoDimensionalArrayXmpPage}
\begin{chunk}{matrix.ht}
\begin{page}{ugxMatrixOpsPage}{Operations on Matrices}
\beginscroll

\labelSpace{3pc}
\xtc{
Axiom provides both left and right scalar multiplication.
}{
\spadpaste{m := matrix [[1,2],[3,4]] \bound{m}}
}
\xtc{
}{
\spadpaste{4 * m * (-5)\free{m}}
}
\xtc{
You can add, subtract, and multiply matrices provided, of course, that
the matrices have compatible dimensions.
If not, an error message is displayed.
}{
\spadpaste{n := matrix([[1,0,-2],[-3,5,1]]) \bound{n}}
}
\xtc{
This following product is defined but \spad{n * m} is not.
}{
\spadpaste{m * n \free{m n}}
}

The operations \spadfunFrom{nrows}{Matrix} and \spadfunFrom{ncols}{Matrix}
return the number of rows and columns of a matrix.
You can extract a row or a column of a matrix using the operations
\spadfunFrom{row}{Matrix} and \spadfunFrom{column}{Matrix}.
The object returned is a \spadtype{Vector}.
\xtc{
Here is the third column of the matrix \spad{n}.
}{
\spadpaste{vec := column(n,3) \free{n} \bound{vec}}
}
\xtc{
You can multiply a matrix on the left by a ``row vector'' and on the right
by a ``column vector.''
}{
\spadpaste{vec * m \free{vec m}}
}
\xtc{
Of course, the dimensions of the vector and the matrix must be compatible
or an error message is returned.
}{
\spadpaste{m * vec \free{vec m}}
}

The operation \spadfunFrom{inverse}{Matrix} computes the inverse of a
matrix if
{Operations on Matrices}
the matrix is invertible, and returns \spad{"failed"} if not.
\xtc{
This Hilbert matrix is invertible.
}{
\spadpaste{hilb := matrix([[1/(i + j) for i in 1..3] for j in 1..3]) 
\bound{hilb}}
}
\xtc{
}{
\spadpaste{inverse(hilb) \free{hilb}}
}
\xtc{
This matrix is not invertible.
}{
\spadpaste{mm := matrix([[1,2,3,4], [5,6,7,8], [9,10,11,12], 
[13,14,15,16]]) \bound{mm}}
}
\xtc{
}{
\spadpaste{inverse(mm) \free{mm}}
}

The operation 
\spadfunFrom{determinant}{Matrix} computes the determinant of a matrix
{Operations on Matrices}
provided that the entries of the matrix belong to a 
\spadtype{CommutativeRing}.
\xtc{
The above matrix \spad{mm} is not invertible and, hence, must have
determinant \spad{0}.
}{
\spadpaste{determinant(mm) \free{mm}}
}
\xtc{
The operation
\spadfunFrom{trace}{SquareMatrix} computes the trace of a {\em square} 
matrix.
{Operations on Matrices}
}{
\spadpaste{trace(mm) \free{mm}}
}

\xtc{
The operation \spadfunFrom{rank}{Matrix} computes the {\it rank} of a
matrix:
the maximal number of linearly independent rows or columns.
}{
\spadpaste{rank(mm) \free{mm}}
}
\xtc{
The operation \spadfunFrom{nullity}{Matrix} computes the {\it nullity} of
a matrix: the dimension of its null space.
}{
\spadpaste{nullity(mm) \free{mm}}
}
\xtc{
The operation \spadfunFrom{nullSpace}{Matrix} returns a list containing 
a basis for the null space of a matrix.
Note that the nullity is the number of elements in a basis for the null 
space.
}{
\spadpaste{nullSpace(mm) \free{mm}}
}
\xtc{
The operation 
\spadfunFrom{rowEchelon}{Matrix} returns the row echelon form of a
{Operations on Matrices}
matrix.
It is easy to see that the rank of this matrix is two and that its nullity
is also two.
}{
\spadpaste{rowEchelon(mm) \free{mm}}
}

For more information on related topics, see
\downlink{``Expanding to Higher Dimensions''}{ugIntroTwoDimPage} in 
Section 1.7\ignore{ugIntroTwoDim},
\downlink{``Computation of Eigenvalues and Eigenvectors''}
{ugProblemEigenPage} in Section 8.4\ignore{ugProblemEigen},
\downlink{``Determinant of a Hilbert Matrix''}
{ugxFloatHilbertPage}\ignore{ugxFloatHilbert},
\downlink{`Permanent'}{PermanentXmpPage}\ignore{Permanent},
\downlink{`Vector'}{VectorXmpPage}\ignore{Vector},
\downlink{`OneDimensionalArray'}{OneDimensionalArrayXmpPage}
\ignore{OneDimensionalArray}, and
\downlink{`TwoDimensionalArray'}{TwoDimensionalArrayXmpPage}
\ignore{TwoDimensionalArray}.
%
\showBlurb{Matrix}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxMatrixOpsPagePatch1}
\begin{paste}{ugxMatrixOpsPageFull1}{ugxMatrixOpsPageEmpty1}
\pastebutton{ugxMatrixOpsPageFull1}{\hidepaste}
\tab{5}\spadcommand{m := matrix [[1,2],[3,4]]\bound{m }}
\indentrel{3}\begin{verbatim}
        Ú1  2¿
   (1)  ³    ³
        À3  4Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPageEmpty1}
\begin{paste}{ugxMatrixOpsPageEmpty1}{ugxMatrixOpsPagePatch1}
\pastebutton{ugxMatrixOpsPageEmpty1}{\showpaste}
\tab{5}\spadcommand{m := matrix [[1,2],[3,4]]\bound{m }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPagePatch2}
\begin{paste}{ugxMatrixOpsPageFull2}{ugxMatrixOpsPageEmpty2}
\pastebutton{ugxMatrixOpsPageFull2}{\hidepaste}
\tab{5}\spadcommand{4 * m * (-5)\free{m }}
\indentrel{3}\begin{verbatim}
        Ú- 20  - 40¿
   (2)  ³          ³
        À- 60  - 80Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPageEmpty2}
\begin{paste}{ugxMatrixOpsPageEmpty2}{ugxMatrixOpsPagePatch2}
\pastebutton{ugxMatrixOpsPageEmpty2}{\showpaste}
\tab{5}\spadcommand{4 * m * (-5)\free{m }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPagePatch3}
\begin{paste}{ugxMatrixOpsPageFull3}{ugxMatrixOpsPageEmpty3}
\pastebutton{ugxMatrixOpsPageFull3}{\hidepaste}
\tab{5}\spadcommand{n := matrix([[1,0,-2],[-3,5,1]])\bound{n }}
\indentrel{3}\begin{verbatim}
        Ú 1   0  - 2¿
   (3)  ³           ³
        À- 3  5   1 Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPageEmpty3}
\begin{paste}{ugxMatrixOpsPageEmpty3}{ugxMatrixOpsPagePatch3}
\pastebutton{ugxMatrixOpsPageEmpty3}{\showpaste}
\tab{5}\spadcommand{n := matrix([[1,0,-2],[-3,5,1]])\bound{n }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPagePatch4}
\begin{paste}{ugxMatrixOpsPageFull4}{ugxMatrixOpsPageEmpty4}
\pastebutton{ugxMatrixOpsPageFull4}{\hidepaste}
\tab{5}\spadcommand{m * n\free{m n }}
\indentrel{3}\begin{verbatim}
        Ú- 5  10   0 ¿
   (4)  ³            ³
        À- 9  20  - 2Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPageEmpty4}
\begin{paste}{ugxMatrixOpsPageEmpty4}{ugxMatrixOpsPagePatch4}
\pastebutton{ugxMatrixOpsPageEmpty4}{\showpaste}
\tab{5}\spadcommand{m * n\free{m n }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPagePatch5}
\begin{paste}{ugxMatrixOpsPageFull5}{ugxMatrixOpsPageEmpty5}
\pastebutton{ugxMatrixOpsPageFull5}{\hidepaste}
\tab{5}\spadcommand{vec := column(n,3)\free{n }\bound{vec }}
\indentrel{3}\begin{verbatim}
   (5)  [- 2,1]
                                   Type: Vector Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPageEmpty5}
\begin{paste}{ugxMatrixOpsPageEmpty5}{ugxMatrixOpsPagePatch5}
\pastebutton{ugxMatrixOpsPageEmpty5}{\showpaste}
\tab{5}\spadcommand{vec := column(n,3)\free{n }\bound{vec }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPagePatch6}
\begin{paste}{ugxMatrixOpsPageFull6}{ugxMatrixOpsPageEmpty6}
\pastebutton{ugxMatrixOpsPageFull6}{\hidepaste}
\tab{5}\spadcommand{vec * m\free{vec m }}
\indentrel{3}\begin{verbatim}
   (6)  [1,0]
                                   Type: Vector Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPageEmpty6}
\begin{paste}{ugxMatrixOpsPageEmpty6}{ugxMatrixOpsPagePatch6}
\pastebutton{ugxMatrixOpsPageEmpty6}{\showpaste}
\tab{5}\spadcommand{vec * m\free{vec m }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPagePatch7}
\begin{paste}{ugxMatrixOpsPageFull7}{ugxMatrixOpsPageEmpty7}
\pastebutton{ugxMatrixOpsPageFull7}{\hidepaste}
\tab{5}\spadcommand{m * vec\free{vec m }}
\indentrel{3}\begin{verbatim}
   (7)  [0,- 2]
                                   Type: Vector Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPageEmpty7}
\begin{paste}{ugxMatrixOpsPageEmpty7}{ugxMatrixOpsPagePatch7}
\pastebutton{ugxMatrixOpsPageEmpty7}{\showpaste}
\tab{5}\spadcommand{m * vec\free{vec m }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPagePatch8}
\begin{paste}{ugxMatrixOpsPageFull8}{ugxMatrixOpsPageEmpty8}
\pastebutton{ugxMatrixOpsPageFull8}{\hidepaste}
\tab{5}\spadcommand{hilb := matrix([[1/(i + j) for i in 1..3] for j in 1..3])\bound{hilb }}
\indentrel{3}\begin{verbatim}
        Ú1  1  1¿
        ³Ä  Ä  Ä³
        ³2  3  4³
        ³       ³
        ³1  1  1³
   (8)  ³Ä  Ä  Ä³
        ³3  4  5³
        ³       ³
        ³1  1  1³
        ³Ä  Ä  Ä³
        À4  5  6Ù
                          Type: Matrix Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPageEmpty8}
\begin{paste}{ugxMatrixOpsPageEmpty8}{ugxMatrixOpsPagePatch8}
\pastebutton{ugxMatrixOpsPageEmpty8}{\showpaste}
\tab{5}\spadcommand{hilb := matrix([[1/(i + j) for i in 1..3] for j in 1..3])\bound{hilb }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPagePatch9}
\begin{paste}{ugxMatrixOpsPageFull9}{ugxMatrixOpsPageEmpty9}
\pastebutton{ugxMatrixOpsPageFull9}{\hidepaste}
\tab{5}\spadcommand{inverse(hilb)\free{hilb }}
\indentrel{3}\begin{verbatim}
        Ú 72    - 240   180 ¿
        ³                   ³
   (9)  ³- 240   900   - 720³
        ³                   ³
        À 180   - 720   600 Ù
               Type: Union(Matrix Fraction Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPageEmpty9}
\begin{paste}{ugxMatrixOpsPageEmpty9}{ugxMatrixOpsPagePatch9}
\pastebutton{ugxMatrixOpsPageEmpty9}{\showpaste}
\tab{5}\spadcommand{inverse(hilb)\free{hilb }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPagePatch10}
\begin{paste}{ugxMatrixOpsPageFull10}{ugxMatrixOpsPageEmpty10}
\pastebutton{ugxMatrixOpsPageFull10}{\hidepaste}
\tab{5}\spadcommand{mm := matrix([[1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14,15,16]])\bound{mm }}
\indentrel{3}\begin{verbatim}
         Ú1   2   3   4 ¿
         ³              ³
         ³5   6   7   8 ³
   (10)  ³              ³
         ³9   10  11  12³
         ³              ³
         À13  14  15  16Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPageEmpty10}
\begin{paste}{ugxMatrixOpsPageEmpty10}{ugxMatrixOpsPagePatch10}
\pastebutton{ugxMatrixOpsPageEmpty10}{\showpaste}
\tab{5}\spadcommand{mm := matrix([[1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14,15,16]])\bound{mm }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPagePatch11}
\begin{paste}{ugxMatrixOpsPageFull11}{ugxMatrixOpsPageEmpty11}
\pastebutton{ugxMatrixOpsPageFull11}{\hidepaste}
\tab{5}\spadcommand{inverse(mm)\free{mm }}
\indentrel{3}\begin{verbatim}
   (11)  "failed"
                              Type: Union("failed",...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPageEmpty11}
\begin{paste}{ugxMatrixOpsPageEmpty11}{ugxMatrixOpsPagePatch11}
\pastebutton{ugxMatrixOpsPageEmpty11}{\showpaste}
\tab{5}\spadcommand{inverse(mm)\free{mm }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPagePatch12}
\begin{paste}{ugxMatrixOpsPageFull12}{ugxMatrixOpsPageEmpty12}
\pastebutton{ugxMatrixOpsPageFull12}{\hidepaste}
\tab{5}\spadcommand{determinant(mm)\free{mm }}
\indentrel{3}\begin{verbatim}
   (12)  0
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPageEmpty12}
\begin{paste}{ugxMatrixOpsPageEmpty12}{ugxMatrixOpsPagePatch12}
\pastebutton{ugxMatrixOpsPageEmpty12}{\showpaste}
\tab{5}\spadcommand{determinant(mm)\free{mm }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPagePatch13}
\begin{paste}{ugxMatrixOpsPageFull13}{ugxMatrixOpsPageEmpty13}
\pastebutton{ugxMatrixOpsPageFull13}{\hidepaste}
\tab{5}\spadcommand{trace(mm)\free{mm }}
\indentrel{3}\begin{verbatim}
   (13)  34
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPageEmpty13}
\begin{paste}{ugxMatrixOpsPageEmpty13}{ugxMatrixOpsPagePatch13}
\pastebutton{ugxMatrixOpsPageEmpty13}{\showpaste}
\tab{5}\spadcommand{trace(mm)\free{mm }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPagePatch14}
\begin{paste}{ugxMatrixOpsPageFull14}{ugxMatrixOpsPageEmpty14}
\pastebutton{ugxMatrixOpsPageFull14}{\hidepaste}
\tab{5}\spadcommand{rank(mm)\free{mm }}
\indentrel{3}\begin{verbatim}
   (14)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPageEmpty14}
\begin{paste}{ugxMatrixOpsPageEmpty14}{ugxMatrixOpsPagePatch14}
\pastebutton{ugxMatrixOpsPageEmpty14}{\showpaste}
\tab{5}\spadcommand{rank(mm)\free{mm }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPagePatch15}
\begin{paste}{ugxMatrixOpsPageFull15}{ugxMatrixOpsPageEmpty15}
\pastebutton{ugxMatrixOpsPageFull15}{\hidepaste}
\tab{5}\spadcommand{nullity(mm)\free{mm }}
\indentrel{3}\begin{verbatim}
   (15)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPageEmpty15}
\begin{paste}{ugxMatrixOpsPageEmpty15}{ugxMatrixOpsPagePatch15}
\pastebutton{ugxMatrixOpsPageEmpty15}{\showpaste}
\tab{5}\spadcommand{nullity(mm)\free{mm }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPagePatch16}
\begin{paste}{ugxMatrixOpsPageFull16}{ugxMatrixOpsPageEmpty16}
\pastebutton{ugxMatrixOpsPageFull16}{\hidepaste}
\tab{5}\spadcommand{nullSpace(mm)\free{mm }}
\indentrel{3}\begin{verbatim}
   (16)  [[1,- 2,1,0],[2,- 3,0,1]]
                              Type: List Vector Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPageEmpty16}
\begin{paste}{ugxMatrixOpsPageEmpty16}{ugxMatrixOpsPagePatch16}
\pastebutton{ugxMatrixOpsPageEmpty16}{\showpaste}
\tab{5}\spadcommand{nullSpace(mm)\free{mm }}
\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPagePatch17}
\begin{paste}{ugxMatrixOpsPageFull17}{ugxMatrixOpsPageEmpty17}
\pastebutton{ugxMatrixOpsPageFull17}{\hidepaste}
\tab{5}\spadcommand{rowEchelon(mm)\free{mm }}
\indentrel{3}\begin{verbatim}
         Ú1  2  3  4 ¿
         ³           ³
         ³0  4  8  12³
   (17)  ³           ³
         ³0  0  0  0 ³
         ³           ³
         À0  0  0  0 Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxMatrixOpsPageEmpty17}
\begin{paste}{ugxMatrixOpsPageEmpty17}{ugxMatrixOpsPagePatch17}
\pastebutton{ugxMatrixOpsPageEmpty17}{\showpaste}
\tab{5}\spadcommand{rowEchelon(mm)\free{mm }}
\end{paste}\end{patch}

\end{chunk}
\section{mkfunc.ht}
\pagetitle{MakeFunctionXmpPage}{mkfunc.ht}{MakeFunction}
\pageto{notitle}{ugUserMakePage}
\begin{chunk}{mkfunc.ht}
\begin{page}{MakeFunctionXmpPage}{MakeFunction}
\beginscroll
It is sometimes useful to be able to define a function given by
the result of a calculation.
%
\xtc{
Suppose that you have obtained the following expression
after several computations
and that you now want to tabulate the numerical values of \spad{f}
for \spad{x} between \spad{-1} and \spad{+1} with increment
\spad{0.1}.
}{
\spadpaste{expr := (x - exp x + 1)**2 * (sin(x**2) * x + 1)**3 
\bound{expr}}
}
%
You could, of course, use the function
\spadfunFrom{eval}{Expression} within a loop and evaluate
\spad{expr} twenty-one times, but this would be quite slow.
A better way is to create a numerical function \spad{f} such that
\spad{f(x)} is defined by the expression \spad{expr} above,
but without retyping \spad{expr}!
The package \spadtype{MakeFunction} provides the operation
\spadfunFrom{function}{MakeFunction} which does exactly this.
%
\xtc{
Issue this to create the function \spad{f(x)} given by \spad{expr}.
}{
\spadpaste{function(expr, f, x) \bound{f}\free{expr}}
}
\xtc{
To tabulate \spad{expr}, we can now quickly evaluate \spad{f} 21 times.
}{
\spadpaste{tbl := [f(0.1 * i - 1) for i in 0..20]; \free{f}\bound{tbl}}
}
%
%
\xtc{
Use the list \spad{[x1,...,xn]} as the
third argument to \spadfunFrom{function}{MakeFunction}
to create a multivariate function \spad{f(x1,...,xn)}.
}{
\spadpaste{e := (x - y + 1)**2 * (x**2 * y + 1)**2 \bound{e}}
}
\xtc{
}{
\spadpaste{function(e, g, [x, y]) \free{e}}
}
%
%
\xtc{
In the case of just two
variables, they can be given as arguments without making them into a list.
}{
\spadpaste{function(e, h, x, y) \free{e}\bound{h}}
}
%
%
\xtc{
Note that the functions created by \spadfunFrom{function}{MakeFunction}
are not limited to floating point numbers, but can be applied to any type
for which they are defined.
}{
\spadpaste{m1 := squareMatrix [[1, 2], [3, 4]] \bound{m1}}
}
\xtc{
}{
\spadpaste{m2 := squareMatrix [[1, 0], [-1, 1]] \bound{m2}}
}
\xtc{
}{
\spadpaste{h(m1, m2) \free{h m1 m2}}
}
%
For more information, see 
\downlink{``Making Functions from Objects''}{ugUserMakePage} 
in Section 6.14\ignore{ugUserMake}.
\showBlurb{MakeFunction}
\endscroll
\autobuttons
\end{page}

\begin{patch}{MakeFunctionXmpPagePatch1}
\begin{paste}{MakeFunctionXmpPageFull1}{MakeFunctionXmpPageEmpty1}
\pastebutton{MakeFunctionXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{expr := (x - exp x + 1)**2 * (sin(x**2) * x + 1)**3\bound{expr }}
\indentrel{3}\begin{verbatim}
   (1)
       3   x 2        4     3   x    5     4    3      2 3
     (x (%e )  + (- 2x  - 2x )%e  + x  + 2x  + x )sin(x )
   + 
          2   x 2        3     2   x     4     3     2
       (3x (%e )  + (- 6x  - 6x )%e  + 3x  + 6x  + 3x )
    *
            2 2
       sin(x )
   + 
            x 2        2        x     3     2           2
     (3x (%e )  + (- 6x  - 6x)%e  + 3x  + 6x  + 3x)sin(x )
   + 
        x 2               x    2
     (%e )  + (- 2x - 2)%e  + x  + 2x + 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MakeFunctionXmpPageEmpty1}
\begin{paste}{MakeFunctionXmpPageEmpty1}{MakeFunctionXmpPagePatch1}
\pastebutton{MakeFunctionXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{expr := (x - exp x + 1)**2 * (sin(x**2) * x + 1)**3\bound{expr }}
\end{paste}\end{patch}

\begin{patch}{MakeFunctionXmpPagePatch2}
\begin{paste}{MakeFunctionXmpPageFull2}{MakeFunctionXmpPageEmpty2}
\pastebutton{MakeFunctionXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{function(expr, f, x)\bound{f }\free{expr }}
\indentrel{3}\begin{verbatim}
   (2)  f
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MakeFunctionXmpPageEmpty2}
\begin{paste}{MakeFunctionXmpPageEmpty2}{MakeFunctionXmpPagePatch2}
\pastebutton{MakeFunctionXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{function(expr, f, x)\bound{f }\free{expr }}
\end{paste}\end{patch}

\begin{patch}{MakeFunctionXmpPagePatch3}
\begin{paste}{MakeFunctionXmpPageFull3}{MakeFunctionXmpPageEmpty3}
\pastebutton{MakeFunctionXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{tbl := [f(0.1 * i - 1) for i in 0..20];\free{f }\bound{tbl }}
\indentrel{3}\begin{verbatim}
                                       Type: List Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MakeFunctionXmpPageEmpty3}
\begin{paste}{MakeFunctionXmpPageEmpty3}{MakeFunctionXmpPagePatch3}
\pastebutton{MakeFunctionXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{tbl := [f(0.1 * i - 1) for i in 0..20];\free{f }\bound{tbl }}
\end{paste}\end{patch}

\begin{patch}{MakeFunctionXmpPagePatch4}
\begin{paste}{MakeFunctionXmpPageFull4}{MakeFunctionXmpPageEmpty4}
\pastebutton{MakeFunctionXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{e := (x - y + 1)**2 * (x**2 * y + 1)**2\bound{e }}
\indentrel{3}\begin{verbatim}
   (4)
      4 4        5     4     2  3
     x y  + (- 2x  - 2x  + 2x )y
   + 
       6     5    4     3     2      2
     (x  + 2x  + x  - 4x  - 4x  + 1)y
   + 
        4     3     2               2
     (2x  + 4x  + 2x  - 2x - 2)y + x  + 2x + 1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MakeFunctionXmpPageEmpty4}
\begin{paste}{MakeFunctionXmpPageEmpty4}{MakeFunctionXmpPagePatch4}
\pastebutton{MakeFunctionXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{e := (x - y + 1)**2 * (x**2 * y + 1)**2\bound{e }}
\end{paste}\end{patch}

\begin{patch}{MakeFunctionXmpPagePatch5}
\begin{paste}{MakeFunctionXmpPageFull5}{MakeFunctionXmpPageEmpty5}
\pastebutton{MakeFunctionXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{function(e, g, [x, y])\free{e }}
\indentrel{3}\begin{verbatim}
   (5)  g
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MakeFunctionXmpPageEmpty5}
\begin{paste}{MakeFunctionXmpPageEmpty5}{MakeFunctionXmpPagePatch5}
\pastebutton{MakeFunctionXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{function(e, g, [x, y])\free{e }}
\end{paste}\end{patch}

\begin{patch}{MakeFunctionXmpPagePatch6}
\begin{paste}{MakeFunctionXmpPageFull6}{MakeFunctionXmpPageEmpty6}
\pastebutton{MakeFunctionXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{function(e, h, x, y)\free{e }\bound{h }}
\indentrel{3}\begin{verbatim}
   (6)  h
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MakeFunctionXmpPageEmpty6}
\begin{paste}{MakeFunctionXmpPageEmpty6}{MakeFunctionXmpPagePatch6}
\pastebutton{MakeFunctionXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{function(e, h, x, y)\free{e }\bound{h }}
\end{paste}\end{patch}

\begin{patch}{MakeFunctionXmpPagePatch7}
\begin{paste}{MakeFunctionXmpPageFull7}{MakeFunctionXmpPageEmpty7}
\pastebutton{MakeFunctionXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{m1 := squareMatrix [[1, 2], [3, 4]]\bound{m1 }}
\indentrel{3}\begin{verbatim}
        Ú1  2¿
   (7)  ³    ³
        À3  4Ù
                          Type: SquareMatrix(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MakeFunctionXmpPageEmpty7}
\begin{paste}{MakeFunctionXmpPageEmpty7}{MakeFunctionXmpPagePatch7}
\pastebutton{MakeFunctionXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{m1 := squareMatrix [[1, 2], [3, 4]]\bound{m1 }}
\end{paste}\end{patch}

\begin{patch}{MakeFunctionXmpPagePatch8}
\begin{paste}{MakeFunctionXmpPageFull8}{MakeFunctionXmpPageEmpty8}
\pastebutton{MakeFunctionXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{m2 := squareMatrix [[1, 0], [-1, 1]]\bound{m2 }}
\indentrel{3}\begin{verbatim}
        Ú 1   0¿
   (8)  ³      ³
        À- 1  1Ù
                          Type: SquareMatrix(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MakeFunctionXmpPageEmpty8}
\begin{paste}{MakeFunctionXmpPageEmpty8}{MakeFunctionXmpPagePatch8}
\pastebutton{MakeFunctionXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{m2 := squareMatrix [[1, 0], [-1, 1]]\bound{m2 }}
\end{paste}\end{patch}

\begin{patch}{MakeFunctionXmpPagePatch9}
\begin{paste}{MakeFunctionXmpPageFull9}{MakeFunctionXmpPageEmpty9}
\pastebutton{MakeFunctionXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{h(m1, m2)\free{h m1 m2 }}
\indentrel{3}\begin{verbatim}
        Ú- 7836   8960 ¿
   (9)  ³              ³
        À- 17132  19588Ù
                          Type: SquareMatrix(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MakeFunctionXmpPageEmpty9}
\begin{paste}{MakeFunctionXmpPageEmpty9}{MakeFunctionXmpPagePatch9}
\pastebutton{MakeFunctionXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{h(m1, m2)\free{h m1 m2 }}
\end{paste}\end{patch}

\end{chunk}
\section{mpoly.ht}
\pagetitle{MultivariatePolyXmpPage}{mpoly.ht}
{MultivariatePolynomial}
\pageto{notitle}{PolynomialXmpPage}
\pageto{notitle}{UnivariatePolyXmpPage}
\pageto{notitle}{DistributedMultivariatePolyXmpPage}
\begin{chunk}{mpoly.ht}
\begin{page}{MultivariatePolyXmpPage}{MultivariatePolynomial}
\beginscroll

The domain constructor \spadtype{MultivariatePolynomial} is similar to
\spadtype{Polynomial} except that it specifies the variables to be used.
\spadtype{Polynomial} are available for \spadtype{MultivariatePolynomial}.
The abbreviation for \spadtype{MultivariatePolynomial} is
\spadtype{MPOLY}.
The type expressions
\centerline{{\spadtype{MultivariatePolynomial([x,y],Integer)}}}
and
\centerline{{\spadtype{MPOLY([x,y],INT)}}}
refer to the domain of multivariate polynomials in the variables
\spad{x} and \spad{y} where the coefficients are restricted to be integers.
The first
variable specified is the main variable and the display of the
polynomial reflects this.
\xtc{
This polynomial appears with
terms in descending powers of the variable \spad{x}.
}{
\spadpaste{m : MPOLY([x,y],INT) := (x**2 - x*y**3 +3*y)**2 \bound{m}}
}
\xtc{
It is easy to see a different variable ordering by doing a conversion.
}{
\spadpaste{m :: MPOLY([y,x],INT) \free{m}}
}
\xtc{
You can use other, unspecified variables, by using
\spadtype{Polynomial} in the coefficient type of \spadtype{MPOLY}.
}{
\spadpaste{p : MPOLY([x,y],POLY INT) \bound{pdec}}
}
\xtc{
}{
\spadpaste{p := (a**2*x - b*y**2 + 1)**2 \free{pdec}\bound{p}}
}
\xtc{
Conversions can be used to re-express such polynomials in terms of
the other variables.  For example, you can first push all the
variables into a polynomial with integer coefficients.
}{
\spadpaste{p :: POLY INT \free{p}\bound{prev}}
}
\xtc{
Now pull out the variables of interest.
}{
\spadpaste{\% :: MPOLY([a,b],POLY INT) \free{prev}}
}

\beginImportant
\noindent {\bf Restriction:}
\texht{\begin{quotation}\noindent}{\newline\indent{5}}
Axiom does not allow you to create types where
\spadtype{MultivariatePolynomial} is contained in the coefficient type of
\spadtype{Polynomial}. Therefore,
\spad{MPOLY([x,y],POLY INT)} is legal but
\spad{POLY MPOLY([x,y],INT)} is not.
\texht{\end{quotation}}{\indent{0}}
\endImportant

\xtc{
Multivariate polynomials may be combined with univariate polynomials
to create types with special structures.
}{
\spadpaste{q : UP(x, FRAC MPOLY([y,z],INT)) \bound{qdec}}
}
\xtc{
This is a polynomial in \spad{x} whose coefficients are
quotients of polynomials in \spad{y} and \spad{z}.
}{
\spadpaste{q := (x**2 - x*(z+1)/y +2)**2 \free{qdec}\bound{q}}
}
\xtc{
Use conversions for structural rearrangements.
\spad{z} does not appear in a denominator and so it can be made
the main variable.
}{
\spadpaste{q :: UP(z, FRAC MPOLY([x,y],INT)) \free{q}}
}
\xtc{
Or you can make a multivariate polynomial in \spad{x} and \spad{z}
whose coefficients are fractions in polynomials in \spad{y}.
}{
\spadpaste{q :: MPOLY([x,z], FRAC UP(y,INT)) \free{q}}
}
A conversion like \spad{q :: MPOLY([x,y], FRAC UP(z,INT))} is not
possible in this example
because \spad{y} appears in the denominator of a fraction.
As you can see, Axiom provides extraordinary flexibility in the
manipulation and display of expressions via its conversion facility.

For more information on related topics, see
\downlink{`Polynomial'}{PolynomialXmpPage}\ignore{Polynomial},
\downlink{`UnivariatePolynomial'}{UnivariatePolyXmpPage}
\ignore{UnivariatePolynomial}, and
\downlink{`DistributedMultivariatePoly'}
{DistributedMultivariatePolyXmpPage}
\ignore{DistributedMultivariatePoly}.
\showBlurb{MultivariatePolynomial}
\endscroll
\autobuttons
\end{page}

\begin{patch}{MultivariatePolyXmpPagePatch1}
\begin{paste}{MultivariatePolyXmpPageFull1}{MultivariatePolyXmpPageEmpty1}
\pastebutton{MultivariatePolyXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{m : MPOLY([x,y],INT) := (x**2 - x*y**3 +3*y)**2\bound{m }}
\indentrel{3}\begin{verbatim}
         4     3 3     6       2     4      2
   (1)  x  - 2y x  + (y  + 6y)x  - 6y x + 9y
            Type: MultivariatePolynomial([x,y],Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MultivariatePolyXmpPageEmpty1}
\begin{paste}{MultivariatePolyXmpPageEmpty1}{MultivariatePolyXmpPagePatch1}
\pastebutton{MultivariatePolyXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{m : MPOLY([x,y],INT) := (x**2 - x*y**3 +3*y)**2\bound{m }}
\end{paste}\end{patch}

\begin{patch}{MultivariatePolyXmpPagePatch2}
\begin{paste}{MultivariatePolyXmpPageFull2}{MultivariatePolyXmpPageEmpty2}
\pastebutton{MultivariatePolyXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{m :: MPOLY([y,x],INT)\free{m }}
\indentrel{3}\begin{verbatim}
         2 6       4     3 3     2     2     4
   (2)  x y  - 6x y  - 2x y  + 9y  + 6x y + x
            Type: MultivariatePolynomial([y,x],Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MultivariatePolyXmpPageEmpty2}
\begin{paste}{MultivariatePolyXmpPageEmpty2}{MultivariatePolyXmpPagePatch2}
\pastebutton{MultivariatePolyXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{m :: MPOLY([y,x],INT)\free{m }}
\end{paste}\end{patch}

\begin{patch}{MultivariatePolyXmpPagePatch3}
\begin{paste}{MultivariatePolyXmpPageFull3}{MultivariatePolyXmpPageEmpty3}
\pastebutton{MultivariatePolyXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{p : MPOLY([x,y],POLY INT)\bound{pdec }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MultivariatePolyXmpPageEmpty3}
\begin{paste}{MultivariatePolyXmpPageEmpty3}{MultivariatePolyXmpPagePatch3}
\pastebutton{MultivariatePolyXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{p : MPOLY([x,y],POLY INT)\bound{pdec }}
\end{paste}\end{patch}

\begin{patch}{MultivariatePolyXmpPagePatch4}
\begin{paste}{MultivariatePolyXmpPageFull4}{MultivariatePolyXmpPageEmpty4}
\pastebutton{MultivariatePolyXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{p := (a**2*x - b*y**2 + 1)**2\free{pdec }\bound{p }}
\indentrel{3}\begin{verbatim}
         4 2        2   2     2      2 4       2
   (4)  a x  + (- 2a b y  + 2a )x + b y  - 2b y  + 1
 Type: MultivariatePolynomial([x,y],Polynomial Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MultivariatePolyXmpPageEmpty4}
\begin{paste}{MultivariatePolyXmpPageEmpty4}{MultivariatePolyXmpPagePatch4}
\pastebutton{MultivariatePolyXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{p := (a**2*x - b*y**2 + 1)**2\free{pdec }\bound{p }}
\end{paste}\end{patch}

\begin{patch}{MultivariatePolyXmpPagePatch5}
\begin{paste}{MultivariatePolyXmpPageFull5}{MultivariatePolyXmpPageEmpty5}
\pastebutton{MultivariatePolyXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{p :: POLY INT\free{p }\bound{prev }}
\indentrel{3}\begin{verbatim}
         2 4        2          2    4 2     2
   (5)  b y  + (- 2a b x - 2b)y  + a x  + 2a x + 1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MultivariatePolyXmpPageEmpty5}
\begin{paste}{MultivariatePolyXmpPageEmpty5}{MultivariatePolyXmpPagePatch5}
\pastebutton{MultivariatePolyXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{p :: POLY INT\free{p }\bound{prev }}
\end{paste}\end{patch}

\begin{patch}{MultivariatePolyXmpPagePatch6}
\begin{paste}{MultivariatePolyXmpPageFull6}{MultivariatePolyXmpPageEmpty6}
\pastebutton{MultivariatePolyXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{\% :: MPOLY([a,b],POLY INT)\free{prev }}
\indentrel{3}\begin{verbatim}
         2 4          2        2    4 2     2
   (6)  x a  + (- 2x y b + 2x)a  + y b  - 2y b + 1
 Type: MultivariatePolynomial([a,b],Polynomial Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MultivariatePolyXmpPageEmpty6}
\begin{paste}{MultivariatePolyXmpPageEmpty6}{MultivariatePolyXmpPagePatch6}
\pastebutton{MultivariatePolyXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{\% :: MPOLY([a,b],POLY INT)\free{prev }}
\end{paste}\end{patch}

\begin{patch}{MultivariatePolyXmpPagePatch7}
\begin{paste}{MultivariatePolyXmpPageFull7}{MultivariatePolyXmpPageEmpty7}
\pastebutton{MultivariatePolyXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{q : UP(x, FRAC MPOLY([y,z],INT))\bound{qdec }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MultivariatePolyXmpPageEmpty7}
\begin{paste}{MultivariatePolyXmpPageEmpty7}{MultivariatePolyXmpPagePatch7}
\pastebutton{MultivariatePolyXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{q : UP(x, FRAC MPOLY([y,z],INT))\bound{qdec }}
\end{paste}\end{patch}

\begin{patch}{MultivariatePolyXmpPagePatch8}
\begin{paste}{MultivariatePolyXmpPageFull8}{MultivariatePolyXmpPageEmpty8}
\pastebutton{MultivariatePolyXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{q := (x**2 - x*(z+1)/y +2)**2\free{qdec }\bound{q }}
\indentrel{3}\begin{verbatim}
   (8)
                          2    2
      4   - 2z - 2  3   4y  + z  + 2z + 1  2   - 4z - 4
     x  + ÄÄÄÄÄÄÄÄ x  + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ x  + ÄÄÄÄÄÄÄÄ x
              y                  2                 y
                                y
   + 
     4
Type: UnivariatePolynomial(x,Fraction MultivariatePolynomial([y,z],Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MultivariatePolyXmpPageEmpty8}
\begin{paste}{MultivariatePolyXmpPageEmpty8}{MultivariatePolyXmpPagePatch8}
\pastebutton{MultivariatePolyXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{q := (x**2 - x*(z+1)/y +2)**2\free{qdec }\bound{q }}
\end{paste}\end{patch}

\begin{patch}{MultivariatePolyXmpPagePatch9}
\begin{paste}{MultivariatePolyXmpPageFull9}{MultivariatePolyXmpPageEmpty9}
\pastebutton{MultivariatePolyXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{q :: UP(z, FRAC MPOLY([x,y],INT))\free{q }}
\indentrel{3}\begin{verbatim}
   (9)
      2            3     2
     x   2   - 2y x  + 2x  - 4y x
     ÄÄ z  + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ z
      2                2
     y                y
   + 
      2 4       3      2      2            2
     y x  - 2y x  + (4y  + 1)x  - 4y x + 4y
     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                         2
                        y
Type: UnivariatePolynomial(z,Fraction MultivariatePolynomial([x,y],Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MultivariatePolyXmpPageEmpty9}
\begin{paste}{MultivariatePolyXmpPageEmpty9}{MultivariatePolyXmpPagePatch9}
\pastebutton{MultivariatePolyXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{q :: UP(z, FRAC MPOLY([x,y],INT))\free{q }}
\end{paste}\end{patch}

\begin{patch}{MultivariatePolyXmpPagePatch10}
\begin{paste}{MultivariatePolyXmpPageFull10}{MultivariatePolyXmpPageEmpty10}
\pastebutton{MultivariatePolyXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{q :: MPOLY([x,z], FRAC UP(y,INT))\free{q }}
\indentrel{3}\begin{verbatim}
   (10)
                                            2
      4      2     2  3     1  2    2     4y  + 1  2
     x  + (- Ä z - Ä)x  + (ÄÄ z  + ÄÄ z + ÄÄÄÄÄÄÄ)x
             y     y        2       2         2
                           y       y         y
   + 
        4     4
     (- Ä z - Ä)x + 4
        y     y
Type: MultivariatePolynomial([x,z],Fraction UnivariatePolynomial(y,Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{MultivariatePolyXmpPageEmpty10}
\begin{paste}{MultivariatePolyXmpPageEmpty10}{MultivariatePolyXmpPagePatch10}
\pastebutton{MultivariatePolyXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{q :: MPOLY([x,z], FRAC UP(y,INT))\free{q }}
\end{paste}\end{patch}

\end{chunk}
\section{newuser.ht}
\pagetitle{NoMoreHelpPage}{newuser.ht}{No More Help :-(}
\begin{chunk}{newuser.ht}
\begin{page}{NoMoreHelpPage}{No More Help :-(}
\beginscroll\vspace{2}
\centerline{No additional or specific help information is available.}
\centerline{Click on \ \ExitButton{QuitPage} \  to get back.}
\endscroll
\end{page}

\end{chunk}
\pagetitle{YouTriedIt}{newuser.ht}{You Tried It!}
\pagepic{ps/v71youtriedit.eps}{youtriedit}{0.50}
\pagefrom{Reference}{TopReferencePage}
\begin{chunk}{newuser.ht}
\begin{page}{YouTriedIt}{You Tried It!}
\beginscroll
\upbutton{Click here}{UpPage} to get back.
\endscroll
\end{page}

\end{chunk}
\section{none.ht}
\pagetitle{NoneXmpPage}{none.ht}{None}
\begin{chunk}{none.ht}
\begin{page}{NoneXmpPage}{None}
\beginscroll
The \spadtype{None} domain is not very useful for interactive
work but it is provided nevertheless for completeness of the
Axiom type system.
\xtc{
Probably the only place you will ever see it is if you enter an
empty list with no type information.
}{
\spadpaste{[]}
}
\xtc{
Such an empty list can be converted into an empty list
of any other type.
}{
\spadpaste{[] :: List Float}
}
\xtc{
If you wish to produce an empty list of a particular
type directly, such as \spadtype{List NonNegativeInteger}, do it this way.
}{
\spadpaste{[]\$List(NonNegativeInteger)}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{NoneXmpPagePatch1}
\begin{paste}{NoneXmpPageFull1}{NoneXmpPageEmpty1}
\pastebutton{NoneXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{[]}
\indentrel{3}\begin{verbatim}
   (1)  []
                                        Type: List None
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{NoneXmpPageEmpty1}
\begin{paste}{NoneXmpPageEmpty1}{NoneXmpPagePatch1}
\pastebutton{NoneXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{[]}
\end{paste}\end{patch}

\begin{patch}{NoneXmpPagePatch2}
\begin{paste}{NoneXmpPageFull2}{NoneXmpPageEmpty2}
\pastebutton{NoneXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{[] :: List Float}
\indentrel{3}\begin{verbatim}
   (2)  []
                                       Type: List Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{NoneXmpPageEmpty2}
\begin{paste}{NoneXmpPageEmpty2}{NoneXmpPagePatch2}
\pastebutton{NoneXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{[] :: List Float}
\end{paste}\end{patch}

\begin{patch}{NoneXmpPagePatch3}
\begin{paste}{NoneXmpPageFull3}{NoneXmpPageEmpty3}
\pastebutton{NoneXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{[]$List(NonNegativeInteger)}
\indentrel{3}\begin{verbatim}
   (3)  []
                          Type: List NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{NoneXmpPageEmpty3}
\begin{paste}{NoneXmpPageEmpty3}{NoneXmpPagePatch3}
\pastebutton{NoneXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{[]$List(NonNegativeInteger)}
\end{paste}\end{patch}

\end{chunk}
\section{numbers.ht}
\pagetitle{NumberPage}{numbers.ht}{Axiom Number Types}
\pagepic{ps/v71numberpage.eps}{numberpage}{0.50}
\pagefrom{Axiom Topics}{TopicPage}
\pageto{Integers}{IntegerPage}
\pageto{Fractions}{FractionPage}
\pageto{Machine Floats}{DoubleFloatXmpPage}
\pageto{Real Numbers}{FloatXmpPage}
\pageto{Complex Numbers}{ComplexXmpPage}
\pageto{Finite Fields}{ugProblemFinitePage}
\pageto{Numeric Functions}{ugProblemNumericPage} 
\pageto{Cardinal Numbers}{CardinalNumberXmpPage} 
\pageto{Machine-sized Integers}{SingleIntegerXmpPage} 
\pageto{Roman Numerals}{RomanNumeralXmpPage}
\pageto{Continued Fractions}{ContinuedFractionXmpPage} 
\pageto{Partial Fractions}{PartialFractionXmpPage} 
\pageto{Quaternions}{QuaternionXmpPage}
\pageto{Octonions}{OctonionXmpPage}
\pageto{Repeating Decimals}{DecimalExpansionXmpPage} 
\pageto{Repeating Binary Expansions}{BinaryExpansionXmpPage} 
\pageto{Repeating Hexadecimal Expansions}{HexExpansionXmpPage} 
\pageto{Expansions in other Bases}{RadixExpansionXmpPage} 
\begin{chunk}{numbers.ht}
\begin{page}{NumberPage}{Axiom Number Types}
\beginscroll
The following types of numbers are among those available in Axiom.
\beginmenu

\menulink{Integers}{IntegerPage}\tab{16}
Arithmetic with arbitrarily large integers.

\menulink{Fractions}{FractionPage} \tab{16}
Rational numbers and general fractions.

\menulink{Machine Floats}{DoubleFloatXmpPage} \tab{16}
Fixed precision machine floating-point.

\menulink{Real Numbers}{FloatXmpPage} \tab{16}
Arbitrary precision decimal arithmetic.

\menulink{Complex Numbers}{ComplexXmpPage} \tab{16}
Complex numbers in general.

\menulink{Finite Fields}{ugProblemFinitePage} \tab{16}
Arithmetic in characteristic \spad{p}.
\endmenu
\horizontalline\newline
Additional Topics
\beginmenu

\menulink{Numeric Functions}{ugProblemNumericPage}
\menulink{Cardinal Numbers}{CardinalNumberXmpPage}
\menulink{Machine-sized Integers}{SingleIntegerXmpPage}
\menulink{Roman Numerals}{RomanNumeralXmpPage}
\menulink{Continued Fractions}{ContinuedFractionXmpPage}
\menulink{Partial Fractions}{PartialFractionXmpPage}
\menulink{Quaternions}{QuaternionXmpPage}
\menulink{Octonions}{OctonionXmpPage}
\menulink{Repeating Decimals}{DecimalExpansionXmpPage}
\menulink{Repeating Binary Expansions}{BinaryExpansionXmpPage}
\menulink{Repeating Hexadecimal Expansions}{HexExpansionXmpPage}
\menulink{Expansions in other Bases}{RadixExpansionXmpPage}

\endmenu

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{FractionPage}{numbers.ht}{Fraction}
\pagepic{ps/v71fractionpage.eps}{FractionPage}{0.50}
\pagefrom{Axiom Number Types}{NumberPage}
\pageto{Rational Numbers}{RationalNumberPage}
\pageto{Quotient Fields}{FractionXmpPage}
\begin{chunk}{numbers.ht}
\begin{page}{FractionPage}{Fractions}
\beginscroll
Axiom handles fractions in many different contexts
and will automatically simplify fractions whenever possible.
Here are some examples:
\spadpaste{1/4 - 1/5}
\spadpaste{f := (x**2 + 1)/(x - 1) \bound{f}}
\spadpaste{g := (x**2 - 3*x + 2)/(x + 2) \bound{g}}
\spadpaste{f * g \free{f g}}
\endscroll
Additional Topics:
\beginmenu
\menulink{Rational Numbers}{RationalNumberPage} \tab{18}
Quotients of integers
\menulink{Quotient Fields}{FractionXmpPage}  \tab{18}
Quotients over an arbitrary integral domain
\endmenu
\autobuttons
\end{page}

\begin{patch}{FractionPagePatch1}
\begin{paste}{FractionPageFull1}{FractionPageEmpty1}
\pastebutton{FractionPageFull1}{\hidepaste}
\tab{5}\spadcommand{1/4 - 1/5}
\indentrel{3}\begin{verbatim}
         1
   (1)  ÄÄ
        20
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FractionPageEmpty1}
\begin{paste}{FractionPageEmpty1}{FractionPagePatch1}
\pastebutton{FractionPageEmpty1}{\showpaste}
\tab{5}\spadcommand{1/4 - 1/5}
\end{paste}\end{patch}

\begin{patch}{FractionPagePatch2}
\begin{paste}{FractionPageFull2}{FractionPageEmpty2}
\pastebutton{FractionPageFull2}{\hidepaste}
\tab{5}\spadcommand{f := (x**2 + 1)/(x - 1)\bound{f }}
\indentrel{3}\begin{verbatim}
         2
        x  + 1
   (2)  ÄÄÄÄÄÄ
         x - 1
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FractionPageEmpty2}
\begin{paste}{FractionPageEmpty2}{FractionPagePatch2}
\pastebutton{FractionPageEmpty2}{\showpaste}
\tab{5}\spadcommand{f := (x**2 + 1)/(x - 1)\bound{f }}
\end{paste}\end{patch}

\begin{patch}{FractionPagePatch3}
\begin{paste}{FractionPageFull3}{FractionPageEmpty3}
\pastebutton{FractionPageFull3}{\hidepaste}
\tab{5}\spadcommand{g := (x**2 - 3*x + 2)/(x + 2)\bound{g }}
\indentrel{3}\begin{verbatim}
         2
        x  - 3x + 2
   (3)  ÄÄÄÄÄÄÄÄÄÄÄ
           x + 2
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FractionPageEmpty3}
\begin{paste}{FractionPageEmpty3}{FractionPagePatch3}
\pastebutton{FractionPageEmpty3}{\showpaste}
\tab{5}\spadcommand{g := (x**2 - 3*x + 2)/(x + 2)\bound{g }}
\end{paste}\end{patch}

\begin{patch}{FractionPagePatch4}
\begin{paste}{FractionPageFull4}{FractionPageEmpty4}
\pastebutton{FractionPageFull4}{\hidepaste}
\tab{5}\spadcommand{f * g\free{f g }}
\indentrel{3}\begin{verbatim}
         3     2
        x  - 2x  + x - 2
   (4)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
              x + 2
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{FractionPageEmpty4}
\begin{paste}{FractionPageEmpty4}{FractionPagePatch4}
\pastebutton{FractionPageEmpty4}{\showpaste}
\tab{5}\spadcommand{f * g\free{f g }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{RationalNumberPage}{numbers.ht}{Rational Number}
\begin{chunk}{numbers.ht}
\begin{page}{RationalNumberPage}{Rational Numbers}
\beginscroll
Like integers, rational numbers can be arbitrarily large.
For example:
\spadpaste{61657 ** 10 / 999983 ** 12}
Rational numbers will not be converted to decimals unless you explicitly
ask Axiom to do so.
To convert a rational number to a decimal, use the function
\spadfun{numeric}.
Here's an example:
\spadpaste{x := 104348/33215 \bound{x}}
\spadpaste{numeric x \free{x}}
You can find the numerator and denominator of rational numbers using
the functions \spadfun{numer} and \spadfun{denom}, respectively.
\spadpaste{numer(x) \free{x}}
\spadpaste{denom(x) \free{x}}
To factor the numerator and denominator of a fraction, use the following
command:
\spadpaste{factor(numer x) / factor(denom x) \free{x}}
\endscroll
\autobuttons
\end{page}

\begin{patch}{RationalNumberPagePatch1}
\begin{paste}{RationalNumberPageFull1}{RationalNumberPageEmpty1}
\pastebutton{RationalNumberPageFull1}{\hidepaste}
\tab{5}\spadcommand{61657 ** 10 / 999983 ** 12}
\indentrel{3}\begin{verbatim}
   (1)
     794006207119672937688869745365148806136551203249
  /
    9997960190729191813417704955587887712239578440952258_
     46167460930641229761
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RationalNumberPageEmpty1}
\begin{paste}{RationalNumberPageEmpty1}{RationalNumberPagePatch1}
\pastebutton{RationalNumberPageEmpty1}{\showpaste}
\tab{5}\spadcommand{61657 ** 10 / 999983 ** 12}
\end{paste}\end{patch}

\begin{patch}{RationalNumberPagePatch2}
\begin{paste}{RationalNumberPageFull2}{RationalNumberPageEmpty2}
\pastebutton{RationalNumberPageFull2}{\hidepaste}
\tab{5}\spadcommand{x := 104348/33215\bound{x }}
\indentrel{3}\begin{verbatim}
        104348
   (2)  ÄÄÄÄÄÄ
         33215
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RationalNumberPageEmpty2}
\begin{paste}{RationalNumberPageEmpty2}{RationalNumberPagePatch2}
\pastebutton{RationalNumberPageEmpty2}{\showpaste}
\tab{5}\spadcommand{x := 104348/33215\bound{x }}
\end{paste}\end{patch}

\begin{patch}{RationalNumberPagePatch3}
\begin{paste}{RationalNumberPageFull3}{RationalNumberPageEmpty3}
\pastebutton{RationalNumberPageFull3}{\hidepaste}
\tab{5}\spadcommand{numeric x\free{x }}
\indentrel{3}\begin{verbatim}
   (3)  3.1415926539 214210447
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RationalNumberPageEmpty3}
\begin{paste}{RationalNumberPageEmpty3}{RationalNumberPagePatch3}
\pastebutton{RationalNumberPageEmpty3}{\showpaste}
\tab{5}\spadcommand{numeric x\free{x }}
\end{paste}\end{patch}

\begin{patch}{RationalNumberPagePatch4}
\begin{paste}{RationalNumberPageFull4}{RationalNumberPageEmpty4}
\pastebutton{RationalNumberPageFull4}{\hidepaste}
\tab{5}\spadcommand{numer(x)\free{x }}
\indentrel{3}\begin{verbatim}
   (4)  104348
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RationalNumberPageEmpty4}
\begin{paste}{RationalNumberPageEmpty4}{RationalNumberPagePatch4}
\pastebutton{RationalNumberPageEmpty4}{\showpaste}
\tab{5}\spadcommand{numer(x)\free{x }}
\end{paste}\end{patch}

\begin{patch}{RationalNumberPagePatch5}
\begin{paste}{RationalNumberPageFull5}{RationalNumberPageEmpty5}
\pastebutton{RationalNumberPageFull5}{\hidepaste}
\tab{5}\spadcommand{denom(x)\free{x }}
\indentrel{3}\begin{verbatim}
   (5)  33215
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RationalNumberPageEmpty5}
\begin{paste}{RationalNumberPageEmpty5}{RationalNumberPagePatch5}
\pastebutton{RationalNumberPageEmpty5}{\showpaste}
\tab{5}\spadcommand{denom(x)\free{x }}
\end{paste}\end{patch}

\begin{patch}{RationalNumberPagePatch6}
\begin{paste}{RationalNumberPageFull6}{RationalNumberPageEmpty6}
\pastebutton{RationalNumberPageFull6}{\hidepaste}
\tab{5}\spadcommand{factor(numer x) / factor(denom x)\free{x }}
\indentrel{3}\begin{verbatim}
         2
        2 19 1373
   (6)  ÄÄÄÄÄÄÄÄÄ
        5 7 13 73
                        Type: Fraction Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RationalNumberPageEmpty6}
\begin{paste}{RationalNumberPageEmpty6}{RationalNumberPagePatch6}
\pastebutton{RationalNumberPageEmpty6}{\showpaste}
\tab{5}\spadcommand{factor(numer x) / factor(denom x)\free{x }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{IntegerPage}{numbers.ht}{Integers}
\pagepic{ps/v71integerpage.eps}{IntegerPage}{0.50}
\pagefrom{Axiom Number Types}{NumberPage}
\pageto{Integer}{IntegerXmpPage}
\pageto{Factorization}{ugxIntegerPrimesPage}
\pageto{Functions}{IntNumberTheoryFnsXmpPage}
\pageto{Examples}{IntegerExamplePage}
\pageto{Problems}{IntegerProblemPage}
\begin{chunk}{numbers.ht}
\begin{page}{IntegerPage}{Integers}
\beginscroll
In Axiom, integers can be as large as you like.
Try the following examples:
\spadpaste{x := factorial(200) \bound{x}}
\spadpaste{y := 2**90 - 1 \bound{y}}
Of course, you can now do arithmetic as usual on these (very)
large integers:
\spadpaste{x + y \free{x y}}
\spadpaste{x - y \free{x y}}
\spadpaste{x * y \free{x y}}
Axiom can factor integers, but numbers with small prime factors
\spadpaste{factor(x) \free{x}}
will factor more rapidly than numbers with large prime factors.
\spadpaste{factor(y) \free{y}}
\horizontalline
Additional Topics
\beginmenu

\menulink{Integer}{IntegerXmpPage} \tab{16}
General information and examples of integers.

\menulink{Factorization}{ugxIntegerPrimesPage} \tab{16}
Primes and factorization.

\menulink{Functions}{IntNumberTheoryFnsXmpPage} \tab{16}
Number theoretic functions.

\menulink{Examples}{IntegerExamplePage} \tab{16}
Examples from number theory.

\menulink{Problems}{IntegerProblemPage} \tab{16}
Problems from number theory.

\endmenu
\endscroll
\autobuttons
\end{page}

\begin{patch}{IntegerPagePatch1}
\begin{paste}{IntegerPageFull1}{IntegerPageEmpty1}
\pastebutton{IntegerPageFull1}{\hidepaste}
\tab{5}\spadcommand{x := factorial(200)\bound{x }}
\indentrel{3}\begin{verbatim}
   (1)
  788657867364790503552363213932185062295135977687173263_
   29474253324435944996340334292030428401198462390417721_
   21389196388302576427902426371050619266249528299311134_
   62857270763317237396988943922445621451664240254033291_
   86413122742829485327752424240757390324032125740557956_
   86602260319041703240623517008587961789222227896237038_
   97374720000000000000000000000000000000000000000000000_
   000
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerPageEmpty1}
\begin{paste}{IntegerPageEmpty1}{IntegerPagePatch1}
\pastebutton{IntegerPageEmpty1}{\showpaste}
\tab{5}\spadcommand{x := factorial(200)\bound{x }}
\end{paste}\end{patch}

\begin{patch}{IntegerPagePatch2}
\begin{paste}{IntegerPageFull2}{IntegerPageEmpty2}
\pastebutton{IntegerPageFull2}{\hidepaste}
\tab{5}\spadcommand{y := 2**90 - 1\bound{y }}
\indentrel{3}\begin{verbatim}
   (2)  1237940039285380274899124223
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerPageEmpty2}
\begin{paste}{IntegerPageEmpty2}{IntegerPagePatch2}
\pastebutton{IntegerPageEmpty2}{\showpaste}
\tab{5}\spadcommand{y := 2**90 - 1\bound{y }}
\end{paste}\end{patch}

\begin{patch}{IntegerPagePatch3}
\begin{paste}{IntegerPageFull3}{IntegerPageEmpty3}
\pastebutton{IntegerPageFull3}{\hidepaste}
\tab{5}\spadcommand{x + y\free{x y }}
\indentrel{3}\begin{verbatim}
   (3)
  788657867364790503552363213932185062295135977687173263_
   29474253324435944996340334292030428401198462390417721_
   21389196388302576427902426371050619266249528299311134_
   62857270763317237396988943922445621451664240254033291_
   86413122742829485327752424240757390324032125740557956_
   86602260319041703240623517008587961789222227896237038_
   97374720000000000000000000001237940039285380274899124_
   223
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerPageEmpty3}
\begin{paste}{IntegerPageEmpty3}{IntegerPagePatch3}
\pastebutton{IntegerPageEmpty3}{\showpaste}
\tab{5}\spadcommand{x + y\free{x y }}
\end{paste}\end{patch}

\begin{patch}{IntegerPagePatch4}
\begin{paste}{IntegerPageFull4}{IntegerPageEmpty4}
\pastebutton{IntegerPageFull4}{\hidepaste}
\tab{5}\spadcommand{x - y\free{x y }}
\indentrel{3}\begin{verbatim}
   (4)
  788657867364790503552363213932185062295135977687173263_
   29474253324435944996340334292030428401198462390417721_
   21389196388302576427902426371050619266249528299311134_
   62857270763317237396988943922445621451664240254033291_
   86413122742829485327752424240757390324032125740557956_
   86602260319041703240623517008587961789222227896237038_
   97374719999999999999999999998762059960714619725100875_
   777
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerPageEmpty4}
\begin{paste}{IntegerPageEmpty4}{IntegerPagePatch4}
\pastebutton{IntegerPageEmpty4}{\showpaste}
\tab{5}\spadcommand{x - y\free{x y }}
\end{paste}\end{patch}

\begin{patch}{IntegerPagePatch5}
\begin{paste}{IntegerPageFull5}{IntegerPageEmpty5}
\pastebutton{IntegerPageFull5}{\hidepaste}
\tab{5}\spadcommand{x * y\free{x y }}
\indentrel{3}\begin{verbatim}
   (5)
  976311151308292982184363119660950225776642966765414042_
   37079496488133389834070329188092355479782812765687260_
   17975734913119466356078732929100728088106228471338396_
   75509315106953260921744797014165125163884859138819053_
   52475858689630194698878995048210905618067437176553811_
   33973032509524956986554360537566475497856969235918273_
   09521182392695050703382396859842560000000000000000000_
   000000000000000000000000000000
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerPageEmpty5}
\begin{paste}{IntegerPageEmpty5}{IntegerPagePatch5}
\pastebutton{IntegerPageEmpty5}{\showpaste}
\tab{5}\spadcommand{x * y\free{x y }}
\end{paste}\end{patch}

\begin{patch}{IntegerPagePatch6}
\begin{paste}{IntegerPageFull6}{IntegerPageEmpty6}
\pastebutton{IntegerPageFull6}{\hidepaste}
\tab{5}\spadcommand{factor(x)\free{x }}
\indentrel{3}\begin{verbatim}
   (6)
      197 97 49 32  19  16  11  10  8  6  6  5  4  4  4  3
     2   3  5  7  11  13  17  19  23 29 31 37 41 43 47 53
  *
       3  3  2  2  2  2  2  2  2
     59 61 67 71 73 79 83 89 97 101 103 107 109 113 127
  *
     131 137 139 149 151 157 163 167 173 179 181 191 193
  *
     197 199
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerPageEmpty6}
\begin{paste}{IntegerPageEmpty6}{IntegerPagePatch6}
\pastebutton{IntegerPageEmpty6}{\showpaste}
\tab{5}\spadcommand{factor(x)\free{x }}
\end{paste}\end{patch}

\begin{patch}{IntegerPagePatch7}
\begin{paste}{IntegerPageFull7}{IntegerPageEmpty7}
\pastebutton{IntegerPageFull7}{\hidepaste}
\tab{5}\spadcommand{factor(y)\free{y }}
\indentrel{3}\begin{verbatim}
         3
   (7)  3 7 11 19 31 73 151 331 631 23311 18837001
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerPageEmpty7}
\begin{paste}{IntegerPageEmpty7}{IntegerPagePatch7}
\pastebutton{IntegerPageEmpty7}{\showpaste}
\tab{5}\spadcommand{factor(y)\free{y }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{IntegerExamplePage}{numbers.ht}{Integer Examples}
\pagepic{ps/v71integerexamplepage.eps}{IntegerExamplePage}{0.50}
\pagefrom{Integers}{IntegerPage}
\pageto{Proof}{IntegerExampleProofPage}
\begin{chunk}{numbers.ht}
\begin{page}{IntegerExamplePage}{Integer Examples}
\beginscroll
One can show that if an integer of the form 2**k + 1 is prime, then
k must be a power of 2.
\downlink{Proof}{IntegerExampleProofPage}
\par
Pierre Fermat conjectured that every integer of the forn 2**(2**n) + 1
is prime.
Let's look for a counterexample.
First define a function:
\spadpaste{f: NNI -> INT \bound{f1}}
\spadpaste{f(n) == 2**(2**n) + 1 \bound{f} \free{f1}}
Now try commands like:
\spadpaste{factor f(1) \free{f}}
\spadpaste{factor f(2) \free{f}}
until you find an integer of this form which is composite.
You can also try the following command:
\spadpaste{for n in 1..6 repeat output factor f(n) \free{f}}
Obviously, Fermat didn't have access to Axiom!
\endscroll
\autobuttons
\end{page}

\begin{patch}{IntegerExamplePagePatch1}
\begin{paste}{IntegerExamplePageFull1}{IntegerExamplePageEmpty1}
\pastebutton{IntegerExamplePageFull1}{\hidepaste}
\tab{5}\spadcommand{f: NNI -> INT\bound{f1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerExamplePageEmpty1}
\begin{paste}{IntegerExamplePageEmpty1}{IntegerExamplePagePatch1}
\pastebutton{IntegerExamplePageEmpty1}{\showpaste}
\tab{5}\spadcommand{f: NNI -> INT\bound{f1 }}
\end{paste}\end{patch}

\begin{patch}{IntegerExamplePagePatch2}
\begin{paste}{IntegerExamplePageFull2}{IntegerExamplePageEmpty2}
\pastebutton{IntegerExamplePageFull2}{\hidepaste}
\tab{5}\spadcommand{f(n) == 2**(2**n) + 1\bound{f }\free{f1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerExamplePageEmpty2}
\begin{paste}{IntegerExamplePageEmpty2}{IntegerExamplePagePatch2}
\pastebutton{IntegerExamplePageEmpty2}{\showpaste}
\tab{5}\spadcommand{f(n) == 2**(2**n) + 1\bound{f }\free{f1 }}
\end{paste}\end{patch}

\begin{patch}{IntegerExamplePagePatch3}
\begin{paste}{IntegerExamplePageFull3}{IntegerExamplePageEmpty3}
\pastebutton{IntegerExamplePageFull3}{\hidepaste}
\tab{5}\spadcommand{factor f(1)\free{f }}
\indentrel{3}\begin{verbatim}
   (3)  5
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerExamplePageEmpty3}
\begin{paste}{IntegerExamplePageEmpty3}{IntegerExamplePagePatch3}
\pastebutton{IntegerExamplePageEmpty3}{\showpaste}
\tab{5}\spadcommand{factor f(1)\free{f }}
\end{paste}\end{patch}

\begin{patch}{IntegerExamplePagePatch4}
\begin{paste}{IntegerExamplePageFull4}{IntegerExamplePageEmpty4}
\pastebutton{IntegerExamplePageFull4}{\hidepaste}
\tab{5}\spadcommand{factor f(2)\free{f }}
\indentrel{3}\begin{verbatim}
   (4)  17
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerExamplePageEmpty4}
\begin{paste}{IntegerExamplePageEmpty4}{IntegerExamplePagePatch4}
\pastebutton{IntegerExamplePageEmpty4}{\showpaste}
\tab{5}\spadcommand{factor f(2)\free{f }}
\end{paste}\end{patch}

\begin{patch}{IntegerExamplePagePatch5}
\begin{paste}{IntegerExamplePageFull5}{IntegerExamplePageEmpty5}
\pastebutton{IntegerExamplePageFull5}{\hidepaste}
\tab{5}\spadcommand{for n in 1..6 repeat output factor f(n)\free{f }}
\indentrel{3}\begin{verbatim}
   5
   17
   257
   65537
   641 6700417
   274177 67280421310721
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerExamplePageEmpty5}
\begin{paste}{IntegerExamplePageEmpty5}{IntegerExamplePagePatch5}
\pastebutton{IntegerExamplePageEmpty5}{\showpaste}
\tab{5}\spadcommand{for n in 1..6 repeat output factor f(n)\free{f }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{IntegerExampleProofPage}{numbers.ht}{Integer Example Proof}
\begin{chunk}{numbers.ht}
\begin{page}{IntegerExampleProofPage}{Integer Example Proof}
\beginscroll
Proposition.  If 2**k + 1 is prime, then k is a power of 2.
\newline
Proof.  Suppose that k = m * n with m > 1 odd.  Then
%
\centerline{2**n = -1 (mod (2**n + 1))}
\centerline{2**(n * m) = (-1)**m = -1 (mod (2**n + 1))}
\centerline{2**k + 1 = 0 (mod (2**n + 1))}
%
Therefore, 2**k + 1 is divisible by 2**n + 1.
Now 1 < 2**n + 1 and since m > 1, 2**n + 1 < 2**k + 1.
Hence, 2**k + 1 has a non-trivial factor.
\newline
QED
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{IntegerProblemPage}{numbers.ht}{Integer Problems}
\pagepic{ps/v71integerproblempage.eps}{IntegerProblemPage}{0.50}
\pagefrom{Integers}{IntegerPage}
\pageto{Proof}{IntegerProblemProofPage}
\pageto{Answer}{IntegerProblemAnswerPage1}
\pageto{Answer}{IntegerProblemAnswerPage2}
\begin{chunk}{numbers.ht}
\begin{page}{IntegerProblemPage}{Integer Problems}
\beginscroll
One can show that if an integer of the form 2**k - 1 is prime, then
k must be prime.
\downlink{Proof}{IntegerProblemProofPage}
\newline
Problem \#1:  Find the smallest prime p such that \spad{2**p - 1} is not prime.
\downlink{Answer}{IntegerProblemAnswerPage1}
\newline
Problem \#2:  Find the smallest positive integer \spad{n} such that
\spad{n**2 - n + 41} isn't prime.
\downlink{Answer}{IntegerProblemAnswerPage2}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{IntegerProblemProofPage}{numbers.ht}{Integer Problem Proof}
\begin{chunk}{numbers.ht}
\begin{page}{IntegerProblemProofPage}{Integer Problem Proof}
\beginscroll
Proposition.  If \spad{2**k - 1} is prime, then \spad{k} is prime.
\newline
Proof.  Suppose that k = m * n is a non-trivial factorization.
Then
%
\centerline{2**m = 1 (mod (2**m - 1))}
\centerline{2**(m * n) = 1 (mod (2**m - 1))}
\newline
and 2**m - 1 is a non-trivial factor of 2**k - 1.
\newline
QED
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{IntegerProblemAnswerPage1}{numbers.ht}{Solution to Problem \#1}
\begin{chunk}{numbers.ht}
\begin{page}{IntegerProblemAnswerPage1}{Solution to Problem \#1}
\beginscroll
Problem \#1:  Find the smallest prime p such that \spad{2**p - 1}
is not prime.
\newline
First, define a function:
\spadpaste{f: NNI -> INT \bound{f1}}
\spadpaste{f(n) == 2**n - 1 \bound{f} \free{f1}}
You can try factoring f(p) as p ranges through the set of primes.
For example,
\spadpaste{factor f(7) \free{f}}
This gets tedious after a while, so let's use Axiom's stream
facility.  (A stream is essentially an infinite sequence.)
\newline
First, we create a stream consisting of the positive integers:
\spadpaste{ints := [n for n in 1..] \bound{ints}}
Now, we create a stream consisting of the primes:
\spadpaste{primes := [x for x in ints | prime? x] \bound{primes} 
\free{ints}}
Here's the 25th prime:
\spadpaste{primes.25 \free{primes}}
Next, create the stream of numbers of the form 2**p - 1 with p prime:
\spadpaste{numbers := [f(n) for n in primes] \bound{numbers} \free{primes f}}
Finally, form
the stream of factorizations of the elements of \spad{numbers}:
\spadpaste{factors := [factor n for n in numbers] \bound{factors} 
\free{numbers}}
You can see that the fifth number in the stream (2047 = 23*89)
is the first one that has a non-trivial factorization.
Since 2**11 = 2048, the solution to the problem is 11.
\newline
Here's another way to see that 2047 is the first number in the stream that
is composite:
\spadpaste{nums := [x for x in numbers | not prime? x] \bound{nums} 
\free{numbers}}
\endscroll
\autobuttons
\end{page}

\begin{patch}{IntegerProblemAnswerPage1Patch1}
\begin{paste}{IntegerProblemAnswerPage1Full1}{IntegerProblemAnswerPage1Empty1}
\pastebutton{IntegerProblemAnswerPage1Full1}{\hidepaste}
\tab{5}\spadcommand{f: NNI -> INT\bound{f1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerProblemAnswerPage1Empty1}
\begin{paste}{IntegerProblemAnswerPage1Empty1}{IntegerProblemAnswerPage1Patch1}
\pastebutton{IntegerProblemAnswerPage1Empty1}{\showpaste}
\tab{5}\spadcommand{f: NNI -> INT\bound{f1 }}
\end{paste}\end{patch}

\begin{patch}{IntegerProblemAnswerPage1Patch2}
\begin{paste}{IntegerProblemAnswerPage1Full2}{IntegerProblemAnswerPage1Empty2}
\pastebutton{IntegerProblemAnswerPage1Full2}{\hidepaste}
\tab{5}\spadcommand{f(n) == 2**n - 1\bound{f }\free{f1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerProblemAnswerPage1Empty2}
\begin{paste}{IntegerProblemAnswerPage1Empty2}{IntegerProblemAnswerPage1Patch2}
\pastebutton{IntegerProblemAnswerPage1Empty2}{\showpaste}
\tab{5}\spadcommand{f(n) == 2**n - 1\bound{f }\free{f1 }}
\end{paste}\end{patch}

\begin{patch}{IntegerProblemAnswerPage1Patch3}
\begin{paste}{IntegerProblemAnswerPage1Full3}{IntegerProblemAnswerPage1Empty3}
\pastebutton{IntegerProblemAnswerPage1Full3}{\hidepaste}
\tab{5}\spadcommand{factor f(7)\free{f }}
\indentrel{3}\begin{verbatim}
   (3)  127
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerProblemAnswerPage1Empty3}
\begin{paste}{IntegerProblemAnswerPage1Empty3}{IntegerProblemAnswerPage1Patch3}
\pastebutton{IntegerProblemAnswerPage1Empty3}{\showpaste}
\tab{5}\spadcommand{factor f(7)\free{f }}
\end{paste}\end{patch}

\begin{patch}{IntegerProblemAnswerPage1Patch4}
\begin{paste}{IntegerProblemAnswerPage1Full4}{IntegerProblemAnswerPage1Empty4}
\pastebutton{IntegerProblemAnswerPage1Full4}{\hidepaste}
\tab{5}\spadcommand{ints := [n for n in 1..]\bound{ints }}
\indentrel{3}\begin{verbatim}
   (4)  [1,2,3,4,5,6,7,8,9,10,...]
                           Type: Stream PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerProblemAnswerPage1Empty4}
\begin{paste}{IntegerProblemAnswerPage1Empty4}{IntegerProblemAnswerPage1Patch4}
\pastebutton{IntegerProblemAnswerPage1Empty4}{\showpaste}
\tab{5}\spadcommand{ints := [n for n in 1..]\bound{ints }}
\end{paste}\end{patch}

\begin{patch}{IntegerProblemAnswerPage1Patch5}
\begin{paste}{IntegerProblemAnswerPage1Full5}{IntegerProblemAnswerPage1Empty5}
\pastebutton{IntegerProblemAnswerPage1Full5}{\hidepaste}
\tab{5}\spadcommand{primes := [x for x in ints | prime? x]\bound{primes }\free{ints }}
\indentrel{3}\begin{verbatim}
   (5)  [2,3,5,7,11,13,17,19,23,29,...]
                           Type: Stream PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerProblemAnswerPage1Empty5}
\begin{paste}{IntegerProblemAnswerPage1Empty5}{IntegerProblemAnswerPage1Patch5}
\pastebutton{IntegerProblemAnswerPage1Empty5}{\showpaste}
\tab{5}\spadcommand{primes := [x for x in ints | prime? x]\bound{primes }\free{ints }}
\end{paste}\end{patch}

\begin{patch}{IntegerProblemAnswerPage1Patch6}
\begin{paste}{IntegerProblemAnswerPage1Full6}{IntegerProblemAnswerPage1Empty6}
\pastebutton{IntegerProblemAnswerPage1Full6}{\hidepaste}
\tab{5}\spadcommand{primes.25\free{primes }}
\indentrel{3}\begin{verbatim}
   (6)  97
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerProblemAnswerPage1Empty6}
\begin{paste}{IntegerProblemAnswerPage1Empty6}{IntegerProblemAnswerPage1Patch6}
\pastebutton{IntegerProblemAnswerPage1Empty6}{\showpaste}
\tab{5}\spadcommand{primes.25\free{primes }}
\end{paste}\end{patch}

\begin{patch}{IntegerProblemAnswerPage1Patch7}
\begin{paste}{IntegerProblemAnswerPage1Full7}{IntegerProblemAnswerPage1Empty7}
\pastebutton{IntegerProblemAnswerPage1Full7}{\hidepaste}
\tab{5}\spadcommand{numbers := [f(n) for n in primes]\bound{numbers }\free{primes f }}
\indentrel{3}\begin{verbatim}
   (7)
   [3, 7, 31, 127, 2047, 8191, 131071, 524287, 8388607,
    536870911, ...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerProblemAnswerPage1Empty7}
\begin{paste}{IntegerProblemAnswerPage1Empty7}{IntegerProblemAnswerPage1Patch7}
\pastebutton{IntegerProblemAnswerPage1Empty7}{\showpaste}
\tab{5}\spadcommand{numbers := [f(n) for n in primes]\bound{numbers }\free{primes f }}
\end{paste}\end{patch}

\begin{patch}{IntegerProblemAnswerPage1Patch8}
\begin{paste}{IntegerProblemAnswerPage1Full8}{IntegerProblemAnswerPage1Empty8}
\pastebutton{IntegerProblemAnswerPage1Full8}{\hidepaste}
\tab{5}\spadcommand{factors := [factor n for n in numbers]\bound{factors }\free{numbers }}
\indentrel{3}\begin{verbatim}
   (8)
   [3, 7, 31, 127, 23 89, 8191, 131071, 524287,
    47 178481, 233 1103 2089, ...]
                          Type: Stream Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerProblemAnswerPage1Empty8}
\begin{paste}{IntegerProblemAnswerPage1Empty8}{IntegerProblemAnswerPage1Patch8}
\pastebutton{IntegerProblemAnswerPage1Empty8}{\showpaste}
\tab{5}\spadcommand{factors := [factor n for n in numbers]\bound{factors }\free{numbers }}
\end{paste}\end{patch}

\begin{patch}{IntegerProblemAnswerPage1Patch9}
\begin{paste}{IntegerProblemAnswerPage1Full9}{IntegerProblemAnswerPage1Empty9}
\pastebutton{IntegerProblemAnswerPage1Full9}{\hidepaste}
\tab{5}\spadcommand{nums := [x for x in numbers | not prime? x]\bound{nums }\free{numbers }}
\indentrel{3}\begin{verbatim}
   (9)
   [2047, 8388607, 536870911, 137438953471,
    2199023255551, 8796093022207, 140737488355327,
    9007199254740991, 576460752303423487,
    147573952589676412927, ...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerProblemAnswerPage1Empty9}
\begin{paste}{IntegerProblemAnswerPage1Empty9}{IntegerProblemAnswerPage1Patch9}
\pastebutton{IntegerProblemAnswerPage1Empty9}{\showpaste}
\tab{5}\spadcommand{nums := [x for x in numbers | not prime? x]\bound{nums }\free{numbers }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{IntegerProblemAnswerPage2}{numbers.ht}{Solution to Problem \#2}
\begin{chunk}{numbers.ht}
\begin{page}{IntegerProblemAnswerPage2}{Solution to Problem \#2}
\beginscroll
Problem \#2:  Find the smallest positive integer n such that
\spad{n**2 - n + 41} is not prime.
\newline
When n = 41, n**2 - n + 41 = 41**2, which certainly isn't prime.
Let's see if any smaller integer works.
Here are the first 40 values:
\spadpaste{numbers := [n**2 - n + 41 for n in 0..40] \bound{numbers}}
Now have Axiom factor the numbers on this list:
\spadpaste{[factor n for n in numbers] \free{numbers}}
You can see that 41 is the smallest positive integer n such that
n**n - n + 41 is not prime.
\endscroll
\autobuttons
\end{page}

\begin{patch}{IntegerProblemAnswerPage2Patch1}
\begin{paste}{IntegerProblemAnswerPage2Full1}{IntegerProblemAnswerPage2Empty1}
\pastebutton{IntegerProblemAnswerPage2Full1}{\hidepaste}
\tab{5}\spadcommand{numbers := [n**2 - n + 41 for n in 0..40]\bound{numbers }}
\indentrel{3}\begin{verbatim}
   (1)
   [41, 41, 43, 47, 53, 61, 71, 83, 97, 113, 131, 151,
    173, 197, 223, 251, 281, 313, 347, 383, 421, 461,
    503, 547, 593, 641, 691, 743, 797, 853, 911, 971,
    1033, 1097, 1163, 1231, 1301, 1373, 1447, 1523, 1601]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerProblemAnswerPage2Empty1}
\begin{paste}{IntegerProblemAnswerPage2Empty1}{IntegerProblemAnswerPage2Patch1}
\pastebutton{IntegerProblemAnswerPage2Empty1}{\showpaste}
\tab{5}\spadcommand{numbers := [n**2 - n + 41 for n in 0..40]\bound{numbers }}
\end{paste}\end{patch}

\begin{patch}{IntegerProblemAnswerPage2Patch2}
\begin{paste}{IntegerProblemAnswerPage2Full2}{IntegerProblemAnswerPage2Empty2}
\pastebutton{IntegerProblemAnswerPage2Full2}{\hidepaste}
\tab{5}\spadcommand{[factor n for n in numbers]\free{numbers }}
\indentrel{3}\begin{verbatim}
   (2)
   [41, 41, 43, 47, 53, 61, 71, 83, 97, 113, 131, 151,
    173, 197, 223, 251, 281, 313, 347, 383, 421, 461,
    503, 547, 593, 641, 691, 743, 797, 853, 911, 971,
    1033, 1097, 1163, 1231, 1301, 1373, 1447, 1523, 1601]
                            Type: List Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerProblemAnswerPage2Empty2}
\begin{paste}{IntegerProblemAnswerPage2Empty2}{IntegerProblemAnswerPage2Patch2}
\pastebutton{IntegerProblemAnswerPage2Empty2}{\showpaste}
\tab{5}\spadcommand{[factor n for n in numbers]\free{numbers }}
\end{paste}\end{patch}

\end{chunk}
\section{oct.ht}
\pagetitle{OctonionXmpPage}{oct.ht}{Octonion}
\pagepic{ps/v71octonionxmppage.eps}{OctonionXmpPage}{0.50}
\pagefrom{Axiom Number Types}{NumberPage}
\pageto{Quaternion}{QuaternionXmpPage}
\begin{chunk}{oct.ht}
\begin{page}{OctonionXmpPage}{Octonion}
\beginscroll
The Octonions, also called the Cayley-Dixon algebra, defined over a
commutative ring are an eight-dimensional non-associative algebra.
Their construction from quaternions is similar to the construction
of quaternions from complex numbers 
(see \downlink{`Quaternion'}{QuaternionXmpPage}\ignore{Quaternion}).
%
\xtc{
As \spadtype{Octonion} creates an eight-dimensional algebra, you have to
give eight components to construct an octonion.
}{
\spadpaste{oci1 := octon(1,2,3,4,5,6,7,8) \bound{oci1}}
}
\xtc{
}{
\spadpaste{oci2 := octon(7,2,3,-4,5,6,-7,0) \bound{oci2}}
}
%
%
\xtc{
Or you can use two quaternions to create an octonion.
}{
\spadpaste{oci3 := octon(quatern(-7,-12,3,-10), quatern(5,6,9,0)) 
\bound{oci3}}
}
%
%
\xtc{
You can easily demonstrate the non-associativity of multiplication.
}{
\spadpaste{(oci1 * oci2) * oci3 - oci1 * (oci2 * oci3) 
\free{oci1 oci2 oci3}}
}
%
As with the quaternions, we have a real part, the imaginary
parts \spad{i}, \spad{j}, \spad{k}, and four
additional imaginary parts \spad{E}, \spad{I}, \spad{J} and \spad{K}.
These parts correspond to the canonical basis
\spad{(1,i,j,k,E,I,J,K)}.
\xtc{
For each basis element there is a component operation to extract
the coefficient of the basis element for a given octonion.
%\spadfunFrom{real}{Octonion},
%\spadfunFrom{imagi}{Octonion},
%\spadfunFrom{imagj}{Octonion},
%\spadfunFrom{imagk}{Octonion},
%\spadfunFrom{imagE}{Octonion},
%\spadfunFrom{imagI}{Octonion},
%\spadfunFrom{imagJ}{Octonion}, and
%\spadfunFrom{imagK}{Octonion}.
}{
\spadpaste{[real oci1, imagi oci1, imagj oci1, imagk oci1, imagE oci1, 
imagI oci1, imagJ oci1, imagK oci1] \free{oci1}}
}
%
A basis with respect to the
quaternions is given by \spad{(1,E)}.
However, you might ask, what then are the commuting rules?
To answer this, we create some generic elements.
%
\xtc{
We do this in Axiom
by simply changing the ground ring from \spadtype{Integer} to
\spadtype{Polynomial Integer}.
}{
\spadpaste{q : Quaternion Polynomial Integer := quatern(q1, qi, qj, qk) 
\bound{q}}
}
\xtc{
}{
\spadpaste{E : Octonion Polynomial Integer:= octon(0,0,0,0,1,0,0,0) 
\bound{E}}
}
%
\xtc{
Note that quaternions are automatically converted to octonions in the
obvious way.
}{
\spadpaste{q * E \free{q E}}
}
\xtc{
}{
\spadpaste{E * q \free{E q}}
}
\xtc{
}{
\spadpaste{q * 1\$(Octonion Polynomial Integer) \free{q}}
}
\xtc{
}{
\spadpaste{1\$(Octonion Polynomial Integer) * q \free{q}}
}
\xtc{
Finally, we check that the \spadfunFrom{norm}{Octonion},
defined as the sum of the squares of the coefficients,
is a multiplicative map.
}{
\spadpaste{o : Octonion Polynomial Integer := octon(o1, oi, oj, ok, oE, 
oI, oJ, oK) \bound{o}}
}
\xtc{
}{
\spadpaste{norm o \free{o}}
}
\xtc{
}{
\spadpaste{p : Octonion Polynomial Integer := octon(p1, pi, pj, pk, pE, 
pI, pJ, pK) \bound{p}}
}
\xtc{
Since the result is \spad{0}, the norm is multiplicative.
}{
\spadpaste{norm(o*p)-norm(p)*norm(p)\free{o p} }
}
\showBlurb{Octonion}
\endscroll
\autobuttons
\end{page}

\begin{patch}{OctonionXmpPagePatch1}
\begin{paste}{OctonionXmpPageFull1}{OctonionXmpPageEmpty1}
\pastebutton{OctonionXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{oci1 := octon(1,2,3,4,5,6,7,8)\bound{oci1 }}
\indentrel{3}\begin{verbatim}
   (1)  1 + 2i + 3j + 4k + 5E + 6I + 7J + 8K
                                 Type: Octonion Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OctonionXmpPageEmpty1}
\begin{paste}{OctonionXmpPageEmpty1}{OctonionXmpPagePatch1}
\pastebutton{OctonionXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{oci1 := octon(1,2,3,4,5,6,7,8)\bound{oci1 }}
\end{paste}\end{patch}

\begin{patch}{OctonionXmpPagePatch2}
\begin{paste}{OctonionXmpPageFull2}{OctonionXmpPageEmpty2}
\pastebutton{OctonionXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{oci2 := octon(7,2,3,-4,5,6,-7,0)\bound{oci2 }}
\indentrel{3}\begin{verbatim}
   (2)  7 + 2i + 3j - 4k + 5E + 6I - 7J
                                 Type: Octonion Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OctonionXmpPageEmpty2}
\begin{paste}{OctonionXmpPageEmpty2}{OctonionXmpPagePatch2}
\pastebutton{OctonionXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{oci2 := octon(7,2,3,-4,5,6,-7,0)\bound{oci2 }}
\end{paste}\end{patch}

\begin{patch}{OctonionXmpPagePatch3}
\begin{paste}{OctonionXmpPageFull3}{OctonionXmpPageEmpty3}
\pastebutton{OctonionXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{oci3 := octon(quatern(-7,-12,3,-10), quatern(5,6,9,0))\bound{oci3 }}
\indentrel{3}\begin{verbatim}
   (3)  - 7 - 12i + 3j - 10k + 5E + 6I + 9J
                                 Type: Octonion Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OctonionXmpPageEmpty3}
\begin{paste}{OctonionXmpPageEmpty3}{OctonionXmpPagePatch3}
\pastebutton{OctonionXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{oci3 := octon(quatern(-7,-12,3,-10), quatern(5,6,9,0))\bound{oci3 }}
\end{paste}\end{patch}

\begin{patch}{OctonionXmpPagePatch4}
\begin{paste}{OctonionXmpPageFull4}{OctonionXmpPageEmpty4}
\pastebutton{OctonionXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{(oci1 * oci2) * oci3 - oci1 * (oci2 * oci3)\free{oci1 oci2 oci3 }}
\indentrel{3}\begin{verbatim}
   (4)
   2696i - 2928j - 4072k + 16E - 1192I + 832J + 2616K
                                 Type: Octonion Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OctonionXmpPageEmpty4}
\begin{paste}{OctonionXmpPageEmpty4}{OctonionXmpPagePatch4}
\pastebutton{OctonionXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{(oci1 * oci2) * oci3 - oci1 * (oci2 * oci3)\free{oci1 oci2 oci3 }}
\end{paste}\end{patch}

\begin{patch}{OctonionXmpPagePatch5}
\begin{paste}{OctonionXmpPageFull5}{OctonionXmpPageEmpty5}
\pastebutton{OctonionXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{[real oci1, imagi oci1, imagj oci1, imagk oci1, imagE oci1, imagI oci1, imagJ oci1, imagK oci1]\free{oci1 }}
\indentrel{3}\begin{verbatim}
   (5)  [1,2,3,4,5,6,7,8]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OctonionXmpPageEmpty5}
\begin{paste}{OctonionXmpPageEmpty5}{OctonionXmpPagePatch5}
\pastebutton{OctonionXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{[real oci1, imagi oci1, imagj oci1, imagk oci1, imagE oci1, imagI oci1, imagJ oci1, imagK oci1]\free{oci1 }}
\end{paste}\end{patch}

\begin{patch}{OctonionXmpPagePatch6}
\begin{paste}{OctonionXmpPageFull6}{OctonionXmpPageEmpty6}
\pastebutton{OctonionXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{q : Quaternion Polynomial Integer := quatern(q1, qi, qj, qk)\bound{q }}
\indentrel{3}\begin{verbatim}
   (6)  q1 + qi i + qj j + qk k
                    Type: Quaternion Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OctonionXmpPageEmpty6}
\begin{paste}{OctonionXmpPageEmpty6}{OctonionXmpPagePatch6}
\pastebutton{OctonionXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{q : Quaternion Polynomial Integer := quatern(q1, qi, qj, qk)\bound{q }}
\end{paste}\end{patch}

\begin{patch}{OctonionXmpPagePatch7}
\begin{paste}{OctonionXmpPageFull7}{OctonionXmpPageEmpty7}
\pastebutton{OctonionXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{E : Octonion Polynomial Integer:= octon(0,0,0,0,1,0,0,0)\bound{E }}
\indentrel{3}\begin{verbatim}
   (7)  E
                      Type: Octonion Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OctonionXmpPageEmpty7}
\begin{paste}{OctonionXmpPageEmpty7}{OctonionXmpPagePatch7}
\pastebutton{OctonionXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{E : Octonion Polynomial Integer:= octon(0,0,0,0,1,0,0,0)\bound{E }}
\end{paste}\end{patch}

\begin{patch}{OctonionXmpPagePatch8}
\begin{paste}{OctonionXmpPageFull8}{OctonionXmpPageEmpty8}
\pastebutton{OctonionXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{q * E\free{q E }}
\indentrel{3}\begin{verbatim}
   (8)  q1 E + qi I + qj J + qk K
                      Type: Octonion Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OctonionXmpPageEmpty8}
\begin{paste}{OctonionXmpPageEmpty8}{OctonionXmpPagePatch8}
\pastebutton{OctonionXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{q * E\free{q E }}
\end{paste}\end{patch}

\begin{patch}{OctonionXmpPagePatch9}
\begin{paste}{OctonionXmpPageFull9}{OctonionXmpPageEmpty9}
\pastebutton{OctonionXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{E * q\free{E q }}
\indentrel{3}\begin{verbatim}
   (9)  q1 E - qi I - qj J - qk K
                      Type: Octonion Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OctonionXmpPageEmpty9}
\begin{paste}{OctonionXmpPageEmpty9}{OctonionXmpPagePatch9}
\pastebutton{OctonionXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{E * q\free{E q }}
\end{paste}\end{patch}

\begin{patch}{OctonionXmpPagePatch10}
\begin{paste}{OctonionXmpPageFull10}{OctonionXmpPageEmpty10}
\pastebutton{OctonionXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{q * 1$(Octonion Polynomial Integer)\free{q }}
\indentrel{3}\begin{verbatim}
   (10)  q1 + qi i + qj j + qk k
                      Type: Octonion Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OctonionXmpPageEmpty10}
\begin{paste}{OctonionXmpPageEmpty10}{OctonionXmpPagePatch10}
\pastebutton{OctonionXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{q * 1$(Octonion Polynomial Integer)\free{q }}
\end{paste}\end{patch}

\begin{patch}{OctonionXmpPagePatch11}
\begin{paste}{OctonionXmpPageFull11}{OctonionXmpPageEmpty11}
\pastebutton{OctonionXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{1$(Octonion Polynomial Integer) * q\free{q }}
\indentrel{3}\begin{verbatim}
   (11)  q1 + qi i + qj j + qk k
                      Type: Octonion Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OctonionXmpPageEmpty11}
\begin{paste}{OctonionXmpPageEmpty11}{OctonionXmpPagePatch11}
\pastebutton{OctonionXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{1$(Octonion Polynomial Integer) * q\free{q }}
\end{paste}\end{patch}

\begin{patch}{OctonionXmpPagePatch12}
\begin{paste}{OctonionXmpPageFull12}{OctonionXmpPageEmpty12}
\pastebutton{OctonionXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{o : Octonion Polynomial Integer := octon(o1, oi, oj, ok, oE, oI, oJ, oK)\bound{o }}
\indentrel{3}\begin{verbatim}
   (12)
   o1 + oi i + oj j + ok k + oE E + oI I + oJ J + oK K
                      Type: Octonion Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OctonionXmpPageEmpty12}
\begin{paste}{OctonionXmpPageEmpty12}{OctonionXmpPagePatch12}
\pastebutton{OctonionXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{o : Octonion Polynomial Integer := octon(o1, oi, oj, ok, oE, oI, oJ, oK)\bound{o }}
\end{paste}\end{patch}

\begin{patch}{OctonionXmpPagePatch13}
\begin{paste}{OctonionXmpPageFull13}{OctonionXmpPageEmpty13}
\pastebutton{OctonionXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{norm o\free{o }}
\indentrel{3}\begin{verbatim}
           2     2     2     2     2     2     2     2
   (13)  ok  + oj  + oi  + oK  + oJ  + oI  + oE  + o1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OctonionXmpPageEmpty13}
\begin{paste}{OctonionXmpPageEmpty13}{OctonionXmpPagePatch13}
\pastebutton{OctonionXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{norm o\free{o }}
\end{paste}\end{patch}

\begin{patch}{OctonionXmpPagePatch14}
\begin{paste}{OctonionXmpPageFull14}{OctonionXmpPageEmpty14}
\pastebutton{OctonionXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{p : Octonion Polynomial Integer := octon(p1, pi, pj, pk, pE, pI, pJ, pK)\bound{p }}
\indentrel{3}\begin{verbatim}
   (14)
   p1 + pi i + pj j + pk k + pE E + pI I + pJ J + pK K
                      Type: Octonion Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OctonionXmpPageEmpty14}
\begin{paste}{OctonionXmpPageEmpty14}{OctonionXmpPagePatch14}
\pastebutton{OctonionXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{p : Octonion Polynomial Integer := octon(p1, pi, pj, pk, pE, pI, pJ, pK)\bound{p }}
\end{paste}\end{patch}

\begin{patch}{OctonionXmpPagePatch15}
\begin{paste}{OctonionXmpPageFull15}{OctonionXmpPageEmpty15}
\pastebutton{OctonionXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{norm(o*p)-norm(p)*norm(p)\free{o p }}
\indentrel{3}\begin{verbatim}
   (15)
         4
     - pk
   + 
              2      2      2      2      2      2      2
         - 2pj  - 2pi  - 2pK  - 2pJ  - 2pI  - 2pE  - 2p1
       + 
           2     2     2     2     2     2     2     2
         ok  + oj  + oi  + oK  + oJ  + oI  + oE  + o1
    *
         2
       pk
   + 
         4
     - pj
   + 
              2      2      2      2      2      2     2
         - 2pi  - 2pK  - 2pJ  - 2pI  - 2pE  - 2p1  + ok
       + 
           2     2     2     2     2     2     2
         oj  + oi  + oK  + oJ  + oI  + oE  + o1
    *
         2
       pj
   + 
         4
     - pi
   + 
              2      2      2      2      2     2     2
         - 2pK  - 2pJ  - 2pI  - 2pE  - 2p1  + ok  + oj
       + 
           2     2     2     2     2     2
         oi  + oK  + oJ  + oI  + oE  + o1
    *
         2
       pi
   + 
         4
     - pK
   + 
              2      2      2      2     2     2     2
         - 2pJ  - 2pI  - 2pE  - 2p1  + ok  + oj  + oi
       + 
           2     2     2     2     2
         oK  + oJ  + oI  + oE  + o1
    *
         2
       pK
   + 
         4
     - pJ
   + 
              2      2      2     2     2     2     2
         - 2pI  - 2pE  - 2p1  + ok  + oj  + oi  + oK
       + 
           2     2     2     2
         oJ  + oI  + oE  + o1
    *
         2
       pJ
   + 
         4
     - pI
   + 
              2      2     2     2     2     2     2     2
         - 2pE  - 2p1  + ok  + oj  + oi  + oK  + oJ  + oI
       + 
           2     2
         oE  + o1
    *
         2
       pI
   + 
         4
     - pE
   + 
              2     2     2     2     2     2     2     2
         - 2p1  + ok  + oj  + oi  + oK  + oJ  + oI  + oE
       + 
           2
         o1
    *
         2
       pE
   + 
         4
     - p1
   + 
        2     2     2     2     2     2     2     2   2
     (ok  + oj  + oi  + oK  + oJ  + oI  + oE  + o1 )p1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OctonionXmpPageEmpty15}
\begin{paste}{OctonionXmpPageEmpty15}{OctonionXmpPagePatch15}
\pastebutton{OctonionXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{norm(o*p)-norm(p)*norm(p)\free{o p }}
\end{paste}\end{patch}

\end{chunk}
\section{odpol.ht}
\pagetitle{OrderlyDifferentialPolyXmpPage}{odpol.ht}
{OrderlyDifferentialPolynomial}
\begin{chunk}{odpol.ht}
\begin{page}{OrderlyDifferentialPolyXmpPage}
{OrderlyDifferentialPolynomial}
\beginscroll

Many systems of differential equations may be transformed to
equivalent systems of ordinary differential equations where the
equations are expressed polynomially in terms of the unknown
functions.  In Axiom, the domain constructors
\spadtype{OrderlyDifferentialPolynomial} (abbreviated
\spadtype{ODPOL}) and \spadtype{SequentialDifferentialPolynomial}
(abbreviation \spadtype{SDPOL}) implement two domains of ordinary
differential polynomials over any differential ring.  In the simplest
case, this differential ring is usually either the ring of integers,
or the field of rational numbers.  However, Axiom can handle ordinary
differential polynomials over a field of rational functions in a
single indeterminate.

The two domains \spadtype{ODPOL} and \spadtype{SDPOL} are almost
identical, the only difference being the choice of a different
ranking, which is an ordering of the derivatives of the
indeterminates.  The first domain uses an orderly ranking, that is,
derivatives of higher order are ranked higher, and derivatives of the
same order are ranked alphabetically.  The second domain uses a
sequential ranking, where derivatives are ordered first alphabetically
by the differential indeterminates, and then by order.  A more general
domain constructor,
\spadtype{DifferentialSparseMultivariatePolynomial} (abbreviation
\spadtype{DSMP}) allows both a user-provided list of differential
indeterminates as well as a user-defined ranking.  We shall illustrate
\spadtype{ODPOL(FRAC INT)}, which constructs a domain of ordinary
differential polynomials in an arbitrary number of differential
indeterminates with rational numbers as coefficients.  \xtc{ }{
\spadpaste{dpol:= ODPOL(FRAC INT) \bound{dpol}} }

\xtc{
A differential indeterminate \spad{w} may be viewed as an infinite
sequence of algebraic indeterminates, which are the derivatives of
\spad{w}.
To facilitate referencing these, Axiom provides the operation
\spadfunFrom{makeVariable}{OrderlyDifferentialPolynomial} to convert an
element of type \spadtype{Symbol} to a map from the natural numbers to the
differential polynomial ring.
}{
\spadpaste{w := makeVariable('w)\$dpol \free{dpol}\bound{w}}
}
\xtc{
}{
\spadpaste{z := makeVariable('z)\$dpol \free{dpol}\bound{z}}
}
\xtc{
The fifth derivative of \spad{w} can be obtained by applying the map
\spad{w} to the number \spad{5.}
Note that the order of differentiation is given as a subscript (except
when the order is 0).
}{
\spadpaste{w.5 \free{w}}
}
\xtc{
}{
\spadpaste{w 0 \free{w}}
}
\xtc{
The first five derivatives of \spad{z} can be generated by a list.
}{
\spadpaste{[z.i for i in 1..5] \free{z}}
}
\xtc{
The usual arithmetic can be used to form a differential polynomial from
the derivatives.
}{
\spadpaste{f:= w.4 - w.1 * w.1 * z.3 \free{w}\free{z}\bound{f}}
}
\xtc{
}{
\spadpaste{g:=(z.1)**3 * (z.2)**2 - w.2 \free{z}\free{w}\bound{g}}
}
\xtc{
The operation \spadfunFrom{D}{OrderlyDifferentialPolynomial}
computes the derivative of any differential polynomial.
}{
\spadpaste{D(f) \free{f}}
}
\xtc{
The same operation can compute higher derivatives, like the
fourth derivative.
}{
\spadpaste{D(f,4) \free{f}}
}
\xtc{
The operation \spadfunFrom{makeVariable}{OrderlyDifferentialPolynomial}
creates a map to facilitate referencing the derivatives of \spad{f},
similar to the map \spad{w}.
}{
\spadpaste{df:=makeVariable(f)\$dpol \free{f}\bound{df}}
}
\xtc{
The fourth derivative of f may be referenced easily.
}{
\spadpaste{df.4 \free{df}}
}
\xtc{
The operation \spadfunFrom{order}{OrderlyDifferentialPolynomial}
returns the order of a differential polynomial, or the order
in a specified differential indeterminate.
}{
\spadpaste{order(g)  \free{g}}
}
\xtc{
}{
\spadpaste{order(g, 'w)  \free{g}}
}
\xtc{
The operation
\spadfunFrom{differentialVariables}{OrderlyDifferentialPolynomial}
returns a list of differential indeterminates occurring in a
differential polynomial.
}{
\spadpaste{differentialVariables(g)  \free{g}}
}
\xtc{
The operation \spadfunFrom{degree}{OrderlyDifferentialPolynomial}
returns the degree, or the degree in the differential indeterminate
specified.
}{
\spadpaste{degree(g) \free{g}}
}
\xtc{
}{
\spadpaste{degree(g, 'w)  \free{g}}
}
\xtc{
The operation \spadfunFrom{weights}{OrderlyDifferentialPolynomial}
returns a list of weights of differential monomials appearing in
differential polynomial, or a list of weights in a specified
differential indeterminate.
}{
\spadpaste{weights(g)  \free{g}}
}
\xtc{
}{
\spadpaste{weights(g,'w) \free{g}}
}
\xtc{
The operation \spadfunFrom{weight}{OrderlyDifferentialPolynomial} returns
the maximum weight of all differential monomials appearing in the
differential polynomial.
}{
\spadpaste{weight(g)  \free{g}}
}
\xtc{
A differential polynomial is {\em isobaric} if the weights of all
differential monomials appearing in it are equal.
}{
\spadpaste{isobaric?(g) \free{g}}
}
\xtc{
To substitute {\em differentially}, use
\spadfunFrom{eval}{OrderlyDifferentialPolynomial}.  Note that we must
coerce \spad{'w} to \spadtype{Symbol}, since in \spadtype{ODPOL},
differential indeterminates belong to the domain \spadtype{Symbol}.
Compare this result to the next, which substitutes {\em algebraically}
(no substitution is done since \spad{w.0} does not appear in \spad{g}).
}{
\spadpaste{eval(g,['w::Symbol],[f]) \free{f}\free{g}}
}
\xtc{
}{
\spadpaste{eval(g,variables(w.0),[f]) \free{f}\free{g}}
}
\xtc{
Since \spadtype{OrderlyDifferentialPolynomial} belongs to
\spadtype{PolynomialCategory}, all the operations defined in the latter
category, or in packages for the latter category, are available.
}{
\spadpaste{monomials(g) \free{g}}
}
\xtc{
}{
\spadpaste{variables(g) \free{g}}
}
\xtc{
}{
\spadpaste{gcd(f,g) \free{f}\free{g}}
}
\xtc{
}{
\spadpaste{groebner([f,g]) \free{f}\free{g}}
}
\xtc{
The next three operations are essential for elimination procedures in
differential polynomial rings.
The operation \spadfunFrom{leader}{OrderlyDifferentialPolynomial} returns
the leader of a differential polynomial, which is the highest ranked
derivative of the differential indeterminates that occurs.
}{
\spadpaste{lg:=leader(g)  \free{g}\bound{lg}}
}
\xtc{
The operation \spadfunFrom{separant}{OrderlyDifferentialPolynomial}
returns the separant of a differential polynomial, which is the
partial derivative with respect to the leader.
}{
\spadpaste{sg:=separant(g)  \free{g}\bound{sg}}
}
\xtc{
The operation \spadfunFrom{initial}{OrderlyDifferentialPolynomial}
returns the initial, which is the leading coefficient when the given
differential polynomial is expressed as a polynomial in the leader.
}{
\spadpaste{ig:=initial(g)  \free{g}\bound{ig}}
}
\xtc{
Using these three operations, it is possible to reduce \spad{f} modulo
the differential ideal generated by \spad{g}.  The general scheme is
to first reduce the order, then reduce the degree in the leader.
First, eliminate \spad{z.3} using the derivative of \spad{g}.
}{
\spadpaste{g1 := D g \free{g}\bound{g1}}
}
\xtc{
Find its leader.
}{
\spadpaste{lg1:= leader g1 \free{g1}\bound{lg1}}
}
\xtc{
Differentiate \spad{f} partially with respect to this leader.
}{
\spadpaste{pdf:=D(f, lg1) \free{f}\free{lg1}\bound{pdf}}
}
\xtc{
Compute the partial remainder of \spad{f} with respect to \spad{g}.
}{
\spadpaste{prf:=sg * f- pdf * g1 \free{f}\free{sg}\free{pdf}
\free{g1}\bound{prf}}
}
\xtc{
Note that high powers of \spad{lg} still appear in \spad{prf}.
Compute the leading coefficient of \spad{prf}
as a polynomial in the leader of \spad{g}.
}{
\spadpaste{lcf:=leadingCoefficient univariate(prf, lg) 
\free{prf}\free{lg}\bound{lcf}}
}
\xtc{
Finally, continue eliminating the high powers of \spad{lg} appearing in
\spad{prf} to obtain the (pseudo) remainder of \spad{f} modulo \spad{g}
and its derivatives.
}{
\spadpaste{ig * prf - lcf * g * lg \free{ig}\free{prf}
\free{lcf}\free{g}\free{lg}}
}
\showBlurb{OrderlyDifferentialPolyomial}
\showBlurb{SequentialDifferentialPolynomial}
\endscroll
\autobuttons
\end{page}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch1}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull1}{OrderlyDifferentialPolynomialXmpPageEmpty1}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{dpol:= ODPOL(FRAC INT)\bound{dpol }}
\indentrel{3}\begin{verbatim}
   (1)  OrderlyDifferentialPolynomial Fraction Integer
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty1}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty1}{OrderlyDifferentialPolynomialXmpPagePatch1}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{dpol:= ODPOL(FRAC INT)\bound{dpol }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch2}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull2}{OrderlyDifferentialPolynomialXmpPageEmpty2}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{w := makeVariable('w)$dpol\free{dpol }\bound{w }}
\indentrel{3}\begin{verbatim}
   (2)  theMap(DPOLCAT-;makeVariable;AM;17!0,62)
Type: (NonNegativeInteger -> OrderlyDifferentialPolynomial Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty2}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty2}{OrderlyDifferentialPolynomialXmpPagePatch2}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{w := makeVariable('w)$dpol\free{dpol }\bound{w }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch3}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull3}{OrderlyDifferentialPolynomialXmpPageEmpty3}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{z := makeVariable('z)$dpol\free{dpol }\bound{z }}
\indentrel{3}\begin{verbatim}
   (3)  theMap(DPOLCAT-;makeVariable;AM;17!0,187)
Type: (NonNegativeInteger -> OrderlyDifferentialPolynomial Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty3}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty3}{OrderlyDifferentialPolynomialXmpPagePatch3}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{z := makeVariable('z)$dpol\free{dpol }\bound{z }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch4}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull4}{OrderlyDifferentialPolynomialXmpPageEmpty4}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{w.5\free{w }}
\indentrel{3}\begin{verbatim}
   (4)  w
         5
   Type: OrderlyDifferentialPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty4}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty4}{OrderlyDifferentialPolynomialXmpPagePatch4}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{w.5\free{w }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch5}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull5}{OrderlyDifferentialPolynomialXmpPageEmpty5}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{w 0\free{w }}
\indentrel{3}\begin{verbatim}
   (5)  w
   Type: OrderlyDifferentialPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty5}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty5}{OrderlyDifferentialPolynomialXmpPagePatch5}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{w 0\free{w }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch6}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull6}{OrderlyDifferentialPolynomialXmpPageEmpty6}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{[z.i for i in 1..5]\free{z }}
\indentrel{3}\begin{verbatim}
   (6)  [z ,z ,z ,z ,z ]
          1  2  3  4  5
Type: List OrderlyDifferentialPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty6}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty6}{OrderlyDifferentialPolynomialXmpPagePatch6}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{[z.i for i in 1..5]\free{z }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch7}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull7}{OrderlyDifferentialPolynomialXmpPageEmpty7}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{f:= w.4 - w.1 * w.1 * z.3\free{w }\free{z }\bound{f }}
\indentrel{3}\begin{verbatim}
               2
   (7)  w  - w  z
         4    1  3
   Type: OrderlyDifferentialPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty7}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty7}{OrderlyDifferentialPolynomialXmpPagePatch7}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{f:= w.4 - w.1 * w.1 * z.3\free{w }\free{z }\bound{f }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch8}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull8}{OrderlyDifferentialPolynomialXmpPageEmpty8}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{g:=(z.1)**3 * (z.2)**2 - w.2\free{z }\free{w }\bound{g }}
\indentrel{3}\begin{verbatim}
          3  2
   (8)  z  z   - w
         1  2     2
   Type: OrderlyDifferentialPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty8}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty8}{OrderlyDifferentialPolynomialXmpPagePatch8}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{g:=(z.1)**3 * (z.2)**2 - w.2\free{z }\free{w }\bound{g }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch9}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull9}{OrderlyDifferentialPolynomialXmpPageEmpty9}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{D(f)\free{f }}
\indentrel{3}\begin{verbatim}
               2
   (9)  w  - w  z  - 2w w z
         5    1  4     1 2 3
   Type: OrderlyDifferentialPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty9}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty9}{OrderlyDifferentialPolynomialXmpPagePatch9}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{D(f)\free{f }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch10}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull10}{OrderlyDifferentialPolynomialXmpPageEmpty10}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{D(f,4)\free{f }}
\indentrel{3}\begin{verbatim}
   (10)
            2                               2
     w  - w  z  - 8w w z  + (- 12w w  - 12w  )z  - 2w z w
      8    1  7     1 2 6         1 3      2   5     1 3 5
   + 
                                         2
     (- 8w w  - 24w w )z  - 8w z w  - 6w  z
          1 4      2 3  4     2 3 4     3  3
   Type: OrderlyDifferentialPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty10}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty10}{OrderlyDifferentialPolynomialXmpPagePatch10}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{D(f,4)\free{f }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch11}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull11}{OrderlyDifferentialPolynomialXmpPageEmpty11}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{df:=makeVariable(f)$dpol\free{f }\bound{df }}
\indentrel{3}\begin{verbatim}
   (11)  theMap(DPOLCAT-;makeVariable;AM;17!0,488)
Type: (NonNegativeInteger -> OrderlyDifferentialPolynomial Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty11}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty11}{OrderlyDifferentialPolynomialXmpPagePatch11}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{df:=makeVariable(f)$dpol\free{f }\bound{df }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch12}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull12}{OrderlyDifferentialPolynomialXmpPageEmpty12}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{df.4\free{df }}
\indentrel{3}\begin{verbatim}
   (12)
            2                               2
     w  - w  z  - 8w w z  + (- 12w w  - 12w  )z  - 2w z w
      8    1  7     1 2 6         1 3      2   5     1 3 5
   + 
                                         2
     (- 8w w  - 24w w )z  - 8w z w  - 6w  z
          1 4      2 3  4     2 3 4     3  3
   Type: OrderlyDifferentialPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty12}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty12}{OrderlyDifferentialPolynomialXmpPagePatch12}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{df.4\free{df }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch13}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull13}{OrderlyDifferentialPolynomialXmpPageEmpty13}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{order(g)\free{g }}
\indentrel{3}\begin{verbatim}
   (13)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty13}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty13}{OrderlyDifferentialPolynomialXmpPagePatch13}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{order(g)\free{g }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch14}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull14}{OrderlyDifferentialPolynomialXmpPageEmpty14}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{order(g, 'w)\free{g }}
\indentrel{3}\begin{verbatim}
   (14)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty14}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty14}{OrderlyDifferentialPolynomialXmpPagePatch14}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{order(g, 'w)\free{g }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch15}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull15}{OrderlyDifferentialPolynomialXmpPageEmpty15}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{differentialVariables(g)\free{g }}
\indentrel{3}\begin{verbatim}
   (15)  [z,w]
                                      Type: List Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty15}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty15}{OrderlyDifferentialPolynomialXmpPagePatch15}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{differentialVariables(g)\free{g }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch16}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull16}{OrderlyDifferentialPolynomialXmpPageEmpty16}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{degree(g)\free{g }}
\indentrel{3}\begin{verbatim}
           2  3
   (16)  z  z
          2  1
Type: IndexedExponents OrderlyDifferentialVariable Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty16}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty16}{OrderlyDifferentialPolynomialXmpPagePatch16}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{degree(g)\free{g }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch17}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull17}{OrderlyDifferentialPolynomialXmpPageEmpty17}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{degree(g, 'w)\free{g }}
\indentrel{3}\begin{verbatim}
   (17)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty17}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty17}{OrderlyDifferentialPolynomialXmpPagePatch17}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{degree(g, 'w)\free{g }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch18}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull18}{OrderlyDifferentialPolynomialXmpPageEmpty18}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{weights(g)\free{g }}
\indentrel{3}\begin{verbatim}
   (18)  [7,2]
                          Type: List NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty18}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty18}{OrderlyDifferentialPolynomialXmpPagePatch18}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{weights(g)\free{g }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch19}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull19}{OrderlyDifferentialPolynomialXmpPageEmpty19}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{weights(g,'w)\free{g }}
\indentrel{3}\begin{verbatim}
   (19)  [2]
                          Type: List NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty19}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty19}{OrderlyDifferentialPolynomialXmpPagePatch19}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{weights(g,'w)\free{g }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch20}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull20}{OrderlyDifferentialPolynomialXmpPageEmpty20}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{weight(g)\free{g }}
\indentrel{3}\begin{verbatim}
   (20)  7
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty20}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty20}{OrderlyDifferentialPolynomialXmpPagePatch20}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{weight(g)\free{g }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch21}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull21}{OrderlyDifferentialPolynomialXmpPageEmpty21}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{isobaric?(g)\free{g }}
\indentrel{3}\begin{verbatim}
   (21)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty21}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty21}{OrderlyDifferentialPolynomialXmpPagePatch21}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{isobaric?(g)\free{g }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch22}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull22}{OrderlyDifferentialPolynomialXmpPageEmpty22}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull22}{\hidepaste}
\tab{5}\spadcommand{eval(g,['w::Symbol],[f])\free{f }\free{g }}
\indentrel{3}\begin{verbatim}
   (22)
            2                           2        3  2
   - w  + w  z  + 4w w z  + (2w w  + 2w  )z  + z  z
      6    1  5     1 2 4      1 3     2   3    1  2
   Type: OrderlyDifferentialPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty22}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty22}{OrderlyDifferentialPolynomialXmpPagePatch22}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty22}{\showpaste}
\tab{5}\spadcommand{eval(g,['w::Symbol],[f])\free{f }\free{g }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch23}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull23}{OrderlyDifferentialPolynomialXmpPageEmpty23}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull23}{\hidepaste}
\tab{5}\spadcommand{eval(g,variables(w.0),[f])\free{f }\free{g }}
\indentrel{3}\begin{verbatim}
           3  2
   (23)  z  z   - w
          1  2     2
   Type: OrderlyDifferentialPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty23}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty23}{OrderlyDifferentialPolynomialXmpPagePatch23}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty23}{\showpaste}
\tab{5}\spadcommand{eval(g,variables(w.0),[f])\free{f }\free{g }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch24}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull24}{OrderlyDifferentialPolynomialXmpPageEmpty24}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull24}{\hidepaste}
\tab{5}\spadcommand{monomials(g)\free{g }}
\indentrel{3}\begin{verbatim}
            3  2
   (24)  [z  z  ,- w ]
           1  2     2
Type: List OrderlyDifferentialPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty24}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty24}{OrderlyDifferentialPolynomialXmpPagePatch24}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty24}{\showpaste}
\tab{5}\spadcommand{monomials(g)\free{g }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch25}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull25}{OrderlyDifferentialPolynomialXmpPageEmpty25}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull25}{\hidepaste}
\tab{5}\spadcommand{variables(g)\free{g }}
\indentrel{3}\begin{verbatim}
   (25)  [z ,w ,z ]
           2  2  1
          Type: List OrderlyDifferentialVariable Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty25}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty25}{OrderlyDifferentialPolynomialXmpPagePatch25}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty25}{\showpaste}
\tab{5}\spadcommand{variables(g)\free{g }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch26}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull26}{OrderlyDifferentialPolynomialXmpPageEmpty26}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull26}{\hidepaste}
\tab{5}\spadcommand{gcd(f,g)\free{f }\free{g }}
\indentrel{3}\begin{verbatim}
   (26)  1
   Type: OrderlyDifferentialPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty26}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty26}{OrderlyDifferentialPolynomialXmpPagePatch26}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty26}{\showpaste}
\tab{5}\spadcommand{gcd(f,g)\free{f }\free{g }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch27}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull27}{OrderlyDifferentialPolynomialXmpPageEmpty27}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull27}{\hidepaste}
\tab{5}\spadcommand{groebner([f,g])\free{f }\free{g }}
\indentrel{3}\begin{verbatim}
                 2     3  2
   (27)  [w  - w  z ,z  z   - w ]
           4    1  3  1  2     2
Type: List OrderlyDifferentialPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty27}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty27}{OrderlyDifferentialPolynomialXmpPagePatch27}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty27}{\showpaste}
\tab{5}\spadcommand{groebner([f,g])\free{f }\free{g }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch28}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull28}{OrderlyDifferentialPolynomialXmpPageEmpty28}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull28}{\hidepaste}
\tab{5}\spadcommand{lg:=leader(g)\free{g }\bound{lg }}
\indentrel{3}\begin{verbatim}
   (28)  z
          2
               Type: OrderlyDifferentialVariable Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty28}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty28}{OrderlyDifferentialPolynomialXmpPagePatch28}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty28}{\showpaste}
\tab{5}\spadcommand{lg:=leader(g)\free{g }\bound{lg }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch29}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull29}{OrderlyDifferentialPolynomialXmpPageEmpty29}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull29}{\hidepaste}
\tab{5}\spadcommand{sg:=separant(g)\free{g }\bound{sg }}
\indentrel{3}\begin{verbatim}
            3
   (29)  2z  z
           1  2
   Type: OrderlyDifferentialPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty29}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty29}{OrderlyDifferentialPolynomialXmpPagePatch29}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty29}{\showpaste}
\tab{5}\spadcommand{sg:=separant(g)\free{g }\bound{sg }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch30}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull30}{OrderlyDifferentialPolynomialXmpPageEmpty30}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull30}{\hidepaste}
\tab{5}\spadcommand{ig:=initial(g)\free{g }\bound{ig }}
\indentrel{3}\begin{verbatim}
           3
   (30)  z
          1
   Type: OrderlyDifferentialPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty30}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty30}{OrderlyDifferentialPolynomialXmpPagePatch30}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty30}{\showpaste}
\tab{5}\spadcommand{ig:=initial(g)\free{g }\bound{ig }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch31}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull31}{OrderlyDifferentialPolynomialXmpPageEmpty31}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull31}{\hidepaste}
\tab{5}\spadcommand{g1 := D g\free{g }\bound{g1 }}
\indentrel{3}\begin{verbatim}
            3               2  3
   (31)  2z  z z  - w  + 3z  z
           1  2 3    3     1  2
   Type: OrderlyDifferentialPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty31}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty31}{OrderlyDifferentialPolynomialXmpPagePatch31}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty31}{\showpaste}
\tab{5}\spadcommand{g1 := D g\free{g }\bound{g1 }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch32}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull32}{OrderlyDifferentialPolynomialXmpPageEmpty32}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull32}{\hidepaste}
\tab{5}\spadcommand{lg1:= leader g1\free{g1 }\bound{lg1 }}
\indentrel{3}\begin{verbatim}
   (32)  z
          3
               Type: OrderlyDifferentialVariable Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty32}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty32}{OrderlyDifferentialPolynomialXmpPagePatch32}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty32}{\showpaste}
\tab{5}\spadcommand{lg1:= leader g1\free{g1 }\bound{lg1 }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch33}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull33}{OrderlyDifferentialPolynomialXmpPageEmpty33}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull33}{\hidepaste}
\tab{5}\spadcommand{pdf:=D(f, lg1)\free{f }\free{lg1 }\bound{pdf }}
\indentrel{3}\begin{verbatim}
             2
   (33)  - w
            1
   Type: OrderlyDifferentialPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty33}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty33}{OrderlyDifferentialPolynomialXmpPagePatch33}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty33}{\showpaste}
\tab{5}\spadcommand{pdf:=D(f, lg1)\free{f }\free{lg1 }\bound{pdf }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch34}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull34}{OrderlyDifferentialPolynomialXmpPageEmpty34}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull34}{\hidepaste}
\tab{5}\spadcommand{prf:=sg * f- pdf * g1\free{f }\free{sg }\free{pdf }\free{g1 }\bound{prf }}
\indentrel{3}\begin{verbatim}
            3         2        2  2  3
   (34)  2z  z w  - w  w  + 3w  z  z
           1  2 4    1  3     1  1  2
   Type: OrderlyDifferentialPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty34}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty34}{OrderlyDifferentialPolynomialXmpPagePatch34}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty34}{\showpaste}
\tab{5}\spadcommand{prf:=sg * f- pdf * g1\free{f }\free{sg }\free{pdf }\free{g1 }\bound{prf }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch35}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull35}{OrderlyDifferentialPolynomialXmpPageEmpty35}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull35}{\hidepaste}
\tab{5}\spadcommand{lcf:=leadingCoefficient univariate(prf, lg)\free{prf }\free{lg }\bound{lcf }}
\indentrel{3}\begin{verbatim}
            2  2
   (35)  3w  z
           1  1
   Type: OrderlyDifferentialPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty35}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty35}{OrderlyDifferentialPolynomialXmpPagePatch35}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty35}{\showpaste}
\tab{5}\spadcommand{lcf:=leadingCoefficient univariate(prf, lg)\free{prf }\free{lg }\bound{lcf }}
\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPagePatch36}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageFull36}{OrderlyDifferentialPolynomialXmpPageEmpty36}
\pastebutton{OrderlyDifferentialPolynomialXmpPageFull36}{\hidepaste}
\tab{5}\spadcommand{ig * prf - lcf * g * lg\free{ig }\free{prf }\free{lcf }\free{g }\free{lg }}
\indentrel{3}\begin{verbatim}
            6         2  3        2  2
   (36)  2z  z w  - w  z  w  + 3w  z  w z
           1  2 4    1  1  3     1  1  2 2
   Type: OrderlyDifferentialPolynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderlyDifferentialPolynomialXmpPageEmpty36}
\begin{paste}{OrderlyDifferentialPolynomialXmpPageEmpty36}{OrderlyDifferentialPolynomialXmpPagePatch36}
\pastebutton{OrderlyDifferentialPolynomialXmpPageEmpty36}{\showpaste}
\tab{5}\spadcommand{ig * prf - lcf * g * lg\free{ig }\free{prf }\free{lcf }\free{g }\free{lg }}
\end{paste}\end{patch}

\end{chunk}
\section{op.ht}
\pagetitle{OperatorXmpPage}{op.ht}{Operator}
\begin{chunk}{op.ht}
\begin{page}{OperatorXmpPage}{Operator}
\beginscroll
Given any ring \spad{R}, the ring of the \spadtype{Integer}-linear
operators over \spad{R} is called \spadtype{Operator(R)}.  To create
an operator over \spad{R}, first create a basic operator using the
operation \spadfun{operator}, and then convert it to
\spadtype{Operator(R)} for the \spad{R} you want.
%
\xtc{
We choose \spad{R} to be the two by two matrices over the integers.
}{
\spadpaste{R := SQMATRIX(2, INT)\bound{r}}
}
\xtc{
Create the operator \spad{tilde} on \spad{R}.
}{
\spadpaste{t := operator("tilde") :: OP(R) \free{r}\bound{t}}
}
%
Since \spadtype{Operator} is unexposed we must either package-call
operations from it, or expose it explicitly.  For convenience we will
do the latter.
%
\noOutputXtc{
Expose \spad{Operator}.
}{
\spadpaste{)set expose add constructor Operator \free{t}\bound{expose}}
}
%
To attach an evaluation function (from \spad{R} to \spad{R}) to an
operator over \spad{R}, use \spad{evaluate(op, f)} where \spad{op}
is an operator over \spad{R} and \spad{f} is a function \spad{R ->
R}.
This needs to be done only once when the operator is defined.
Note that \spad{f} must be \spadtype{Integer}-linear (that is,
\spad{f(ax+y) = a f(x) + f(y)} for any integer \spad{a}, and any
\spad{x} and \spad{y} in \spad{R}).
%
\xtc{
We now attach the transpose map to the above operator \spad{t}.
}{
\spadpaste{evaluate(t, m +-> transpose m)\free{expose}\free{t}\bound{evt}}
}
%
Operators can be manipulated formally as in any ring: \spadop{+} is the
pointwise addition and \spadop{*} is composition.
Any element \spad{x} of \spad{R} can be converted to an operator
\subscriptText{\tt op}{\tt x}
over \spad{R}, and the evaluation function of
\subscriptText{\tt op}{\tt x}
is left-multiplication by \spad{x}.
%
\xtc{
Multiplying on the
left by this matrix swaps the two rows.
}{
\spadpaste{s : R := matrix [[0, 1], [1, 0]]\bound{s}}
}
%
\xtc{
Can you guess what is the action of the following operator?
}{
\spadpaste{rho := t * s\free{evt s}\bound{rho}}
}
%
%
\xtc{
Hint: applying \spad{rho} four times gives the identity, so
\spad{rho**4-1} should return 0 when applied to any two by two matrix.
}{
\spadpaste{z := rho**4 - 1\free{rho}\bound{z}}
}
%
%
\xtc{
Now check with this matrix.
}{
\spadpaste{m:R := matrix [[1, 2], [3, 4]]\bound{m}}
}
\xtc{
}{
\spadpaste{z m\free{z m}}
}
%
%
\xtc{
As you have probably guessed by now, \spad{rho} acts on matrices
by rotating the elements clockwise.
}{
\spadpaste{rho m\free{rho m}}
}
\xtc{
}{
\spadpaste{rho rho m\free{rho m}}
}
\xtc{
}{
\spadpaste{(rho**3) m\free{rho m}}
}
%
%
\xtc{
Do the swapping of rows and transposition commute?
We can check by computing their bracket.
}{
\spadpaste{b := t * s - s * t\free{s evt}\bound{b}}
}
%
%
\xtc{
Now apply it to \spad{m}.
}{
\spadpaste{b m \free{b m}}
}
%
 
Next we demonstrate how to define a differential operator
on a polynomial ring.
\xtc{
This is the recursive definition of the \spad{n}-th Legendre polynomial.
}{
\begin{spadsrc}[\bound{l}]
L n ==
  n = 0 => 1
  n = 1 => x
  (2*n-1)/n * x * L(n-1) - (n-1)/n * L(n-2)
\end{spadsrc}
}
\xtc{
Create the differential operator \texht{$d \over {dx}$}{\spad{d/dx}} on
polynomials in \spad{x} over the rational numbers.
}{
\spadpaste{dx := operator("D") :: OP(POLY FRAC INT) \bound{dx}}
}
\xtc{
Now attach the map to it.
}{
\spadpaste{evaluate(dx, p +-> D(p, 'x)) \free{dx}\bound{edx}}
}
\xtc{
This is the differential equation satisfied by the \spad{n}-th
Legendre polynomial.
}{
\spadpaste{E n == (1 - x**2) * dx**2 - 2 * x * dx + n*(n+1) 
\free{edx}\bound{E}}
}
\xtc{
Now we verify this for \spad{n = 15}.
Here is the polynomial.
}{
\spadpaste{L 15 \free{L}}
}
\xtc{
Here is the operator.
}{
\spadpaste{E 15 \free{E}}
}
\xtc{
Here is the evaluation.
}{
\spadpaste{(E 15)(L 15) \free{L E}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{OperatorXmpPagePatch1}
\begin{paste}{OperatorXmpPageFull1}{OperatorXmpPageEmpty1}
\pastebutton{OperatorXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{R := SQMATRIX(2, INT)\bound{r }}
\indentrel{3}\begin{verbatim}
   (1)  SquareMatrix(2,Integer)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OperatorXmpPageEmpty1}
\begin{paste}{OperatorXmpPageEmpty1}{OperatorXmpPagePatch1}
\pastebutton{OperatorXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{R := SQMATRIX(2, INT)\bound{r }}
\end{paste}\end{patch}

\begin{patch}{OperatorXmpPagePatch2}
\begin{paste}{OperatorXmpPageFull2}{OperatorXmpPageEmpty2}
\pastebutton{OperatorXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{t := operator("tilde") :: OP(R)\free{r }\bound{t }}
\indentrel{3}\begin{verbatim}
   (2)  tilde
                 Type: Operator SquareMatrix(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OperatorXmpPageEmpty2}
\begin{paste}{OperatorXmpPageEmpty2}{OperatorXmpPagePatch2}
\pastebutton{OperatorXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{t := operator("tilde") :: OP(R)\free{r }\bound{t }}
\end{paste}\end{patch}

\begin{patch}{OperatorXmpPagePatch3}
\begin{paste}{OperatorXmpPageFull3}{OperatorXmpPageEmpty3}
\pastebutton{OperatorXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{)set expose add constructor Operator\free{t }\bound{expose }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OperatorXmpPageEmpty3}
\begin{paste}{OperatorXmpPageEmpty3}{OperatorXmpPagePatch3}
\pastebutton{OperatorXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{)set expose add constructor Operator\free{t }\bound{expose }}
\end{paste}\end{patch}

\begin{patch}{OperatorXmpPagePatch4}
\begin{paste}{OperatorXmpPageFull4}{OperatorXmpPageEmpty4}
\pastebutton{OperatorXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{evaluate(t, m +-> transpose m)\free{expose }\free{t }\bound{evt }}
\indentrel{3}\begin{verbatim}
   (3)  tilde
                 Type: Operator SquareMatrix(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OperatorXmpPageEmpty4}
\begin{paste}{OperatorXmpPageEmpty4}{OperatorXmpPagePatch4}
\pastebutton{OperatorXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{evaluate(t, m +-> transpose m)\free{expose }\free{t }\bound{evt }}
\end{paste}\end{patch}

\begin{patch}{OperatorXmpPagePatch5}
\begin{paste}{OperatorXmpPageFull5}{OperatorXmpPageEmpty5}
\pastebutton{OperatorXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{s : R := matrix [[0, 1], [1, 0]]\bound{s }}
\indentrel{3}\begin{verbatim}
        Ú0  1¿
   (4)  ³    ³
        À1  0Ù
                          Type: SquareMatrix(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OperatorXmpPageEmpty5}
\begin{paste}{OperatorXmpPageEmpty5}{OperatorXmpPagePatch5}
\pastebutton{OperatorXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{s : R := matrix [[0, 1], [1, 0]]\bound{s }}
\end{paste}\end{patch}

\begin{patch}{OperatorXmpPagePatch6}
\begin{paste}{OperatorXmpPageFull6}{OperatorXmpPageEmpty6}
\pastebutton{OperatorXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{rho := t * s\free{evt s }\bound{rho }}
\indentrel{3}\begin{verbatim}
             Ú0  1¿
   (5)  tilde³    ³
             À1  0Ù
                 Type: Operator SquareMatrix(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OperatorXmpPageEmpty6}
\begin{paste}{OperatorXmpPageEmpty6}{OperatorXmpPagePatch6}
\pastebutton{OperatorXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{rho := t * s\free{evt s }\bound{rho }}
\end{paste}\end{patch}

\begin{patch}{OperatorXmpPagePatch7}
\begin{paste}{OperatorXmpPageFull7}{OperatorXmpPageEmpty7}
\pastebutton{OperatorXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{z := rho**4 - 1\free{rho }\bound{z }}
\indentrel{3}\begin{verbatim}
   (6)
              Ú0  1¿     Ú0  1¿     Ú0  1¿     Ú0  1¿
   - 1 + tilde³    ³tilde³    ³tilde³    ³tilde³    ³
              À1  0Ù     À1  0Ù     À1  0Ù     À1  0Ù
                 Type: Operator SquareMatrix(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OperatorXmpPageEmpty7}
\begin{paste}{OperatorXmpPageEmpty7}{OperatorXmpPagePatch7}
\pastebutton{OperatorXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{z := rho**4 - 1\free{rho }\bound{z }}
\end{paste}\end{patch}

\begin{patch}{OperatorXmpPagePatch8}
\begin{paste}{OperatorXmpPageFull8}{OperatorXmpPageEmpty8}
\pastebutton{OperatorXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{m:R := matrix [[1, 2], [3, 4]]\bound{m }}
\indentrel{3}\begin{verbatim}
        Ú1  2¿
   (7)  ³    ³
        À3  4Ù
                          Type: SquareMatrix(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OperatorXmpPageEmpty8}
\begin{paste}{OperatorXmpPageEmpty8}{OperatorXmpPagePatch8}
\pastebutton{OperatorXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{m:R := matrix [[1, 2], [3, 4]]\bound{m }}
\end{paste}\end{patch}

\begin{patch}{OperatorXmpPagePatch9}
\begin{paste}{OperatorXmpPageFull9}{OperatorXmpPageEmpty9}
\pastebutton{OperatorXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{z m\free{z m }}
\indentrel{3}\begin{verbatim}
        Ú0  0¿
   (8)  ³    ³
        À0  0Ù
                          Type: SquareMatrix(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OperatorXmpPageEmpty9}
\begin{paste}{OperatorXmpPageEmpty9}{OperatorXmpPagePatch9}
\pastebutton{OperatorXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{z m\free{z m }}
\end{paste}\end{patch}

\begin{patch}{OperatorXmpPagePatch10}
\begin{paste}{OperatorXmpPageFull10}{OperatorXmpPageEmpty10}
\pastebutton{OperatorXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{rho m\free{rho m }}
\indentrel{3}\begin{verbatim}
        Ú3  1¿
   (9)  ³    ³
        À4  2Ù
                          Type: SquareMatrix(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OperatorXmpPageEmpty10}
\begin{paste}{OperatorXmpPageEmpty10}{OperatorXmpPagePatch10}
\pastebutton{OperatorXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{rho m\free{rho m }}
\end{paste}\end{patch}

\begin{patch}{OperatorXmpPagePatch11}
\begin{paste}{OperatorXmpPageFull11}{OperatorXmpPageEmpty11}
\pastebutton{OperatorXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{rho rho m\free{rho m }}
\indentrel{3}\begin{verbatim}
         Ú4  3¿
   (10)  ³    ³
         À2  1Ù
                          Type: SquareMatrix(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OperatorXmpPageEmpty11}
\begin{paste}{OperatorXmpPageEmpty11}{OperatorXmpPagePatch11}
\pastebutton{OperatorXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{rho rho m\free{rho m }}
\end{paste}\end{patch}

\begin{patch}{OperatorXmpPagePatch12}
\begin{paste}{OperatorXmpPageFull12}{OperatorXmpPageEmpty12}
\pastebutton{OperatorXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{(rho**3) m\free{rho m }}
\indentrel{3}\begin{verbatim}
         Ú2  4¿
   (11)  ³    ³
         À1  3Ù
                          Type: SquareMatrix(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OperatorXmpPageEmpty12}
\begin{paste}{OperatorXmpPageEmpty12}{OperatorXmpPagePatch12}
\pastebutton{OperatorXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{(rho**3) m\free{rho m }}
\end{paste}\end{patch}

\begin{patch}{OperatorXmpPagePatch13}
\begin{paste}{OperatorXmpPageFull13}{OperatorXmpPageEmpty13}
\pastebutton{OperatorXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{b := t * s - s * t\free{s evt }\bound{b }}
\indentrel{3}\begin{verbatim}
           Ú0  1¿             Ú0  1¿
   (12)  - ³    ³tilde + tilde³    ³
           À1  0Ù             À1  0Ù
                 Type: Operator SquareMatrix(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OperatorXmpPageEmpty13}
\begin{paste}{OperatorXmpPageEmpty13}{OperatorXmpPagePatch13}
\pastebutton{OperatorXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{b := t * s - s * t\free{s evt }\bound{b }}
\end{paste}\end{patch}

\begin{patch}{OperatorXmpPagePatch14}
\begin{paste}{OperatorXmpPageFull14}{OperatorXmpPageEmpty14}
\pastebutton{OperatorXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{b m\free{b m }}
\indentrel{3}\begin{verbatim}
         Ú1  - 3¿
   (13)  ³      ³
         À3  - 1Ù
                          Type: SquareMatrix(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OperatorXmpPageEmpty14}
\begin{paste}{OperatorXmpPageEmpty14}{OperatorXmpPagePatch14}
\pastebutton{OperatorXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{b m\free{b m }}
\end{paste}\end{patch}

\begin{patch}{OperatorXmpPagePatch15}
\begin{paste}{OperatorXmpPageFull15}{OperatorXmpPageEmpty15}
\pastebutton{OperatorXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{L n ==
  n = 0 => 1
  n = 1 => x
  (2*n-1)/n * x * L(n-1) - (n-1)/n * L(n-2)
\bound{l }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OperatorXmpPageEmpty15}
\begin{paste}{OperatorXmpPageEmpty15}{OperatorXmpPagePatch15}
\pastebutton{OperatorXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{L n ==
  n = 0 => 1
  n = 1 => x
  (2*n-1)/n * x * L(n-1) - (n-1)/n * L(n-2)
\bound{l }}
\end{paste}\end{patch}

\begin{patch}{OperatorXmpPagePatch16}
\begin{paste}{OperatorXmpPageFull16}{OperatorXmpPageEmpty16}
\pastebutton{OperatorXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{dx := operator("D") :: OP(POLY FRAC INT)\bound{dx }}
\indentrel{3}\begin{verbatim}
   (15)  D
             Type: Operator Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OperatorXmpPageEmpty16}
\begin{paste}{OperatorXmpPageEmpty16}{OperatorXmpPagePatch16}
\pastebutton{OperatorXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{dx := operator("D") :: OP(POLY FRAC INT)\bound{dx }}
\end{paste}\end{patch}

\begin{patch}{OperatorXmpPagePatch17}
\begin{paste}{OperatorXmpPageFull17}{OperatorXmpPageEmpty17}
\pastebutton{OperatorXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{evaluate(dx, p +-> D(p, 'x))\free{dx }\bound{edx }}
\indentrel{3}\begin{verbatim}
   (16)  D
             Type: Operator Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OperatorXmpPageEmpty17}
\begin{paste}{OperatorXmpPageEmpty17}{OperatorXmpPagePatch17}
\pastebutton{OperatorXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{evaluate(dx, p +-> D(p, 'x))\free{dx }\bound{edx }}
\end{paste}\end{patch}

\begin{patch}{OperatorXmpPagePatch18}
\begin{paste}{OperatorXmpPageFull18}{OperatorXmpPageEmpty18}
\pastebutton{OperatorXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{E n == (1 - x**2) * dx**2 - 2 * x * dx + n*(n+1)\free{edx }\bound{E }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OperatorXmpPageEmpty18}
\begin{paste}{OperatorXmpPageEmpty18}{OperatorXmpPagePatch18}
\pastebutton{OperatorXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{E n == (1 - x**2) * dx**2 - 2 * x * dx + n*(n+1)\free{edx }\bound{E }}
\end{paste}\end{patch}

\begin{patch}{OperatorXmpPagePatch19}
\begin{paste}{OperatorXmpPageFull19}{OperatorXmpPageEmpty19}
\pastebutton{OperatorXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{L 15\free{L }}
\indentrel{3}\begin{verbatim}
   (18)
     9694845  15   35102025  13   50702925  11
     ÄÄÄÄÄÄÄ x   - ÄÄÄÄÄÄÄÄ x   + ÄÄÄÄÄÄÄÄ x
       2048          2048           2048
   + 
       37182145  9   14549535  7   2909907  5   255255  3
     - ÄÄÄÄÄÄÄÄ x  + ÄÄÄÄÄÄÄÄ x  - ÄÄÄÄÄÄÄ x  + ÄÄÄÄÄÄ x
         2048          2048          2048        2048
   + 
       6435
     - ÄÄÄÄ x
       2048
                      Type: Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OperatorXmpPageEmpty19}
\begin{paste}{OperatorXmpPageEmpty19}{OperatorXmpPagePatch19}
\pastebutton{OperatorXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{L 15\free{L }}
\end{paste}\end{patch}

\begin{patch}{OperatorXmpPagePatch20}
\begin{paste}{OperatorXmpPageFull20}{OperatorXmpPageEmpty20}
\pastebutton{OperatorXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{E 15\free{E }}
\indentrel{3}\begin{verbatim}
                        2      2
   (19)  240 - 2x D - (x  - 1)D
             Type: Operator Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OperatorXmpPageEmpty20}
\begin{paste}{OperatorXmpPageEmpty20}{OperatorXmpPagePatch20}
\pastebutton{OperatorXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{E 15\free{E }}
\end{paste}\end{patch}

\begin{patch}{OperatorXmpPagePatch21}
\begin{paste}{OperatorXmpPageFull21}{OperatorXmpPageEmpty21}
\pastebutton{OperatorXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{(E 15)(L 15)\free{L E }}
\indentrel{3}\begin{verbatim}
   (20)  0
                      Type: Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OperatorXmpPageEmpty21}
\begin{paste}{OperatorXmpPageEmpty21}{OperatorXmpPagePatch21}
\pastebutton{OperatorXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{(E 15)(L 15)\free{L E }}
\end{paste}\end{patch}

\end{chunk}
\section{ovar.ht}
\pagetitle{OrderedVariableListXmpPage}{ovar.ht}{OrderedVariableList}
\begin{chunk}{ovar.ht}
\begin{page}{OrderedVariableListXmpPage}{OrderedVariableList}
\beginscroll

The domain \spadtype{OrderedVariableList} provides symbols
which are restricted to a particular list and have a definite 
ordering. Those two features are specified by a \spadtype{List Symbol}
object that is the argument to the domain.
\xtc{
This is a sample ordering of three symbols.
}{
\spadpaste{ls:List Symbol:=['x,'a,'z] \bound{ls}}
}
\xtc{
Let's build the domain
}{
\spadpaste{Z:=OVAR ls \bound{Z} \free{ls}}
}
\xtc{
How many variables does it have?
}{
\spadpaste{size()$Z \free{Z}}
}
\xtc{
They are (in the imposed order)
}{
\spadpaste{lv:=[index(i::PI)$Z for i in 1..size()$Z] \bound{lv}\free{Z}}
}
\xtc{
Check that the ordering is right
}{
\spadpaste{sorted?(>,lv) \free{lv}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{OrderedVariableListXmpPagePatch1}
\begin{paste}{OrderedVariableListXmpPageFull1}{OrderedVariableListXmpPageEmpty1}
\pastebutton{OrderedVariableListXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{ls:List Symbol:=['x,'a,'z]\bound{ls }}
\indentrel{3}\begin{verbatim}
   (1)  [x,a,z]
                                      Type: List Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderedVariableListXmpPageEmpty1}
\begin{paste}{OrderedVariableListXmpPageEmpty1}{OrderedVariableListXmpPagePatch1}
\pastebutton{OrderedVariableListXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{ls:List Symbol:=['x,'a,'z]\bound{ls }}
\end{paste}\end{patch}

\begin{patch}{OrderedVariableListXmpPagePatch2}
\begin{paste}{OrderedVariableListXmpPageFull2}{OrderedVariableListXmpPageEmpty2}
\pastebutton{OrderedVariableListXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{Z:=OVAR ls\bound{Z }\free{ls }}
\indentrel{3}\begin{verbatim}
   (2)  OrderedVariableList [x,a,z]
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderedVariableListXmpPageEmpty2}
\begin{paste}{OrderedVariableListXmpPageEmpty2}{OrderedVariableListXmpPagePatch2}
\pastebutton{OrderedVariableListXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{Z:=OVAR ls\bound{Z }\free{ls }}
\end{paste}\end{patch}

\begin{patch}{OrderedVariableListXmpPagePatch3}
\begin{paste}{OrderedVariableListXmpPageFull3}{OrderedVariableListXmpPageEmpty3}
\pastebutton{OrderedVariableListXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{size()$Z\free{Z }}
\indentrel{3}\begin{verbatim}
   (3)  3
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderedVariableListXmpPageEmpty3}
\begin{paste}{OrderedVariableListXmpPageEmpty3}{OrderedVariableListXmpPagePatch3}
\pastebutton{OrderedVariableListXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{size()$Z\free{Z }}
\end{paste}\end{patch}

\begin{patch}{OrderedVariableListXmpPagePatch4}
\begin{paste}{OrderedVariableListXmpPageFull4}{OrderedVariableListXmpPageEmpty4}
\pastebutton{OrderedVariableListXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{lv:=[index(i::PI)$Z for i in 1..size()$Z]\bound{lv }\free{Z }}
\indentrel{3}\begin{verbatim}
   (4)  [x,a,z]
                 Type: List OrderedVariableList [x,a,z]
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderedVariableListXmpPageEmpty4}
\begin{paste}{OrderedVariableListXmpPageEmpty4}{OrderedVariableListXmpPagePatch4}
\pastebutton{OrderedVariableListXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{lv:=[index(i::PI)$Z for i in 1..size()$Z]\bound{lv }\free{Z }}
\end{paste}\end{patch}

\begin{patch}{OrderedVariableListXmpPagePatch5}
\begin{paste}{OrderedVariableListXmpPageFull5}{OrderedVariableListXmpPageEmpty5}
\pastebutton{OrderedVariableListXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{sorted?(>,lv)\free{lv }}
\indentrel{3}\begin{verbatim}
   (5)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{OrderedVariableListXmpPageEmpty5}
\begin{paste}{OrderedVariableListXmpPageEmpty5}{OrderedVariableListXmpPagePatch5}
\pastebutton{OrderedVariableListXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{sorted?(>,lv)\free{lv }}
\end{paste}\end{patch}

\end{chunk}
\section{perman.ht}
\pagetitle{PermanentXmpPage}{perman.ht}{Permanent}
\begin{chunk}{perman.ht}
\begin{page}{PermanentXmpPage}{Permanent}
\beginscroll
The package \spadtype{Permanent} provides the function
\spadfunFrom{permanent}{Permanent} for square matrices.
The \spadfunFrom{permanent}{Permanent} of a square matrix can be computed
in the same way as the determinant by expansion of minors except that for
the permanent the sign for each element is \spad{1}, rather than being
\spad{1} if the row plus column indices is positive and \spad{-1}
otherwise.
This function is much more difficult to compute efficiently than the
\spadfunFrom{determinant}{Matrix}.
An example of the use of \spadfunFrom{permanent}{Permanent} is the
calculation of the \eth{\spad{n}} derangement number, defined to be
the number of different possibilities for \spad{n} couples to dance
but never with their own spouse.
\xtc{
Consider an \spad{n} by \spad{n} matrix with entries 
\spad{0} on the diagonal and
\spad{1} elsewhere.
Think of the rows as one-half of each couple (for example, the males)
and the columns the other half.  The permanent of such a matrix gives
the desired derangement number.
}{
\begin{spadsrc}[\bound{kn}]
kn n ==
  r : MATRIX INT := new(n,n,1)
  for i in 1..n repeat
    r.i.i := 0
  r
\end{spadsrc}
}
\xtc{
Here are some derangement numbers, which you see grow quite fast.
}{
\spadpaste{permanent(kn(5) :: SQMATRIX(5,INT)) \free{kn}}
}
\xtc{
}{
\spadpaste{[permanent(kn(n) :: SQMATRIX(n,INT)) for n in 1..13] \free{kn}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{PermanentXmpPagePatch1}
\begin{paste}{PermanentXmpPageFull1}{PermanentXmpPageEmpty1}
\pastebutton{PermanentXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{kn n ==
  r : MATRIX INT := new(n,n,1)
  for i in 1..n repeat
    r.i.i := 0
  r
\bound{kn }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PermanentXmpPageEmpty1}
\begin{paste}{PermanentXmpPageEmpty1}{PermanentXmpPagePatch1}
\pastebutton{PermanentXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{kn n ==
  r : MATRIX INT := new(n,n,1)
  for i in 1..n repeat
    r.i.i := 0
  r
\bound{kn }}
\end{paste}\end{patch}

\begin{patch}{PermanentXmpPagePatch2}
\begin{paste}{PermanentXmpPageFull2}{PermanentXmpPageEmpty2}
\pastebutton{PermanentXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{permanent(kn(5) :: SQMATRIX(5,INT))\free{kn }}
\indentrel{3}\begin{verbatim}
   (2)  44
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PermanentXmpPageEmpty2}
\begin{paste}{PermanentXmpPageEmpty2}{PermanentXmpPagePatch2}
\pastebutton{PermanentXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{permanent(kn(5) :: SQMATRIX(5,INT))\free{kn }}
\end{paste}\end{patch}

\begin{patch}{PermanentXmpPagePatch3}
\begin{paste}{PermanentXmpPageFull3}{PermanentXmpPageEmpty3}
\pastebutton{PermanentXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{[permanent(kn(n) :: SQMATRIX(n,INT)) for n in 1..13]\free{kn }}
\indentrel{3}\begin{verbatim}
   (3)
   [0, 1, 2, 9, 44, 265, 1854, 14833, 133496, 1334961,
    14684570, 176214841, 2290792932]
                          Type: List NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PermanentXmpPageEmpty3}
\begin{paste}{PermanentXmpPageEmpty3}{PermanentXmpPagePatch3}
\pastebutton{PermanentXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{[permanent(kn(n) :: SQMATRIX(n,INT)) for n in 1..13]\free{kn }}
\end{paste}\end{patch}

\end{chunk}
\section{pfr.ht}
\pagetitle{PartialFractionXmpPage}{pfr.ht}{PartialFraction}
\pagepic{ps/v71partialfractionxmppage.eps}{PartialFractionXmpPage}{0.50}
\pagefrom{Axiom Number Types}{NumberPage}
\pageto{FullPartialFracExpansion}{FullPartialFracExpansionXmpPage}
\begin{chunk}{pfr.ht}
\begin{page}{PartialFractionXmpPage}{PartialFraction}
\beginscroll
A {\it partial fraction} is a decomposition of a quotient into a sum
of quotients where the denominators of the summands are powers of
primes.\footnote{Most people first encounter partial fractions when
they are learning integral calculus.  For a technical discussion of
partial fractions, see, for example, Lang's {\it Algebra.}} For
example, the rational number \spad{1/6} is decomposed into 
\spad{1/2-1/3}.  You can compute partial fractions of quotients of 
objects from domains belonging to the category 
\spadtype{EuclideanDomain}.  For
example, \spadtype{Integer}, \spadtype{Complex Integer}, and
\spadtype{UnivariatePolynomial(x, Fraction Integer)} all belong to
\spadtype{EuclideanDomain}.  In the examples following, we demonstrate
how to decompose quotients of each of these kinds of object into
partial fractions.  Issue the system command \spadcmd{)show
PartialFraction} to display the full list of operations defined by
\spadtype{PartialFraction}.

It is necessary that we know how to factor the denominator when we
want to compute a partial fraction.  Although the interpreter can
often do this automatically, it may be necessary for you to include a
call to \spadfun{factor}.  In these examples, it is not necessary to
factor the denominators explicitly.
%
\xtc{
The main operation for computing partial fractions is called
\spadfunFrom{partialFraction}{PartialFraction} and we use this to
compute a decomposition of \spad{1 / 10!}.
The first argument to \spadfunFrom{partialFraction}{PartialFraction} is
the numerator of the quotient and the second argument is the factored
denominator.
}{
\spadpaste{partialFraction(1,factorial 10) \bound{prev1}}
}
\xtc{
Since the denominators are powers of primes, it may be possible
to expand the numerators further with respect to those primes. Use the
operation \spadfunFrom{padicFraction}{PartialFraction} to do this.
}{
\spadpaste{f := padicFraction(\%) \free{prev1}\bound{f}}
}
%
%
\xtc{
The operation \spadfunFrom{compactFraction}{PartialFraction} returns an
expanded fraction into the usual form.
The compacted version is used internally for computational efficiency.
}{
\spadpaste{compactFraction(f) \free{f}}
}
%
\xtc{
You can add, subtract, multiply
and divide partial fractions.  In addition, you can extract the parts
of the decomposition.
\spadfunFrom{numberOfFractionalTerms}{PartialFraction} computes
the number of terms in the fractional part.
This does not include the whole part of the fraction,
which you get by calling \spadfunFrom{wholePart}{PartialFraction}.
In this example, the whole part is just \spad{0}.
}{
\spadpaste{numberOfFractionalTerms(f) \free{f}}
}
\xtc{
The operation \spadfunFrom{nthFractionalTerm}{PartialFraction} returns
the individual terms in the decomposition.  Notice that the object
returned is a partial fraction itself.
\spadfunFrom{firstNumer}{PartialFraction} and
\spadfunFrom{firstDenom}{PartialFraction} extract the numerator and
denominator of the first term of the fraction.
}{
\spadpaste{nthFractionalTerm(f,3) \free{f}}
}
%

%
\xtc{
Given two gaussian integers (see 
\downlink{`Complex'}{ComplexXmpPage}\ignore{Complex}), you can
decompose their quotient into a partial fraction.
}{
\spadpaste{partialFraction(1,- 13 + 14 * \%i) \bound{prev2}}
}
%
\xtc{
To convert back to a quotient, simply use a conversion.
}{
\spadpaste{\% :: Fraction Complex Integer \free{prev2}}
}

To conclude this section, we compute the decomposition of
\texht{\narrowDisplay{1 \over {{(x + 1)}{(x + 2)}^2{(x + 3)}^3{(x + 4)}^4}}}{
\begin{verbatim}
                   1
     -------------------------------
                   2       3       4
     (x + 1)(x + 2) (x + 3) (x + 4)
\end{verbatim}
}
The polynomials in this object have type
\spadtype{UnivariatePolynomial(x, Fraction Integer)}.
%
\xtc{
We use the \spadfunFrom{primeFactor}{Factored} operation (see
\downlink{`Factored'}{FactoredXmpPage}
\ignore{Factored}) to create the denominator in factored form directly.
}{
\spadpaste{u : FR UP(x, FRAC INT) := reduce(*,[primeFactor(x+i,i) 
for i in 1..4]) \bound{u}}
}
%
%
\xtc{
These are the compact and expanded partial fractions for the quotient.
}{
\spadpaste{partialFraction(1,u) \free{u}\bound{prev3}}
}
\xtc{
}{
\spadpaste{padicFraction \% \free{prev3}}
}

All see \downlink{`FullPartialFracExpansion'}
{FullPartialFracExpansionXmpPage}
\ignore{FullPartialFracExpansion} for examples of
factor-free conversion of quotients to full partial fractions.
\endscroll
\autobuttons
\end{page}

\begin{patch}{PartialFractionXmpPagePatch1}
\begin{paste}{PartialFractionXmpPageFull1}{PartialFractionXmpPageEmpty1}
\pastebutton{PartialFractionXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{partialFraction(1,factorial 10)\bound{prev1 }}
\indentrel{3}\begin{verbatim}
        159   23   12   1
   (1)  ÄÄÄ - ÄÄ - ÄÄ + Ä
          8    4    2   7
         2    3    5
                          Type: PartialFraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PartialFractionXmpPageEmpty1}
\begin{paste}{PartialFractionXmpPageEmpty1}{PartialFractionXmpPagePatch1}
\pastebutton{PartialFractionXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{partialFraction(1,factorial 10)\bound{prev1 }}
\end{paste}\end{patch}

\begin{patch}{PartialFractionXmpPagePatch2}
\begin{paste}{PartialFractionXmpPageFull2}{PartialFractionXmpPageEmpty2}
\pastebutton{PartialFractionXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{f := padicFraction(\%)\free{prev1 }\bound{f }}
\indentrel{3}\begin{verbatim}
   (2)
   1    1    1    1    1    1    2    1    2   2    2   1
   Ä + ÄÄ + ÄÄ + ÄÄ + ÄÄ + ÄÄ - ÄÄ - ÄÄ - ÄÄ - Ä - ÄÄ + Ä
   2    4    5    6    7    8    2    3    4   5    2   7
       2    2    2    2    2    3    3    3        5
                          Type: PartialFraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PartialFractionXmpPageEmpty2}
\begin{paste}{PartialFractionXmpPageEmpty2}{PartialFractionXmpPagePatch2}
\pastebutton{PartialFractionXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{f := padicFraction(\%)\free{prev1 }\bound{f }}
\end{paste}\end{patch}

\begin{patch}{PartialFractionXmpPagePatch3}
\begin{paste}{PartialFractionXmpPageFull3}{PartialFractionXmpPageEmpty3}
\pastebutton{PartialFractionXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{compactFraction(f)\free{f }}
\indentrel{3}\begin{verbatim}
        159   23   12   1
   (3)  ÄÄÄ - ÄÄ - ÄÄ + Ä
          8    4    2   7
         2    3    5
                          Type: PartialFraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PartialFractionXmpPageEmpty3}
\begin{paste}{PartialFractionXmpPageEmpty3}{PartialFractionXmpPagePatch3}
\pastebutton{PartialFractionXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{compactFraction(f)\free{f }}
\end{paste}\end{patch}

\begin{patch}{PartialFractionXmpPagePatch4}
\begin{paste}{PartialFractionXmpPageFull4}{PartialFractionXmpPageEmpty4}
\pastebutton{PartialFractionXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{numberOfFractionalTerms(f)\free{f }}
\indentrel{3}\begin{verbatim}
   (4)  12
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PartialFractionXmpPageEmpty4}
\begin{paste}{PartialFractionXmpPageEmpty4}{PartialFractionXmpPagePatch4}
\pastebutton{PartialFractionXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{numberOfFractionalTerms(f)\free{f }}
\end{paste}\end{patch}

\begin{patch}{PartialFractionXmpPagePatch5}
\begin{paste}{PartialFractionXmpPageFull5}{PartialFractionXmpPageEmpty5}
\pastebutton{PartialFractionXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{nthFractionalTerm(f,3)\free{f }}
\indentrel{3}\begin{verbatim}
         1
   (5)  ÄÄ
         5
        2
                          Type: PartialFraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PartialFractionXmpPageEmpty5}
\begin{paste}{PartialFractionXmpPageEmpty5}{PartialFractionXmpPagePatch5}
\pastebutton{PartialFractionXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{nthFractionalTerm(f,3)\free{f }}
\end{paste}\end{patch}

\begin{patch}{PartialFractionXmpPagePatch6}
\begin{paste}{PartialFractionXmpPageFull6}{PartialFractionXmpPageEmpty6}
\pastebutton{PartialFractionXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{partialFraction(1,- 13 + 14 * \%i)\bound{prev2 }}
\indentrel{3}\begin{verbatim}
             1         4
   (6)  - ÄÄÄÄÄÄÄ + ÄÄÄÄÄÄÄ
          1 + 2%i   3 + 8%i
                  Type: PartialFraction Complex Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PartialFractionXmpPageEmpty6}
\begin{paste}{PartialFractionXmpPageEmpty6}{PartialFractionXmpPagePatch6}
\pastebutton{PartialFractionXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{partialFraction(1,- 13 + 14 * \%i)\bound{prev2 }}
\end{paste}\end{patch}

\begin{patch}{PartialFractionXmpPagePatch7}
\begin{paste}{PartialFractionXmpPageFull7}{PartialFractionXmpPageEmpty7}
\pastebutton{PartialFractionXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{\% :: Fraction Complex Integer\free{prev2 }}
\indentrel{3}\begin{verbatim}
              %i
   (7)  - ÄÄÄÄÄÄÄÄÄ
          14 + 13%i
                         Type: Fraction Complex Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PartialFractionXmpPageEmpty7}
\begin{paste}{PartialFractionXmpPageEmpty7}{PartialFractionXmpPagePatch7}
\pastebutton{PartialFractionXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{\% :: Fraction Complex Integer\free{prev2 }}
\end{paste}\end{patch}

\begin{patch}{PartialFractionXmpPagePatch8}
\begin{paste}{PartialFractionXmpPageFull8}{PartialFractionXmpPageEmpty8}
\pastebutton{PartialFractionXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{u : FR UP(x, FRAC INT) := reduce(*,[primeFactor(x+i,i) for i in 1..4])\bound{u }}
\indentrel{3}\begin{verbatim}
                      2       3       4
   (8)  (x + 1)(x + 2) (x + 3) (x + 4)
Type: Factored UnivariatePolynomial(x,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PartialFractionXmpPageEmpty8}
\begin{paste}{PartialFractionXmpPageEmpty8}{PartialFractionXmpPagePatch8}
\pastebutton{PartialFractionXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{u : FR UP(x, FRAC INT) := reduce(*,[primeFactor(x+i,i) for i in 1..4])\bound{u }}
\end{paste}\end{patch}

\begin{patch}{PartialFractionXmpPagePatch9}
\begin{paste}{PartialFractionXmpPageFull9}{PartialFractionXmpPageEmpty9}
\pastebutton{PartialFractionXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{partialFraction(1,u)\free{u }\bound{prev3 }}
\indentrel{3}\begin{verbatim}
   (9)
       1     1      7     17  2         139
      ÄÄÄ    Ä x + ÄÄ   - ÄÄ x  - 12x - ÄÄÄ
      648    4     16      8             8
     ÄÄÄÄÄ + ÄÄÄÄÄÄÄÄ + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
     x + 1          2                3
             (x + 2)          (x + 3)
   + 
     607  3   10115  2   391     44179
     ÄÄÄ x  + ÄÄÄÄÄ x  + ÄÄÄ x + ÄÄÄÄÄ
     324       432        4       324
     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                         4
                  (x + 4)
Type: PartialFraction UnivariatePolynomial(x,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PartialFractionXmpPageEmpty9}
\begin{paste}{PartialFractionXmpPageEmpty9}{PartialFractionXmpPagePatch9}
\pastebutton{PartialFractionXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{partialFraction(1,u)\free{u }\bound{prev3 }}
\end{paste}\end{patch}

\begin{patch}{PartialFractionXmpPagePatch10}
\begin{paste}{PartialFractionXmpPageFull10}{PartialFractionXmpPageEmpty10}
\pastebutton{PartialFractionXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{padicFraction \%\free{prev3 }}
\indentrel{3}\begin{verbatim}
   (10)
       1       1         1        17        3
      ÄÄÄ      Ä        ÄÄ        ÄÄ        Ä
      648      4        16         8        4
     ÄÄÄÄÄ + ÄÄÄÄÄ - ÄÄÄÄÄÄÄÄ - ÄÄÄÄÄ + ÄÄÄÄÄÄÄÄ
     x + 1   x + 2          2   x + 3          2
                     (x + 2)            (x + 3)
   + 
           1       607       403        13          1
           Ä       ÄÄÄ       ÄÄÄ        ÄÄ         ÄÄ
           2       324       432        36         12
     - ÄÄÄÄÄÄÄÄ + ÄÄÄÄÄ + ÄÄÄÄÄÄÄÄ + ÄÄÄÄÄÄÄÄ + ÄÄÄÄÄÄÄÄ
              3   x + 4          2          3          4
       (x + 3)            (x + 4)    (x + 4)    (x + 4)
Type: PartialFraction UnivariatePolynomial(x,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PartialFractionXmpPageEmpty10}
\begin{paste}{PartialFractionXmpPageEmpty10}{PartialFractionXmpPagePatch10}
\pastebutton{PartialFractionXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{padicFraction \%\free{prev3 }}
\end{paste}\end{patch}

\end{chunk}
\section{poly.ht}
\pagetitle{PolynomialPage}{poly.ht}{Polynomials}
\pagepic{ps/v71polynomialpage.eps}{polynomialpage}{0.50}
\pagefrom{Topics}{TopicPage}
\pageto{Basic Functions}{PolynomialBasicPage}
\pageto{Substitutions}{PolynomialSubstitutionPage} 
\pageto{Factorizations}{ugProblemFactorPage}
\pageto{GCDs and Friends}{PolynomialGCDPage}
\pageto{Roots}{PolynomialRootPage}
\pageto{Specific Types}{PolynomialTypesPage}
\begin{chunk}{poly.ht}
\begin{page}{PolynomialPage}{Polynomials}
\beginscroll
\beginmenu
\menulink{Basic Functions}{PolynomialBasicPage} \tab{18}
Create and manipulate polynomials.
\menulink{Substitutions}{PolynomialSubstitutionPage} \tab{18}
Evaluate polynomials.
\menulink{Factorization}{ugProblemFactorPage} \tab{18}
Factor in different contexts.
\menulink{GCDs and Friends}{PolynomialGCDPage} \tab{18}
Greatest common divisors etc..
\menulink{Roots}{PolynomialRootPage}\tab{18}
Work with and solve for roots.
\menulink{Specific Types}{PolynomialTypesPage}\tab{18}
More specific information.
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{PolynomialTypesPage}{poly.ht}{The Specific Polynomial Types}
\begin{chunk}{poly.ht}
\begin{page}{PolynomialTypesPage}{The Specific Polynomial Types}
\beginscroll
\beginmenu
\menulink{Polynomial}{PolynomialXmpPage} \newline
The general type.
\menulink{UnivariatePolynomial}{UnivariatePolyXmpPage} \newline
One variable polynomials.
\menulink{MultivariatePolynomial}{MultivariatePolyXmpPage} 
\newline
Multiple variable polynomials, recursive structure.
\menulink{DistributedMultivariatePoly}
{DistributedMultivariatePolyXmpPage}
\newline
Multiple variable polynomials, non-recursive structure.
\menulink{UnivariateSkewPolynomial}
{UnivariateSkewPolynomial}
\newline
Skew or Ore polynomials
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{PolynomialBasicPage}{poly.ht}{Basic Operations On Polynomials}
\begin{chunk}{poly.ht}
\begin{page}{PolynomialBasicPage}{Basic Operations On Polynomials}
\beginscroll
You create
polynomials using the usual operations of \spadopFrom{+}{Polynomial},
\spadopFrom{-}{Polynomial}, \spadopFrom{*}{Polynomial}
(for multiplication), and 
\spadopFrom{**}{Polynomial} (for exponentiation).
Here are two examples: \newline
\spadpaste{p := a*x**2 + b*x*y + c*y**2 \bound{p}} 
\spadpaste{q := 13*x**2 + 3*z \bound{q}} 
These operations can also be used to combine polynomials.
Try the following:
\spadpaste{p + q \free{p q}} 
\spadpaste{p - 3*q \free{p q}} 
\spadpaste{p**2 + p*q \free{p q}} 
\spadpaste{r := (p + q)**2 \bound{r} \free{p q}}
As you can see from the above examples, the variables are ordered
by defaults \spad{z > y > x > c > b > a},
that is, \spad{z} is the main variable, then
\spad{y} and so on in reverse alphabetical order.
You can redefine this
ordering (for display purposes only) with the \spadfun{setVariableOrder}
command.
For example, the following
makes \spad{a} the main variable, then \spad{b}, and so on:
\spadpaste{setVariableOrder [a,b,c,x,y,z] \bound{vord}}
Now compare the way polynomials are displayed:
\spadpaste{p \free{p vord}}
\spadpaste{q \free{q vord}}
\spadpaste{r \free{r vord}}
To return to the system's default ordering,
use \spadfun{resetVariableOrder}.
\spadpaste{resetVariableOrder() \bound{rvord}}
\spadpaste{p \free{p rvord}}
Polynomial coefficients can be pulled out
using the function \spadfun{coefficient}. \newline
For example:
\spadpaste{coefficient(q,x,2) \free{q}} 
will give you the coefficient of \spad{x**2} in the polynomial \spad{q}.
\newline
Try these commands:
\spadpaste{coefficient(r,x,3) \free{r}} 
\spadpaste{c := coefficient(r,z,1) \free{r} \bound{c}} 
\spadpaste{coefficient(c,x,2) \free{c}}
Coefficients of monomials can be obtained as follows:
\spadpaste{coefficient(q**2, [x,z], [2,1]) \free{q}}
This will return the coefficient of x**2 * z in the polynomial q**2.
Also,
\spadpaste{coefficient(r, [x,y], [2,2]) \free{r}}
will return the coefficient of \spad{x**2 * y**2}
in the polynomial \spad{r(x,y)}.
\endscroll
\autobuttons
\end{page}

\begin{patch}{PolynomialBasicPagePatch1}
\begin{paste}{PolynomialBasicPageFull1}{PolynomialBasicPageEmpty1}
\pastebutton{PolynomialBasicPageFull1}{\hidepaste}
\tab{5}\spadcommand{p := a*x**2 + b*x*y + c*y**2\bound{p }}
\indentrel{3}\begin{verbatim}
           2              2
   (1)  c y  + b x y + a x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPageEmpty1}
\begin{paste}{PolynomialBasicPageEmpty1}{PolynomialBasicPagePatch1}
\pastebutton{PolynomialBasicPageEmpty1}{\showpaste}
\tab{5}\spadcommand{p := a*x**2 + b*x*y + c*y**2\bound{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPagePatch2}
\begin{paste}{PolynomialBasicPageFull2}{PolynomialBasicPageEmpty2}
\pastebutton{PolynomialBasicPageFull2}{\hidepaste}
\tab{5}\spadcommand{q := 13*x**2 + 3*z\bound{q }}
\indentrel{3}\begin{verbatim}
                2
   (2)  3z + 13x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPageEmpty2}
\begin{paste}{PolynomialBasicPageEmpty2}{PolynomialBasicPagePatch2}
\pastebutton{PolynomialBasicPageEmpty2}{\showpaste}
\tab{5}\spadcommand{q := 13*x**2 + 3*z\bound{q }}
\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPagePatch3}
\begin{paste}{PolynomialBasicPageFull3}{PolynomialBasicPageEmpty3}
\pastebutton{PolynomialBasicPageFull3}{\hidepaste}
\tab{5}\spadcommand{p + q\free{p q }}
\indentrel{3}\begin{verbatim}
                2                    2
   (3)  3z + c y  + b x y + (a + 13)x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPageEmpty3}
\begin{paste}{PolynomialBasicPageEmpty3}{PolynomialBasicPagePatch3}
\pastebutton{PolynomialBasicPageEmpty3}{\showpaste}
\tab{5}\spadcommand{p + q\free{p q }}
\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPagePatch4}
\begin{paste}{PolynomialBasicPageFull4}{PolynomialBasicPageEmpty4}
\pastebutton{PolynomialBasicPageFull4}{\hidepaste}
\tab{5}\spadcommand{p - 3*q\free{p q }}
\indentrel{3}\begin{verbatim}
                  2                    2
   (4)  - 9z + c y  + b x y + (a - 39)x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPageEmpty4}
\begin{paste}{PolynomialBasicPageEmpty4}{PolynomialBasicPagePatch4}
\pastebutton{PolynomialBasicPageEmpty4}{\showpaste}
\tab{5}\spadcommand{p - 3*q\free{p q }}
\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPagePatch5}
\begin{paste}{PolynomialBasicPageFull5}{PolynomialBasicPageEmpty5}
\pastebutton{PolynomialBasicPageFull5}{\hidepaste}
\tab{5}\spadcommand{p**2 + p*q\free{p q }}
\indentrel{3}\begin{verbatim}
   (5)
          2                2      2 4           3
     (3c y  + 3b x y + 3a x )z + c y  + 2b c x y
   + 
                  2  2 2               3      2        4
   ((2a + 13)c + b )x y  + (2a + 13)b x y + (a  + 13a)x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPageEmpty5}
\begin{paste}{PolynomialBasicPageEmpty5}{PolynomialBasicPagePatch5}
\pastebutton{PolynomialBasicPageEmpty5}{\showpaste}
\tab{5}\spadcommand{p**2 + p*q\free{p q }}
\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPagePatch6}
\begin{paste}{PolynomialBasicPageFull6}{PolynomialBasicPageEmpty6}
\pastebutton{PolynomialBasicPageFull6}{\hidepaste}
\tab{5}\spadcommand{r := (p + q)**2\bound{r }\free{p q }}
\indentrel{3}\begin{verbatim}
   (6)
       2        2                      2      2 4
     9z  + (6c y  + 6b x y + (6a + 78)x )z + c y
   + 
             3                  2  2 2               3
     2b c x y  + ((2a + 26)c + b )x y  + (2a + 26)b x y
   + 
       2              4
     (a  + 26a + 169)x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPageEmpty6}
\begin{paste}{PolynomialBasicPageEmpty6}{PolynomialBasicPagePatch6}
\pastebutton{PolynomialBasicPageEmpty6}{\showpaste}
\tab{5}\spadcommand{r := (p + q)**2\bound{r }\free{p q }}
\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPagePatch7}
\begin{paste}{PolynomialBasicPageFull7}{PolynomialBasicPageEmpty7}
\pastebutton{PolynomialBasicPageFull7}{\hidepaste}
\tab{5}\spadcommand{setVariableOrder [a,b,c,x,y,z]\bound{vord }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPageEmpty7}
\begin{paste}{PolynomialBasicPageEmpty7}{PolynomialBasicPagePatch7}
\pastebutton{PolynomialBasicPageEmpty7}{\showpaste}
\tab{5}\spadcommand{setVariableOrder [a,b,c,x,y,z]\bound{vord }}
\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPagePatch8}
\begin{paste}{PolynomialBasicPageFull8}{PolynomialBasicPageEmpty8}
\pastebutton{PolynomialBasicPageFull8}{\hidepaste}
\tab{5}\spadcommand{p\free{p vord }}
\indentrel{3}\begin{verbatim}
         2             2
   (8)  x a + y x b + y c
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPageEmpty8}
\begin{paste}{PolynomialBasicPageEmpty8}{PolynomialBasicPagePatch8}
\pastebutton{PolynomialBasicPageEmpty8}{\showpaste}
\tab{5}\spadcommand{p\free{p vord }}
\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPagePatch9}
\begin{paste}{PolynomialBasicPageFull9}{PolynomialBasicPageEmpty9}
\pastebutton{PolynomialBasicPageFull9}{\hidepaste}
\tab{5}\spadcommand{q\free{q vord }}
\indentrel{3}\begin{verbatim}
           2
   (9)  13x  + 3z
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPageEmpty9}
\begin{paste}{PolynomialBasicPageEmpty9}{PolynomialBasicPagePatch9}
\pastebutton{PolynomialBasicPageEmpty9}{\showpaste}
\tab{5}\spadcommand{q\free{q vord }}
\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPagePatch10}
\begin{paste}{PolynomialBasicPageFull10}{PolynomialBasicPageEmpty10}
\pastebutton{PolynomialBasicPageFull10}{\hidepaste}
\tab{5}\spadcommand{r\free{r vord }}
\indentrel{3}\begin{verbatim}
   (10)
      4 2        3      2 2       4       2      2 2 2
     x a  + (2y x b + 2y x c + 26x  + 6z x )a + y x b
   + 
        3           3               4 2
     (2y x c + 26y x  + 6z y x)b + y c
   + 
         2 2       2         4        2     2
     (26y x  + 6z y )c + 169x  + 78z x  + 9z
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPageEmpty10}
\begin{paste}{PolynomialBasicPageEmpty10}{PolynomialBasicPagePatch10}
\pastebutton{PolynomialBasicPageEmpty10}{\showpaste}
\tab{5}\spadcommand{r\free{r vord }}
\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPagePatch11}
\begin{paste}{PolynomialBasicPageFull11}{PolynomialBasicPageEmpty11}
\pastebutton{PolynomialBasicPageFull11}{\hidepaste}
\tab{5}\spadcommand{resetVariableOrder()\bound{rvord }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPageEmpty11}
\begin{paste}{PolynomialBasicPageEmpty11}{PolynomialBasicPagePatch11}
\pastebutton{PolynomialBasicPageEmpty11}{\showpaste}
\tab{5}\spadcommand{resetVariableOrder()\bound{rvord }}
\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPagePatch12}
\begin{paste}{PolynomialBasicPageFull12}{PolynomialBasicPageEmpty12}
\pastebutton{PolynomialBasicPageFull12}{\hidepaste}
\tab{5}\spadcommand{p\free{p rvord }}
\indentrel{3}\begin{verbatim}
            2              2
   (12)  c y  + b x y + a x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPageEmpty12}
\begin{paste}{PolynomialBasicPageEmpty12}{PolynomialBasicPagePatch12}
\pastebutton{PolynomialBasicPageEmpty12}{\showpaste}
\tab{5}\spadcommand{p\free{p rvord }}
\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPagePatch13}
\begin{paste}{PolynomialBasicPageFull13}{PolynomialBasicPageEmpty13}
\pastebutton{PolynomialBasicPageFull13}{\hidepaste}
\tab{5}\spadcommand{coefficient(q,x,2)\free{q }}
\indentrel{3}\begin{verbatim}
   (13)  13
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPageEmpty13}
\begin{paste}{PolynomialBasicPageEmpty13}{PolynomialBasicPagePatch13}
\pastebutton{PolynomialBasicPageEmpty13}{\showpaste}
\tab{5}\spadcommand{coefficient(q,x,2)\free{q }}
\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPagePatch14}
\begin{paste}{PolynomialBasicPageFull14}{PolynomialBasicPageEmpty14}
\pastebutton{PolynomialBasicPageFull14}{\hidepaste}
\tab{5}\spadcommand{coefficient(r,x,3)\free{r }}
\indentrel{3}\begin{verbatim}
   (14)  (2a + 26)b y
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPageEmpty14}
\begin{paste}{PolynomialBasicPageEmpty14}{PolynomialBasicPagePatch14}
\pastebutton{PolynomialBasicPageEmpty14}{\showpaste}
\tab{5}\spadcommand{coefficient(r,x,3)\free{r }}
\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPagePatch15}
\begin{paste}{PolynomialBasicPageFull15}{PolynomialBasicPageEmpty15}
\pastebutton{PolynomialBasicPageFull15}{\hidepaste}
\tab{5}\spadcommand{c := coefficient(r,z,1)\free{r }\bound{c }}
\indentrel{3}\begin{verbatim}
             2                      2
   (15)  6c y  + 6b x y + (6a + 78)x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPageEmpty15}
\begin{paste}{PolynomialBasicPageEmpty15}{PolynomialBasicPagePatch15}
\pastebutton{PolynomialBasicPageEmpty15}{\showpaste}
\tab{5}\spadcommand{c := coefficient(r,z,1)\free{r }\bound{c }}
\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPagePatch16}
\begin{paste}{PolynomialBasicPageFull16}{PolynomialBasicPageEmpty16}
\pastebutton{PolynomialBasicPageFull16}{\hidepaste}
\tab{5}\spadcommand{coefficient(c,x,2)\free{c }}
\indentrel{3}\begin{verbatim}
   (16)  6a + 78
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPageEmpty16}
\begin{paste}{PolynomialBasicPageEmpty16}{PolynomialBasicPagePatch16}
\pastebutton{PolynomialBasicPageEmpty16}{\showpaste}
\tab{5}\spadcommand{coefficient(c,x,2)\free{c }}
\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPagePatch17}
\begin{paste}{PolynomialBasicPageFull17}{PolynomialBasicPageEmpty17}
\pastebutton{PolynomialBasicPageFull17}{\hidepaste}
\tab{5}\spadcommand{coefficient(q**2, [x,z], [2,1])\free{q }}
\indentrel{3}\begin{verbatim}
   (17)  78
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPageEmpty17}
\begin{paste}{PolynomialBasicPageEmpty17}{PolynomialBasicPagePatch17}
\pastebutton{PolynomialBasicPageEmpty17}{\showpaste}
\tab{5}\spadcommand{coefficient(q**2, [x,z], [2,1])\free{q }}
\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPagePatch18}
\begin{paste}{PolynomialBasicPageFull18}{PolynomialBasicPageEmpty18}
\pastebutton{PolynomialBasicPageFull18}{\hidepaste}
\tab{5}\spadcommand{coefficient(r, [x,y], [2,2])\free{r }}
\indentrel{3}\begin{verbatim}
                       2
   (18)  (2a + 26)c + b
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialBasicPageEmpty18}
\begin{paste}{PolynomialBasicPageEmpty18}{PolynomialBasicPagePatch18}
\pastebutton{PolynomialBasicPageEmpty18}{\showpaste}
\tab{5}\spadcommand{coefficient(r, [x,y], [2,2])\free{r }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{PolynomialSubstitutionPage}{poly.ht}
{Polynomial Evaluation and Substitution}
\begin{chunk}{poly.ht}
\begin{page}{PolynomialSubstitutionPage}
{Polynomial Evaluation and Substitution}
\beginscroll
The function \spadfun{eval} is used to substitute values into polynomials.
Here's an example of how to use it:
\spadpaste{p := x**2 + y**2 \bound{p}}
\spadpaste{eval(p,x=5) \free{p}}
\newline
This example would give you the value of the polynomial \spad{p} at 5.
You can also substitute into polynomials with
several variables.  First, specify the polynomial, then give
a list of bindings of the form \spad{variable = value}. For example:
\spadpaste{eval(p,[x = a + b,y = c + d]) \free{p}}
Here \spad{x} was replaced by \spad{a + b},
and \spad{y} was replaced by \spad{c + d}.
Here's another example:
\spadpaste{q := x**3 + 5*x - y**4 \bound{q}}
\spadpaste{eval(q,[x=y,y=x]) \free{q}}
Substitution is done ``in parallel.''
That is, Axiom takes
\spad{q(x,y)} and returns \spad{q(y,x)}.
\newline
You can also substitute numerical values for some or all of the
variables:
\spadpaste{px := eval(p, y = sin(2.0)) \bound{px} \free{p}}
\spadpaste{eval(px, x = cos(2.0)) \free{px}}
\endscroll
\autobuttons
\end{page}

\begin{patch}{PolynomialSubstitutionPagePatch1}
\begin{paste}{PolynomialSubstitutionPageFull1}{PolynomialSubstitutionPageEmpty1}
\pastebutton{PolynomialSubstitutionPageFull1}{\hidepaste}
\tab{5}\spadcommand{p := x**2 + y**2\bound{p }}
\indentrel{3}\begin{verbatim}
         2    2
   (1)  y  + x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialSubstitutionPageEmpty1}
\begin{paste}{PolynomialSubstitutionPageEmpty1}{PolynomialSubstitutionPagePatch1}
\pastebutton{PolynomialSubstitutionPageEmpty1}{\showpaste}
\tab{5}\spadcommand{p := x**2 + y**2\bound{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialSubstitutionPagePatch2}
\begin{paste}{PolynomialSubstitutionPageFull2}{PolynomialSubstitutionPageEmpty2}
\pastebutton{PolynomialSubstitutionPageFull2}{\hidepaste}
\tab{5}\spadcommand{eval(p,x=5)\free{p }}
\indentrel{3}\begin{verbatim}
         2
   (2)  y  + 25
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialSubstitutionPageEmpty2}
\begin{paste}{PolynomialSubstitutionPageEmpty2}{PolynomialSubstitutionPagePatch2}
\pastebutton{PolynomialSubstitutionPageEmpty2}{\showpaste}
\tab{5}\spadcommand{eval(p,x=5)\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialSubstitutionPagePatch3}
\begin{paste}{PolynomialSubstitutionPageFull3}{PolynomialSubstitutionPageEmpty3}
\pastebutton{PolynomialSubstitutionPageFull3}{\hidepaste}
\tab{5}\spadcommand{eval(p,[x = a + b,y = c + d])\free{p }}
\indentrel{3}\begin{verbatim}
         2           2    2           2
   (3)  d  + 2c d + c  + b  + 2a b + a
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialSubstitutionPageEmpty3}
\begin{paste}{PolynomialSubstitutionPageEmpty3}{PolynomialSubstitutionPagePatch3}
\pastebutton{PolynomialSubstitutionPageEmpty3}{\showpaste}
\tab{5}\spadcommand{eval(p,[x = a + b,y = c + d])\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialSubstitutionPagePatch4}
\begin{paste}{PolynomialSubstitutionPageFull4}{PolynomialSubstitutionPageEmpty4}
\pastebutton{PolynomialSubstitutionPageFull4}{\hidepaste}
\tab{5}\spadcommand{q := x**3 + 5*x - y**4\bound{q }}
\indentrel{3}\begin{verbatim}
           4    3
   (4)  - y  + x  + 5x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialSubstitutionPageEmpty4}
\begin{paste}{PolynomialSubstitutionPageEmpty4}{PolynomialSubstitutionPagePatch4}
\pastebutton{PolynomialSubstitutionPageEmpty4}{\showpaste}
\tab{5}\spadcommand{q := x**3 + 5*x - y**4\bound{q }}
\end{paste}\end{patch}

\begin{patch}{PolynomialSubstitutionPagePatch5}
\begin{paste}{PolynomialSubstitutionPageFull5}{PolynomialSubstitutionPageEmpty5}
\pastebutton{PolynomialSubstitutionPageFull5}{\hidepaste}
\tab{5}\spadcommand{eval(q,[x=y,y=x])\free{q }}
\indentrel{3}\begin{verbatim}
         3         4
   (5)  y  + 5y - x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialSubstitutionPageEmpty5}
\begin{paste}{PolynomialSubstitutionPageEmpty5}{PolynomialSubstitutionPagePatch5}
\pastebutton{PolynomialSubstitutionPageEmpty5}{\showpaste}
\tab{5}\spadcommand{eval(q,[x=y,y=x])\free{q }}
\end{paste}\end{patch}

\begin{patch}{PolynomialSubstitutionPagePatch6}
\begin{paste}{PolynomialSubstitutionPageFull6}{PolynomialSubstitutionPageEmpty6}
\pastebutton{PolynomialSubstitutionPageFull6}{\hidepaste}
\tab{5}\spadcommand{px := eval(p, y = sin(2.0))\bound{px }\free{p }}
\indentrel{3}\begin{verbatim}
         2
   (6)  x  + 0.8268218104 3180595732
                                 Type: Polynomial Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialSubstitutionPageEmpty6}
\begin{paste}{PolynomialSubstitutionPageEmpty6}{PolynomialSubstitutionPagePatch6}
\pastebutton{PolynomialSubstitutionPageEmpty6}{\showpaste}
\tab{5}\spadcommand{px := eval(p, y = sin(2.0))\bound{px }\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialSubstitutionPagePatch7}
\begin{paste}{PolynomialSubstitutionPageFull7}{PolynomialSubstitutionPageEmpty7}
\pastebutton{PolynomialSubstitutionPageFull7}{\hidepaste}
\tab{5}\spadcommand{eval(px, x = cos(2.0))\free{px }}
\indentrel{3}\begin{verbatim}
   (7)  1.0
                                 Type: Polynomial Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialSubstitutionPageEmpty7}
\begin{paste}{PolynomialSubstitutionPageEmpty7}{PolynomialSubstitutionPagePatch7}
\pastebutton{PolynomialSubstitutionPageEmpty7}{\showpaste}
\tab{5}\spadcommand{eval(px, x = cos(2.0))\free{px }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{PolynomialGCDPage}{poly.ht}
{Greatest Common Divisors, Resultants, and Discriminants}
\begin{chunk}{poly.ht}
\begin{page}{PolynomialGCDPage}
{Greatest Common Divisors, Resultants, and Discriminants}
\beginscroll
You can compute the greatest common divisor of two polynomials using 
the function \spadfun{gcd}.
Here's an example:
\spadpaste{p := 3*x**8 + 2*x**7 + 6*x**2 + 7*x + 2 \bound{p}}
\spadpaste{q := 2*x**13 + 9*x**7 + 2*x**6 + 10*x + 5 \bound{q}}
\spadpaste{gcd(p,q) \free{p q}}
You could also see that \spad{p} and \spad{q} have a factor in 
common by using the function \spadfun{resultant}:
\spadpaste{resultant(p,q,x) \free{p q}}
The resultant of two polynomials vanishes precisely when they have a
factor in common.
(In the example above
we specified the variable with
which we wanted to compute the resultant because the
polynomials could have involved variables other than x.)
\endscroll
\autobuttons
\end{page}

\begin{patch}{PolynomialGCDPagePatch1}
\begin{paste}{PolynomialGCDPageFull1}{PolynomialGCDPageEmpty1}
\pastebutton{PolynomialGCDPageFull1}{\hidepaste}
\tab{5}\spadcommand{p := 3*x**8 + 2*x**7 + 6*x**2 + 7*x + 2\bound{p }}
\indentrel{3}\begin{verbatim}
          8     7     2
   (1)  3x  + 2x  + 6x  + 7x + 2
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialGCDPageEmpty1}
\begin{paste}{PolynomialGCDPageEmpty1}{PolynomialGCDPagePatch1}
\pastebutton{PolynomialGCDPageEmpty1}{\showpaste}
\tab{5}\spadcommand{p := 3*x**8 + 2*x**7 + 6*x**2 + 7*x + 2\bound{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialGCDPagePatch2}
\begin{paste}{PolynomialGCDPageFull2}{PolynomialGCDPageEmpty2}
\pastebutton{PolynomialGCDPageFull2}{\hidepaste}
\tab{5}\spadcommand{q := 2*x**13 + 9*x**7 + 2*x**6 + 10*x + 5\bound{q }}
\indentrel{3}\begin{verbatim}
          13     7     6
   (2)  2x   + 9x  + 2x  + 10x + 5
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialGCDPageEmpty2}
\begin{paste}{PolynomialGCDPageEmpty2}{PolynomialGCDPagePatch2}
\pastebutton{PolynomialGCDPageEmpty2}{\showpaste}
\tab{5}\spadcommand{q := 2*x**13 + 9*x**7 + 2*x**6 + 10*x + 5\bound{q }}
\end{paste}\end{patch}

\begin{patch}{PolynomialGCDPagePatch3}
\begin{paste}{PolynomialGCDPageFull3}{PolynomialGCDPageEmpty3}
\pastebutton{PolynomialGCDPageFull3}{\hidepaste}
\tab{5}\spadcommand{gcd(p,q)\free{p q }}
\indentrel{3}\begin{verbatim}
         7
   (3)  x  + 2x + 1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialGCDPageEmpty3}
\begin{paste}{PolynomialGCDPageEmpty3}{PolynomialGCDPagePatch3}
\pastebutton{PolynomialGCDPageEmpty3}{\showpaste}
\tab{5}\spadcommand{gcd(p,q)\free{p q }}
\end{paste}\end{patch}

\begin{patch}{PolynomialGCDPagePatch4}
\begin{paste}{PolynomialGCDPageFull4}{PolynomialGCDPageEmpty4}
\pastebutton{PolynomialGCDPageFull4}{\hidepaste}
\tab{5}\spadcommand{resultant(p,q,x)\free{p q }}
\indentrel{3}\begin{verbatim}
   (4)  0
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialGCDPageEmpty4}
\begin{paste}{PolynomialGCDPageEmpty4}{PolynomialGCDPagePatch4}
\pastebutton{PolynomialGCDPageEmpty4}{\showpaste}
\tab{5}\spadcommand{resultant(p,q,x)\free{p q }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{PolynomialRootPage}{poly.ht}{Roots of Polynomials}
\begin{chunk}{poly.ht}
\begin{page}{PolynomialRootPage}{Roots of Polynomials}
\beginscroll
\beginmenu
\menulink{Using a Single Root of a Polynomial}{ugxProblemSymRootOnePage}
\newline
Working with a single root of a polynomial.
\menulink{Using All Roots of a Polynomial}{ugxProblemSymRootAllPage}
\newline
Working with all the roots of a polynomial.
\menulink{Solution of a Single Polynomial Equation}
{ugxProblemOnePolPage}
\newline
Finding the roots of one polynomial.
\menulink{Solution of Systems of Polynomial Equations}
{ugxProblemPolSysPage}
\newline
Finding the roots of a system of polynomials.
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\section{poly1.ht}
\pagetitle{PolynomialXmpPage}{poly1.ht}{Polynomial}
\pageto{notitle}{DistributedMultivariatePolyXmpPage}
\pageto{notitle}{MultivariatePolyXmpPage}
\pageto{notitle}{UnivariatePolyXmpPage}
\pageto{notitle}{FactoredXmpPage}
\pageto{notitle}{ugProblemFactorPage}
\begin{chunk}{poly1.ht}
\begin{page}{PolynomialXmpPage}{Polynomial}
\beginscroll

The domain constructor \spadtype{Polynomial} 
(abbreviation: \spadtype{POLY})
provides polynomials with an arbitrary number of unspecified
variables.

\xtc{
It is used to create the default polynomial domains
in Axiom.
Here the coefficients are integers.
}{
\spadpaste{x + 1}
}
\xtc{
Here the coefficients have type \spadtype{Float}.
}{
\spadpaste{z - 2.3}
}
\xtc{
And here we have a polynomial in two variables with coefficients 
which have type \spadtype{Fraction Integer}.
}{
\spadpaste{y**2 - z + 3/4}
}

The representation of objects of domains created by \spadtype{Polynomial}
is that of recursive univariate polynomials.\footnote{The term
\spad{univariate} means ``one variable.'' \spad{multivariate} means
``possibly more than one variable.''}
\xtc{
This recursive structure is sometimes obvious from the display of
a polynomial.
}{
\spadpaste{y **2 + x*y + y \bound{prev}}
}
In this example, you see that the polynomial is stored as a polynomial in
\spad{y} with coefficients that are polynomials in \spad{x} with integer
coefficients.
In fact, you really don't need to worry about the representation unless
you are working on an advanced application where it is critical.
The polynomial types created from
\spadtype{DistributedMultivariatePoly} and
\spadtype{NewDistributedMultivariatePoly} (discussed in
\downlink{`DistributedMultivariatePoly'}
{DistributedMultivariatePolyXmpPage}
\ignore{DistributedMultivariatePoly}) are stored and displayed in a
non-recursive manner.
\xtc{
You see a ``flat'' display of the above
polynomial by converting to one of those types.
}{
\spadpaste{\% :: DMP([y,x],INT) \free{prev}}
}

We will demonstrate many of the polynomial facilities by using two
polynomials with integer coefficients.
\xtc{
By default, the interpreter expands polynomial expressions, even if they
are written in a factored format.
}{
\spadpaste{p := (y-1)**2 * x * z \bound{p}}
}
\xtc{
See \downlink{`Factored'}{FactoredXmpPage}\ignore{Factored} to see
how to create objects in factored form directly.
}{
\spadpaste{q := (y-1) * x * (z+5) \bound{q}}
}
\xtc{
The fully factored form can be recovered by using
\spadfunFrom{factor}{Polynomial}.
}{
\spadpaste{factor(q) \free{q}}
}
This is the same name used for the operation to factor integers.  Such
reuse of names is called \spadglos{overloading} and makes it much
easier to think of solving problems in general ways.  Axiom facilities
for factoring polynomials created with \spadtype{Polynomial} are
currently restricted to the integer and rational number coefficient
cases.  There are more complete facilities for factoring univariate
polynomials: see
\downlink{``Polynomial Factorization''}{ugProblemFactorPage} in 
Section 8.2\ignore{ugProblemFactor}.

\xtc{
The standard arithmetic operations are available for polynomials.
}{
\spadpaste{p - q**2\free{p q}}
}
\xtc{
The operation \spadfunFrom{gcd}{Polynomial} is used to compute the
greatest common divisor of two polynomials.
}{
\spadpaste{gcd(p,q) \free{p q}\bound{prev4}}
}
\xtc{
In the case of \spad{p} and \spad{q}, the gcd is obvious from their
definitions.
We factor the gcd to show this relationship better.
}{
\spadpaste{factor \% \free{prev4}}
}
\xtc{
The least common multiple is computed by using 
\spadfunFrom{lcm}{Polynomial}.
}{
\spadpaste{lcm(p,q) \free{p q}}
}
\xtc{
Use \spadfunFrom{content}{Polynomial} to compute the 
greatest common divisor of the
coefficients of the polynomial.
}{
\spadpaste{content p \free{p}}
}

Many of the operations on polynomials require you to specify a variable.
For example, \spadfunFrom{resultant}{Polynomial} requires you to give the
variable in which the polynomials should be expressed.
\xtc{
This computes the resultant of the values of \spad{p} and
\spad{q}, considering them as polynomials in the variable \spad{z}.
They do not share a root when thought of as polynomials in \spad{z}.
}{
\spadpaste{resultant(p,q,z) \free{p q}}
}
\xtc{
This value is \spad{0} because as polynomials in \spad{x} the polynomials
have a common root.
}{
\spadpaste{resultant(p,q,x) \free{p}\free{q}}
}
The data type used for the variables created by \spadtype{Polynomial} is
\spadtype{Symbol}.
As mentioned above, the representation used by \spadtype{Polynomial} is
recursive and so there is a main variable for nonconstant polynomials.
\xtc{
The operation \spadfunFrom{mainVariable}{Polynomial} returns this
variable.
The return type is actually a union of \spadtype{Symbol} and
\spad{"failed"}.
}{
\spadpaste{mainVariable p \free{p}}
}
\xtc{
The latter branch of the union is be used if the polynomial has no
variables, that is, is a constant.
}{
\spadpaste{mainVariable(1 :: POLY INT)}
}
\xtc{
You can also use the predicate \spadfunFrom{ground?}{Polynomial} to test
whether a polynomial is in fact a member of its ground ring.
}{
\spadpaste{ground? p \free{p}}
}
\xtc{
}{
\spadpaste{ground?(1 :: POLY INT)}
}
\xtc{
The complete list of variables actually used in a particular polynomial is
returned by \spadfunFrom{variables}{Polynomial}.
For constant polynomials, this list is empty.
}{
\spadpaste{variables p \free{p}}
}

\xtc{
The \spadfunFrom{degree}{Polynomial} operation returns the
degree of a polynomial in a specific variable.
}{
\spadpaste{degree(p,x) \free{p}}
}
\xtc{
}{
\spadpaste{degree(p,y) \free{p}}
}
\xtc{
}{
\spadpaste{degree(p,z) \free{p}}
}
\xtc{
If you give a list of variables for the second argument, a list
of the degrees in those variables is returned.
}{
\spadpaste{degree(p,[x,y,z]) \free{p}}
}
\xtc{
The minimum degree of a variable in a polynomial is computed using
\spadfunFrom{minimumDegree}{Polynomial}.
}{
\spadpaste{minimumDegree(p,z) \free{p}}
}
\xtc{
The total degree of a polynomial is returned by
\spadfunFrom{totalDegree}{Polynomial}.
}{
\spadpaste{totalDegree p \free{p}}
}

\xtc{
It is often convenient to think of a polynomial as a leading monomial 
plus the remaining terms.
}{
\spadpaste{leadingMonomial p \free{p}}
}
\xtc{
The \spadfunFrom{reductum}{Polynomial} operation returns a polynomial
consisting of the sum of the monomials after the first.
}{
\spadpaste{reductum p \free{p}}
}
\xtc{
These have the obvious relationship that the original polynomial
is equal to the leading monomial plus the reductum.
}{
\spadpaste{p - leadingMonomial p - reductum p \free{p}}
}
\xtc{
The value returned by \spadfunFrom{leadingMonomial}{Polynomial} includes
the coefficient of that term.
This is extracted by using
\spadfunFrom{leadingCoefficient}{Polynomial} on the original polynomial.
}{
\spadpaste{leadingCoefficient p \free{p}}
}
\xtc{
The operation \spadfunFrom{eval}{Polynomial} is used to substitute a 
value for a variable in a polynomial.
}{
\spadpaste{p  \free{p}}
}
\xtc{
This value may be another variable, a constant or a polynomial.
}{
\spadpaste{eval(p,x,w) \free{p}}
}
\xtc{
}{
\spadpaste{eval(p,x,1) \free{p}}
}
\xtc{
Actually, all the things being substituted are just polynomials,
some more trivial than others.
}{
\spadpaste{eval(p,x,y**2 - 1) \free{p}}
}

\xtc{
Derivatives are computed using the \spadfunFrom{D}{Polynomial}
operation.
}{
\spadpaste{D(p,x) \free{p}}
}
\xtc{
The first argument is the polynomial and the second is the variable.
}{
\spadpaste{D(p,y) \free{p}}
}
\xtc{
Even if the polynomial has only one variable, you must specify it.
}{
\spadpaste{D(p,z) \free{p}}
}

Integration of polynomials is similar and the
\spadfunFrom{integrate}{Polynomial} operation is used.

\xtc{
Integration requires that the coefficients support division.
Consequently,
Axiom converts polynomials over the integers to polynomials over
the rational numbers before integrating them.
}{
\spadpaste{integrate(p,y) \free{p}}
}

It is not possible, in general, to divide two polynomials.
In our example using polynomials over the integers, the operation
\spadfunFrom{monicDivide}{Polynomial} divides a polynomial by a monic
polynomial (that is, a polynomial with leading coefficient equal to 1).
The result is a record of the quotient and remainder of the
division.
\xtc{
You must specify the variable in which to express the polynomial.
}{
\spadpaste{qr := monicDivide(p,x+1,x) \free{p}\bound{qr}}
}
\xtc{
The selectors of the components of the record are
\spad{quotient} and \spad{remainder}.
Issue this to extract the remainder.
}{
\spadpaste{qr.remainder \free{qr}}
}
\xtc{
Now that we can extract the components, we can demonstrate the
relationship among them and the arguments to our original expression
\spad{qr := monicDivide(p,x+1,x)}.
}{
\spadpaste{p - ((x+1) * qr.quotient + qr.remainder) \free{p}\free{qr}}
}

\xtc{
If the \spadopFrom{/}{Fraction} operator is used with polynomials, a
fraction object is created.
In this example, the result is an object of type \spadtype{Fraction
Polynomial Integer}.
}{
\spadpaste{p/q \free{p}\free{q}}
}
\xtc{
If you use rational numbers as polynomial coefficients, the
resulting object is of type \spadtype{Polynomial Fraction Integer}.
}{
\spadpaste{(2/3) * x**2 - y + 4/5 \bound{prev1}}
}
\xtc{
This can be converted to a fraction of polynomials and back again, if
required.
}{
\spadpaste{\% :: FRAC POLY INT \free{prev1}\bound{prev2}}
}
\xtc{
}{
\spadpaste{\% :: POLY FRAC INT \free{prev2}\bound{prev3}}
}
\xtc{
To convert the coefficients to floating point,
map the \spadfun{numeric} operation on the coefficients of the polynomial.
}{
\spadpaste{map(numeric,\%) \free{prev3}}
}

For more information on related topics, see
\downlink{`UnivariatePolynomial'}{UnivariatePolyXmpPage}
\ignore{UnivariatePolynomial},
\downlink{`MultivariatePolynomial'}{MultivariatePolyXmpPage}
\ignore{MultivariatePolynomial}, and
\downlink{`DistributedMultivariatePoly'}
{DistributedMultivariatePolyXmpPage}
\ignore{DistributedMultivariatePoly}.
You can also issue the system command
\spadcmd{)show Polynomial}
to display the full list of operations defined by
\spadtype{Polynomial}.
\endscroll
\autobuttons
\end{page}

\begin{patch}{PolynomialXmpPagePatch1}
\begin{paste}{PolynomialXmpPageFull1}{PolynomialXmpPageEmpty1}
\pastebutton{PolynomialXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{x + 1}
\indentrel{3}\begin{verbatim}
   (1)  x + 1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty1}
\begin{paste}{PolynomialXmpPageEmpty1}{PolynomialXmpPagePatch1}
\pastebutton{PolynomialXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{x + 1}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch2}
\begin{paste}{PolynomialXmpPageFull2}{PolynomialXmpPageEmpty2}
\pastebutton{PolynomialXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{z - 2.3}
\indentrel{3}\begin{verbatim}
   (2)  z - 2.3
                                 Type: Polynomial Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty2}
\begin{paste}{PolynomialXmpPageEmpty2}{PolynomialXmpPagePatch2}
\pastebutton{PolynomialXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{z - 2.3}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch3}
\begin{paste}{PolynomialXmpPageFull3}{PolynomialXmpPageEmpty3}
\pastebutton{PolynomialXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{y**2 - z + 3/4}
\indentrel{3}\begin{verbatim}
               2   3
   (3)  - z + y  + Ä
                   4
                      Type: Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty3}
\begin{paste}{PolynomialXmpPageEmpty3}{PolynomialXmpPagePatch3}
\pastebutton{PolynomialXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{y**2 - z + 3/4}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch4}
\begin{paste}{PolynomialXmpPageFull4}{PolynomialXmpPageEmpty4}
\pastebutton{PolynomialXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{y **2 + x*y + y\bound{prev }}
\indentrel{3}\begin{verbatim}
         2
   (4)  y  + (x + 1)y
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty4}
\begin{paste}{PolynomialXmpPageEmpty4}{PolynomialXmpPagePatch4}
\pastebutton{PolynomialXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{y **2 + x*y + y\bound{prev }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch5}
\begin{paste}{PolynomialXmpPageFull5}{PolynomialXmpPageEmpty5}
\pastebutton{PolynomialXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{\% :: DMP([y,x],INT)\free{prev }}
\indentrel{3}\begin{verbatim}
         2
   (5)  y  + y x + y
 Type: DistributedMultivariatePolynomial([y,x],Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty5}
\begin{paste}{PolynomialXmpPageEmpty5}{PolynomialXmpPagePatch5}
\pastebutton{PolynomialXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{\% :: DMP([y,x],INT)\free{prev }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch6}
\begin{paste}{PolynomialXmpPageFull6}{PolynomialXmpPageEmpty6}
\pastebutton{PolynomialXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{p := (y-1)**2 * x * z\bound{p }}
\indentrel{3}\begin{verbatim}
            2
   (6)  (x y  - 2x y + x)z
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty6}
\begin{paste}{PolynomialXmpPageEmpty6}{PolynomialXmpPagePatch6}
\pastebutton{PolynomialXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{p := (y-1)**2 * x * z\bound{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch7}
\begin{paste}{PolynomialXmpPageFull7}{PolynomialXmpPageEmpty7}
\pastebutton{PolynomialXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{q := (y-1) * x * (z+5)\bound{q }}
\indentrel{3}\begin{verbatim}
   (7)  (x y - x)z + 5x y - 5x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty7}
\begin{paste}{PolynomialXmpPageEmpty7}{PolynomialXmpPagePatch7}
\pastebutton{PolynomialXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{q := (y-1) * x * (z+5)\bound{q }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch8}
\begin{paste}{PolynomialXmpPageFull8}{PolynomialXmpPageEmpty8}
\pastebutton{PolynomialXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{factor(q)\free{q }}
\indentrel{3}\begin{verbatim}
   (8)  x(y - 1)(z + 5)
                      Type: Factored Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty8}
\begin{paste}{PolynomialXmpPageEmpty8}{PolynomialXmpPagePatch8}
\pastebutton{PolynomialXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{factor(q)\free{q }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch9}
\begin{paste}{PolynomialXmpPageFull9}{PolynomialXmpPageEmpty9}
\pastebutton{PolynomialXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{p - q**2\free{p q }}
\indentrel{3}\begin{verbatim}
   (9)
         2 2     2     2  2
     (- x y  + 2x y - x )z
   + 
            2      2       2             2            2 2
     ((- 10x  + x)y  + (20x  - 2x)y - 10x  + x)z - 25x y
   + 
        2       2
     50x y - 25x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty9}
\begin{paste}{PolynomialXmpPageEmpty9}{PolynomialXmpPagePatch9}
\pastebutton{PolynomialXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{p - q**2\free{p q }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch10}
\begin{paste}{PolynomialXmpPageFull10}{PolynomialXmpPageEmpty10}
\pastebutton{PolynomialXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{gcd(p,q)\free{p q }\bound{prev4 }}
\indentrel{3}\begin{verbatim}
   (10)  x y - x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty10}
\begin{paste}{PolynomialXmpPageEmpty10}{PolynomialXmpPagePatch10}
\pastebutton{PolynomialXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{gcd(p,q)\free{p q }\bound{prev4 }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch11}
\begin{paste}{PolynomialXmpPageFull11}{PolynomialXmpPageEmpty11}
\pastebutton{PolynomialXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{factor \%\free{prev4 }}
\indentrel{3}\begin{verbatim}
   (11)  x(y - 1)
                      Type: Factored Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty11}
\begin{paste}{PolynomialXmpPageEmpty11}{PolynomialXmpPagePatch11}
\pastebutton{PolynomialXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{factor \%\free{prev4 }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch12}
\begin{paste}{PolynomialXmpPageFull12}{PolynomialXmpPageEmpty12}
\pastebutton{PolynomialXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{lcm(p,q)\free{p q }}
\indentrel{3}\begin{verbatim}
             2             2        2
   (12)  (x y  - 2x y + x)z  + (5x y  - 10x y + 5x)z
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty12}
\begin{paste}{PolynomialXmpPageEmpty12}{PolynomialXmpPagePatch12}
\pastebutton{PolynomialXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{lcm(p,q)\free{p q }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch13}
\begin{paste}{PolynomialXmpPageFull13}{PolynomialXmpPageEmpty13}
\pastebutton{PolynomialXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{content p\free{p }}
\indentrel{3}\begin{verbatim}
   (13)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty13}
\begin{paste}{PolynomialXmpPageEmpty13}{PolynomialXmpPagePatch13}
\pastebutton{PolynomialXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{content p\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch14}
\begin{paste}{PolynomialXmpPageFull14}{PolynomialXmpPageEmpty14}
\pastebutton{PolynomialXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{resultant(p,q,z)\free{p q }}
\indentrel{3}\begin{verbatim}
           2 3      2 2      2      2
   (14)  5x y  - 15x y  + 15x y - 5x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty14}
\begin{paste}{PolynomialXmpPageEmpty14}{PolynomialXmpPagePatch14}
\pastebutton{PolynomialXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{resultant(p,q,z)\free{p q }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch15}
\begin{paste}{PolynomialXmpPageFull15}{PolynomialXmpPageEmpty15}
\pastebutton{PolynomialXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{resultant(p,q,x)\free{p }\free{q }}
\indentrel{3}\begin{verbatim}
   (15)  0
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty15}
\begin{paste}{PolynomialXmpPageEmpty15}{PolynomialXmpPagePatch15}
\pastebutton{PolynomialXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{resultant(p,q,x)\free{p }\free{q }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch16}
\begin{paste}{PolynomialXmpPageFull16}{PolynomialXmpPageEmpty16}
\pastebutton{PolynomialXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{mainVariable p\free{p }}
\indentrel{3}\begin{verbatim}
   (16)  z
                                Type: Union(Symbol,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty16}
\begin{paste}{PolynomialXmpPageEmpty16}{PolynomialXmpPagePatch16}
\pastebutton{PolynomialXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{mainVariable p\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch17}
\begin{paste}{PolynomialXmpPageFull17}{PolynomialXmpPageEmpty17}
\pastebutton{PolynomialXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{mainVariable(1 :: POLY INT)}
\indentrel{3}\begin{verbatim}
   (17)  "failed"
                              Type: Union("failed",...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty17}
\begin{paste}{PolynomialXmpPageEmpty17}{PolynomialXmpPagePatch17}
\pastebutton{PolynomialXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{mainVariable(1 :: POLY INT)}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch18}
\begin{paste}{PolynomialXmpPageFull18}{PolynomialXmpPageEmpty18}
\pastebutton{PolynomialXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{ground? p\free{p }}
\indentrel{3}\begin{verbatim}
   (18)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty18}
\begin{paste}{PolynomialXmpPageEmpty18}{PolynomialXmpPagePatch18}
\pastebutton{PolynomialXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{ground? p\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch19}
\begin{paste}{PolynomialXmpPageFull19}{PolynomialXmpPageEmpty19}
\pastebutton{PolynomialXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{ground?(1 :: POLY INT)}
\indentrel{3}\begin{verbatim}
   (19)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty19}
\begin{paste}{PolynomialXmpPageEmpty19}{PolynomialXmpPagePatch19}
\pastebutton{PolynomialXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{ground?(1 :: POLY INT)}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch20}
\begin{paste}{PolynomialXmpPageFull20}{PolynomialXmpPageEmpty20}
\pastebutton{PolynomialXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{variables p\free{p }}
\indentrel{3}\begin{verbatim}
   (20)  [z,y,x]
                                      Type: List Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty20}
\begin{paste}{PolynomialXmpPageEmpty20}{PolynomialXmpPagePatch20}
\pastebutton{PolynomialXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{variables p\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch21}
\begin{paste}{PolynomialXmpPageFull21}{PolynomialXmpPageEmpty21}
\pastebutton{PolynomialXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{degree(p,x)\free{p }}
\indentrel{3}\begin{verbatim}
   (21)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty21}
\begin{paste}{PolynomialXmpPageEmpty21}{PolynomialXmpPagePatch21}
\pastebutton{PolynomialXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{degree(p,x)\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch22}
\begin{paste}{PolynomialXmpPageFull22}{PolynomialXmpPageEmpty22}
\pastebutton{PolynomialXmpPageFull22}{\hidepaste}
\tab{5}\spadcommand{degree(p,y)\free{p }}
\indentrel{3}\begin{verbatim}
   (22)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty22}
\begin{paste}{PolynomialXmpPageEmpty22}{PolynomialXmpPagePatch22}
\pastebutton{PolynomialXmpPageEmpty22}{\showpaste}
\tab{5}\spadcommand{degree(p,y)\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch23}
\begin{paste}{PolynomialXmpPageFull23}{PolynomialXmpPageEmpty23}
\pastebutton{PolynomialXmpPageFull23}{\hidepaste}
\tab{5}\spadcommand{degree(p,z)\free{p }}
\indentrel{3}\begin{verbatim}
   (23)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty23}
\begin{paste}{PolynomialXmpPageEmpty23}{PolynomialXmpPagePatch23}
\pastebutton{PolynomialXmpPageEmpty23}{\showpaste}
\tab{5}\spadcommand{degree(p,z)\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch24}
\begin{paste}{PolynomialXmpPageFull24}{PolynomialXmpPageEmpty24}
\pastebutton{PolynomialXmpPageFull24}{\hidepaste}
\tab{5}\spadcommand{degree(p,[x,y,z])\free{p }}
\indentrel{3}\begin{verbatim}
   (24)  [1,2,1]
                          Type: List NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty24}
\begin{paste}{PolynomialXmpPageEmpty24}{PolynomialXmpPagePatch24}
\pastebutton{PolynomialXmpPageEmpty24}{\showpaste}
\tab{5}\spadcommand{degree(p,[x,y,z])\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch25}
\begin{paste}{PolynomialXmpPageFull25}{PolynomialXmpPageEmpty25}
\pastebutton{PolynomialXmpPageFull25}{\hidepaste}
\tab{5}\spadcommand{minimumDegree(p,z)\free{p }}
\indentrel{3}\begin{verbatim}
   (25)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty25}
\begin{paste}{PolynomialXmpPageEmpty25}{PolynomialXmpPagePatch25}
\pastebutton{PolynomialXmpPageEmpty25}{\showpaste}
\tab{5}\spadcommand{minimumDegree(p,z)\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch26}
\begin{paste}{PolynomialXmpPageFull26}{PolynomialXmpPageEmpty26}
\pastebutton{PolynomialXmpPageFull26}{\hidepaste}
\tab{5}\spadcommand{totalDegree p\free{p }}
\indentrel{3}\begin{verbatim}
   (26)  4
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty26}
\begin{paste}{PolynomialXmpPageEmpty26}{PolynomialXmpPagePatch26}
\pastebutton{PolynomialXmpPageEmpty26}{\showpaste}
\tab{5}\spadcommand{totalDegree p\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch27}
\begin{paste}{PolynomialXmpPageFull27}{PolynomialXmpPageEmpty27}
\pastebutton{PolynomialXmpPageFull27}{\hidepaste}
\tab{5}\spadcommand{leadingMonomial p\free{p }}
\indentrel{3}\begin{verbatim}
            2
   (27)  x y z
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty27}
\begin{paste}{PolynomialXmpPageEmpty27}{PolynomialXmpPagePatch27}
\pastebutton{PolynomialXmpPageEmpty27}{\showpaste}
\tab{5}\spadcommand{leadingMonomial p\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch28}
\begin{paste}{PolynomialXmpPageFull28}{PolynomialXmpPageEmpty28}
\pastebutton{PolynomialXmpPageFull28}{\hidepaste}
\tab{5}\spadcommand{reductum p\free{p }}
\indentrel{3}\begin{verbatim}
   (28)  (- 2x y + x)z
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty28}
\begin{paste}{PolynomialXmpPageEmpty28}{PolynomialXmpPagePatch28}
\pastebutton{PolynomialXmpPageEmpty28}{\showpaste}
\tab{5}\spadcommand{reductum p\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch29}
\begin{paste}{PolynomialXmpPageFull29}{PolynomialXmpPageEmpty29}
\pastebutton{PolynomialXmpPageFull29}{\hidepaste}
\tab{5}\spadcommand{p - leadingMonomial p - reductum p\free{p }}
\indentrel{3}\begin{verbatim}
   (29)  0
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty29}
\begin{paste}{PolynomialXmpPageEmpty29}{PolynomialXmpPagePatch29}
\pastebutton{PolynomialXmpPageEmpty29}{\showpaste}
\tab{5}\spadcommand{p - leadingMonomial p - reductum p\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch30}
\begin{paste}{PolynomialXmpPageFull30}{PolynomialXmpPageEmpty30}
\pastebutton{PolynomialXmpPageFull30}{\hidepaste}
\tab{5}\spadcommand{leadingCoefficient p\free{p }}
\indentrel{3}\begin{verbatim}
   (30)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty30}
\begin{paste}{PolynomialXmpPageEmpty30}{PolynomialXmpPagePatch30}
\pastebutton{PolynomialXmpPageEmpty30}{\showpaste}
\tab{5}\spadcommand{leadingCoefficient p\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch31}
\begin{paste}{PolynomialXmpPageFull31}{PolynomialXmpPageEmpty31}
\pastebutton{PolynomialXmpPageFull31}{\hidepaste}
\tab{5}\spadcommand{p\free{p }}
\indentrel{3}\begin{verbatim}
             2
   (31)  (x y  - 2x y + x)z
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty31}
\begin{paste}{PolynomialXmpPageEmpty31}{PolynomialXmpPagePatch31}
\pastebutton{PolynomialXmpPageEmpty31}{\showpaste}
\tab{5}\spadcommand{p\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch32}
\begin{paste}{PolynomialXmpPageFull32}{PolynomialXmpPageEmpty32}
\pastebutton{PolynomialXmpPageFull32}{\hidepaste}
\tab{5}\spadcommand{eval(p,x,w)\free{p }}
\indentrel{3}\begin{verbatim}
             2
   (32)  (w y  - 2w y + w)z
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty32}
\begin{paste}{PolynomialXmpPageEmpty32}{PolynomialXmpPagePatch32}
\pastebutton{PolynomialXmpPageEmpty32}{\showpaste}
\tab{5}\spadcommand{eval(p,x,w)\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch33}
\begin{paste}{PolynomialXmpPageFull33}{PolynomialXmpPageEmpty33}
\pastebutton{PolynomialXmpPageFull33}{\hidepaste}
\tab{5}\spadcommand{eval(p,x,1)\free{p }}
\indentrel{3}\begin{verbatim}
           2
   (33)  (y  - 2y + 1)z
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty33}
\begin{paste}{PolynomialXmpPageEmpty33}{PolynomialXmpPagePatch33}
\pastebutton{PolynomialXmpPageEmpty33}{\showpaste}
\tab{5}\spadcommand{eval(p,x,1)\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch34}
\begin{paste}{PolynomialXmpPageFull34}{PolynomialXmpPageEmpty34}
\pastebutton{PolynomialXmpPageFull34}{\hidepaste}
\tab{5}\spadcommand{eval(p,x,y**2 - 1)\free{p }}
\indentrel{3}\begin{verbatim}
           4     3
   (34)  (y  - 2y  + 2y - 1)z
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty34}
\begin{paste}{PolynomialXmpPageEmpty34}{PolynomialXmpPagePatch34}
\pastebutton{PolynomialXmpPageEmpty34}{\showpaste}
\tab{5}\spadcommand{eval(p,x,y**2 - 1)\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch35}
\begin{paste}{PolynomialXmpPageFull35}{PolynomialXmpPageEmpty35}
\pastebutton{PolynomialXmpPageFull35}{\hidepaste}
\tab{5}\spadcommand{D(p,x)\free{p }}
\indentrel{3}\begin{verbatim}
           2
   (35)  (y  - 2y + 1)z
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty35}
\begin{paste}{PolynomialXmpPageEmpty35}{PolynomialXmpPagePatch35}
\pastebutton{PolynomialXmpPageEmpty35}{\showpaste}
\tab{5}\spadcommand{D(p,x)\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch36}
\begin{paste}{PolynomialXmpPageFull36}{PolynomialXmpPageEmpty36}
\pastebutton{PolynomialXmpPageFull36}{\hidepaste}
\tab{5}\spadcommand{D(p,y)\free{p }}
\indentrel{3}\begin{verbatim}
   (36)  (2x y - 2x)z
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty36}
\begin{paste}{PolynomialXmpPageEmpty36}{PolynomialXmpPagePatch36}
\pastebutton{PolynomialXmpPageEmpty36}{\showpaste}
\tab{5}\spadcommand{D(p,y)\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch37}
\begin{paste}{PolynomialXmpPageFull37}{PolynomialXmpPageEmpty37}
\pastebutton{PolynomialXmpPageFull37}{\hidepaste}
\tab{5}\spadcommand{D(p,z)\free{p }}
\indentrel{3}\begin{verbatim}
            2
   (37)  x y  - 2x y + x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty37}
\begin{paste}{PolynomialXmpPageEmpty37}{PolynomialXmpPagePatch37}
\pastebutton{PolynomialXmpPageEmpty37}{\showpaste}
\tab{5}\spadcommand{D(p,z)\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch38}
\begin{paste}{PolynomialXmpPageFull38}{PolynomialXmpPageEmpty38}
\pastebutton{PolynomialXmpPageFull38}{\hidepaste}
\tab{5}\spadcommand{integrate(p,y)\free{p }}
\indentrel{3}\begin{verbatim}
          1    3      2
   (38)  (Ä x y  - x y  + x y)z
          3
                      Type: Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty38}
\begin{paste}{PolynomialXmpPageEmpty38}{PolynomialXmpPagePatch38}
\pastebutton{PolynomialXmpPageEmpty38}{\showpaste}
\tab{5}\spadcommand{integrate(p,y)\free{p }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch39}
\begin{paste}{PolynomialXmpPageFull39}{PolynomialXmpPageEmpty39}
\pastebutton{PolynomialXmpPageFull39}{\hidepaste}
\tab{5}\spadcommand{qr := monicDivide(p,x+1,x)\free{p }\bound{qr }}
\indentrel{3}\begin{verbatim}
   (39)
                2                           2
   [quotient= (y  - 2y + 1)z,remainder= (- y  + 2y - 1)z]
Type: Record(quotient: Polynomial Integer,remainder: Polynomial Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty39}
\begin{paste}{PolynomialXmpPageEmpty39}{PolynomialXmpPagePatch39}
\pastebutton{PolynomialXmpPageEmpty39}{\showpaste}
\tab{5}\spadcommand{qr := monicDivide(p,x+1,x)\free{p }\bound{qr }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch40}
\begin{paste}{PolynomialXmpPageFull40}{PolynomialXmpPageEmpty40}
\pastebutton{PolynomialXmpPageFull40}{\hidepaste}
\tab{5}\spadcommand{qr.remainder\free{qr }}
\indentrel{3}\begin{verbatim}
             2
   (40)  (- y  + 2y - 1)z
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty40}
\begin{paste}{PolynomialXmpPageEmpty40}{PolynomialXmpPagePatch40}
\pastebutton{PolynomialXmpPageEmpty40}{\showpaste}
\tab{5}\spadcommand{qr.remainder\free{qr }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch41}
\begin{paste}{PolynomialXmpPageFull41}{PolynomialXmpPageEmpty41}
\pastebutton{PolynomialXmpPageFull41}{\hidepaste}
\tab{5}\spadcommand{p - ((x+1) * qr.quotient + qr.remainder)\free{p }\free{qr }}
\indentrel{3}\begin{verbatim}
   (41)  0
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty41}
\begin{paste}{PolynomialXmpPageEmpty41}{PolynomialXmpPagePatch41}
\pastebutton{PolynomialXmpPageEmpty41}{\showpaste}
\tab{5}\spadcommand{p - ((x+1) * qr.quotient + qr.remainder)\free{p }\free{qr }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch42}
\begin{paste}{PolynomialXmpPageFull42}{PolynomialXmpPageEmpty42}
\pastebutton{PolynomialXmpPageFull42}{\hidepaste}
\tab{5}\spadcommand{p/q\free{p }\free{q }}
\indentrel{3}\begin{verbatim}
         (y - 1)z
   (42)  ÄÄÄÄÄÄÄÄ
           z + 5
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty42}
\begin{paste}{PolynomialXmpPageEmpty42}{PolynomialXmpPagePatch42}
\pastebutton{PolynomialXmpPageEmpty42}{\showpaste}
\tab{5}\spadcommand{p/q\free{p }\free{q }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch43}
\begin{paste}{PolynomialXmpPageFull43}{PolynomialXmpPageEmpty43}
\pastebutton{PolynomialXmpPageFull43}{\hidepaste}
\tab{5}\spadcommand{(2/3) * x**2 - y + 4/5\bound{prev1 }}
\indentrel{3}\begin{verbatim}
               2  2   4
   (43)  - y + Ä x  + Ä
               3      5
                      Type: Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty43}
\begin{paste}{PolynomialXmpPageEmpty43}{PolynomialXmpPagePatch43}
\pastebutton{PolynomialXmpPageEmpty43}{\showpaste}
\tab{5}\spadcommand{(2/3) * x**2 - y + 4/5\bound{prev1 }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch44}
\begin{paste}{PolynomialXmpPageFull44}{PolynomialXmpPageEmpty44}
\pastebutton{PolynomialXmpPageFull44}{\hidepaste}
\tab{5}\spadcommand{\% :: FRAC POLY INT\free{prev1 }\bound{prev2 }}
\indentrel{3}\begin{verbatim}
                    2
         - 15y + 10x  + 12
   (44)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                 15
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty44}
\begin{paste}{PolynomialXmpPageEmpty44}{PolynomialXmpPagePatch44}
\pastebutton{PolynomialXmpPageEmpty44}{\showpaste}
\tab{5}\spadcommand{\% :: FRAC POLY INT\free{prev1 }\bound{prev2 }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch45}
\begin{paste}{PolynomialXmpPageFull45}{PolynomialXmpPageEmpty45}
\pastebutton{PolynomialXmpPageFull45}{\hidepaste}
\tab{5}\spadcommand{\% :: POLY FRAC INT\free{prev2 }\bound{prev3 }}
\indentrel{3}\begin{verbatim}
               2  2   4
   (45)  - y + Ä x  + Ä
               3      5
                      Type: Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty45}
\begin{paste}{PolynomialXmpPageEmpty45}{PolynomialXmpPagePatch45}
\pastebutton{PolynomialXmpPageEmpty45}{\showpaste}
\tab{5}\spadcommand{\% :: POLY FRAC INT\free{prev2 }\bound{prev3 }}
\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPagePatch46}
\begin{paste}{PolynomialXmpPageFull46}{PolynomialXmpPageEmpty46}
\pastebutton{PolynomialXmpPageFull46}{\hidepaste}
\tab{5}\spadcommand{map(numeric,\%)\free{prev3 }}
\indentrel{3}\begin{verbatim}
                                            2
   (46)  - 1.0 y + 0.6666666666 6666666667 x  + 0.8
                                 Type: Polynomial Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{PolynomialXmpPageEmpty46}
\begin{paste}{PolynomialXmpPageEmpty46}{PolynomialXmpPagePatch46}
\pastebutton{PolynomialXmpPageEmpty46}{\showpaste}
\tab{5}\spadcommand{map(numeric,\%)\free{prev3 }}
\end{paste}\end{patch}

\end{chunk}
\section{quat.ht}
\pagetitle{QuaternionXmpPage}{quat.ht}{Quaternion}
\pagepic{ps/v71quaternionxmppage.eps}{QuaternionXmpPage}{0.50}
\pagefrom{Axiom Number Types}{NumberPage}
\pageto{Complex}{ComplexXmpPage}
\pageto{Octonion}{OctonionXmpPage}
\begin{chunk}{quat.ht}
\begin{page}{QuaternionXmpPage}{Quaternion}
\beginscroll
The domain constructor \spadtype{Quaternion} implements quaternions over
commutative rings.
For information on related topics, see
\downlink{`Complex'}{ComplexXmpPage}\ignore{Complex} and
\downlink{`Octonion'}{OctonionXmpPage}\ignore{Octonion}.
You can also issue the system command
\spadcmd{)show Quaternion}
to display the full list of operations defined by
\spadtype{Quaternion}.

\xtc{
The basic operation for creating quaternions is
\spadfunFrom{quatern}{Quaternion}.
This is a quaternion over the rational numbers.
}{
\spadpaste{q := quatern(2/11,-8,3/4,1) \bound{q}}
}
\xtc{
The four arguments are the real part, the \spad{i} imaginary part, the
\spad{j} imaginary part, and the \spad{k} imaginary part, respectively.
}{
\spadpaste{[real q, imagI q, imagJ q, imagK q] \free{q}}
}
\xtc{
Because \spad{q} is over the rationals (and nonzero), you can invert it.
}{
\spadpaste{inv q \free{q}}
}
\xtc{
The usual arithmetic (ring) operations are available
}{
\spadpaste{q**6 \free{q}}
}
\xtc{
}{
\spadpaste{r := quatern(-2,3,23/9,-89); q + r \bound{r}\free{q}}
}
%
\xtc{
In general, multiplication is not commutative.
}{
\spadpaste{q * r - r * q\free{q r}}
}
\xtc{
There are no predefined constants for the imaginary \spad{i, j},
and \spad{k} parts, but you can easily define them.
}{
\spadpaste{i:=quatern(0,1,0,0); j:=quatern(0,0,1,0); 
k:=quatern(0,0,0,1) \bound{i j k}}
}
\xtc{
These satisfy the normal identities.
}{
\spadpaste{[i*i, j*j, k*k, i*j, j*k, k*i, q*i] \free{i j k q}}
}
\xtc{
The norm is the quaternion times its conjugate.
}{
\spadpaste{norm q \free{q}}
}
\xtc{
}{
\spadpaste{conjugate q \free{q} \bound{prev}}
}
\xtc{
}{
\spadpaste{q * \% \free{q prev}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{QuaternionXmpPagePatch1}
\begin{paste}{QuaternionXmpPageFull1}{QuaternionXmpPageEmpty1}
\pastebutton{QuaternionXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{q := quatern(2/11,-8,3/4,1)\bound{q }}
\indentrel{3}\begin{verbatim}
         2        3
   (1)  ÄÄ - 8i + Ä j + k
        11        4
                      Type: Quaternion Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{QuaternionXmpPageEmpty1}
\begin{paste}{QuaternionXmpPageEmpty1}{QuaternionXmpPagePatch1}
\pastebutton{QuaternionXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{q := quatern(2/11,-8,3/4,1)\bound{q }}
\end{paste}\end{patch}

\begin{patch}{QuaternionXmpPagePatch2}
\begin{paste}{QuaternionXmpPageFull2}{QuaternionXmpPageEmpty2}
\pastebutton{QuaternionXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{[real q, imagI q, imagJ q, imagK q]\free{q }}
\indentrel{3}\begin{verbatim}
          2     3
   (2)  [ÄÄ,- 8,Ä,1]
         11     4
                            Type: List Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{QuaternionXmpPageEmpty2}
\begin{paste}{QuaternionXmpPageEmpty2}{QuaternionXmpPagePatch2}
\pastebutton{QuaternionXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{[real q, imagI q, imagJ q, imagK q]\free{q }}
\end{paste}\end{patch}

\begin{patch}{QuaternionXmpPagePatch3}
\begin{paste}{QuaternionXmpPageFull3}{QuaternionXmpPageEmpty3}
\pastebutton{QuaternionXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{inv q\free{q }}
\indentrel{3}\begin{verbatim}
          352     15488      484       1936
   (3)  ÄÄÄÄÄÄ + ÄÄÄÄÄÄ i - ÄÄÄÄÄ j - ÄÄÄÄÄÄ k
        126993   126993     42331     126993
                      Type: Quaternion Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{QuaternionXmpPageEmpty3}
\begin{paste}{QuaternionXmpPageEmpty3}{QuaternionXmpPagePatch3}
\pastebutton{QuaternionXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{inv q\free{q }}
\end{paste}\end{patch}

\begin{patch}{QuaternionXmpPagePatch4}
\begin{paste}{QuaternionXmpPageFull4}{QuaternionXmpPageEmpty4}
\pastebutton{QuaternionXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{q**6\free{q }}
\indentrel{3}\begin{verbatim}
   (4)
       2029490709319345   48251690851     144755072553
     - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ - ÄÄÄÄÄÄÄÄÄÄÄ i + ÄÄÄÄÄÄÄÄÄÄÄÄ j
          7256313856        1288408         41229056
   + 
     48251690851
     ÄÄÄÄÄÄÄÄÄÄÄ k
       10307264
                      Type: Quaternion Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{QuaternionXmpPageEmpty4}
\begin{paste}{QuaternionXmpPageEmpty4}{QuaternionXmpPagePatch4}
\pastebutton{QuaternionXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{q**6\free{q }}
\end{paste}\end{patch}

\begin{patch}{QuaternionXmpPagePatch5}
\begin{paste}{QuaternionXmpPageFull5}{QuaternionXmpPageEmpty5}
\pastebutton{QuaternionXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{r := quatern(-2,3,23/9,-89); q + r\bound{r }\free{q }}
\indentrel{3}\begin{verbatim}
          20        119
   (5)  - ÄÄ - 5i + ÄÄÄ j - 88k
          11         36
                      Type: Quaternion Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{QuaternionXmpPageEmpty5}
\begin{paste}{QuaternionXmpPageEmpty5}{QuaternionXmpPagePatch5}
\pastebutton{QuaternionXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{r := quatern(-2,3,23/9,-89); q + r\bound{r }\free{q }}
\end{paste}\end{patch}

\begin{patch}{QuaternionXmpPagePatch6}
\begin{paste}{QuaternionXmpPageFull6}{QuaternionXmpPageEmpty6}
\pastebutton{QuaternionXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{q * r - r * q\free{q r }}
\indentrel{3}\begin{verbatim}
          2495             817
   (6)  - ÄÄÄÄ i - 1418j - ÄÄÄ k
           18               18
                      Type: Quaternion Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{QuaternionXmpPageEmpty6}
\begin{paste}{QuaternionXmpPageEmpty6}{QuaternionXmpPagePatch6}
\pastebutton{QuaternionXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{q * r - r * q\free{q r }}
\end{paste}\end{patch}

\begin{patch}{QuaternionXmpPagePatch7}
\begin{paste}{QuaternionXmpPageFull7}{QuaternionXmpPageEmpty7}
\pastebutton{QuaternionXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{i:=quatern(0,1,0,0); j:=quatern(0,0,1,0); k:=quatern(0,0,0,1)\bound{i j k }}
\indentrel{3}\begin{verbatim}
   (7)  k
                               Type: Quaternion Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{QuaternionXmpPageEmpty7}
\begin{paste}{QuaternionXmpPageEmpty7}{QuaternionXmpPagePatch7}
\pastebutton{QuaternionXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{i:=quatern(0,1,0,0); j:=quatern(0,0,1,0); k:=quatern(0,0,0,1)\bound{i j k }}
\end{paste}\end{patch}

\begin{patch}{QuaternionXmpPagePatch8}
\begin{paste}{QuaternionXmpPageFull8}{QuaternionXmpPageEmpty8}
\pastebutton{QuaternionXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{[i*i, j*j, k*k, i*j, j*k, k*i, q*i]\free{i j k q }}
\indentrel{3}\begin{verbatim}
                                2         3
   (8)  [- 1,- 1,- 1,k,i,j,8 + ÄÄ i + j - Ä k]
                               11         4
                 Type: List Quaternion Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{QuaternionXmpPageEmpty8}
\begin{paste}{QuaternionXmpPageEmpty8}{QuaternionXmpPagePatch8}
\pastebutton{QuaternionXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{[i*i, j*j, k*k, i*j, j*k, k*i, q*i]\free{i j k q }}
\end{paste}\end{patch}

\begin{patch}{QuaternionXmpPagePatch9}
\begin{paste}{QuaternionXmpPageFull9}{QuaternionXmpPageEmpty9}
\pastebutton{QuaternionXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{norm q\free{q }}
\indentrel{3}\begin{verbatim}
        126993
   (9)  ÄÄÄÄÄÄ
         1936
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{QuaternionXmpPageEmpty9}
\begin{paste}{QuaternionXmpPageEmpty9}{QuaternionXmpPagePatch9}
\pastebutton{QuaternionXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{norm q\free{q }}
\end{paste}\end{patch}

\begin{patch}{QuaternionXmpPagePatch10}
\begin{paste}{QuaternionXmpPageFull10}{QuaternionXmpPageEmpty10}
\pastebutton{QuaternionXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{conjugate q\free{q }\bound{prev }}
\indentrel{3}\begin{verbatim}
          2        3
   (10)  ÄÄ + 8i - Ä j - k
         11        4
                      Type: Quaternion Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{QuaternionXmpPageEmpty10}
\begin{paste}{QuaternionXmpPageEmpty10}{QuaternionXmpPagePatch10}
\pastebutton{QuaternionXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{conjugate q\free{q }\bound{prev }}
\end{paste}\end{patch}

\begin{patch}{QuaternionXmpPagePatch11}
\begin{paste}{QuaternionXmpPageFull11}{QuaternionXmpPageEmpty11}
\pastebutton{QuaternionXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{q * \%\free{q prev }}
\indentrel{3}\begin{verbatim}
         126993
   (11)  ÄÄÄÄÄÄ
          1936
                      Type: Quaternion Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{QuaternionXmpPageEmpty11}
\begin{paste}{QuaternionXmpPageEmpty11}{QuaternionXmpPagePatch11}
\pastebutton{QuaternionXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{q * \%\free{q prev }}
\end{paste}\end{patch}

\end{chunk}
\section{radix.ht}
\pagetitle{RadixExpansionXmpPage}{radix.ht}{RadixExpansion}
\pagepic{ps/v71radixexpansionxmppage.eps}{RadixExpansionXmpPage}{0.50}
\pagefrom{Axiom Number Types}{NumberPage}
\pagefrom{Integer}{IntegerXmpPage}
\pageto{HexadecimalExpansion}{HexExpansionXmpPage}
\pageto{DecimalExpansion}{DecimalExpansionXmpPage}
\pageto{BinaryExpansion}{BinaryExpansionXmpPage}
\begin{chunk}{radix.ht}
\begin{page}{RadixExpansionXmpPage}{RadixExpansion}
\beginscroll
It is possible to expand numbers in general bases.
\labelSpace{2pc}
\xtc{
Here we expand \spad{111} in base \spad{5}.
This means
\texht{$10^2+10^1+10^0 = 4 \cdot 5^2+2 \cdot 5^1 + 5^0.$}{%
\spad{10**2+10**1+10**0 = 4*5**2+2*5**1+5**0.}}
}{
\spadpaste{111::RadixExpansion(5)}
}

\xtc{
You can expand fractions to form repeating expansions.
}{
\spadpaste{(5/24)::RadixExpansion(2)}
}
\xtc{
}{
\spadpaste{(5/24)::RadixExpansion(3)}
}
\xtc{
}{
\spadpaste{(5/24)::RadixExpansion(8)}
}
\xtc{
}{
\spadpaste{(5/24)::RadixExpansion(10)}
}
\xtc{
For bases from 11 to 36 the letters A through Z are used.
}{
\spadpaste{(5/24)::RadixExpansion(12)}
}
\xtc{
}{
\spadpaste{(5/24)::RadixExpansion(16)}
}
\xtc{
}{
\spadpaste{(5/24)::RadixExpansion(36)}
}
\xtc{
For bases greater than 36, the ragits are separated by blanks.
}{
\spadpaste{(5/24)::RadixExpansion(38)}
}
\xtc{
The \spadtype{RadixExpansion} type provides operations to obtain the
individual ragits.
Here is a rational number in base \spad{8}.
}{
\spadpaste{a := (76543/210)::RadixExpansion(8) \bound{a}}
}
\xtc{
The operation \spadfunFrom{wholeRagits}{RadixExpansion} returns a 
list of the ragits for the integral part of the number.
}{
\spadpaste{w := wholeRagits a \free{a}\bound{w}}
}
\xtc{
The operations \spadfunFrom{prefixRagits}{RadixExpansion} and 
\spadfunFrom{cycleRagits}{RadixExpansion}
return lists of the initial and repeating ragits in the
fractional part of the number.
}{
\spadpaste{f0 := prefixRagits a \free{a}\bound{f0}}
}
\xtc{
}{
\spadpaste{f1 := cycleRagits a \free{a}\bound{f1}}
}
\xtc{
You can construct any radix expansion by giving the
whole, prefix and cycle parts.
The declaration is necessary to let Axiom
know the base of the ragits.
}{
\spadpaste{u:RadixExpansion(8):=wholeRadix(w)+fractRadix(f0,f1) 
\free{w f0 f1}\bound{u}}
}
\xtc{
If there is no repeating part, then the list \spad{[0]} should be used.
}{
\spadpaste{v: RadixExpansion(12) := fractRadix([1,2,3,11], [0]) \bound{v}}
}
\xtc{
If you are not interested in the repeating nature of the expansion,
an infinite stream of ragits can be obtained using
\spadfunFrom{fractRagits}{RadixExpansion}.
}{
\spadpaste{fractRagits(u) \free{u}}
}
\xtc{
Of course, it's possible to recover the fraction representation:
}{
\spadpaste{a :: Fraction(Integer) \free{a}}
}

\showBlurb{RadixExpansion}
More examples of expansions are available in
\downlink{`DecimalExpansion'}{DecimalExpansionXmpPage}
\ignore{DecimalExpansion},
\downlink{`BinaryExpansion'}{BinaryExpansionXmpPage}
\ignore{BinaryExpansion}, and
\downlink{`HexadecimalExpansion'}{HexExpansionXmpPage}
\ignore{HexadecimalExpansion}.
\endscroll
\autobuttons
\end{page}

\begin{patch}{RadixExpansionXmpPagePatch1}
\begin{paste}{RadixExpansionXmpPageFull1}{RadixExpansionXmpPageEmpty1}
\pastebutton{RadixExpansionXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{111::RadixExpansion(5)}
\indentrel{3}\begin{verbatim}
   (1)  421
                                 Type: RadixExpansion 5
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPageEmpty1}
\begin{paste}{RadixExpansionXmpPageEmpty1}{RadixExpansionXmpPagePatch1}
\pastebutton{RadixExpansionXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{111::RadixExpansion(5)}
\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPagePatch2}
\begin{paste}{RadixExpansionXmpPageFull2}{RadixExpansionXmpPageEmpty2}
\pastebutton{RadixExpansionXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{(5/24)::RadixExpansion(2)}
\indentrel{3}\begin{verbatim}
             __
   (2)  0.00110
                                 Type: RadixExpansion 2
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPageEmpty2}
\begin{paste}{RadixExpansionXmpPageEmpty2}{RadixExpansionXmpPagePatch2}
\pastebutton{RadixExpansionXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{(5/24)::RadixExpansion(2)}
\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPagePatch3}
\begin{paste}{RadixExpansionXmpPageFull3}{RadixExpansionXmpPageEmpty3}
\pastebutton{RadixExpansionXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{(5/24)::RadixExpansion(3)}
\indentrel{3}\begin{verbatim}
           __
   (3)  0.012
                                 Type: RadixExpansion 3
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPageEmpty3}
\begin{paste}{RadixExpansionXmpPageEmpty3}{RadixExpansionXmpPagePatch3}
\pastebutton{RadixExpansionXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{(5/24)::RadixExpansion(3)}
\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPagePatch4}
\begin{paste}{RadixExpansionXmpPageFull4}{RadixExpansionXmpPageEmpty4}
\pastebutton{RadixExpansionXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{(5/24)::RadixExpansion(8)}
\indentrel{3}\begin{verbatim}
           __
   (4)  0.152
                                 Type: RadixExpansion 8
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPageEmpty4}
\begin{paste}{RadixExpansionXmpPageEmpty4}{RadixExpansionXmpPagePatch4}
\pastebutton{RadixExpansionXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{(5/24)::RadixExpansion(8)}
\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPagePatch5}
\begin{paste}{RadixExpansionXmpPageFull5}{RadixExpansionXmpPageEmpty5}
\pastebutton{RadixExpansionXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{(5/24)::RadixExpansion(10)}
\indentrel{3}\begin{verbatim}
             _
   (5)  0.2083
                                Type: RadixExpansion 10
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPageEmpty5}
\begin{paste}{RadixExpansionXmpPageEmpty5}{RadixExpansionXmpPagePatch5}
\pastebutton{RadixExpansionXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{(5/24)::RadixExpansion(10)}
\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPagePatch6}
\begin{paste}{RadixExpansionXmpPageFull6}{RadixExpansionXmpPageEmpty6}
\pastebutton{RadixExpansionXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{(5/24)::RadixExpansion(12)}
\indentrel{3}\begin{verbatim}
   (6)  0.26
                                Type: RadixExpansion 12
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPageEmpty6}
\begin{paste}{RadixExpansionXmpPageEmpty6}{RadixExpansionXmpPagePatch6}
\pastebutton{RadixExpansionXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{(5/24)::RadixExpansion(12)}
\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPagePatch7}
\begin{paste}{RadixExpansionXmpPageFull7}{RadixExpansionXmpPageEmpty7}
\pastebutton{RadixExpansionXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{(5/24)::RadixExpansion(16)}
\indentrel{3}\begin{verbatim}
           _
   (7)  0.35
                                Type: RadixExpansion 16
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPageEmpty7}
\begin{paste}{RadixExpansionXmpPageEmpty7}{RadixExpansionXmpPagePatch7}
\pastebutton{RadixExpansionXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{(5/24)::RadixExpansion(16)}
\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPagePatch8}
\begin{paste}{RadixExpansionXmpPageFull8}{RadixExpansionXmpPageEmpty8}
\pastebutton{RadixExpansionXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{(5/24)::RadixExpansion(36)}
\indentrel{3}\begin{verbatim}
   (8)  0.7I
                                Type: RadixExpansion 36
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPageEmpty8}
\begin{paste}{RadixExpansionXmpPageEmpty8}{RadixExpansionXmpPagePatch8}
\pastebutton{RadixExpansionXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{(5/24)::RadixExpansion(36)}
\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPagePatch9}
\begin{paste}{RadixExpansionXmpPageFull9}{RadixExpansionXmpPageEmpty9}
\pastebutton{RadixExpansionXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{(5/24)::RadixExpansion(38)}
\indentrel{3}\begin{verbatim}
                    _____
   (9)  0 . 7 34 31 25 12
                                Type: RadixExpansion 38
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPageEmpty9}
\begin{paste}{RadixExpansionXmpPageEmpty9}{RadixExpansionXmpPagePatch9}
\pastebutton{RadixExpansionXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{(5/24)::RadixExpansion(38)}
\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPagePatch10}
\begin{paste}{RadixExpansionXmpPageFull10}{RadixExpansionXmpPageEmpty10}
\pastebutton{RadixExpansionXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{a := (76543/210)::RadixExpansion(8)\bound{a }}
\indentrel{3}\begin{verbatim}
              ____
   (10)  554.37307
                                 Type: RadixExpansion 8
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPageEmpty10}
\begin{paste}{RadixExpansionXmpPageEmpty10}{RadixExpansionXmpPagePatch10}
\pastebutton{RadixExpansionXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{a := (76543/210)::RadixExpansion(8)\bound{a }}
\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPagePatch11}
\begin{paste}{RadixExpansionXmpPageFull11}{RadixExpansionXmpPageEmpty11}
\pastebutton{RadixExpansionXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{w := wholeRagits a\free{a }\bound{w }}
\indentrel{3}\begin{verbatim}
   (11)  [5,5,4]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPageEmpty11}
\begin{paste}{RadixExpansionXmpPageEmpty11}{RadixExpansionXmpPagePatch11}
\pastebutton{RadixExpansionXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{w := wholeRagits a\free{a }\bound{w }}
\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPagePatch12}
\begin{paste}{RadixExpansionXmpPageFull12}{RadixExpansionXmpPageEmpty12}
\pastebutton{RadixExpansionXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{f0 := prefixRagits a\free{a }\bound{f0 }}
\indentrel{3}\begin{verbatim}
   (12)  [3]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPageEmpty12}
\begin{paste}{RadixExpansionXmpPageEmpty12}{RadixExpansionXmpPagePatch12}
\pastebutton{RadixExpansionXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{f0 := prefixRagits a\free{a }\bound{f0 }}
\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPagePatch13}
\begin{paste}{RadixExpansionXmpPageFull13}{RadixExpansionXmpPageEmpty13}
\pastebutton{RadixExpansionXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{f1 := cycleRagits a\free{a }\bound{f1 }}
\indentrel{3}\begin{verbatim}
   (13)  [7,3,0,7]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPageEmpty13}
\begin{paste}{RadixExpansionXmpPageEmpty13}{RadixExpansionXmpPagePatch13}
\pastebutton{RadixExpansionXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{f1 := cycleRagits a\free{a }\bound{f1 }}
\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPagePatch14}
\begin{paste}{RadixExpansionXmpPageFull14}{RadixExpansionXmpPageEmpty14}
\pastebutton{RadixExpansionXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{u:RadixExpansion(8):=wholeRadix(w)+fractRadix(f0,f1)\free{w f0 f1 }\bound{u }}
\indentrel{3}\begin{verbatim}
              ____
   (14)  554.37307
                                 Type: RadixExpansion 8
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPageEmpty14}
\begin{paste}{RadixExpansionXmpPageEmpty14}{RadixExpansionXmpPagePatch14}
\pastebutton{RadixExpansionXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{u:RadixExpansion(8):=wholeRadix(w)+fractRadix(f0,f1)\free{w f0 f1 }\bound{u }}
\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPagePatch15}
\begin{paste}{RadixExpansionXmpPageFull15}{RadixExpansionXmpPageEmpty15}
\pastebutton{RadixExpansionXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{v: RadixExpansion(12) := fractRadix([1,2,3,11], [0])\bound{v }}
\indentrel{3}\begin{verbatim}
               _
   (15)  0.123B0
                                Type: RadixExpansion 12
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPageEmpty15}
\begin{paste}{RadixExpansionXmpPageEmpty15}{RadixExpansionXmpPagePatch15}
\pastebutton{RadixExpansionXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{v: RadixExpansion(12) := fractRadix([1,2,3,11], [0])\bound{v }}
\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPagePatch16}
\begin{paste}{RadixExpansionXmpPageFull16}{RadixExpansionXmpPageEmpty16}
\pastebutton{RadixExpansionXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{fractRagits(u)\free{u }}
\indentrel{3}\begin{verbatim}
              _______
   (16)  [3,7,3,0,7,7]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPageEmpty16}
\begin{paste}{RadixExpansionXmpPageEmpty16}{RadixExpansionXmpPagePatch16}
\pastebutton{RadixExpansionXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{fractRagits(u)\free{u }}
\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPagePatch17}
\begin{paste}{RadixExpansionXmpPageFull17}{RadixExpansionXmpPageEmpty17}
\pastebutton{RadixExpansionXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{a :: Fraction(Integer)\free{a }}
\indentrel{3}\begin{verbatim}
         76543
   (17)  ÄÄÄÄÄ
          210
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RadixExpansionXmpPageEmpty17}
\begin{paste}{RadixExpansionXmpPageEmpty17}{RadixExpansionXmpPagePatch17}
\pastebutton{RadixExpansionXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{a :: Fraction(Integer)\free{a }}
\end{paste}\end{patch}

\end{chunk}
\section{reclos.ht}
\pagetitle{RealClosureXmpPage}{reclos.ht}{RealClosure}
\begin{chunk}{reclos.ht}
\begin{page}{RealClosureXmpPage}{RealClosure}
\beginscroll

The Real Closure 1.0 package provided by 
Renaud Rioboo (Renaud.Rioboo@lip6.fr) consists of different
packages, categories and domains :

\begin{items}
\item The package \axiomType{RealPolynomialUtilitiesPackage} which
needs a \axiomType{Field} {\em F} and a
\axiomType{UnivariatePolynomialCategory} domain with coefficients in
{\em F}.  It computes some simple functions such as Sturm and
Sylvester sequences
(\axiomOpFrom{sturmSequence}{RealPolynomialUtilitiesPackage},
\axiomOpFrom{sylvesterSequence}{RealPolynomialUtilitiesPackage}).

\item The category \axiomType{RealRootCharacterizationCategory}
provides abstract functions to work with "real roots" of univariate
polynomials. These resemble variables with some functionality needed
to compute important operations.

\item The category \axiomType{RealClosedField} provides common
operations available over real closed fiels. These include finding all
the roots of a univariate polynomial, taking square (and higher)
roots, ...

\item The domain \axiomType{RightOpenIntervalRootCharacterization} is
the main code that provides the functionality of
\axiomType{RealRootCharacterizationCategory} for the case of
archimedean fields. Abstract roots are encoded with a left closed
right open interval containing the root together with a defining
polynomial for the root.

\item The \axiomType{RealClosure} domain is the end-user code. It
provides usual arithmetic with real algebraic numbers, along with the
functionality of a real closed field. It also provides functions to
approximate a real algebraic number by an element of the base
field. This approximation may either be absolute
(\axiomOpFrom{approximate}{RealClosure}) or relative
(\axiomOpFrom{relativeApprox}{RealClosure}).


\end{items}

\centerline{CAVEATS}

Since real algebraic expressions are stored as depending on "real
roots" which are managed like variables, there is an ordering on
these. This ordering is dynamical in the sense that any new algebraic
takes precedence over older ones. In particular every creation
function raises a new "real root". This has the effect that when you
type something like \spad{sqrt(2) + sqrt(2)} you have two new
variables which happen to be equal. To avoid this name the expression
such as in \spad{s2 := sqrt(2) ; s2 + s2}

Also note that computing times depend strongly on the ordering you
implicitly provide. Please provide algebraics in the order which seems
most natural to you.

\centerline{LIMITATIONS}

This packages uses algorithms which are published in [1] and [2] which
are based on field arithmetics, in particular for polynomial gcd
related algorithms. This can be quite slow for high degree polynomials
and subresultants methods usually work best. Beta versions of the
package try to use these techniques in a better way and work
significantly faster. These are mostly based on unpublished algorithms
and cannot be distributed. Please contact the author if you have a
particular problem to solve or want to use these versions.

Be aware that approximations behave as post-processing and that all
computations are done exactly. They can thus be quite time consuming
when depending on several "real roots".

\centerline{REFERENCES}


[1]  R. Rioboo : Real Algebraic Closure of an ordered Field : Implementation 
     in Axiom. 
     In proceedings of the ISSAC'92 Conference, Berkeley 1992 pp. 206-215.

[2]  Z. Ligatsikas, R. Rioboo, M. F. Roy : Generic computation of the real
     closure of an ordered field.
     In Mathematics and Computers in Simulation Volume 42, Issue 4-6,
     November 1996.

\centerline{EXAMPLES}
\xtc{
We shall work with the real closure of the ordered field of 
rational numbers.
}{
\spadpaste{Ran := RECLOS(FRAC INT) \bound{Ran}}
}
\xtc{
Some simple signs for square roots, these correspond to an extension
of degree 16 of the rational numbers. Examples provided by J. Abbot.
}{
\spadpaste{fourSquares(a:Ran,b:Ran,c:Ran,d:Ran):Ran == sqrt(a)+sqrt(b) - 
sqrt(c)-sqrt(d) \free{Ran} \bound{fs}}
}
\xtc{
These produce values very close to zero.
}{
\spadpaste{squareDiff1 := fourSquares(73,548,60,586) \free{fs}
\bound{sd1}}
}
\xtc{
}{
\spadpaste{recip(squareDiff1)\free{sd1}}
}
\xtc{
}{
\spadpaste{sign(squareDiff1)\free{sd1}}
}
\xtc{
}{
\spadpaste{squareDiff2 := fourSquares(165,778,86,990) \free{fs}
\bound{sd2}}
}
\xtc{
}{
\spadpaste{recip(squareDiff2)\free{sd2}}
}
\xtc{
}{
\spadpaste{sign(squareDiff2)\free{sd2}}
}
\xtc{
}{
\spadpaste{squareDiff3 := fourSquares(217,708,226,692) \free{fs}
\bound{sd3}}
}
\xtc{
}{
\spadpaste{recip(squareDiff3)\free{sd3}}
}
\xtc{
}{
\spadpaste{sign(squareDiff3)\free{sd3}}
}
\xtc{
}{
\spadpaste{squareDiff4 := fourSquares(155,836,162,820)  
\free{fs}\bound{sd4}}
}
\xtc{
}{
\spadpaste{recip(squareDiff4)\free{sd4}}
}
\xtc{
}{
\spadpaste{sign(squareDiff4)\free{sd4}}
}
\xtc{
}{
\spadpaste{squareDiff5 := fourSquares(591,772,552,818) 
\free{fs}\bound{sd5}}
}
\xtc{
}{
\spadpaste{recip(squareDiff5)\free{sd5}}
}
\xtc{
}{
\spadpaste{sign(squareDiff5)\free{sd5}}
}
\xtc{
}{
\spadpaste{squareDiff6 := fourSquares(434,1053,412,1088) 
\free{fs}\bound{sd6}}
}
\xtc{
}{
\spadpaste{recip(squareDiff6)\free{sd6}}
}
\xtc{
}{
\spadpaste{sign(squareDiff6)\free{sd6}}
}
\xtc{
}{
\spadpaste{squareDiff7 := fourSquares(514,1049,446,1152) 
\free{fs}\bound{sd7}}
}
\xtc{
}{
\spadpaste{recip(squareDiff7)\free{sd7}}
}
\xtc{
}{
\spadpaste{sign(squareDiff7)\free{sd7}}
}
\xtc{
}{
\spadpaste{squareDiff8 := fourSquares(190,1751,208,1698) 
\free{fs}\bound{sd8}}
}
\xtc{
}{
\spadpaste{recip(squareDiff8)\free{sd8}}
}
\xtc{
}{
\spadpaste{sign(squareDiff8)\free{sd8}}
}
\xtc{
This should give three digits of precision
}{
\spadpaste{relativeApprox(squareDiff8,10**(-3))::Float \free{sd8}}
}
\xtc{
The sum of these 4 roots is 0
}{
\spadpaste{l := allRootsOf((x**2-2)**2-2)$Ran \free{Ran} \bound{l}}
}
\xtc{
Check that they are all roots of the same polynomial
}{
\spadpaste{removeDuplicates map(mainDefiningPolynomial,l) \free{l}}
}
\xtc{
We can see at a glance that they are separate roots
}{
\spadpaste{map(mainCharacterization,l) \free{l}}
}
\xtc{
Check the sum and product
}{
\spadpaste{[reduce(+,l),reduce(*,l)-2] \free{l}}
}
\xtc{
A more complicated test that involve an extension of degree 256.
This is a way of checking nested radical identities.
}{
\spadpaste{(s2, s5, s10) := (sqrt(2)$Ran, sqrt(5)$Ran, sqrt(10)$Ran) 
\free{Ran}\bound{s2}\bound{s5}\bound{s10}}
}
\xtc{
}{
\spadpaste{eq1:=sqrt(s10+3)*sqrt(s5+2) - sqrt(s10-3)*sqrt(s5-2) = 
sqrt(10*s2+10) \free{s2}\free{s5}\free{s10}\bound{eq1}}
}
\xtc{
}{
\spadpaste{eq1::Boolean \free{eq1}}
}
\xtc{
}{
\spadpaste{eq2:=sqrt(s5+2)*sqrt(s2+1) - sqrt(s5-2)*sqrt(s2-1) = 
sqrt(2*s10+2)\free{s2}\free{s5}\free{s10}\bound{eq2}}
}
\xtc{
}{
\spadpaste{eq2::Boolean \free{eq2}}
}
\xtc{
Some more examples from J. M. Arnaudies
}{
\spadpaste{s3 := sqrt(3)$Ran \free{Ran}\bound{s3}}
}
\xtc{
}{
\spadpaste{s7:= sqrt(7)$Ran \free{Ran}\bound{s7}}
}
\xtc{
}{
\spadpaste{e1 := sqrt(2*s7-3*s3,3) \free{s7} \free{s3} \bound{e1}}
}
\xtc{
}{
\spadpaste{e2 := sqrt(2*s7+3*s3,3) \free{s7} \free{s3} \bound{e2}}
}
\xtc{
This should be null
}{
\spadpaste{e2-e1-s3 \free{e2} \free{e1} \free{s3}}
}
\xtc{
A quartic polynomial
}{
\spadpaste{pol : UP(x,Ran) := x**4+(7/3)*x**2+30*x-(100/3) 
\free{Ran} \bound{pol}}
}
\xtc{
Add some cubic roots
}{
\spadpaste{r1 := sqrt(7633)$Ran \free{Ran}\bound{r1}}
}
\xtc{
}{
\spadpaste{alpha := sqrt(5*r1-436,3)/3 \free{r1} \bound{alpha}}
}
\xtc{
}{
\spadpaste{beta := -sqrt(5*r1+436,3)/3 \free{r1} \bound{beta}}
}
\xtc{
this should be null
}{
\spadpaste{pol.(alpha+beta-1/3) \free{pol} \free{alpha} \free{beta}}
}
\xtc{
A quintic polynomial
}{
\spadpaste{qol : UP(x,Ran) := x**5+10*x**3+20*x+22 \free{Ran}\bound{qol}}
}
\xtc{
Add some cubic roots
}{
\spadpaste{r2 := sqrt(153)$Ran \free{Ran}\bound{r2}}
}
\xtc{
}{
\spadpaste{alpha2 := sqrt(r2-11,5) \free{r2}\bound{alpha2}}
}
\xtc{
}{
\spadpaste{beta2 := -sqrt(r2+11,5) \free{r2}\bound{beta2}}
}
\xtc{
this should be null
}{
\spadpaste{qol(alpha2+beta2) \free{qol}\free{alpha2}\free{beta2}}
}
\xtc{
Finally, some examples from the book Computer Algebra by 
Davenport, Siret and Tournier (page 77).
The last one is due to Ramanujan.
}{
\spadpaste{dst1:=sqrt(9+4*s2)=1+2*s2 \free{s2}\bound{dst1}}
}
\xtc{
}{
\spadpaste{dst1::Boolean \free{dst1}}
}
\xtc{
}{
\spadpaste{s6:Ran:=sqrt 6 \free{Ran}\bound{s6}}
}
\xtc{
}{
\spadpaste{dst2:=sqrt(5+2*s6)+sqrt(5-2*s6) = 2*s3 
\free{s6}\free{s3}\bound{dst2}}
}
\xtc{
}{
\spadpaste{dst2::Boolean \free{dst2}}
}
\xtc{
}{
\spadpaste{s29:Ran:=sqrt 29 \free{Ran}\bound{s29}}
}
\xtc{
}{
\spadpaste{dst4:=sqrt(16-2*s29+2*sqrt(55-10*s29)) = 
sqrt(22+2*s5)-sqrt(11+2*s29)+s5 \free{s29}\free{s5}\bound{dst4}}
}
\xtc{
}{
\spadpaste{dst4::Boolean \free{dst4}}
}
\xtc{
}{
\spadpaste{dst6:=sqrt((112+70*s2)+(46+34*s2)*s5) = 
(5+4*s2)+(3+s2)*s5 \free{s2}\free{s5}\bound{dst6}}
}
\xtc{
}{
\spadpaste{dst6::Boolean \free{dst6}}
}
\xtc{
}{
\spadpaste{f3:Ran:=sqrt(3,5) \free{Ran}\bound{f3}}
}
\xtc{
}{
\spadpaste{f25:Ran:=sqrt(1/25,5) \free{Ran}\bound{f25}}
}
\xtc{
}{
\spadpaste{f32:Ran:=sqrt(32/5,5) \free{Ran}\bound{f32}}
}
\xtc{
}{
\spadpaste{f27:Ran:=sqrt(27/5,5) \free{Ran}\bound{f27}}
}
\xtc{
}{
\spadpaste{dst5:=sqrt((f32-f27,3)) = f25*(1+f3-f3**2)
\free{f32}\free{f27}\free{f25}\free{f3}\bound{dst5}}
}
\xtc{
}{
\spadpaste{dst5::Boolean \free{dst5}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{RealClosureXmpPagePatch1}
\begin{paste}{RealClosureXmpPageFull1}{RealClosureXmpPageEmpty1}
\pastebutton{RealClosureXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{Ran := RECLOS(FRAC INT)\bound{Ran }}
\indentrel{3}\begin{verbatim}
   (1)  RealClosure Fraction Integer
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty1}
\begin{paste}{RealClosureXmpPageEmpty1}{RealClosureXmpPagePatch1}
\pastebutton{RealClosureXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{Ran := RECLOS(FRAC INT)\bound{Ran }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch2}
\begin{paste}{RealClosureXmpPageFull2}{RealClosureXmpPageEmpty2}
\pastebutton{RealClosureXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{fourSquares(a:Ran,b:Ran,c:Ran,d:Ran):Ran == sqrt(a)+sqrt(b) - sqrt(c)-sqrt(d)\free{Ran }\bound{fs }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty2}
\begin{paste}{RealClosureXmpPageEmpty2}{RealClosureXmpPagePatch2}
\pastebutton{RealClosureXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{fourSquares(a:Ran,b:Ran,c:Ran,d:Ran):Ran == sqrt(a)+sqrt(b) - sqrt(c)-sqrt(d)\free{Ran }\bound{fs }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch3}
\begin{paste}{RealClosureXmpPageFull3}{RealClosureXmpPageEmpty3}
\pastebutton{RealClosureXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{squareDiff1 := fourSquares(73,548,60,586)\free{fs }\bound{sd1 }}
\indentrel{3}\begin{verbatim}
           ÚÄÄÄ¿    ÚÄÄ¿    ÚÄÄÄ¿    ÚÄÄ¿
   (3)  - \³586  - \³60  + \³548  + \³73
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty3}
\begin{paste}{RealClosureXmpPageEmpty3}{RealClosureXmpPagePatch3}
\pastebutton{RealClosureXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{squareDiff1 := fourSquares(73,548,60,586)\free{fs }\bound{sd1 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch4}
\begin{paste}{RealClosureXmpPageFull4}{RealClosureXmpPageEmpty4}
\pastebutton{RealClosureXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{recip(squareDiff1)\free{sd1 }}
\indentrel{3}\begin{verbatim}
   (4)
                ÚÄÄÄ¿          ÚÄÄ¿  ÚÄÄ¿
         (54602\³548  + 149602\³73 )\³60
       + 
               ÚÄÄ¿ ÚÄÄÄ¿
         49502\³73 \³548  + 9900895
    *
        ÚÄÄÄ¿
       \³586
   + 
             ÚÄÄ¿ ÚÄÄÄ¿             ÚÄÄ¿            ÚÄÄÄ¿
     (154702\³73 \³548  + 30941947)\³60  + 10238421\³548
   + 
              ÚÄÄ¿
     28051871\³73
          Type: Union(RealClosure Fraction Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty4}
\begin{paste}{RealClosureXmpPageEmpty4}{RealClosureXmpPagePatch4}
\pastebutton{RealClosureXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{recip(squareDiff1)\free{sd1 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch5}
\begin{paste}{RealClosureXmpPageFull5}{RealClosureXmpPageEmpty5}
\pastebutton{RealClosureXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{sign(squareDiff1)\free{sd1 }}
\indentrel{3}\begin{verbatim}
   (5)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty5}
\begin{paste}{RealClosureXmpPageEmpty5}{RealClosureXmpPagePatch5}
\pastebutton{RealClosureXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{sign(squareDiff1)\free{sd1 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch6}
\begin{paste}{RealClosureXmpPageFull6}{RealClosureXmpPageEmpty6}
\pastebutton{RealClosureXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{squareDiff2 := fourSquares(165,778,86,990)\free{fs }\bound{sd2 }}
\indentrel{3}\begin{verbatim}
           ÚÄÄÄ¿    ÚÄÄ¿    ÚÄÄÄ¿    ÚÄÄÄ¿
   (6)  - \³990  - \³86  + \³778  + \³165
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty6}
\begin{paste}{RealClosureXmpPageEmpty6}{RealClosureXmpPagePatch6}
\pastebutton{RealClosureXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{squareDiff2 := fourSquares(165,778,86,990)\free{fs }\bound{sd2 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch7}
\begin{paste}{RealClosureXmpPageFull7}{RealClosureXmpPageEmpty7}
\pastebutton{RealClosureXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{recip(squareDiff2)\free{sd2 }}
\indentrel{3}\begin{verbatim}
   (7)
                 ÚÄÄÄ¿           ÚÄÄÄ¿  ÚÄÄ¿
         (556778\³778  + 1209010\³165 )\³86
       + 
                ÚÄÄÄ¿ ÚÄÄÄ¿
         401966\³165 \³778  + 144019431
    *
        ÚÄÄÄ¿
       \³990
   + 
              ÚÄÄÄ¿ ÚÄÄÄ¿              ÚÄÄ¿
     (1363822\³165 \³778  + 488640503)\³86
   + 
               ÚÄÄÄ¿             ÚÄÄÄ¿
     162460913\³778  + 352774119\³165
          Type: Union(RealClosure Fraction Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty7}
\begin{paste}{RealClosureXmpPageEmpty7}{RealClosureXmpPagePatch7}
\pastebutton{RealClosureXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{recip(squareDiff2)\free{sd2 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch8}
\begin{paste}{RealClosureXmpPageFull8}{RealClosureXmpPageEmpty8}
\pastebutton{RealClosureXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{sign(squareDiff2)\free{sd2 }}
\indentrel{3}\begin{verbatim}
   (8)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty8}
\begin{paste}{RealClosureXmpPageEmpty8}{RealClosureXmpPagePatch8}
\pastebutton{RealClosureXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{sign(squareDiff2)\free{sd2 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch9}
\begin{paste}{RealClosureXmpPageFull9}{RealClosureXmpPageEmpty9}
\pastebutton{RealClosureXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{squareDiff3 := fourSquares(217,708,226,692)\free{fs }\bound{sd3 }}
\indentrel{3}\begin{verbatim}
           ÚÄÄÄ¿    ÚÄÄÄ¿    ÚÄÄÄ¿    ÚÄÄÄ¿
   (9)  - \³692  - \³226  + \³708  + \³217
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty9}
\begin{paste}{RealClosureXmpPageEmpty9}{RealClosureXmpPagePatch9}
\pastebutton{RealClosureXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{squareDiff3 := fourSquares(217,708,226,692)\free{fs }\bound{sd3 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch10}
\begin{paste}{RealClosureXmpPageFull10}{RealClosureXmpPageEmpty10}
\pastebutton{RealClosureXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{recip(squareDiff3)\free{sd3 }}
\indentrel{3}\begin{verbatim}
   (10)
                  ÚÄÄÄ¿         ÚÄÄÄ¿  ÚÄÄÄ¿
         (- 34102\³708  - 61598\³217 )\³226
       + 
                 ÚÄÄÄ¿ ÚÄÄÄ¿
         - 34802\³217 \³708  - 13641141
    *
        ÚÄÄÄ¿
       \³692
   + 
              ÚÄÄÄ¿ ÚÄÄÄ¿             ÚÄÄÄ¿
     (- 60898\³217 \³708  - 23869841)\³226
   + 
                ÚÄÄÄ¿            ÚÄÄÄ¿
     - 13486123\³708  - 24359809\³217
          Type: Union(RealClosure Fraction Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty10}
\begin{paste}{RealClosureXmpPageEmpty10}{RealClosureXmpPagePatch10}
\pastebutton{RealClosureXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{recip(squareDiff3)\free{sd3 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch11}
\begin{paste}{RealClosureXmpPageFull11}{RealClosureXmpPageEmpty11}
\pastebutton{RealClosureXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{sign(squareDiff3)\free{sd3 }}
\indentrel{3}\begin{verbatim}
   (11)  - 1
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty11}
\begin{paste}{RealClosureXmpPageEmpty11}{RealClosureXmpPagePatch11}
\pastebutton{RealClosureXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{sign(squareDiff3)\free{sd3 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch12}
\begin{paste}{RealClosureXmpPageFull12}{RealClosureXmpPageEmpty12}
\pastebutton{RealClosureXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{squareDiff4 := fourSquares(155,836,162,820)\free{fs }\bound{sd4 }}
\indentrel{3}\begin{verbatim}
            ÚÄÄÄ¿    ÚÄÄÄ¿    ÚÄÄÄ¿    ÚÄÄÄ¿
   (12)  - \³820  - \³162  + \³836  + \³155
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty12}
\begin{paste}{RealClosureXmpPageEmpty12}{RealClosureXmpPagePatch12}
\pastebutton{RealClosureXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{squareDiff4 := fourSquares(155,836,162,820)\free{fs }\bound{sd4 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch13}
\begin{paste}{RealClosureXmpPageFull13}{RealClosureXmpPageEmpty13}
\pastebutton{RealClosureXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{recip(squareDiff4)\free{sd4 }}
\indentrel{3}\begin{verbatim}
   (13)
                  ÚÄÄÄ¿         ÚÄÄÄ¿  ÚÄÄÄ¿
         (- 37078\³836  - 86110\³155 )\³162
       + 
                 ÚÄÄÄ¿ ÚÄÄÄ¿
         - 37906\³155 \³836  - 13645107
    *
        ÚÄÄÄ¿
       \³820
   + 
              ÚÄÄÄ¿ ÚÄÄÄ¿             ÚÄÄÄ¿
     (- 85282\³155 \³836  - 30699151)\³162
   + 
                ÚÄÄÄ¿            ÚÄÄÄ¿
     - 13513901\³836  - 31384703\³155
          Type: Union(RealClosure Fraction Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty13}
\begin{paste}{RealClosureXmpPageEmpty13}{RealClosureXmpPagePatch13}
\pastebutton{RealClosureXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{recip(squareDiff4)\free{sd4 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch14}
\begin{paste}{RealClosureXmpPageFull14}{RealClosureXmpPageEmpty14}
\pastebutton{RealClosureXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{sign(squareDiff4)\free{sd4 }}
\indentrel{3}\begin{verbatim}
   (14)  - 1
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty14}
\begin{paste}{RealClosureXmpPageEmpty14}{RealClosureXmpPagePatch14}
\pastebutton{RealClosureXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{sign(squareDiff4)\free{sd4 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch15}
\begin{paste}{RealClosureXmpPageFull15}{RealClosureXmpPageEmpty15}
\pastebutton{RealClosureXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{squareDiff5 := fourSquares(591,772,552,818)\free{fs }\bound{sd5 }}
\indentrel{3}\begin{verbatim}
            ÚÄÄÄ¿    ÚÄÄÄ¿    ÚÄÄÄ¿    ÚÄÄÄ¿
   (15)  - \³818  - \³552  + \³772  + \³591
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty15}
\begin{paste}{RealClosureXmpPageEmpty15}{RealClosureXmpPagePatch15}
\pastebutton{RealClosureXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{squareDiff5 := fourSquares(591,772,552,818)\free{fs }\bound{sd5 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch16}
\begin{paste}{RealClosureXmpPageFull16}{RealClosureXmpPageEmpty16}
\pastebutton{RealClosureXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{recip(squareDiff5)\free{sd5 }}
\indentrel{3}\begin{verbatim}
   (16)
                ÚÄÄÄ¿         ÚÄÄÄ¿  ÚÄÄÄ¿
         (70922\³772  + 81058\³591 )\³552
       + 
               ÚÄÄÄ¿ ÚÄÄÄ¿
         68542\³591 \³772  + 46297673
    *
        ÚÄÄÄ¿
       \³818
   + 
            ÚÄÄÄ¿ ÚÄÄÄ¿             ÚÄÄÄ¿            ÚÄÄÄ¿
     (83438\³591 \³772  + 56359389)\³552  + 47657051\³772
   + 
              ÚÄÄÄ¿
     54468081\³591
          Type: Union(RealClosure Fraction Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty16}
\begin{paste}{RealClosureXmpPageEmpty16}{RealClosureXmpPagePatch16}
\pastebutton{RealClosureXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{recip(squareDiff5)\free{sd5 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch17}
\begin{paste}{RealClosureXmpPageFull17}{RealClosureXmpPageEmpty17}
\pastebutton{RealClosureXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{sign(squareDiff5)\free{sd5 }}
\indentrel{3}\begin{verbatim}
   (17)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty17}
\begin{paste}{RealClosureXmpPageEmpty17}{RealClosureXmpPagePatch17}
\pastebutton{RealClosureXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{sign(squareDiff5)\free{sd5 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch18}
\begin{paste}{RealClosureXmpPageFull18}{RealClosureXmpPageEmpty18}
\pastebutton{RealClosureXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{squareDiff6 := fourSquares(434,1053,412,1088)\free{fs }\bound{sd6 }}
\indentrel{3}\begin{verbatim}
            ÚÄÄÄÄ¿    ÚÄÄÄ¿    ÚÄÄÄÄ¿    ÚÄÄÄ¿
   (18)  - \³1088  - \³412  + \³1053  + \³434
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty18}
\begin{paste}{RealClosureXmpPageEmpty18}{RealClosureXmpPagePatch18}
\pastebutton{RealClosureXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{squareDiff6 := fourSquares(434,1053,412,1088)\free{fs }\bound{sd6 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch19}
\begin{paste}{RealClosureXmpPageFull19}{RealClosureXmpPageEmpty19}
\pastebutton{RealClosureXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{recip(squareDiff6)\free{sd6 }}
\indentrel{3}\begin{verbatim}
   (19)
                 ÚÄÄÄÄ¿          ÚÄÄÄ¿  ÚÄÄÄ¿
         (115442\³1053  + 179818\³434 )\³412
       + 
                ÚÄÄÄ¿ ÚÄÄÄÄ¿
         112478\³434 \³1053  + 76037291
    *
        ÚÄÄÄÄ¿
       \³1088
   + 
             ÚÄÄÄ¿ ÚÄÄÄÄ¿              ÚÄÄÄ¿
     (182782\³434 \³1053  + 123564147)\³412
   + 
              ÚÄÄÄÄ¿             ÚÄÄÄ¿
     77290639\³1053  + 120391609\³434
          Type: Union(RealClosure Fraction Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty19}
\begin{paste}{RealClosureXmpPageEmpty19}{RealClosureXmpPagePatch19}
\pastebutton{RealClosureXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{recip(squareDiff6)\free{sd6 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch20}
\begin{paste}{RealClosureXmpPageFull20}{RealClosureXmpPageEmpty20}
\pastebutton{RealClosureXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{sign(squareDiff6)\free{sd6 }}
\indentrel{3}\begin{verbatim}
   (20)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty20}
\begin{paste}{RealClosureXmpPageEmpty20}{RealClosureXmpPagePatch20}
\pastebutton{RealClosureXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{sign(squareDiff6)\free{sd6 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch21}
\begin{paste}{RealClosureXmpPageFull21}{RealClosureXmpPageEmpty21}
\pastebutton{RealClosureXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{squareDiff7 := fourSquares(514,1049,446,1152)\free{fs }\bound{sd7 }}
\indentrel{3}\begin{verbatim}
            ÚÄÄÄÄ¿    ÚÄÄÄ¿    ÚÄÄÄÄ¿    ÚÄÄÄ¿
   (21)  - \³1152  - \³446  + \³1049  + \³514
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty21}
\begin{paste}{RealClosureXmpPageEmpty21}{RealClosureXmpPagePatch21}
\pastebutton{RealClosureXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{squareDiff7 := fourSquares(514,1049,446,1152)\free{fs }\bound{sd7 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch22}
\begin{paste}{RealClosureXmpPageFull22}{RealClosureXmpPageEmpty22}
\pastebutton{RealClosureXmpPageFull22}{\hidepaste}
\tab{5}\spadcommand{recip(squareDiff7)\free{sd7 }}
\indentrel{3}\begin{verbatim}
   (22)
                 ÚÄÄÄÄ¿          ÚÄÄÄ¿  ÚÄÄÄ¿
         (349522\³1049  + 499322\³514 )\³446
       + 
                ÚÄÄÄ¿ ÚÄÄÄÄ¿
         325582\³514 \³1049  + 239072537
    *
        ÚÄÄÄÄ¿
       \³1152
   + 
             ÚÄÄÄ¿ ÚÄÄÄÄ¿              ÚÄÄÄ¿
     (523262\³514 \³1049  + 384227549)\³446
   + 
               ÚÄÄÄÄ¿             ÚÄÄÄ¿
     250534873\³1049  + 357910443\³514
          Type: Union(RealClosure Fraction Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty22}
\begin{paste}{RealClosureXmpPageEmpty22}{RealClosureXmpPagePatch22}
\pastebutton{RealClosureXmpPageEmpty22}{\showpaste}
\tab{5}\spadcommand{recip(squareDiff7)\free{sd7 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch23}
\begin{paste}{RealClosureXmpPageFull23}{RealClosureXmpPageEmpty23}
\pastebutton{RealClosureXmpPageFull23}{\hidepaste}
\tab{5}\spadcommand{sign(squareDiff7)\free{sd7 }}
\indentrel{3}\begin{verbatim}
   (23)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty23}
\begin{paste}{RealClosureXmpPageEmpty23}{RealClosureXmpPagePatch23}
\pastebutton{RealClosureXmpPageEmpty23}{\showpaste}
\tab{5}\spadcommand{sign(squareDiff7)\free{sd7 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch24}
\begin{paste}{RealClosureXmpPageFull24}{RealClosureXmpPageEmpty24}
\pastebutton{RealClosureXmpPageFull24}{\hidepaste}
\tab{5}\spadcommand{squareDiff8 := fourSquares(190,1751,208,1698)\free{fs }\bound{sd8 }}
\indentrel{3}\begin{verbatim}
            ÚÄÄÄÄ¿    ÚÄÄÄ¿    ÚÄÄÄÄ¿    ÚÄÄÄ¿
   (24)  - \³1698  - \³208  + \³1751  + \³190
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty24}
\begin{paste}{RealClosureXmpPageEmpty24}{RealClosureXmpPagePatch24}
\pastebutton{RealClosureXmpPageEmpty24}{\showpaste}
\tab{5}\spadcommand{squareDiff8 := fourSquares(190,1751,208,1698)\free{fs }\bound{sd8 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch25}
\begin{paste}{RealClosureXmpPageFull25}{RealClosureXmpPageEmpty25}
\pastebutton{RealClosureXmpPageFull25}{\hidepaste}
\tab{5}\spadcommand{recip(squareDiff8)\free{sd8 }}
\indentrel{3}\begin{verbatim}
   (25)
                   ÚÄÄÄÄ¿          ÚÄÄÄ¿  ÚÄÄÄ¿
         (- 214702\³1751  - 651782\³190 )\³208
       + 
                  ÚÄÄÄ¿ ÚÄÄÄÄ¿
         - 224642\³190 \³1751  - 129571901
    *
        ÚÄÄÄÄ¿
       \³1698
   + 
               ÚÄÄÄ¿ ÚÄÄÄÄ¿              ÚÄÄÄ¿
     (- 641842\³190 \³1751  - 370209881)\³208
   + 
                 ÚÄÄÄÄ¿             ÚÄÄÄ¿
     - 127595865\³1751  - 387349387\³190
          Type: Union(RealClosure Fraction Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty25}
\begin{paste}{RealClosureXmpPageEmpty25}{RealClosureXmpPagePatch25}
\pastebutton{RealClosureXmpPageEmpty25}{\showpaste}
\tab{5}\spadcommand{recip(squareDiff8)\free{sd8 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch26}
\begin{paste}{RealClosureXmpPageFull26}{RealClosureXmpPageEmpty26}
\pastebutton{RealClosureXmpPageFull26}{\hidepaste}
\tab{5}\spadcommand{sign(squareDiff8)\free{sd8 }}
\indentrel{3}\begin{verbatim}
   (26)  - 1
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty26}
\begin{paste}{RealClosureXmpPageEmpty26}{RealClosureXmpPagePatch26}
\pastebutton{RealClosureXmpPageEmpty26}{\showpaste}
\tab{5}\spadcommand{sign(squareDiff8)\free{sd8 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch27}
\begin{paste}{RealClosureXmpPageFull27}{RealClosureXmpPageEmpty27}
\pastebutton{RealClosureXmpPageFull27}{\hidepaste}
\tab{5}\spadcommand{relativeApprox(squareDiff8,10**(-3))::Float\free{sd8 }}
\indentrel{3}\begin{verbatim}
   (27)  - 0.2340527771 5937700123 E -10
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty27}
\begin{paste}{RealClosureXmpPageEmpty27}{RealClosureXmpPagePatch27}
\pastebutton{RealClosureXmpPageEmpty27}{\showpaste}
\tab{5}\spadcommand{relativeApprox(squareDiff8,10**(-3))::Float\free{sd8 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch28}
\begin{paste}{RealClosureXmpPageFull28}{RealClosureXmpPageEmpty28}
\pastebutton{RealClosureXmpPageFull28}{\hidepaste}
\tab{5}\spadcommand{l := allRootsOf((x**2-2)**2-2)$Ran\free{Ran }\bound{l }}
\indentrel{3}\begin{verbatim}
   (28)  [%R33,%R34,%R35,%R36]
                Type: List RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty28}
\begin{paste}{RealClosureXmpPageEmpty28}{RealClosureXmpPagePatch28}
\pastebutton{RealClosureXmpPageEmpty28}{\showpaste}
\tab{5}\spadcommand{l := allRootsOf((x**2-2)**2-2)$Ran\free{Ran }\bound{l }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch29}
\begin{paste}{RealClosureXmpPageFull29}{RealClosureXmpPageEmpty29}
\pastebutton{RealClosureXmpPageFull29}{\hidepaste}
\tab{5}\spadcommand{removeDuplicates map(mainDefiningPolynomial,l)\free{l }}
\indentrel{3}\begin{verbatim}
           4     2
   (29)  [?  - 4?  + 2]
Type: List Union(SparseUnivariatePolynomial RealClosure Fraction Integer,"failed")
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty29}
\begin{paste}{RealClosureXmpPageEmpty29}{RealClosureXmpPagePatch29}
\pastebutton{RealClosureXmpPageEmpty29}{\showpaste}
\tab{5}\spadcommand{removeDuplicates map(mainDefiningPolynomial,l)\free{l }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch30}
\begin{paste}{RealClosureXmpPageFull30}{RealClosureXmpPageEmpty30}
\pastebutton{RealClosureXmpPageFull30}{\hidepaste}
\tab{5}\spadcommand{map(mainCharacterization,l)\free{l }}
\indentrel{3}\begin{verbatim}
   (30)  [[- 2,- 1[,[- 1,0[,[0,1[,[1,2[]
Type: List Union(RightOpenIntervalRootCharacterization(RealClosure Fraction Integer,SparseUnivariatePolynomial RealClosure Fraction Integer),"failed")
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty30}
\begin{paste}{RealClosureXmpPageEmpty30}{RealClosureXmpPagePatch30}
\pastebutton{RealClosureXmpPageEmpty30}{\showpaste}
\tab{5}\spadcommand{map(mainCharacterization,l)\free{l }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch31}
\begin{paste}{RealClosureXmpPageFull31}{RealClosureXmpPageEmpty31}
\pastebutton{RealClosureXmpPageFull31}{\hidepaste}
\tab{5}\spadcommand{[reduce(+,l),reduce(*,l)-2]\free{l }}
\indentrel{3}\begin{verbatim}
   (31)  [0,0]
                Type: List RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty31}
\begin{paste}{RealClosureXmpPageEmpty31}{RealClosureXmpPagePatch31}
\pastebutton{RealClosureXmpPageEmpty31}{\showpaste}
\tab{5}\spadcommand{[reduce(+,l),reduce(*,l)-2]\free{l }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch32}
\begin{paste}{RealClosureXmpPageFull32}{RealClosureXmpPageEmpty32}
\pastebutton{RealClosureXmpPageFull32}{\hidepaste}
\tab{5}\spadcommand{(s2, s5, s10) := (sqrt(2)$Ran, sqrt(5)$Ran, sqrt(10)$Ran)\free{Ran }\bound{s2 }\bound{s5 }\bound{s10 }}
\indentrel{3}\begin{verbatim}
          ÚÄÄ¿
   (32)  \³10
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty32}
\begin{paste}{RealClosureXmpPageEmpty32}{RealClosureXmpPagePatch32}
\pastebutton{RealClosureXmpPageEmpty32}{\showpaste}
\tab{5}\spadcommand{(s2, s5, s10) := (sqrt(2)$Ran, sqrt(5)$Ran, sqrt(10)$Ran)\free{Ran }\bound{s2 }\bound{s5 }\bound{s10 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch33}
\begin{paste}{RealClosureXmpPageFull33}{RealClosureXmpPageEmpty33}
\pastebutton{RealClosureXmpPageFull33}{\hidepaste}
\tab{5}\spadcommand{eq1:=sqrt(s10+3)*sqrt(s5+2) - sqrt(s10-3)*sqrt(s5-2) = sqrt(10*s2+10)\free{s2 }\free{s5 }\free{s10 }\bound{eq1 }}
\indentrel{3}\begin{verbatim}
   (33)
      ÚÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄ¿    ÚÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄ¿
      ³ ÚÄÄ¿      ³ ÚÄ¿         ³ ÚÄÄ¿      ³ ÚÄ¿
   - \³\³10  - 3 \³\³5  - 2  + \³\³10  + 3 \³\³5  + 2  =
      ÚÄÄÄÄÄÄÄÄÄÄÄ¿
      ³   ÚÄ¿
     \³10\³2  + 10
            Type: Equation RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty33}
\begin{paste}{RealClosureXmpPageEmpty33}{RealClosureXmpPagePatch33}
\pastebutton{RealClosureXmpPageEmpty33}{\showpaste}
\tab{5}\spadcommand{eq1:=sqrt(s10+3)*sqrt(s5+2) - sqrt(s10-3)*sqrt(s5-2) = sqrt(10*s2+10)\free{s2 }\free{s5 }\free{s10 }\bound{eq1 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch34}
\begin{paste}{RealClosureXmpPageFull34}{RealClosureXmpPageEmpty34}
\pastebutton{RealClosureXmpPageFull34}{\hidepaste}
\tab{5}\spadcommand{eq1::Boolean\free{eq1 }}
\indentrel{3}\begin{verbatim}
   (34)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty34}
\begin{paste}{RealClosureXmpPageEmpty34}{RealClosureXmpPagePatch34}
\pastebutton{RealClosureXmpPageEmpty34}{\showpaste}
\tab{5}\spadcommand{eq1::Boolean\free{eq1 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch35}
\begin{paste}{RealClosureXmpPageFull35}{RealClosureXmpPageEmpty35}
\pastebutton{RealClosureXmpPageFull35}{\hidepaste}
\tab{5}\spadcommand{eq2:=sqrt(s5+2)*sqrt(s2+1) - sqrt(s5-2)*sqrt(s2-1) = sqrt(2*s10+2)\free{s2 }\free{s5 }\free{s10 }\bound{eq2 }}
\indentrel{3}\begin{verbatim}
   (35)
      ÚÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄ¿    ÚÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄ¿
      ³ ÚÄ¿      ³ ÚÄ¿         ³ ÚÄ¿      ³ ÚÄ¿
   - \³\³5  - 2 \³\³2  - 1  + \³\³5  + 2 \³\³2  + 1  =
      ÚÄÄÄÄÄÄÄÄÄÄ¿
      ³  ÚÄÄ¿
     \³2\³10  + 2
            Type: Equation RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty35}
\begin{paste}{RealClosureXmpPageEmpty35}{RealClosureXmpPagePatch35}
\pastebutton{RealClosureXmpPageEmpty35}{\showpaste}
\tab{5}\spadcommand{eq2:=sqrt(s5+2)*sqrt(s2+1) - sqrt(s5-2)*sqrt(s2-1) = sqrt(2*s10+2)\free{s2 }\free{s5 }\free{s10 }\bound{eq2 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch36}
\begin{paste}{RealClosureXmpPageFull36}{RealClosureXmpPageEmpty36}
\pastebutton{RealClosureXmpPageFull36}{\hidepaste}
\tab{5}\spadcommand{eq2::Boolean\free{eq2 }}
\indentrel{3}\begin{verbatim}
   (36)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty36}
\begin{paste}{RealClosureXmpPageEmpty36}{RealClosureXmpPagePatch36}
\pastebutton{RealClosureXmpPageEmpty36}{\showpaste}
\tab{5}\spadcommand{eq2::Boolean\free{eq2 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch37}
\begin{paste}{RealClosureXmpPageFull37}{RealClosureXmpPageEmpty37}
\pastebutton{RealClosureXmpPageFull37}{\hidepaste}
\tab{5}\spadcommand{s3 := sqrt(3)$Ran\free{Ran }\bound{s3 }}
\indentrel{3}\begin{verbatim}
          ÚÄ¿
   (37)  \³3
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty37}
\begin{paste}{RealClosureXmpPageEmpty37}{RealClosureXmpPagePatch37}
\pastebutton{RealClosureXmpPageEmpty37}{\showpaste}
\tab{5}\spadcommand{s3 := sqrt(3)$Ran\free{Ran }\bound{s3 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch38}
\begin{paste}{RealClosureXmpPageFull38}{RealClosureXmpPageEmpty38}
\pastebutton{RealClosureXmpPageFull38}{\hidepaste}
\tab{5}\spadcommand{s7:= sqrt(7)$Ran\free{Ran }\bound{s7 }}
\indentrel{3}\begin{verbatim}
          ÚÄ¿
   (38)  \³7
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty38}
\begin{paste}{RealClosureXmpPageEmpty38}{RealClosureXmpPagePatch38}
\pastebutton{RealClosureXmpPageEmpty38}{\showpaste}
\tab{5}\spadcommand{s7:= sqrt(7)$Ran\free{Ran }\bound{s7 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch39}
\begin{paste}{RealClosureXmpPageFull39}{RealClosureXmpPageEmpty39}
\pastebutton{RealClosureXmpPageFull39}{\hidepaste}
\tab{5}\spadcommand{e1 := sqrt(2*s7-3*s3,3)\free{s7 }\free{s3 }\bound{e1 }}
\indentrel{3}\begin{verbatim}
          ÚÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
         3³  ÚÄ¿     ÚÄ¿
   (39)  \³2\³7  - 3\³3
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty39}
\begin{paste}{RealClosureXmpPageEmpty39}{RealClosureXmpPagePatch39}
\pastebutton{RealClosureXmpPageEmpty39}{\showpaste}
\tab{5}\spadcommand{e1 := sqrt(2*s7-3*s3,3)\free{s7 }\free{s3 }\bound{e1 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch40}
\begin{paste}{RealClosureXmpPageFull40}{RealClosureXmpPageEmpty40}
\pastebutton{RealClosureXmpPageFull40}{\hidepaste}
\tab{5}\spadcommand{e2 := sqrt(2*s7+3*s3,3)\free{s7 }\free{s3 }\bound{e2 }}
\indentrel{3}\begin{verbatim}
          ÚÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
         3³  ÚÄ¿     ÚÄ¿
   (40)  \³2\³7  + 3\³3
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty40}
\begin{paste}{RealClosureXmpPageEmpty40}{RealClosureXmpPagePatch40}
\pastebutton{RealClosureXmpPageEmpty40}{\showpaste}
\tab{5}\spadcommand{e2 := sqrt(2*s7+3*s3,3)\free{s7 }\free{s3 }\bound{e2 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch41}
\begin{paste}{RealClosureXmpPageFull41}{RealClosureXmpPageEmpty41}
\pastebutton{RealClosureXmpPageFull41}{\hidepaste}
\tab{5}\spadcommand{e2-e1-s3\free{e2 }\free{e1 }\free{s3 }}
\indentrel{3}\begin{verbatim}
   (41)  0
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty41}
\begin{paste}{RealClosureXmpPageEmpty41}{RealClosureXmpPagePatch41}
\pastebutton{RealClosureXmpPageEmpty41}{\showpaste}
\tab{5}\spadcommand{e2-e1-s3\free{e2 }\free{e1 }\free{s3 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch42}
\begin{paste}{RealClosureXmpPageFull42}{RealClosureXmpPageEmpty42}
\pastebutton{RealClosureXmpPageFull42}{\hidepaste}
\tab{5}\spadcommand{pol : UP(x,Ran) := x**4+(7/3)*x**2+30*x-(100/3)\free{Ran }\bound{pol }}
\indentrel{3}\begin{verbatim}
          4   7  2         100
   (42)  x  + Ä x  + 30x - ÄÄÄ
              3             3
Type: UnivariatePolynomial(x,RealClosure Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty42}
\begin{paste}{RealClosureXmpPageEmpty42}{RealClosureXmpPagePatch42}
\pastebutton{RealClosureXmpPageEmpty42}{\showpaste}
\tab{5}\spadcommand{pol : UP(x,Ran) := x**4+(7/3)*x**2+30*x-(100/3)\free{Ran }\bound{pol }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch43}
\begin{paste}{RealClosureXmpPageFull43}{RealClosureXmpPageEmpty43}
\pastebutton{RealClosureXmpPageFull43}{\hidepaste}
\tab{5}\spadcommand{r1 := sqrt(7633)$Ran\free{Ran }\bound{r1 }}
\indentrel{3}\begin{verbatim}
          ÚÄÄÄÄ¿
   (43)  \³7633
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty43}
\begin{paste}{RealClosureXmpPageEmpty43}{RealClosureXmpPagePatch43}
\pastebutton{RealClosureXmpPageEmpty43}{\showpaste}
\tab{5}\spadcommand{r1 := sqrt(7633)$Ran\free{Ran }\bound{r1 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch44}
\begin{paste}{RealClosureXmpPageFull44}{RealClosureXmpPageEmpty44}
\pastebutton{RealClosureXmpPageFull44}{\hidepaste}
\tab{5}\spadcommand{alpha := sqrt(5*r1-436,3)/3\free{r1 }\bound{alpha }}
\indentrel{3}\begin{verbatim}
            ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
         1 3³  ÚÄÄÄÄ¿
   (44)  Ä \³5\³7633  - 436
         3
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty44}
\begin{paste}{RealClosureXmpPageEmpty44}{RealClosureXmpPagePatch44}
\pastebutton{RealClosureXmpPageEmpty44}{\showpaste}
\tab{5}\spadcommand{alpha := sqrt(5*r1-436,3)/3\free{r1 }\bound{alpha }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch45}
\begin{paste}{RealClosureXmpPageFull45}{RealClosureXmpPageEmpty45}
\pastebutton{RealClosureXmpPageFull45}{\hidepaste}
\tab{5}\spadcommand{beta := -sqrt(5*r1+436,3)/3\free{r1 }\bound{beta }}
\indentrel{3}\begin{verbatim}
              ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
           1 3³  ÚÄÄÄÄ¿
   (45)  - Ä \³5\³7633  + 436
           3
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty45}
\begin{paste}{RealClosureXmpPageEmpty45}{RealClosureXmpPagePatch45}
\pastebutton{RealClosureXmpPageEmpty45}{\showpaste}
\tab{5}\spadcommand{beta := -sqrt(5*r1+436,3)/3\free{r1 }\bound{beta }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch46}
\begin{paste}{RealClosureXmpPageFull46}{RealClosureXmpPageEmpty46}
\pastebutton{RealClosureXmpPageFull46}{\hidepaste}
\tab{5}\spadcommand{pol.(alpha+beta-1/3)\free{pol }\free{alpha }\free{beta }}
\indentrel{3}\begin{verbatim}
   (46)  0
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty46}
\begin{paste}{RealClosureXmpPageEmpty46}{RealClosureXmpPagePatch46}
\pastebutton{RealClosureXmpPageEmpty46}{\showpaste}
\tab{5}\spadcommand{pol.(alpha+beta-1/3)\free{pol }\free{alpha }\free{beta }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch47}
\begin{paste}{RealClosureXmpPageFull47}{RealClosureXmpPageEmpty47}
\pastebutton{RealClosureXmpPageFull47}{\hidepaste}
\tab{5}\spadcommand{qol : UP(x,Ran) := x**5+10*x**3+20*x+22\free{Ran }\bound{qol }}
\indentrel{3}\begin{verbatim}
          5      3
   (47)  x  + 10x  + 20x + 22
Type: UnivariatePolynomial(x,RealClosure Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty47}
\begin{paste}{RealClosureXmpPageEmpty47}{RealClosureXmpPagePatch47}
\pastebutton{RealClosureXmpPageEmpty47}{\showpaste}
\tab{5}\spadcommand{qol : UP(x,Ran) := x**5+10*x**3+20*x+22\free{Ran }\bound{qol }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch48}
\begin{paste}{RealClosureXmpPageFull48}{RealClosureXmpPageEmpty48}
\pastebutton{RealClosureXmpPageFull48}{\hidepaste}
\tab{5}\spadcommand{r2 := sqrt(153)$Ran\free{Ran }\bound{r2 }}
\indentrel{3}\begin{verbatim}
          ÚÄÄÄ¿
   (48)  \³153
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty48}
\begin{paste}{RealClosureXmpPageEmpty48}{RealClosureXmpPagePatch48}
\pastebutton{RealClosureXmpPageEmpty48}{\showpaste}
\tab{5}\spadcommand{r2 := sqrt(153)$Ran\free{Ran }\bound{r2 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch49}
\begin{paste}{RealClosureXmpPageFull49}{RealClosureXmpPageEmpty49}
\pastebutton{RealClosureXmpPageFull49}{\hidepaste}
\tab{5}\spadcommand{alpha2 := sqrt(r2-11,5)\free{r2 }\bound{alpha2 }}
\indentrel{3}\begin{verbatim}
          ÚÄÄÄÄÄÄÄÄÄÄÄ¿
         5³ ÚÄÄÄ¿
   (49)  \³\³153  - 11
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty49}
\begin{paste}{RealClosureXmpPageEmpty49}{RealClosureXmpPagePatch49}
\pastebutton{RealClosureXmpPageEmpty49}{\showpaste}
\tab{5}\spadcommand{alpha2 := sqrt(r2-11,5)\free{r2 }\bound{alpha2 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch50}
\begin{paste}{RealClosureXmpPageFull50}{RealClosureXmpPageEmpty50}
\pastebutton{RealClosureXmpPageFull50}{\hidepaste}
\tab{5}\spadcommand{beta2 := -sqrt(r2+11,5)\free{r2 }\bound{beta2 }}
\indentrel{3}\begin{verbatim}
            ÚÄÄÄÄÄÄÄÄÄÄÄ¿
           5³ ÚÄÄÄ¿
   (50)  - \³\³153  + 11
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty50}
\begin{paste}{RealClosureXmpPageEmpty50}{RealClosureXmpPagePatch50}
\pastebutton{RealClosureXmpPageEmpty50}{\showpaste}
\tab{5}\spadcommand{beta2 := -sqrt(r2+11,5)\free{r2 }\bound{beta2 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch51}
\begin{paste}{RealClosureXmpPageFull51}{RealClosureXmpPageEmpty51}
\pastebutton{RealClosureXmpPageFull51}{\hidepaste}
\tab{5}\spadcommand{qol(alpha2+beta2)\free{qol }\free{alpha2 }\free{beta2 }}
\indentrel{3}\begin{verbatim}
   (51)  0
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty51}
\begin{paste}{RealClosureXmpPageEmpty51}{RealClosureXmpPagePatch51}
\pastebutton{RealClosureXmpPageEmpty51}{\showpaste}
\tab{5}\spadcommand{qol(alpha2+beta2)\free{qol }\free{alpha2 }\free{beta2 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch52}
\begin{paste}{RealClosureXmpPageFull52}{RealClosureXmpPageEmpty52}
\pastebutton{RealClosureXmpPageFull52}{\hidepaste}
\tab{5}\spadcommand{dst1:=sqrt(9+4*s2)=1+2*s2\free{s2 }\bound{dst1 }}
\indentrel{3}\begin{verbatim}
          ÚÄÄÄÄÄÄÄÄÄ¿
          ³  ÚÄ¿         ÚÄ¿
   (52)  \³4\³2  + 9 = 2\³2  + 1
            Type: Equation RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty52}
\begin{paste}{RealClosureXmpPageEmpty52}{RealClosureXmpPagePatch52}
\pastebutton{RealClosureXmpPageEmpty52}{\showpaste}
\tab{5}\spadcommand{dst1:=sqrt(9+4*s2)=1+2*s2\free{s2 }\bound{dst1 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch53}
\begin{paste}{RealClosureXmpPageFull53}{RealClosureXmpPageEmpty53}
\pastebutton{RealClosureXmpPageFull53}{\hidepaste}
\tab{5}\spadcommand{dst1::Boolean\free{dst1 }}
\indentrel{3}\begin{verbatim}
   (53)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty53}
\begin{paste}{RealClosureXmpPageEmpty53}{RealClosureXmpPagePatch53}
\pastebutton{RealClosureXmpPageEmpty53}{\showpaste}
\tab{5}\spadcommand{dst1::Boolean\free{dst1 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch54}
\begin{paste}{RealClosureXmpPageFull54}{RealClosureXmpPageEmpty54}
\pastebutton{RealClosureXmpPageFull54}{\hidepaste}
\tab{5}\spadcommand{s6:Ran:=sqrt 6\free{Ran }\bound{s6 }}
\indentrel{3}\begin{verbatim}
          ÚÄ¿
   (54)  \³6
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty54}
\begin{paste}{RealClosureXmpPageEmpty54}{RealClosureXmpPagePatch54}
\pastebutton{RealClosureXmpPageEmpty54}{\showpaste}
\tab{5}\spadcommand{s6:Ran:=sqrt 6\free{Ran }\bound{s6 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch55}
\begin{paste}{RealClosureXmpPageFull55}{RealClosureXmpPageEmpty55}
\pastebutton{RealClosureXmpPageFull55}{\hidepaste}
\tab{5}\spadcommand{dst2:=sqrt(5+2*s6)+sqrt(5-2*s6) = 2*s3\free{s6 }\free{s3 }\bound{dst2 }}
\indentrel{3}\begin{verbatim}
          ÚÄÄÄÄÄÄÄÄÄÄÄ¿    ÚÄÄÄÄÄÄÄÄÄ¿
          ³    ÚÄ¿         ³  ÚÄ¿         ÚÄ¿
   (55)  \³- 2\³6  + 5  + \³2\³6  + 5 = 2\³3
            Type: Equation RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty55}
\begin{paste}{RealClosureXmpPageEmpty55}{RealClosureXmpPagePatch55}
\pastebutton{RealClosureXmpPageEmpty55}{\showpaste}
\tab{5}\spadcommand{dst2:=sqrt(5+2*s6)+sqrt(5-2*s6) = 2*s3\free{s6 }\free{s3 }\bound{dst2 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch56}
\begin{paste}{RealClosureXmpPageFull56}{RealClosureXmpPageEmpty56}
\pastebutton{RealClosureXmpPageFull56}{\hidepaste}
\tab{5}\spadcommand{dst2::Boolean\free{dst2 }}
\indentrel{3}\begin{verbatim}
   (56)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty56}
\begin{paste}{RealClosureXmpPageEmpty56}{RealClosureXmpPagePatch56}
\pastebutton{RealClosureXmpPageEmpty56}{\showpaste}
\tab{5}\spadcommand{dst2::Boolean\free{dst2 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch57}
\begin{paste}{RealClosureXmpPageFull57}{RealClosureXmpPageEmpty57}
\pastebutton{RealClosureXmpPageFull57}{\hidepaste}
\tab{5}\spadcommand{s29:Ran:=sqrt 29\free{Ran }\bound{s29 }}
\indentrel{3}\begin{verbatim}
          ÚÄÄ¿
   (57)  \³29
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty57}
\begin{paste}{RealClosureXmpPageEmpty57}{RealClosureXmpPagePatch57}
\pastebutton{RealClosureXmpPageEmpty57}{\showpaste}
\tab{5}\spadcommand{s29:Ran:=sqrt 29\free{Ran }\bound{s29 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch58}
\begin{paste}{RealClosureXmpPageFull58}{RealClosureXmpPageEmpty58}
\pastebutton{RealClosureXmpPageFull58}{\hidepaste}
\tab{5}\spadcommand{dst4:=sqrt(16-2*s29+2*sqrt(55-10*s29)) = sqrt(22+2*s5)-sqrt(11+2*s29)+s5\free{s29 }\free{s5 }\bound{dst4 }}
\indentrel{3}\begin{verbatim}
   (58)
    ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
    ³  ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
    ³  ³     ÚÄÄ¿           ÚÄÄ¿
   \³2\³- 10\³29  + 55  - 2\³29  + 16  =
        ÚÄÄÄÄÄÄÄÄÄÄÄ¿    ÚÄÄÄÄÄÄÄÄÄÄ¿
        ³  ÚÄÄ¿          ³  ÚÄ¿          ÚÄ¿
     - \³2\³29  + 11  + \³2\³5  + 22  + \³5
            Type: Equation RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty58}
\begin{paste}{RealClosureXmpPageEmpty58}{RealClosureXmpPagePatch58}
\pastebutton{RealClosureXmpPageEmpty58}{\showpaste}
\tab{5}\spadcommand{dst4:=sqrt(16-2*s29+2*sqrt(55-10*s29)) = sqrt(22+2*s5)-sqrt(11+2*s29)+s5\free{s29 }\free{s5 }\bound{dst4 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch59}
\begin{paste}{RealClosureXmpPageFull59}{RealClosureXmpPageEmpty59}
\pastebutton{RealClosureXmpPageFull59}{\hidepaste}
\tab{5}\spadcommand{dst4::Boolean\free{dst4 }}
\indentrel{3}\begin{verbatim}
   (59)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty59}
\begin{paste}{RealClosureXmpPageEmpty59}{RealClosureXmpPagePatch59}
\pastebutton{RealClosureXmpPageEmpty59}{\showpaste}
\tab{5}\spadcommand{dst4::Boolean\free{dst4 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch60}
\begin{paste}{RealClosureXmpPageFull60}{RealClosureXmpPageEmpty60}
\pastebutton{RealClosureXmpPageFull60}{\hidepaste}
\tab{5}\spadcommand{dst6:=sqrt((112+70*s2)+(46+34*s2)*s5) = (5+4*s2)+(3+s2)*s5\free{s2 }\free{s5 }\bound{dst6 }}
\indentrel{3}\begin{verbatim}
   (60)
    ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
    ³    ÚÄ¿       ÚÄ¿      ÚÄ¿
   \³(34\³2  + 46)\³5  + 70\³2  + 112  =
       ÚÄ¿      ÚÄ¿     ÚÄ¿
     (\³2  + 3)\³5  + 4\³2  + 5
            Type: Equation RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty60}
\begin{paste}{RealClosureXmpPageEmpty60}{RealClosureXmpPagePatch60}
\pastebutton{RealClosureXmpPageEmpty60}{\showpaste}
\tab{5}\spadcommand{dst6:=sqrt((112+70*s2)+(46+34*s2)*s5) = (5+4*s2)+(3+s2)*s5\free{s2 }\free{s5 }\bound{dst6 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch61}
\begin{paste}{RealClosureXmpPageFull61}{RealClosureXmpPageEmpty61}
\pastebutton{RealClosureXmpPageFull61}{\hidepaste}
\tab{5}\spadcommand{dst6::Boolean\free{dst6 }}
\indentrel{3}\begin{verbatim}
   (61)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty61}
\begin{paste}{RealClosureXmpPageEmpty61}{RealClosureXmpPagePatch61}
\pastebutton{RealClosureXmpPageEmpty61}{\showpaste}
\tab{5}\spadcommand{dst6::Boolean\free{dst6 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch62}
\begin{paste}{RealClosureXmpPageFull62}{RealClosureXmpPageEmpty62}
\pastebutton{RealClosureXmpPageFull62}{\hidepaste}
\tab{5}\spadcommand{f3:Ran:=sqrt(3,5)\free{Ran }\bound{f3 }}
\indentrel{3}\begin{verbatim}
         5ÚÄ¿
   (62)  \³3
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty62}
\begin{paste}{RealClosureXmpPageEmpty62}{RealClosureXmpPagePatch62}
\pastebutton{RealClosureXmpPageEmpty62}{\showpaste}
\tab{5}\spadcommand{f3:Ran:=sqrt(3,5)\free{Ran }\bound{f3 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch63}
\begin{paste}{RealClosureXmpPageFull63}{RealClosureXmpPageEmpty63}
\pastebutton{RealClosureXmpPageFull63}{\hidepaste}
\tab{5}\spadcommand{f25:Ran:=sqrt(1/25,5)\free{Ran }\bound{f25 }}
\indentrel{3}\begin{verbatim}
          ÚÄÄ¿
          ³ 1
   (63)  5³ÄÄ
         \³25
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty63}
\begin{paste}{RealClosureXmpPageEmpty63}{RealClosureXmpPagePatch63}
\pastebutton{RealClosureXmpPageEmpty63}{\showpaste}
\tab{5}\spadcommand{f25:Ran:=sqrt(1/25,5)\free{Ran }\bound{f25 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch64}
\begin{paste}{RealClosureXmpPageFull64}{RealClosureXmpPageEmpty64}
\pastebutton{RealClosureXmpPageFull64}{\hidepaste}
\tab{5}\spadcommand{f32:Ran:=sqrt(32/5,5)\free{Ran }\bound{f32 }}
\indentrel{3}\begin{verbatim}
          ÚÄÄ¿
          ³32
   (64)  5³ÄÄ
         \³ 5
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty64}
\begin{paste}{RealClosureXmpPageEmpty64}{RealClosureXmpPagePatch64}
\pastebutton{RealClosureXmpPageEmpty64}{\showpaste}
\tab{5}\spadcommand{f32:Ran:=sqrt(32/5,5)\free{Ran }\bound{f32 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch65}
\begin{paste}{RealClosureXmpPageFull65}{RealClosureXmpPageEmpty65}
\pastebutton{RealClosureXmpPageFull65}{\hidepaste}
\tab{5}\spadcommand{f27:Ran:=sqrt(27/5,5)\free{Ran }\bound{f27 }}
\indentrel{3}\begin{verbatim}
          ÚÄÄ¿
          ³27
   (65)  5³ÄÄ
         \³ 5
                     Type: RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty65}
\begin{paste}{RealClosureXmpPageEmpty65}{RealClosureXmpPagePatch65}
\pastebutton{RealClosureXmpPageEmpty65}{\showpaste}
\tab{5}\spadcommand{f27:Ran:=sqrt(27/5,5)\free{Ran }\bound{f27 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch66}
\begin{paste}{RealClosureXmpPageFull66}{RealClosureXmpPageEmpty66}
\pastebutton{RealClosureXmpPageFull66}{\hidepaste}
\tab{5}\spadcommand{dst5:=sqrt((f32-f27,3)) = f25*(1+f3-f3**2)\free{f32 }\free{f27 }\free{f25 }\free{f3 }\bound{dst5 }}
\indentrel{3}\begin{verbatim}
          ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
          ³   ÚÄÄ¿    ÚÄÄ¿                         ÚÄÄ¿
          ³   ³27     ³32       5ÚÄ¿2   5ÚÄ¿       ³ 1
   (66)  3³- 5³ÄÄ  + 5³ÄÄ  = (- \³3   + \³3  + 1) 5³ÄÄ
         \³  \³ 5    \³ 5                         \³25
            Type: Equation RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty66}
\begin{paste}{RealClosureXmpPageEmpty66}{RealClosureXmpPagePatch66}
\pastebutton{RealClosureXmpPageEmpty66}{\showpaste}
\tab{5}\spadcommand{dst5:=sqrt((f32-f27,3)) = f25*(1+f3-f3**2)\free{f32 }\free{f27 }\free{f25 }\free{f3 }\bound{dst5 }}
\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPagePatch67}
\begin{paste}{RealClosureXmpPageFull67}{RealClosureXmpPageEmpty67}
\pastebutton{RealClosureXmpPageFull67}{\hidepaste}
\tab{5}\spadcommand{dst5::Boolean\free{dst5 }}
\indentrel{3}\begin{verbatim}
   (67)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RealClosureXmpPageEmpty67}
\begin{paste}{RealClosureXmpPageEmpty67}{RealClosureXmpPagePatch67}
\pastebutton{RealClosureXmpPageEmpty67}{\showpaste}
\tab{5}\spadcommand{dst5::Boolean\free{dst5 }}
\end{paste}\end{patch}

\end{chunk}
\section{record.ht}
\pagetitle{DomainRecord}{record.ht}{Domain {\bf Record(a:A,...,b:B)}}
\pageto{Description}{LispFunctions}
\pageto{Operations}{LispFunctions}
\begin{chunk}{record.ht}
\begin{page}{DomainRecord}{Domain {\em Record(a:A,...,b:B)}}
\beginscroll
{\em Record} takes any number of selector-domain pairs as arguments:
\indentrel{2}
\newline \spad{a}, a selector, an element of domain \spadtype{Symbol}
\newline \spad{A}, a domain of category \spadtype{SetCategory}
\newline\tab{10}...
\newline \spad{b}, a selector, an element of domain \spadtype{Symbol}
\newline \spad{B}, a domain of category \spadtype{SetCategory}
\indentrel{-2}\newline
This constructor is a primitive in Axiom. 
\newline
\beginmenu
\item\menulispdownlink{Description}
{(|dbSpecialDescription| '|Record|)}\tab{15}General description
\item\menulispdownlink{Operations}
{(|dbSpecialOperations| '|Record|)}
\tab{15}All exported operations of {\em Record(a:A,b:B)}
%\item\menudownlink{Examples}   {RecordExamples}   
\tab{15}Examples illustrating use
%\item\menudownlink{Exports}    {RecordExports}    
\tab{15}Explicit categories and operations
\endmenu
\vspace{1}\newline
The selectors {\em a,...,b} of a \spad{Record} type must be distinct.
\endscroll\end{page}
 
\end{chunk}
\pagetitle{RecordDescription}{record.ht}{Domain Constructor {\bf Record}}
\begin{chunk}{record.ht}
\begin{page}{RecordDescription}{Domain Constructor {\em Record}}
\beginscroll
\newline\menuitemstyle{}\tab{2}Record({\em a:A},{\em b:B})
\newline\tab{2}{\em Arguments:}\indent{17}\tab{-2}
{\em a}, a selector, an element of domain \spadtype{Symbol}
\newline\tab{-2}
{\em A}, a domain of category \spadtype{SetCategory}
\newline\tab{10}...
\newline\tab{-2}
{\em b}, a selector, an element of domain \spadtype{Symbol}
\newline\tab{-2}
{\em B}, a domain of category \spadtype{SetCategory}
\indent{0}\newline\tab{2}{\em Returns:}\indent{15}\tab{0}
a record object with component objects of type {\em A},...,{\em B} with 
correponding selectors {\em a},...,{\em b}
as described below.
\indent{0}\newline\tab{2}{\em Description:}\indent{15}\tab{0}
{\em Record(a:A,b:B)} is used to create the class of pairs of objects made
up of a value of type {\em A} selected by the symbol {\em a} and
a value of type {\em B} selected by the symbol {\em b}.
In general, the {\em Record} constructor can take any 
number of arguments and thus can 
be used to create aggregates of 
heterogeneous components of arbitrary size selectable by name.
{\em Record} is a primitive domain of Axiom which cannot be
defined in the Axiom language. 
\endscroll
\end{page}


\end{chunk}
\section{regset.ht}
\pagetitle{RegularTriangularSetXmpPage}{regset.ht}{RegularTriangularSet}
\begin{chunk}{regset.ht}
\begin{page}{RegularTriangularSetXmpPage}{RegularTriangularSet}
\beginscroll
The \spadtype{RegularTriangularSet} domain constructor implements
regular triangular sets.  These particular triangular sets were
introduced by M. Kalkbrener (1991) in his PhD Thesis under the name
regular chains.  Regular chains and their related concepts are
presented in the paper "On the Theories of Triangular sets" By
P. Aubry, D. Lazard and M. Moreno Maza (to appear in the Journal of
Symbolic Computation).  The \spadtype{RegularTriangularSet}
constructor also provides a new method (by the third author) for
solving polynomial system by means of regular chains.  This method has
two ways of solving.  One has the same specifications as Kalkbrener's
algorithm (1991) and the other is closer to Lazard's method
(Discr. App. Math, 1991).  Moreover, this new method removes redundant
component from the decompositions when this is not {\em too
expensive}.  This is always the case with square-free regular chains.
So if you want to obtain decompositions without redundant components
just use the \spadtype{SquareFreeRegularTriangularSet} domain
constructor or the \spadtype{LazardSetSolvingPackage} package
constructor.  See also the \spadtype{LexTriangularPackage} and
\spadtype{ZeroDimensionalSolvePackage} for the case of algebraic
systems with a finite number of (complex) solutions.

One of the main features of regular triangular sets is that they
naturally define towers of simple extensions of a field.
This allows to perform with multivariate polynomials the 
same kind of operations as one can do in an \spadtype{EuclideanDomain}.

The \spadtype{RegularTriangularSet} constructor takes four arguments.
The first one, {\bf R}, is the coefficient ring of the polynomials; it
must belong to the category \spadtype{GcdDomain}.  The second one,
{\bf E}, is the exponent monoid of the polynomials; it must belong to
the category \spadtype{OrderedAbelianMonoidSup}.  the third one, {\bf
V}, is the ordered set of variables; it must belong to the category
\spadtype{OrderedSet}.  The last one is the polynomial ring; it must
belong to the category \spadtype{RecursivePolynomialCategory(R,E,V)}.
The abbreviation for \spadtype{RegularTriangularSet} is
\spadtype{REGSET}.  See also the constructor \spadtype{RegularChain}
which only takes two arguments, the coefficient ring and the ordered
set of variables; in that case, polynomials are necessarily built with
the \spadtype{NewSparseMultivariatePolynomial} domain constructor.

We shall explain now how to use the constructor \spadtype{REGSET} 
and how to read the decomposition of a polynomial system by means 
of regular sets.

Let us give some examples.  We start with an easy one
(Donati-Traverso) in order to understand the two ways of solving
polynomial systems provided by the \spadtype{REGSET} constructor.
\xtc{
Define the coefficient ring.
}{
\spadpaste{R := Integer \bound{R}}
}
\xtc{
Define the list of variables,
}{
\spadpaste{ls : List Symbol := [x,y,z,t] \bound{ls}}
}
\xtc{
and make it an ordered set;
}{
\spadpaste{V := OVAR(ls) \free{ls} \bound{V}}
}
\xtc{
then define the exponent monoid.
}{
\spadpaste{E := IndexedExponents V \free{V} \bound{E}}
}
\xtc{
Define the polynomial ring.
}{
\spadpaste{P := NSMP(R, V) \free{R} \free{V} \bound{P}}
}
\xtc{
Let the variables be polynomial.
}{
\spadpaste{x: P := 'x \free{P} \bound{x}}
}
\xtc{
}{
\spadpaste{y: P := 'y \free{P} \bound{y}}
}
\xtc{
}{
\spadpaste{z: P := 'z \free{P} \bound{z}}
}
\xtc{
}{
\spadpaste{t: P := 't \free{P} \bound{t}}
}
\xtc{
Now call the \spadtype{RegularTriangularSet} domain constructor.
}{
\spadpaste{T := REGSET(R,E,V,P) \free{R} \free{E} 
\free{V} \free{P} \bound{T} }
}
\xtc{
Define a polynomial system.
}{
\spadpaste{p1 := x ** 31 - x ** 6 - x - y \free{x} \free{y} \bound{p1}}
}
\xtc{
}{
\spadpaste{p2 := x ** 8  - z \free{x} \free{z} \bound{p2}}
}
\xtc{
}{
\spadpaste{p3 := x ** 10 - t \free{x} \free{t} \bound{p3}}
}
\xtc{
}{
\spadpaste{lp := [p1, p2, p3] \free{p1} \free{p2} \free{p3} \bound{lp}}
}
\xtc{
First of all, let us solve this system in the sense of Kalkbrener.
}{
\spadpaste{zeroSetSplit(lp)$T \free{lp} \free{T}}
}
\xtc{
And now in the sense of Lazard (or Wu and other authors).
}{
\spadpaste{lts := zeroSetSplit(lp,false)$T \free{lp} \free{T} \bound{lts}}
}

We can see that the first decomposition is a subset of the second.
So how can both be correct ?

Recall first that polynomials from a domain of the category
\spadtype{RecursivePolynomialCategory} are regarded as univariate
polynomials in their main variable.  For instance the second
polynomial in the first set of each decomposition has main variable
{\bf y} and its initial (i.e. its leading coefficient w.r.t. its main
variable) is {\bf t z}.

Now let us explain how to read the second decomposition.  Note that
the non-constant initials of the first set are \texht{$t^4-t$}{{\bf
t^4 - t}} and \texht{$t z$}{{\bf t z}}.  Then the solutions described
by this first set are the common zeros of its polynomials that do not
cancel the polynomials \texht{$t^4-t$}{{\bf t^4 - t}} and 
\texht{$ty z$}{{\bf t z}}.  
Now the solutions of the input system {\bf lp}
satisfying these equations are described by the second and the third
sets of the decomposition.  Thus, in some sense, they can be
considered as degenerated solutions.  The solutions given by the first
set are called the generic points of the system; they give the general
form of the solutions.  The first decomposition only provides these
generic points.  This latter decomposition is useful when they are
many degenerated solutions (which is sometimes hard to compute) and
when one is only interested in general informations, like the
dimension of the input system.

\xtc{
We can get the dimensions of each component
of a decomposition as follows.
}{
\spadpaste{[coHeight(ts) for ts in lts] \free{lts}}
}

Thus the first set has dimension one.
Indeed {\bf t} can take any value, except {\bf 0}
or any third root of {\bf 1}, whereas {\bf z}
is completely determined from {\bf t},
{\bf y} is given by {\bf z} and {\bf t},
and finally {\bf x} is given by the other three variables.
In the second and the third sets of the second decomposition
the four variables are completely determined and thus
these sets have dimension zero.

We give now the precise specifications of each decomposition. 
This assume some mathematical knowledge.
However, for the non-expert user, the above explanations will 
be sufficient to understand the other features of the
\spadtype{RSEGSET} constructor.

The input system {\bf lp} is decomposed in the sense
of Kalkbrener as finitely many regular sets {\bf T1,...,Ts}
such that the radical ideal generated by {\bf lp}
is the intersection of the radicals of the
saturated ideals of {\bf T1,...,Ts}.
In other words, the affine variety associated with {\bf lp} 
is the union of the closures (w.r.t. Zarisky topology)
of the regular-zeros sets of {\bf T1,...,Ts}.

{\bf N. B.} The prime ideals associated with the 
radical of the saturated ideal of
a regular triangular set have all the same dimension;
moreover these prime ideals can be given by characteristic
sets with the same main variables. 
Thus a decomposition in the sense of Kalkbrener
is unmixed dimensional.
Then it can be viewed as a {\em lazy}
decomposition into prime ideals (some of these 
prime ideals being merged into unmixed dimensional ideals).

Now we explain the other way of solving by means of regular 
triangular sets.
The input system {\bf lp} is decomposed in the sense
of Lazard as finitely many regular triangular sets {\bf T1,...,Ts}
such that the affine variety associated with {\bf lp}
is the union of the regular-zeros sets of {\bf T1,...,Ts}.
Thus a decomposition in the sense of Lazard is also
a decomposition in the sense of Kalkbrener; the converse
is false as we have seen before.

When the input system has a finite number of solutions,
both ways of solving provide similar decompositions as
we shall see with this second example (Caprasse).


\xtc{
Define a polynomial system.
}{
\spadpaste{f1 := y**2*z+2*x*y*t-2*x-z \free{z} \free{x} 
\free{y} \free{t} \bound{f1}}
}
\xtc{
}{
\spadpaste{f2 :=   -x**3*z+ 4*x*y**2*z+ 4*x**2*y*t+ 2*y**3*t+ 
4*x**2- 10*y**2+ 4*x*z- 10*y*t+ 2 \free{z} \free{x} \free{y} 
\free{t} \bound{f2}}
}
\xtc{
}{
\spadpaste{f3 :=  2*y*z*t+x*t**2-x-2*z \free{z} \free{x} \free{y} 
\free{t} \bound{f3}}
}
\xtc{
}{
\spadpaste{f4 :=   -x*z**3+ 4*y*z**2*t+ 4*x*z*t**2+ 2*y*t**3+ 
4*x*z+ 4*z**2-10*y*t- 10*t**2+2 \free{z} \free{x} \free{y} 
\free{t} \bound{f4}}
}
\xtc{
}{
\spadpaste{lf := [f1, f2, f3, f4] \free{f1} \free{f2} 
\free{f3}  \free{f4} \bound{lf}}
}

\xtc{
First of all, let us solve this system in the sense of Kalkbrener.
}{
\spadpaste{zeroSetSplit(lf)$T \free{lf} \free{T}}
}
\xtc{
And now in the sense of Lazard (or Wu and other authors).
}{
\spadpaste{lts2 := zeroSetSplit(lf,false)$T \free{lf} 
\free{T} \bound{lts2}}
}

Up to the ordering of the components, both decompositions are identical.

\xtc{
Let us check that each component has a finite number of solutions.
}{
\spadpaste{[coHeight(ts) for ts in lts2] \free{lts2}}
}

\xtc{
Let us count the degrees of each component,
}{
\spadpaste{degrees := [degree(ts) for ts in lts2] 
\free{lts2} \bound{degrees}}
}
\xtc{
and compute their sum.
}{
\spadpaste{reduce(+,degrees) \free{degrees}}
}

We study now the options of the \spadfun{zeroSetSplit} operation.
As we have seen yet, there is an optional second argument 
which is a boolean value. If this value is true (this
is the default) then the decomposition is computed
in the sense of Kalkbrener, otherwise it is computed
in the sense of Lazard.

There is a second boolean optional argument that
can be used (in that case the first optional
argument must be present).
This second option allows you to get some information
during the computations.

Therefore, we need to understand a little what is going on during the
computations.  An important feature of the algorithm is that the
intermediate computations are managed in some sense like the processes
of a Unix system.  Indeed, each intermediate computation may generate
other intermediate computations and the management of all these
computations is a crucial task for the efficiency.  Thus any
intermediate computation may be suspended, killed or resumed,
depending on algebraic considerations that determine priorities for
these processes.  The goal is of course to go as fast as possible
towards the final decomposition which means to avoid as much as
possible unnecessary computations.

To follow the computations, one needs to set to \spad{true} the second
argument.  Then a lot of numbers and letters are displayed.  Between a
\spad{[} and a \spad{]} one has the state of the processes at a given
time.  Just after \spad{[} one can see the number of processes.  Then
each process is represented by two numbers between \spad{<} and
\spad{>}.  A process consists of a list of polynomial {\bf ps} and a
triangular set {\bf ts}; its goal is to compute the common zeros of
{\bf ps} that belong to the regular-zeros set of {\bf ts}.  After the
processes, the number between pipes gives the total number of
polynomials in all the sets \spad{ps}.  Finally, the number between
braces gives the number of components of a decomposition that are
already computed. This number may decrease.

Let us take a third example (Czapor-Geddes-Wang) to see how these
informations are displayed.

\xtc{
Define a polynomial system.
}{
\spadpaste{u : R := 2  \free{R} \bound{u}}
}
\xtc{
}{
\spadpaste{q1 := 2*(u-1)**2+ 2*(x-z*x+z**2)+ y**2*(x-1)**2- 
2*u*x+ 2*y*t*(1-x)*(x-z)+ 2*u*z*t*(t-y)+ u**2*t**2*(1-2*z)+ 
2*u*t**2*(z-x)+ 2*u*t*y*(z-1)+ 2*u*z*x*(y+1)+ 
(u**2-2*u)*z**2*t**2+ 2*u**2*z**2+ 4*u*(1-u)*z+ t**2*(z-x)**2 
\free{z} \free{x} \free{y} \free{t} \free{u} \bound{q1}}
}
\xtc{
}{
\spadpaste{q2 := t*(2*z+1)*(x-z)+ y*(z+2)*(1-x)+ u*(u-2)*t+ 
u*(1-2*u)*z*t+ u*y*(x+u-z*x-1)+ u*(u+1)*z**2*t \free{z} 
\free{x} \free{y} \free{t} \free{u} \bound{q2}}
}
\xtc{
}{
\spadpaste{q3 := -u**2*(z-1)**2+ 2*z*(z-x)-2*(x-1) \free{z} 
\free{x} \free{y} \free{t} \free{u}  \bound{q3}}
}
\xtc{
}{
\spadpaste{q4 :=   u**2+4*(z-x**2)+3*y**2*(x-1)**2- 
3*t**2*(z-x)**2 +3*u**2*t**2*(z-1)**2+u**2*z*(z-2)+
6*u*t*y*(z+x+z*x-1) \free{z} \free{x} \free{y} \free{t} 
\free{u} \bound{q4}}
}
\xtc{
}{
\spadpaste{lq := [q1, q2, q3, q4] \free{q1} \free{q2} 
\free{q3}  \free{q4} \bound{lq}}
}

\xtc{
Let us try the information option.
N.B. The timing should be between 1 and 10 minutes, depending on your machine.
}{
\spadpaste{zeroSetSplit(lq,true,true)$T \free{lq} \free{T}}
}

Between a sequence of processes, thus between a \spad{]} and a
\spad{[} you can see capital letters \spad{W, G, I} and lower case
letters \spad{i, w}. Each time a capital letter appears a non-trivial
computation has be performed and its result is put in a hash-table.
Each time a lower case letter appears a needed result has been found
in an hash-table.  The use of these hash-tables generally speed up the
computations.  However, on very large systems, it may happen that
these hash-tables become too big to be handle by your Axiom
configuration.  Then in these exceptional cases, you may prefer
getting a result (even if it takes a long time) than getting nothing.
Hence you need to know how to prevent the \spadtype{RSEGSET}
constructor from using these hash-tables.  In that case you will be
using the \spadfun{zeroSetSplit} with five arguments.  The first one
is the input system {\bf lp} as above.  The second one is a boolean
value \spad{hash?} which is \spad{true} iff you want to use
hash-tables.  The third one is boolean value \spad{clos?} which is
\spad{true} iff you want to solve your system in the sense of
Kalkbrener, the other way remaining that of Lazard.  The fourth
argument is boolean value \spad{info?} which is \spad{true} iff you
want to display information during the computations.  The last one is
boolean value \spad{prep?} which is \spad{true} iff you want to use
some heuristics that are performed on the input system before starting
the real algorithm.  The value of this flag is \spad{true} when you
are using \spadfun{zeroSetSplit} with less than five arguments.  Note
that there is no available signature for \spadfun{zeroSetSplit} with
four arguments.

We finish this section by some remarks about both ways of solving, in
the sense of Kalkbrener or in the sense of Lazard.  For problems with
a finite number of solutions, there are theoretically equivalent and
the resulting decompositions are identical, up to the ordering of the
components.  However, when solving in the sense of Lazard, the
algorithm behaves differently.  In that case, it becomes more
incremental than in the sense of Kalkbrener. That means the
polynomials of the input system are considered one after another
whereas in the sense of Kalkbrener the input system is treated more
globally.

This makes an important difference in positive dimension.  Indeed when
solving in the sense of Kalkbrener, the {\em Primeidealkettensatz} of
Krull is used.  That means any regular triangular containing more
polynomials than the input system can be deleted.  This is not
possible when solving in the sense of Lazard.  This explains why
Kalkbrener's decompositions usually contain less components than those
of Lazard.  However, it may happen with some examples that the
incremental process (that cannot be used when solving in the sense of
Kalkbrener) provide a more efficient way of solving than the global
one even if the {\em Primeidealkettensatz} is used.  Thus just try
both, with the various options, before concluding that you cannot
solve your favorite system with \spadfun{zeroSetSplit}.  There exist
more options at the development level that are not currently available
in this public version.  So you are welcome to contact {\em
marc@nag.co.uk} for more information and help.

\endscroll
\autobuttons
\end{page}

\begin{patch}{RegularTriangularSetXmpPagePatch1}
\begin{paste}{RegularTriangularSetXmpPageFull1}{RegularTriangularSetXmpPageEmpty1}
\pastebutton{RegularTriangularSetXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{R := Integer\bound{R }}
\indentrel{3}\begin{verbatim}
   (1)  Integer
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty1}
\begin{paste}{RegularTriangularSetXmpPageEmpty1}{RegularTriangularSetXmpPagePatch1}
\pastebutton{RegularTriangularSetXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{R := Integer\bound{R }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch2}
\begin{paste}{RegularTriangularSetXmpPageFull2}{RegularTriangularSetXmpPageEmpty2}
\pastebutton{RegularTriangularSetXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{ls : List Symbol := [x,y,z,t]\bound{ls }}
\indentrel{3}\begin{verbatim}
   (2)  [x,y,z,t]
                                      Type: List Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty2}
\begin{paste}{RegularTriangularSetXmpPageEmpty2}{RegularTriangularSetXmpPagePatch2}
\pastebutton{RegularTriangularSetXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{ls : List Symbol := [x,y,z,t]\bound{ls }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch3}
\begin{paste}{RegularTriangularSetXmpPageFull3}{RegularTriangularSetXmpPageEmpty3}
\pastebutton{RegularTriangularSetXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{V := OVAR(ls)\free{ls }\bound{V }}
\indentrel{3}\begin{verbatim}
   (3)  OrderedVariableList [x,y,z,t]
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty3}
\begin{paste}{RegularTriangularSetXmpPageEmpty3}{RegularTriangularSetXmpPagePatch3}
\pastebutton{RegularTriangularSetXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{V := OVAR(ls)\free{ls }\bound{V }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch4}
\begin{paste}{RegularTriangularSetXmpPageFull4}{RegularTriangularSetXmpPageEmpty4}
\pastebutton{RegularTriangularSetXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{E := IndexedExponents V\free{V }\bound{E }}
\indentrel{3}\begin{verbatim}
   (4)  IndexedExponents OrderedVariableList [x,y,z,t]
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty4}
\begin{paste}{RegularTriangularSetXmpPageEmpty4}{RegularTriangularSetXmpPagePatch4}
\pastebutton{RegularTriangularSetXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{E := IndexedExponents V\free{V }\bound{E }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch5}
\begin{paste}{RegularTriangularSetXmpPageFull5}{RegularTriangularSetXmpPageEmpty5}
\pastebutton{RegularTriangularSetXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{P := NSMP(R, V)\free{R }\free{V }\bound{P }}
\indentrel{3}\begin{verbatim}
   (5)
  NewSparseMultivariatePolynomial(Integer,OrderedVariable
  List [x,y,z,t])
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty5}
\begin{paste}{RegularTriangularSetXmpPageEmpty5}{RegularTriangularSetXmpPagePatch5}
\pastebutton{RegularTriangularSetXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{P := NSMP(R, V)\free{R }\free{V }\bound{P }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch6}
\begin{paste}{RegularTriangularSetXmpPageFull6}{RegularTriangularSetXmpPageEmpty6}
\pastebutton{RegularTriangularSetXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{x: P := 'x\free{P }\bound{x }}
\indentrel{3}\begin{verbatim}
   (6)  x
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty6}
\begin{paste}{RegularTriangularSetXmpPageEmpty6}{RegularTriangularSetXmpPagePatch6}
\pastebutton{RegularTriangularSetXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{x: P := 'x\free{P }\bound{x }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch7}
\begin{paste}{RegularTriangularSetXmpPageFull7}{RegularTriangularSetXmpPageEmpty7}
\pastebutton{RegularTriangularSetXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{y: P := 'y\free{P }\bound{y }}
\indentrel{3}\begin{verbatim}
   (7)  y
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty7}
\begin{paste}{RegularTriangularSetXmpPageEmpty7}{RegularTriangularSetXmpPagePatch7}
\pastebutton{RegularTriangularSetXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{y: P := 'y\free{P }\bound{y }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch8}
\begin{paste}{RegularTriangularSetXmpPageFull8}{RegularTriangularSetXmpPageEmpty8}
\pastebutton{RegularTriangularSetXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{z: P := 'z\free{P }\bound{z }}
\indentrel{3}\begin{verbatim}
   (8)  z
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty8}
\begin{paste}{RegularTriangularSetXmpPageEmpty8}{RegularTriangularSetXmpPagePatch8}
\pastebutton{RegularTriangularSetXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{z: P := 'z\free{P }\bound{z }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch9}
\begin{paste}{RegularTriangularSetXmpPageFull9}{RegularTriangularSetXmpPageEmpty9}
\pastebutton{RegularTriangularSetXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{t: P := 't\free{P }\bound{t }}
\indentrel{3}\begin{verbatim}
   (9)  t
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty9}
\begin{paste}{RegularTriangularSetXmpPageEmpty9}{RegularTriangularSetXmpPagePatch9}
\pastebutton{RegularTriangularSetXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{t: P := 't\free{P }\bound{t }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch10}
\begin{paste}{RegularTriangularSetXmpPageFull10}{RegularTriangularSetXmpPageEmpty10}
\pastebutton{RegularTriangularSetXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{T := REGSET(R,E,V,P)\free{R }\free{E }\free{V }\free{P }\bound{T }}
\indentrel{3}\begin{verbatim}
   (10)
  RegularTriangularSet(Integer,IndexedExponents OrderedVa
  riableList [x,y,z,t],OrderedVariableList [x,y,z,t],NewS
  parseMultivariatePolynomial(Integer,OrderedVariableList
   [x,y,z,t]))
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty10}
\begin{paste}{RegularTriangularSetXmpPageEmpty10}{RegularTriangularSetXmpPagePatch10}
\pastebutton{RegularTriangularSetXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{T := REGSET(R,E,V,P)\free{R }\free{E }\free{V }\free{P }\bound{T }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch11}
\begin{paste}{RegularTriangularSetXmpPageFull11}{RegularTriangularSetXmpPageEmpty11}
\pastebutton{RegularTriangularSetXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{p1 := x ** 31 - x ** 6 - x - y\free{x }\free{y }\bound{p1 }}
\indentrel{3}\begin{verbatim}
          31    6
   (11)  x   - x  - x - y
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty11}
\begin{paste}{RegularTriangularSetXmpPageEmpty11}{RegularTriangularSetXmpPagePatch11}
\pastebutton{RegularTriangularSetXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{p1 := x ** 31 - x ** 6 - x - y\free{x }\free{y }\bound{p1 }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch12}
\begin{paste}{RegularTriangularSetXmpPageFull12}{RegularTriangularSetXmpPageEmpty12}
\pastebutton{RegularTriangularSetXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{p2 := x ** 8 - z\free{x }\free{z }\bound{p2 }}
\indentrel{3}\begin{verbatim}
          8
   (12)  x  - z
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty12}
\begin{paste}{RegularTriangularSetXmpPageEmpty12}{RegularTriangularSetXmpPagePatch12}
\pastebutton{RegularTriangularSetXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{p2 := x ** 8 - z\free{x }\free{z }\bound{p2 }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch13}
\begin{paste}{RegularTriangularSetXmpPageFull13}{RegularTriangularSetXmpPageEmpty13}
\pastebutton{RegularTriangularSetXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{p3 := x ** 10 - t\free{x }\free{t }\bound{p3 }}
\indentrel{3}\begin{verbatim}
          10
   (13)  x   - t
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty13}
\begin{paste}{RegularTriangularSetXmpPageEmpty13}{RegularTriangularSetXmpPagePatch13}
\pastebutton{RegularTriangularSetXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{p3 := x ** 10 - t\free{x }\free{t }\bound{p3 }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch14}
\begin{paste}{RegularTriangularSetXmpPageFull14}{RegularTriangularSetXmpPageEmpty14}
\pastebutton{RegularTriangularSetXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{lp := [p1, p2, p3]\free{p1 }\free{p2 }\free{p3 }\bound{lp }}
\indentrel{3}\begin{verbatim}
           31    6          8      10
   (14)  [x   - x  - x - y,x  - z,x   - t]
Type: List NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty14}
\begin{paste}{RegularTriangularSetXmpPageEmpty14}{RegularTriangularSetXmpPagePatch14}
\pastebutton{RegularTriangularSetXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{lp := [p1, p2, p3]\free{p1 }\free{p2 }\free{p3 }\bound{lp }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch15}
\begin{paste}{RegularTriangularSetXmpPageFull15}{RegularTriangularSetXmpPageEmpty15}
\pastebutton{RegularTriangularSetXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{zeroSetSplit(lp)$T\free{lp }\free{T }}
\indentrel{3}\begin{verbatim}
   (15)
   [
       5    4       2     3     8     5    3    2
     {z  - t , t z y  + 2z y - t  + 2t  + t  - t ,
        4                2
      (t  - t)x - t y - z }
     ]
Type: List RegularTriangularSet(Integer,IndexedExponents OrderedVariableList [x,y,z,t],OrderedVariableList [x,y,z,t],NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t]))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty15}
\begin{paste}{RegularTriangularSetXmpPageEmpty15}{RegularTriangularSetXmpPagePatch15}
\pastebutton{RegularTriangularSetXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{zeroSetSplit(lp)$T\free{lp }\free{T }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch16}
\begin{paste}{RegularTriangularSetXmpPageFull16}{RegularTriangularSetXmpPageEmpty16}
\pastebutton{RegularTriangularSetXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{lts := zeroSetSplit(lp,false)$T\free{lp }\free{T }\bound{lts }}
\indentrel{3}\begin{verbatim}
   (16)
   [
       5    4       2     3     8     5    3    2
     {z  - t , t z y  + 2z y - t  + 2t  + t  - t ,
        4                2
      (t  - t)x - t y - z }
     ,
      3      5          2     3         2
    {t  - 1,z  - t,t z y  + 2z y + 1,z x  - t},
    {t,z,y,x}]
Type: List RegularTriangularSet(Integer,IndexedExponents OrderedVariableList [x,y,z,t],OrderedVariableList [x,y,z,t],NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t]))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty16}
\begin{paste}{RegularTriangularSetXmpPageEmpty16}{RegularTriangularSetXmpPagePatch16}
\pastebutton{RegularTriangularSetXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{lts := zeroSetSplit(lp,false)$T\free{lp }\free{T }\bound{lts }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch17}
\begin{paste}{RegularTriangularSetXmpPageFull17}{RegularTriangularSetXmpPageEmpty17}
\pastebutton{RegularTriangularSetXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{[coHeight(ts) for ts in lts]\free{lts }}
\indentrel{3}\begin{verbatim}
   (17)  [1,0,0]
                          Type: List NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty17}
\begin{paste}{RegularTriangularSetXmpPageEmpty17}{RegularTriangularSetXmpPagePatch17}
\pastebutton{RegularTriangularSetXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{[coHeight(ts) for ts in lts]\free{lts }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch18}
\begin{paste}{RegularTriangularSetXmpPageFull18}{RegularTriangularSetXmpPageEmpty18}
\pastebutton{RegularTriangularSetXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{f1 := y**2*z+2*x*y*t-2*x-z\free{z }\free{x }\free{y }\free{t }\bound{f1 }}
\indentrel{3}\begin{verbatim}
                          2
   (18)  (2t y - 2)x + z y  - z
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty18}
\begin{paste}{RegularTriangularSetXmpPageEmpty18}{RegularTriangularSetXmpPagePatch18}
\pastebutton{RegularTriangularSetXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{f1 := y**2*z+2*x*y*t-2*x-z\free{z }\free{x }\free{y }\free{t }\bound{f1 }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch19}
\begin{paste}{RegularTriangularSetXmpPageFull19}{RegularTriangularSetXmpPageEmpty19}
\pastebutton{RegularTriangularSetXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{f2 := -x**3*z+ 4*x*y**2*z+ 4*x**2*y*t+ 2*y**3*t+ 4*x**2- 10*y**2+ 4*x*z- 10*y*t+ 2\free{z }\free{x }\free{y }\free{t }\bound{f2 }}
\indentrel{3}\begin{verbatim}
   (19)
          3              2        2              3      2
     - z x  + (4t y + 4)x  + (4z y  + 4z)x + 2t y  - 10y
   + 
     - 10t y + 2
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty19}
\begin{paste}{RegularTriangularSetXmpPageEmpty19}{RegularTriangularSetXmpPagePatch19}
\pastebutton{RegularTriangularSetXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{f2 := -x**3*z+ 4*x*y**2*z+ 4*x**2*y*t+ 2*y**3*t+ 4*x**2- 10*y**2+ 4*x*z- 10*y*t+ 2\free{z }\free{x }\free{y }\free{t }\bound{f2 }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch20}
\begin{paste}{RegularTriangularSetXmpPageFull20}{RegularTriangularSetXmpPageEmpty20}
\pastebutton{RegularTriangularSetXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{f3 := 2*y*z*t+x*t**2-x-2*z\free{z }\free{x }\free{y }\free{t }\bound{f3 }}
\indentrel{3}\begin{verbatim}
           2
   (20)  (t  - 1)x + 2t z y - 2z
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty20}
\begin{paste}{RegularTriangularSetXmpPageEmpty20}{RegularTriangularSetXmpPagePatch20}
\pastebutton{RegularTriangularSetXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{f3 := 2*y*z*t+x*t**2-x-2*z\free{z }\free{x }\free{y }\free{t }\bound{f3 }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch21}
\begin{paste}{RegularTriangularSetXmpPageFull21}{RegularTriangularSetXmpPageEmpty21}
\pastebutton{RegularTriangularSetXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{f4 := -x*z**3+ 4*y*z**2*t+ 4*x*z*t**2+ 2*y*t**3+ 4*x*z+ 4*z**2-10*y*t- 10*t**2+2\free{z }\free{x }\free{y }\free{t }\bound{f4 }}
\indentrel{3}\begin{verbatim}
   (21)
         3      2                2     3             2
     (- z  + (4t  + 4)z)x + (4t z  + 2t  - 10t)y + 4z
   + 
          2
     - 10t  + 2
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty21}
\begin{paste}{RegularTriangularSetXmpPageEmpty21}{RegularTriangularSetXmpPagePatch21}
\pastebutton{RegularTriangularSetXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{f4 := -x*z**3+ 4*y*z**2*t+ 4*x*z*t**2+ 2*y*t**3+ 4*x*z+ 4*z**2-10*y*t- 10*t**2+2\free{z }\free{x }\free{y }\free{t }\bound{f4 }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch22}
\begin{paste}{RegularTriangularSetXmpPageFull22}{RegularTriangularSetXmpPageEmpty22}
\pastebutton{RegularTriangularSetXmpPageFull22}{\hidepaste}
\tab{5}\spadcommand{lf := [f1, f2, f3, f4]\free{f1 }\free{f2 }\free{f3 }\free{f4 }\bound{lf }}
\indentrel{3}\begin{verbatim}
   (22)
                     2
   [(2t y - 2)x + z y  - z,

            3              2        2              3
       - z x  + (4t y + 4)x  + (4z y  + 4z)x + 2t y
     + 
            2
       - 10y  - 10t y + 2
     ,
      2
    (t  - 1)x + 2t z y - 2z,

           3      2                2     3             2
       (- z  + (4t  + 4)z)x + (4t z  + 2t  - 10t)y + 4z
     + 
            2
       - 10t  + 2
     ]
Type: List NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty22}
\begin{paste}{RegularTriangularSetXmpPageEmpty22}{RegularTriangularSetXmpPagePatch22}
\pastebutton{RegularTriangularSetXmpPageEmpty22}{\showpaste}
\tab{5}\spadcommand{lf := [f1, f2, f3, f4]\free{f1 }\free{f2 }\free{f3 }\free{f4 }\bound{lf }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch23}
\begin{paste}{RegularTriangularSetXmpPageFull23}{RegularTriangularSetXmpPageEmpty23}
\pastebutton{RegularTriangularSetXmpPageFull23}{\hidepaste}
\tab{5}\spadcommand{zeroSetSplit(lf)$T\free{lf }\free{T }}
\indentrel{3}\begin{verbatim}
   (23)
   [
       2       8      6       2
     {t  - 1, z  - 16z  + 256z  - 256, t y - 1,
        3            2
      (z  - 8z)x - 8z  + 16}
     ,
       2      2     2
    {3t  + 1,z  - 7t  - 1,y + t,x + z},
      8      6      2         3            2
    {t  - 10t  + 10t  - 1,z,(t  - 5t)y - 5t  + 1,x},
      2      2
    {t  + 3,z  - 4,y + t,x - z}]
Type: List RegularTriangularSet(Integer,IndexedExponents OrderedVariableList [x,y,z,t],OrderedVariableList [x,y,z,t],NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t]))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty23}
\begin{paste}{RegularTriangularSetXmpPageEmpty23}{RegularTriangularSetXmpPagePatch23}
\pastebutton{RegularTriangularSetXmpPageEmpty23}{\showpaste}
\tab{5}\spadcommand{zeroSetSplit(lf)$T\free{lf }\free{T }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch24}
\begin{paste}{RegularTriangularSetXmpPageFull24}{RegularTriangularSetXmpPageEmpty24}
\pastebutton{RegularTriangularSetXmpPageFull24}{\hidepaste}
\tab{5}\spadcommand{lts2 := zeroSetSplit(lf,false)$T\free{lf }\free{T }\bound{lts2 }}
\indentrel{3}\begin{verbatim}
   (24)
      8      6      2         3            2
   [{t  - 10t  + 10t  - 1,z,(t  - 5t)y - 5t  + 1,x},

       2       8      6       2
     {t  - 1, z  - 16z  + 256z  - 256, t y - 1,
        3            2
      (z  - 8z)x - 8z  + 16}
     ,
       2      2     2
    {3t  + 1,z  - 7t  - 1,y + t,x + z},
      2      2
    {t  + 3,z  - 4,y + t,x - z}]
Type: List RegularTriangularSet(Integer,IndexedExponents OrderedVariableList [x,y,z,t],OrderedVariableList [x,y,z,t],NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t]))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty24}
\begin{paste}{RegularTriangularSetXmpPageEmpty24}{RegularTriangularSetXmpPagePatch24}
\pastebutton{RegularTriangularSetXmpPageEmpty24}{\showpaste}
\tab{5}\spadcommand{lts2 := zeroSetSplit(lf,false)$T\free{lf }\free{T }\bound{lts2 }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch25}
\begin{paste}{RegularTriangularSetXmpPageFull25}{RegularTriangularSetXmpPageEmpty25}
\pastebutton{RegularTriangularSetXmpPageFull25}{\hidepaste}
\tab{5}\spadcommand{[coHeight(ts) for ts in lts2]\free{lts2 }}
\indentrel{3}\begin{verbatim}
   (25)  [0,0,0,0]
                          Type: List NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty25}
\begin{paste}{RegularTriangularSetXmpPageEmpty25}{RegularTriangularSetXmpPagePatch25}
\pastebutton{RegularTriangularSetXmpPageEmpty25}{\showpaste}
\tab{5}\spadcommand{[coHeight(ts) for ts in lts2]\free{lts2 }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch26}
\begin{paste}{RegularTriangularSetXmpPageFull26}{RegularTriangularSetXmpPageEmpty26}
\pastebutton{RegularTriangularSetXmpPageFull26}{\hidepaste}
\tab{5}\spadcommand{degrees := [degree(ts) for ts in lts2]\free{lts2 }\bound{degrees }}
\indentrel{3}\begin{verbatim}
   (26)  [8,16,4,4]
                          Type: List NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty26}
\begin{paste}{RegularTriangularSetXmpPageEmpty26}{RegularTriangularSetXmpPagePatch26}
\pastebutton{RegularTriangularSetXmpPageEmpty26}{\showpaste}
\tab{5}\spadcommand{degrees := [degree(ts) for ts in lts2]\free{lts2 }\bound{degrees }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch27}
\begin{paste}{RegularTriangularSetXmpPageFull27}{RegularTriangularSetXmpPageEmpty27}
\pastebutton{RegularTriangularSetXmpPageFull27}{\hidepaste}
\tab{5}\spadcommand{reduce(+,degrees)\free{degrees }}
\indentrel{3}\begin{verbatim}
   (27)  32
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty27}
\begin{paste}{RegularTriangularSetXmpPageEmpty27}{RegularTriangularSetXmpPagePatch27}
\pastebutton{RegularTriangularSetXmpPageEmpty27}{\showpaste}
\tab{5}\spadcommand{reduce(+,degrees)\free{degrees }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch28}
\begin{paste}{RegularTriangularSetXmpPageFull28}{RegularTriangularSetXmpPageEmpty28}
\pastebutton{RegularTriangularSetXmpPageFull28}{\hidepaste}
\tab{5}\spadcommand{u : R := 2\free{R }\bound{u }}
\indentrel{3}\begin{verbatim}
   (28)  2
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty28}
\begin{paste}{RegularTriangularSetXmpPageEmpty28}{RegularTriangularSetXmpPagePatch28}
\pastebutton{RegularTriangularSetXmpPageEmpty28}{\showpaste}
\tab{5}\spadcommand{u : R := 2\free{R }\bound{u }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch29}
\begin{paste}{RegularTriangularSetXmpPageFull29}{RegularTriangularSetXmpPageEmpty29}
\pastebutton{RegularTriangularSetXmpPageFull29}{\hidepaste}
\tab{5}\spadcommand{q1 := 2*(u-1)**2+ 2*(x-z*x+z**2)+ y**2*(x-1)**2- 2*u*x+ 2*y*t*(1-x)*(x-z)+ 2*u*z*t*(t-y)+ u**2*t**2*(1-2*z)+ 2*u*t**2*(z-x)+ 2*u*t*y*(z-1)+ 2*u*z*x*(y+1)+ (u**2-2*u)*z**2*t**2+ 2*u**2*z**2+ 4*u*(1-u)*z+ t**2*(z-x)**2\free{z }\free{x }\free{y }\free{t }\free{u }\bound{q1 }}
\indentrel{3}\begin{verbatim}
   (29)
       2           2  2
     (y  - 2t y + t )x
   + 
          2                            2           2
     (- 2y  + ((2t + 4)z + 2t)y + (- 2t  + 2)z - 4t  - 2)x
   + 
      2                      2       2          2
     y  + (- 2t z - 4t)y + (t  + 10)z  - 8z + 4t  + 2
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty29}
\begin{paste}{RegularTriangularSetXmpPageEmpty29}{RegularTriangularSetXmpPagePatch29}
\pastebutton{RegularTriangularSetXmpPageEmpty29}{\showpaste}
\tab{5}\spadcommand{q1 := 2*(u-1)**2+ 2*(x-z*x+z**2)+ y**2*(x-1)**2- 2*u*x+ 2*y*t*(1-x)*(x-z)+ 2*u*z*t*(t-y)+ u**2*t**2*(1-2*z)+ 2*u*t**2*(z-x)+ 2*u*t*y*(z-1)+ 2*u*z*x*(y+1)+ (u**2-2*u)*z**2*t**2+ 2*u**2*z**2+ 4*u*(1-u)*z+ t**2*(z-x)**2\free{z }\free{x }\free{y }\free{t }\free{u }\bound{q1 }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch30}
\begin{paste}{RegularTriangularSetXmpPageFull30}{RegularTriangularSetXmpPageEmpty30}
\pastebutton{RegularTriangularSetXmpPageFull30}{\hidepaste}
\tab{5}\spadcommand{q2 := t*(2*z+1)*(x-z)+ y*(z+2)*(1-x)+ u*(u-2)*t+ u*(1-2*u)*z*t+ u*y*(x+u-z*x-1)+ u*(u+1)*z**2*t\free{z }\free{x }\free{y }\free{t }\free{u }\bound{q2 }}
\indentrel{3}\begin{verbatim}
                                               2
   (30)  (- 3z y + 2t z + t)x + (z + 4)y + 4t z  - 7t z
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty30}
\begin{paste}{RegularTriangularSetXmpPageEmpty30}{RegularTriangularSetXmpPagePatch30}
\pastebutton{RegularTriangularSetXmpPageEmpty30}{\showpaste}
\tab{5}\spadcommand{q2 := t*(2*z+1)*(x-z)+ y*(z+2)*(1-x)+ u*(u-2)*t+ u*(1-2*u)*z*t+ u*y*(x+u-z*x-1)+ u*(u+1)*z**2*t\free{z }\free{x }\free{y }\free{t }\free{u }\bound{q2 }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch31}
\begin{paste}{RegularTriangularSetXmpPageFull31}{RegularTriangularSetXmpPageEmpty31}
\pastebutton{RegularTriangularSetXmpPageFull31}{\hidepaste}
\tab{5}\spadcommand{q3 := -u**2*(z-1)**2+ 2*z*(z-x)-2*(x-1)\free{z }\free{x }\free{y }\free{t }\free{u }\bound{q3 }}
\indentrel{3}\begin{verbatim}
                         2
   (31)  (- 2z - 2)x - 2z  + 8z - 2
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty31}
\begin{paste}{RegularTriangularSetXmpPageEmpty31}{RegularTriangularSetXmpPagePatch31}
\pastebutton{RegularTriangularSetXmpPageEmpty31}{\showpaste}
\tab{5}\spadcommand{q3 := -u**2*(z-1)**2+ 2*z*(z-x)-2*(x-1)\free{z }\free{x }\free{y }\free{t }\free{u }\bound{q3 }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch32}
\begin{paste}{RegularTriangularSetXmpPageFull32}{RegularTriangularSetXmpPageEmpty32}
\pastebutton{RegularTriangularSetXmpPageFull32}{\hidepaste}
\tab{5}\spadcommand{q4 := u**2+4*(z-x**2)+3*y**2*(x-1)**2- 3*t**2*(z-x)**2 +3*u**2*t**2*(z-1)**2+u**2*z*(z-2)+6*u*t*y*(z+x+z*x-1)\free{z }\free{x }\free{y }\free{t }\free{u }\bound{q4 }}
\indentrel{3}\begin{verbatim}
   (32)
        2     2      2        2                      2
     (3y  - 3t  - 4)x  + (- 6y  + (12t z + 12t)y + 6t z)x
   + 
       2                       2      2         2
     3y  + (12t z - 12t)y + (9t  + 4)z  + (- 24t  - 4)z
   + 
        2
     12t  + 4
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty32}
\begin{paste}{RegularTriangularSetXmpPageEmpty32}{RegularTriangularSetXmpPagePatch32}
\pastebutton{RegularTriangularSetXmpPageEmpty32}{\showpaste}
\tab{5}\spadcommand{q4 := u**2+4*(z-x**2)+3*y**2*(x-1)**2- 3*t**2*(z-x)**2 +3*u**2*t**2*(z-1)**2+u**2*z*(z-2)+6*u*t*y*(z+x+z*x-1)\free{z }\free{x }\free{y }\free{t }\free{u }\bound{q4 }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch33}
\begin{paste}{RegularTriangularSetXmpPageFull33}{RegularTriangularSetXmpPageEmpty33}
\pastebutton{RegularTriangularSetXmpPageFull33}{\hidepaste}
\tab{5}\spadcommand{lq := [q1, q2, q3, q4]\free{q1 }\free{q2 }\free{q3 }\free{q4 }\bound{lq }}
\indentrel{3}\begin{verbatim}
   (33)
   [
         2           2  2
       (y  - 2t y + t )x
     + 
               2                            2           2
           - 2y  + ((2t + 4)z + 2t)y + (- 2t  + 2)z - 4t
         + 
           - 2
      *
         x
     + 
        2                      2       2          2
       y  + (- 2t z - 4t)y + (t  + 10)z  - 8z + 4t  + 2
     ,
                                          2
    (- 3z y + 2t z + t)x + (z + 4)y + 4t z  - 7t z,
                    2
    (- 2z - 2)x - 2z  + 8z - 2,

          2     2      2
       (3y  - 3t  - 4)x
     + 
            2                      2        2
       (- 6y  + (12t z + 12t)y + 6t z)x + 3y
     + 
                           2      2         2            2
       (12t z - 12t)y + (9t  + 4)z  + (- 24t  - 4)z + 12t
     + 
       4
     ]
Type: List NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty33}
\begin{paste}{RegularTriangularSetXmpPageEmpty33}{RegularTriangularSetXmpPagePatch33}
\pastebutton{RegularTriangularSetXmpPageEmpty33}{\showpaste}
\tab{5}\spadcommand{lq := [q1, q2, q3, q4]\free{q1 }\free{q2 }\free{q3 }\free{q4 }\bound{lq }}
\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPagePatch34}
\begin{paste}{RegularTriangularSetXmpPageFull34}{RegularTriangularSetXmpPageEmpty34}
\pastebutton{RegularTriangularSetXmpPageFull34}{\hidepaste}
\tab{5}\spadcommand{zeroSetSplit(lq,true,true)$T\free{lq }\free{T }}
\indentrel{3}\begin{verbatim}

   *** QCMPACK Statistics ***
      Table     size:  36
      Entries reused:  255

   *** REGSETGCD: Gcd Statistics ***
      Table     size:  125
      Entries reused:  0

   *** REGSETGCD: Inv Set Statistics ***
      Table     size:  30
      Entries reused:  0
   (34)
   [
     {
                         24                   23
         960725655771966t   + 386820897948702t
       + 
                          22                    21
         8906817198608181t   + 2704966893949428t
       + 
                           20                    19
         37304033340228264t   + 7924782817170207t
       + 
                           18                     17
         93126799040354990t   + 13101273653130910t
       + 
                            16                     15
         156146250424711858t   + 16626490957259119t
       + 
                            14                     13
         190699288479805763t   + 24339173367625275t
       + 
                            12                     11
         180532313014960135t   + 35288089030975378t
       + 
                            10                     9
         135054975747656285t   + 34733736952488540t
       + 
                           8                     7
         75947600354493972t  + 19772555692457088t
       + 
                           6                    5
         28871558573755428t  + 5576152439081664t
       + 
                          4                   3
         6321711820352976t  + 438314209312320t
       + 
                       2
       581105748367008t  - 60254467992576t + 1449115951104
       ,

              266042108694913023855152657370520823616684_
               74181372891857784
            *
                23
               t
           + 
              443104378424686086067294899528296664238693_
               556855017735265295
            *
                22
               t
           + 
              279078393286701234679141342358988327155321_
               305829547090310242
            *
                21
               t
           + 
              339027636141323246510761717661554305462062_
               6391823613392185226
            *
                20
               t
           + 
              941478179503540575554198645220352803719793_
               196473813837434129
            *
                19
               t
           + 
              115478551946794752422116967496739493525857_
               47674184320988144390
            *
                18
               t
           + 
              134360956676559778988170165669941321646721_
               5660333356417241432
            *
                17
               t
           + 
              232338138681478735039335516171756408598991_
               02987800663566699334
            *
                16
               t
           + 
              869574020537672336950845440508790740850931_
               336484983573386433
            *
                15
               t
           + 
              315615543058769348754194614869699265542417_
               50065103460820476969
            *
                14
               t
           + 
              127140099028771748744206595254773187955482_
               3889855386072264931
            *
                13
               t
           + 
              319450899138637360448025269640795401983370_
               49550503295825160523
            *
                12
               t
           + 
              373873570428814450987137156023284588443910_
               2270778010470931960
            *
                11
               t
           + 
              252939975123914120261446014357711315875619_
               05532992045692885927
            *
                10
               t
           + 
              521023900984606712346926279987005277341047_
               1135950175008046524
            *
                9
               t
           + 
              150838879869302971662598705686082704274031_
               87606238713491129188
            *
                8
               t
           + 
              352208723469293012638368627077577955348176_
               9125670839075109000
            *
                7
               t
           + 
              607994520039568101308653379256888649110124_
               4247440034969288588
            *
                6
               t
           + 
              109063485243390088819991375624798602319698_
               7723469934933603680
            *
                5
               t
           + 
              140581943087190710229443253753833540210283_
               8994019667487458352
            *
                4
               t
           + 
              880715279503204500725366712655077488783478_
               28884933605202432
            *
                3
               t
           + 
              135882489433640933229781177155977768016065_
               765482378657129440
            *
                2
               t
           + 
             -
                 139572834428822622305598946074003140825_
                  16690749975646520320
               *
                  t
           + 
            33463769297318929927725832570930847259211711_
             2855749713920
        *
           z
       + 
          8567175484043952879756725964506833932149637101_
           090521164936
        *
            23
           t
       + 
          1497923928642017918457083740327289424987975192_
           51667250945721
        *
            22
           t
       + 
          7725837178364582215741086158215976413812300307_
           4190374021550
        *
            21
           t
       + 
          1108862254126854214498918940708612211184560556_
           764334742191654
        *
            20
           t
       + 
          2132504944606788652197744801068260537838157896_
           21501732672327
        *
            19
           t
       + 
          3668929075160666195729177894178343514501987898_
           410131431699882
        *
            18
           t
       + 
          1713889064710018728794901243687482363147654590_
           39567820048872
        *
            17
           t
       + 
          7192430746914602166660233477331022483144921771_
           645523139658986
        *
            16
           t
       + 
         -
             1287986746896900728128799656330902919596631_
              43108437362453385
           *
               15
              t
       + 
          9553010858341425909306423132921134040856028790_
           803526430270671
        *
            14
           t
       + 
         -
             1329609624567549287453868764630043782465845_
              8709144441096603
           *
               13
              t
       + 
          9475806805814145326383085518325333106881690568_
           644274964864413
        *
            12
           t
       + 
          8032346879251334588616598556640849276062987947_
           99856265539336
        *
            11
           t
       + 
          7338202759292865165994622349207516400662174302_
           614595173333825
        *
            10
           t
       + 
          1308004628480367351164369613111971668880538855_
           640917200187108
        *
            9
           t
       + 
          4268059455741255498880229598973705747098216067_
           697754352634748
        *
            8
           t
       + 
          8928935268585140957913187759040933001030456015_
           14470613580600
        *
            7
           t
       + 
          1679152575460683956631925852181341501981598137_
           465328797013652
        *
            6
           t
       + 
          2697574157679229803789671541433578355441131582_
           80591408043936
        *
            5
           t
       + 
          3809515278646575290335808298012827240813453726_
           80202920198224
        *
            4
           t
       + 
          1978554529422849503299882693760134113272503533_
           9452913286656
        *
            3
           t
       + 
          3647741205738478294236663530339663776330392817_
           4935079178528
        *
            2
           t
       + 
         -
             3722212879279038648713080422224976273210890_
              229485838670848
           *
              t
       + 
        890797248531143483612306344840138620247285999068_
         74105856
       ,
         3      2                  3       2
      (3z  - 11z  + 8z + 4)y + 2t z  + 4t z  - 5t z - t,
                  2
      (z + 1)x + z  - 4z + 1}
     ]
Type: List RegularTriangularSet(Integer,IndexedExponents OrderedVariableList [x,y,z,t],OrderedVariableList [x,y,z,t],NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t]))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RegularTriangularSetXmpPageEmpty34}
\begin{paste}{RegularTriangularSetXmpPageEmpty34}{RegularTriangularSetXmpPagePatch34}
\pastebutton{RegularTriangularSetXmpPageEmpty34}{\showpaste}
\tab{5}\spadcommand{zeroSetSplit(lq,true,true)$T\free{lq }\free{T }}
\end{paste}\end{patch}

\end{chunk}
\section{roman.ht}
\pagetitle{RomanNumeralXmpPage}{roman.ht}{RomanNumeral}
\pagepic{ps/v71romannumeralxmppage.eps}{RomanNumeralXmpPage}{0.50}
\pagefrom{Axiom Number Types}{NumberPage}
\begin{chunk}{roman.ht}
\begin{page}{RomanNumeralXmpPage}{RomanNumeral}
\beginscroll
The Roman numeral package was added to Axiom in MCMLXXXVI
for use in denoting higher order derivatives.

\xtc{
For example, let \spad{f} be a symbolic operator.
}{
\spadpaste{f := operator 'f \bound{f}}
}
\xtc{
This is the seventh derivative of \spad{f} with respect to \spad{x}.
}{
\spadpaste{D(f x,x,7) \free{f}}
}
\xtc{
You can have integers printed as Roman numerals by declaring variables to
be of type \spadtype{RomanNumeral} (abbreviation \spadtype{ROMAN}).
}{
\spadpaste{a := roman(1978 - 1965) \bound{a}}
}

This package now has a small but devoted group of followers that claim
this domain has shown its efficacy in many other contexts.
They claim that Roman numerals are every bit as useful as ordinary
integers.
\xtc{
In a sense, they are correct, because Roman numerals form a ring and you
can therefore construct polynomials with Roman numeral coefficients,
matrices over Roman numerals, etc..
}{
\spadpaste{x : UTS(ROMAN,'x,0) := x \bound{x}}
}
\xtc{
Was Fibonacci Italian or ROMAN?
}{
\spadpaste{recip(1 - x - x**2) \free{x}}
}
\xtc{
You can also construct fractions with Roman numeral numerators and
denominators, as this matrix Hilberticus illustrates.
}{
\spadpaste{m : MATRIX FRAC ROMAN \bound{m}}
}
\xtc{
}{
\spadpaste{m := matrix [[1/(i + j) for i in 1..3] for j in 1..3] 
\free{m} \bound{m1}}
}
\xtc{
Note that the inverse of the matrix has integral \spadtype{ROMAN} 
entries.
}{
\spadpaste{inverse m \free{m1}}
}
\xtc{
Unfortunately, the spoil-sports say that the fun stops when
the numbers get big---mostly
because the Romans didn't establish conventions about representing
very large numbers.
}{
\spadpaste{y := factorial 10 \bound{y}}
}
\xtc{
You work it out!
}{
\spadpaste{roman y \free{y}}
}
Issue the system command
\spadcmd{)show RomanNumeral}
to display the full list of operations defined by
\spadtype{RomanNumeral}.
\endscroll
\autobuttons
\end{page}

\begin{patch}{RomanNumeralXmpPagePatch1}
\begin{paste}{RomanNumeralXmpPageFull1}{RomanNumeralXmpPageEmpty1}
\pastebutton{RomanNumeralXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{f := operator 'f\bound{f }}
\indentrel{3}\begin{verbatim}
   (1)  f
                                    Type: BasicOperator
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RomanNumeralXmpPageEmpty1}
\begin{paste}{RomanNumeralXmpPageEmpty1}{RomanNumeralXmpPagePatch1}
\pastebutton{RomanNumeralXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{f := operator 'f\bound{f }}
\end{paste}\end{patch}

\begin{patch}{RomanNumeralXmpPagePatch2}
\begin{paste}{RomanNumeralXmpPageFull2}{RomanNumeralXmpPageEmpty2}
\pastebutton{RomanNumeralXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{D(f x,x,7)\free{f }}
\indentrel{3}\begin{verbatim}
         (vii)
   (2)  f     (x)

                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RomanNumeralXmpPageEmpty2}
\begin{paste}{RomanNumeralXmpPageEmpty2}{RomanNumeralXmpPagePatch2}
\pastebutton{RomanNumeralXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{D(f x,x,7)\free{f }}
\end{paste}\end{patch}

\begin{patch}{RomanNumeralXmpPagePatch3}
\begin{paste}{RomanNumeralXmpPageFull3}{RomanNumeralXmpPageEmpty3}
\pastebutton{RomanNumeralXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{a := roman(1978 - 1965)\bound{a }}
\indentrel{3}\begin{verbatim}
   (3)  XIII
                                     Type: RomanNumeral
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RomanNumeralXmpPageEmpty3}
\begin{paste}{RomanNumeralXmpPageEmpty3}{RomanNumeralXmpPagePatch3}
\pastebutton{RomanNumeralXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{a := roman(1978 - 1965)\bound{a }}
\end{paste}\end{patch}

\begin{patch}{RomanNumeralXmpPagePatch4}
\begin{paste}{RomanNumeralXmpPageFull4}{RomanNumeralXmpPageEmpty4}
\pastebutton{RomanNumeralXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{x : UTS(ROMAN,'x,0) := x\bound{x }}
\indentrel{3}\begin{verbatim}
   (4)  x
         Type: UnivariateTaylorSeries(RomanNumeral,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RomanNumeralXmpPageEmpty4}
\begin{paste}{RomanNumeralXmpPageEmpty4}{RomanNumeralXmpPagePatch4}
\pastebutton{RomanNumeralXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{x : UTS(ROMAN,'x,0) := x\bound{x }}
\end{paste}\end{patch}

\begin{patch}{RomanNumeralXmpPagePatch5}
\begin{paste}{RomanNumeralXmpPageFull5}{RomanNumeralXmpPageEmpty5}
\pastebutton{RomanNumeralXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{recip(1 - x - x**2)\free{x }}
\indentrel{3}\begin{verbatim}
   (5)
                 2        3      4         5         6
     I + x + II x  + III x  + V x  + VIII x  + XIII x
   + 
          7          8       9           10      11
     XXI x  + XXXIV x  + LV x  + LXXXIX x   + O(x  )
Type: Union(UnivariateTaylorSeries(RomanNumeral,x,0),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RomanNumeralXmpPageEmpty5}
\begin{paste}{RomanNumeralXmpPageEmpty5}{RomanNumeralXmpPagePatch5}
\pastebutton{RomanNumeralXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{recip(1 - x - x**2)\free{x }}
\end{paste}\end{patch}

\begin{patch}{RomanNumeralXmpPagePatch6}
\begin{paste}{RomanNumeralXmpPageFull6}{RomanNumeralXmpPageEmpty6}
\pastebutton{RomanNumeralXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{m : MATRIX FRAC ROMAN\bound{m }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RomanNumeralXmpPageEmpty6}
\begin{paste}{RomanNumeralXmpPageEmpty6}{RomanNumeralXmpPagePatch6}
\pastebutton{RomanNumeralXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{m : MATRIX FRAC ROMAN\bound{m }}
\end{paste}\end{patch}

\begin{patch}{RomanNumeralXmpPagePatch7}
\begin{paste}{RomanNumeralXmpPageFull7}{RomanNumeralXmpPageEmpty7}
\pastebutton{RomanNumeralXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{m := matrix [[1/(i + j) for i in 1..3] for j in 1..3]\free{m }\bound{m1 }}
\indentrel{3}\begin{verbatim}
        Ú I    I    I¿
        ³ÄÄ   ÄÄÄ  ÄÄ³
        ³II   III  IV³
        ³            ³
        ³ I    I   I ³
   (7)  ³ÄÄÄ  ÄÄ   Ä ³
        ³III  IV   V ³
        ³            ³
        ³ I    I    I³
        ³ÄÄ    Ä   ÄÄ³
        ÀIV    V   VIÙ
                     Type: Matrix Fraction RomanNumeral
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RomanNumeralXmpPageEmpty7}
\begin{paste}{RomanNumeralXmpPageEmpty7}{RomanNumeralXmpPagePatch7}
\pastebutton{RomanNumeralXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{m := matrix [[1/(i + j) for i in 1..3] for j in 1..3]\free{m }\bound{m1 }}
\end{paste}\end{patch}

\begin{patch}{RomanNumeralXmpPagePatch8}
\begin{paste}{RomanNumeralXmpPageFull8}{RomanNumeralXmpPageEmpty8}
\pastebutton{RomanNumeralXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{inverse m\free{m1 }}
\indentrel{3}\begin{verbatim}
        ÚLXXII   - CCXL    CLXXX ¿
        ³                        ³
   (8)  ³- CCXL    CM     - DCCXX³
        ³                        ³
        ÀCLXXX   - DCCXX    DC   Ù
          Type: Union(Matrix Fraction RomanNumeral,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RomanNumeralXmpPageEmpty8}
\begin{paste}{RomanNumeralXmpPageEmpty8}{RomanNumeralXmpPagePatch8}
\pastebutton{RomanNumeralXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{inverse m\free{m1 }}
\end{paste}\end{patch}

\begin{patch}{RomanNumeralXmpPagePatch9}
\begin{paste}{RomanNumeralXmpPageFull9}{RomanNumeralXmpPageEmpty9}
\pastebutton{RomanNumeralXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{y := factorial 10\bound{y }}
\indentrel{3}\begin{verbatim}
   (9)  3628800
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RomanNumeralXmpPageEmpty9}
\begin{paste}{RomanNumeralXmpPageEmpty9}{RomanNumeralXmpPagePatch9}
\pastebutton{RomanNumeralXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{y := factorial 10\bound{y }}
\end{paste}\end{patch}

\begin{patch}{RomanNumeralXmpPagePatch10}
\begin{paste}{RomanNumeralXmpPageFull10}{RomanNumeralXmpPageEmpty10}
\pastebutton{RomanNumeralXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{roman y\free{y }}
\indentrel{3}\begin{verbatim}
   (10)
  ((((I))))((((I))))((((I)))) (((I)))(((I)))(((I)))(((I))
  )(((I)))(((I))) ((I))((I)) MMMMMMMMDCCC
                                     Type: RomanNumeral
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{RomanNumeralXmpPageEmpty10}
\begin{paste}{RomanNumeralXmpPageEmpty10}{RomanNumeralXmpPagePatch10}
\pastebutton{RomanNumeralXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{roman y\free{y }}
\end{paste}\end{patch}

\end{chunk}
\section{seg.ht}
\pagetitle{SegmentXmpPage}{seg.ht}{Segment}
\pageto{notitle}{SegmentBindingXmpPage}
\pageto{notitle}{UniversalSegmentXmpPage}
\begin{chunk}{seg.ht}
\begin{page}{SegmentXmpPage}{Segment}
\beginscroll

The \spadtype{Segment} domain provides a generalized interval type.

\labelSpace{2pc}
\xtc{
Segments are created using the \spadSyntax{..} construct
by indicating the (included) end points.
}{
\spadpaste{s := 3..10 \bound{s}}
}
\xtc{
The first end point is called the \spadfunFrom{lo}{Segment}
and the second is called \spadfunFrom{hi}{Segment}.
}{
\spadpaste{lo s \free{s}}
}
\xtc{
These names are used even though the end points might belong to an
unordered set.
}{
\spadpaste{hi s \free{s}}
}

\xtc{
In addition to the end points, each segment has an integer ``increment.''
An increment can be specified using the ``\spad{by}'' construct.
\spadkey{by}
}{
\spadpaste{t := 10..3 by -2 \bound{t}}
}
\xtc{
This part can be obtained using the \spadfunFrom{incr}{Segment} 
function.
}{
\spadpaste{incr s \free{s}}
}
\xtc{
Unless otherwise specified, the increment is \spad{1}.
}{
\spadpaste{incr t \free{t}}
}

\xtc{
A single value can be converted to a segment with equal end points.
This happens if segments and single values are mixed in a list.
}{
\spadpaste{l := [1..3, 5, 9, 15..11 by -1] \bound{l}}
}

\xtc{
If the underlying type is an ordered ring, it is possible to perform
additional operations.
The \spadfunFrom{expand}{Segment} operation creates a list of
points in a segment.
}{
\spadpaste{expand s \free{s}}
}
\xtc{
If \spad{k > 0}, then \spad{expand(l..h by k)} creates the list
\spad{[l, l+k, ..., lN]} where \spad{lN <= h < lN+k}.
If \spad{k < 0}, then \spad{lN >= h > lN+k}.
}{
\spadpaste{expand t \free{t}}
}

\xtc{
It is also possible to expand a list of segments.  This is equivalent
to appending lists obtained by expanding each segment individually.
}{
\spadpaste{expand l \free{l}}
}

For more information on related topics, see
\downlink{`SegmentBinding'}{SegmentBindingXmpPage}\ignore{SegmentBinding} 
and \downlink{`UniversalSegment'}{UniversalSegmentXmpPage}
\ignore{UniversalSegment}.
%
\showBlurb{Segment}
\endscroll
\autobuttons
\end{page}

\begin{patch}{SegmentXmpPagePatch1}
\begin{paste}{SegmentXmpPageFull1}{SegmentXmpPageEmpty1}
\pastebutton{SegmentXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{s := 3..10\bound{s }}
\indentrel{3}\begin{verbatim}
   (1)  3..10
                          Type: Segment PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SegmentXmpPageEmpty1}
\begin{paste}{SegmentXmpPageEmpty1}{SegmentXmpPagePatch1}
\pastebutton{SegmentXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{s := 3..10\bound{s }}
\end{paste}\end{patch}

\begin{patch}{SegmentXmpPagePatch2}
\begin{paste}{SegmentXmpPageFull2}{SegmentXmpPageEmpty2}
\pastebutton{SegmentXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{lo s\free{s }}
\indentrel{3}\begin{verbatim}
   (2)  3
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SegmentXmpPageEmpty2}
\begin{paste}{SegmentXmpPageEmpty2}{SegmentXmpPagePatch2}
\pastebutton{SegmentXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{lo s\free{s }}
\end{paste}\end{patch}

\begin{patch}{SegmentXmpPagePatch3}
\begin{paste}{SegmentXmpPageFull3}{SegmentXmpPageEmpty3}
\pastebutton{SegmentXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{hi s\free{s }}
\indentrel{3}\begin{verbatim}
   (3)  10
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SegmentXmpPageEmpty3}
\begin{paste}{SegmentXmpPageEmpty3}{SegmentXmpPagePatch3}
\pastebutton{SegmentXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{hi s\free{s }}
\end{paste}\end{patch}

\begin{patch}{SegmentXmpPagePatch4}
\begin{paste}{SegmentXmpPageFull4}{SegmentXmpPageEmpty4}
\pastebutton{SegmentXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{t := 10..3 by -2\bound{t }}
\indentrel{3}\begin{verbatim}
   (4)  10..3 by - 2
                          Type: Segment PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SegmentXmpPageEmpty4}
\begin{paste}{SegmentXmpPageEmpty4}{SegmentXmpPagePatch4}
\pastebutton{SegmentXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{t := 10..3 by -2\bound{t }}
\end{paste}\end{patch}

\begin{patch}{SegmentXmpPagePatch5}
\begin{paste}{SegmentXmpPageFull5}{SegmentXmpPageEmpty5}
\pastebutton{SegmentXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{incr s\free{s }}
\indentrel{3}\begin{verbatim}
   (5)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SegmentXmpPageEmpty5}
\begin{paste}{SegmentXmpPageEmpty5}{SegmentXmpPagePatch5}
\pastebutton{SegmentXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{incr s\free{s }}
\end{paste}\end{patch}

\begin{patch}{SegmentXmpPagePatch6}
\begin{paste}{SegmentXmpPageFull6}{SegmentXmpPageEmpty6}
\pastebutton{SegmentXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{incr t\free{t }}
\indentrel{3}\begin{verbatim}
   (6)  - 2
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SegmentXmpPageEmpty6}
\begin{paste}{SegmentXmpPageEmpty6}{SegmentXmpPagePatch6}
\pastebutton{SegmentXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{incr t\free{t }}
\end{paste}\end{patch}

\begin{patch}{SegmentXmpPagePatch7}
\begin{paste}{SegmentXmpPageFull7}{SegmentXmpPageEmpty7}
\pastebutton{SegmentXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{l := [1..3, 5, 9, 15..11 by -1]\bound{l }}
\indentrel{3}\begin{verbatim}
   (7)  [1..3,5..5,9..9,15..11 by - 1]
                     Type: List Segment PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SegmentXmpPageEmpty7}
\begin{paste}{SegmentXmpPageEmpty7}{SegmentXmpPagePatch7}
\pastebutton{SegmentXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{l := [1..3, 5, 9, 15..11 by -1]\bound{l }}
\end{paste}\end{patch}

\begin{patch}{SegmentXmpPagePatch8}
\begin{paste}{SegmentXmpPageFull8}{SegmentXmpPageEmpty8}
\pastebutton{SegmentXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{expand s\free{s }}
\indentrel{3}\begin{verbatim}
   (8)  [3,4,5,6,7,8,9,10]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SegmentXmpPageEmpty8}
\begin{paste}{SegmentXmpPageEmpty8}{SegmentXmpPagePatch8}
\pastebutton{SegmentXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{expand s\free{s }}
\end{paste}\end{patch}

\begin{patch}{SegmentXmpPagePatch9}
\begin{paste}{SegmentXmpPageFull9}{SegmentXmpPageEmpty9}
\pastebutton{SegmentXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{expand t\free{t }}
\indentrel{3}\begin{verbatim}
   (9)  [10,8,6,4]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SegmentXmpPageEmpty9}
\begin{paste}{SegmentXmpPageEmpty9}{SegmentXmpPagePatch9}
\pastebutton{SegmentXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{expand t\free{t }}
\end{paste}\end{patch}

\begin{patch}{SegmentXmpPagePatch10}
\begin{paste}{SegmentXmpPageFull10}{SegmentXmpPageEmpty10}
\pastebutton{SegmentXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{expand l\free{l }}
\indentrel{3}\begin{verbatim}
   (10)  [1,2,3,5,9,15,14,13,12,11]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SegmentXmpPageEmpty10}
\begin{paste}{SegmentXmpPageEmpty10}{SegmentXmpPagePatch10}
\pastebutton{SegmentXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{expand l\free{l }}
\end{paste}\end{patch}

\end{chunk}
\section{segbind.ht}
\pagetitle{SegmentBindingXmpPage}{segbind.ht}{SegmentBinding}
\pageto{notitle}{SegmentXmpPage}
\pageto{notitle}{UniversalSegmentXmpPage}
\begin{chunk}{segbind.ht}
\begin{page}{SegmentBindingXmpPage}{SegmentBinding}
\beginscroll

The \spadtype{SegmentBinding} type is used
to indicate a range for a named symbol.

\labelSpace{2pc}
\xtc{
First give the symbol, then an \spadSyntax{=} and finally a
segment of values.
}{
\spadpaste{x = a..b}
}
\xtc{
This is used to provide a convenient
syntax for arguments to certain operations.
}{
\spadpaste{sum(i**2, i = 0..n)}
}
\graphpaste{draw(x**2, x = -2..2)}

\xtc{
The left-hand side must be of type \spadtype{Symbol} but the
right-hand side can be a segment over any type.
}{
\spadpaste{sb := y = 1/2..3/2 \bound{sb}}
}
\xtc{
The left- and right-hand sides can be obtained using the
\spadfunFrom{variable}{SegmentBinding} and
\spadfunFrom{segment}{SegmentBinding} operations.
}{
\spadpaste{variable(sb) \free{sb}}
}
\xtc{
}{
\spadpaste{segment(sb)  \free{sb}}
}

For more information on related topics, see
\downlink{`Segment'}{SegmentXmpPage}\ignore{Segment} and 
\downlink{`UniversalSegment'}{UniversalSegmentXmpPage}
\ignore{UniversalSegment}.
%
\showBlurb{SegmentBinding}
\endscroll
\autobuttons
\end{page}

\begin{patch}{SegmentBindingXmpPagePatch1}
\begin{paste}{SegmentBindingXmpPageFull1}{SegmentBindingXmpPageEmpty1}
\pastebutton{SegmentBindingXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{x = a..b}
\indentrel{3}\begin{verbatim}
   (1)  x= a..b
                            Type: SegmentBinding Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SegmentBindingXmpPageEmpty1}
\begin{paste}{SegmentBindingXmpPageEmpty1}{SegmentBindingXmpPagePatch1}
\pastebutton{SegmentBindingXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{x = a..b}
\end{paste}\end{patch}

\begin{patch}{SegmentBindingXmpPagePatch2}
\begin{paste}{SegmentBindingXmpPageFull2}{SegmentBindingXmpPageEmpty2}
\pastebutton{SegmentBindingXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{sum(i**2, i = 0..n)}
\indentrel{3}\begin{verbatim}
          3     2
        2n  + 3n  + n
   (2)  ÄÄÄÄÄÄÄÄÄÄÄÄÄ
              6
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SegmentBindingXmpPageEmpty2}
\begin{paste}{SegmentBindingXmpPageEmpty2}{SegmentBindingXmpPagePatch2}
\pastebutton{SegmentBindingXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{sum(i**2, i = 0..n)}
\end{paste}\end{patch}

\begin{patch}{SegmentBindingXmpPagePatch3}
\begin{paste}{SegmentBindingXmpPageFull3}{SegmentBindingXmpPageEmpty3}
\pastebutton{SegmentBindingXmpPageFull3}{\hidepaste}
\tab{5}\spadgraph{draw(x**2, x = -2..2)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/segmentbindingxmppage3.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/segmentbindingxmppage3}}
\end{paste}\end{patch}

\begin{patch}{SegmentBindingXmpPageEmpty3}
\begin{paste}{SegmentBindingXmpPageEmpty3}{SegmentBindingXmpPagePatch3}
\pastebutton{SegmentBindingXmpPageEmpty3}{\showpaste}
\tab{5}\spadgraph{draw(x**2, x = -2..2)}
\end{paste}\end{patch}

\begin{patch}{SegmentBindingXmpPagePatch4}
\begin{paste}{SegmentBindingXmpPageFull4}{SegmentBindingXmpPageEmpty4}
\pastebutton{SegmentBindingXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{sb := y = 1/2..3/2\bound{sb }}
\indentrel{3}\begin{verbatim}
            1    3
   (4)  y= (Ä)..(Ä)
            2    2
                  Type: SegmentBinding Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SegmentBindingXmpPageEmpty4}
\begin{paste}{SegmentBindingXmpPageEmpty4}{SegmentBindingXmpPagePatch4}
\pastebutton{SegmentBindingXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{sb := y = 1/2..3/2\bound{sb }}
\end{paste}\end{patch}

\begin{patch}{SegmentBindingXmpPagePatch5}
\begin{paste}{SegmentBindingXmpPageFull5}{SegmentBindingXmpPageEmpty5}
\pastebutton{SegmentBindingXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{variable(sb)\free{sb }}
\indentrel{3}\begin{verbatim}
   (5)  y
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SegmentBindingXmpPageEmpty5}
\begin{paste}{SegmentBindingXmpPageEmpty5}{SegmentBindingXmpPagePatch5}
\pastebutton{SegmentBindingXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{variable(sb)\free{sb }}
\end{paste}\end{patch}

\begin{patch}{SegmentBindingXmpPagePatch6}
\begin{paste}{SegmentBindingXmpPageFull6}{SegmentBindingXmpPageEmpty6}
\pastebutton{SegmentBindingXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{segment(sb)\free{sb }}
\indentrel{3}\begin{verbatim}
         1    3
   (6)  (Ä)..(Ä)
         2    2
                         Type: Segment Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SegmentBindingXmpPageEmpty6}
\begin{paste}{SegmentBindingXmpPageEmpty6}{SegmentBindingXmpPagePatch6}
\pastebutton{SegmentBindingXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{segment(sb)\free{sb }}
\end{paste}\end{patch}

\end{chunk}
\section{set.ht}
\pagetitle{SetXmpPage}{page.ht}{Set}
\pageto{notitle}{ListXmpPage}
\begin{chunk}{set.ht}
\begin{page}{SetXmpPage}{Set}
\beginscroll

The \spadtype{Set} domain allows one to represent explicit finite 
sets of values.
These are similar to lists, but duplicate elements are not allowed.
\xtc{
Sets can be created by giving a fixed set of values \ldots
}{
\spadpaste{s := set [x**2-1, y**2-1, z**2-1] \bound{s}}
}
\xtc{
or by using a collect form, just as for lists.
In either case, the set is formed from a finite collection of values.
}{
\spadpaste{t := set [x**i - i+1 for i in 2..10 | prime? i] \bound{t}}
}

\xtc{
The basic operations on sets are
\spadfunFrom{intersect}{Set}, \spadfunFrom{union}{Set},
\spadfunFrom{difference}{Set},
and \spadfunFrom{symmetricDifference}{Set}.
}{
\spadpaste{i := intersect(s,t)      \free{s t}\bound{i}}
}
\xtc{
}{
\spadpaste{u := union(s,t)          \free{s t}\bound{u}}
}
\xtc{
The set \spad{difference(s,t)} contains those members of \spad{s} which
are not in \spad{t}.
}{
\spadpaste{difference(s,t)          \free{s t}}
}
\xtc{
The set \spad{symmetricDifference(s,t)} contains those elements which are
in \spad{s} or \spad{t} but not in both.
}{
\spadpaste{symmetricDifference(s,t)          \free{s t}}
}

\xtc{
Set membership is tested using the \spadfunFrom{member?}{Set} operation.
}{
\spadpaste{member?(y, s)               \free{s}}
}
\xtc{
}{
\spadpaste{member?((y+1)*(y-1), s)     \free{s}}
}
\xtc{
The \spadfunFrom{subset?}{Set} function determines whether one set 
is a subset of another.
}{
\spadpaste{subset?(i, s)               \free{i s}}
}
\xtc{
}{
\spadpaste{subset?(u, s)               \free{u s}}
}

\xtc{
When the base type is finite, the absolute complement of a set is
defined.
This finds the set of all multiplicative generators of
\spadtype{PrimeField 11}---the integers mod \spad{11.}
}{
\spadpaste{gs := set [g for i in 1..11 | primitive?(g := i::PF 11)] 
\bound{gs}}
}
\xtc{
The following values are not generators.
}{
\spadpaste{complement gs \free{gs}}
}

Often the members of a set are computed individually; in addition,
values can be inserted or removed from a set over the course of a
computation.
\xtc{
There are two ways to do this:
}{
\spadpaste{a := set [i**2 for i in 1..5] \bound{a}}
}
\xtc{
One is to view a set as a data structure and to apply updating 
operations.
}{
\spadpaste{insert!(32, a) \free{a}\bound{ainsert}}
}
\xtc{
}{
\spadpaste{remove!(25, a) \free{a}\bound{aremove}}
}
\xtc{
}{
\spadpaste{a \free{aremove ainsert}}
}
\xtc{
The other way is to view a set as a mathematical entity and to
create new sets from old.
}{
\spadpaste{b := b0 := set [i**2 for i in 1..5] \bound{b}}
}
\xtc{
}{
\spadpaste{b := union(b, {32})         \free{b}\bound{binsert}}
}
\xtc{
}{
\spadpaste{b := difference(b, {25})    \free{binsert}\bound{bremove}}
}
\xtc{
}{
\spadpaste{b0 \free{bremove}}
}

For more information about lists, see 
\downlink{`List'}{ListXmpPage}\ignore{List}.
\showBlurb{Set}
\endscroll
\autobuttons
\end{page}

\begin{patch}{SetXmpPagePatch1}
\begin{paste}{SetXmpPageFull1}{SetXmpPageEmpty1}
\pastebutton{SetXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{s := set [x**2-1, y**2-1, z**2-1]\bound{s }}
\indentrel{3}\begin{verbatim}
          2      2      2
   (1)  {x  - 1,y  - 1,z  - 1}
                           Type: Set Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SetXmpPageEmpty1}
\begin{paste}{SetXmpPageEmpty1}{SetXmpPagePatch1}
\pastebutton{SetXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{s := set [x**2-1, y**2-1, z**2-1]\bound{s }}
\end{paste}\end{patch}

\begin{patch}{SetXmpPagePatch2}
\begin{paste}{SetXmpPageFull2}{SetXmpPageEmpty2}
\pastebutton{SetXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{t := set [x**i - i+1 for i in 2..10 | prime? i]\bound{t }}
\indentrel{3}\begin{verbatim}
          2      3      5      7
   (2)  {x  - 1,x  - 2,x  - 4,x  - 6}
                           Type: Set Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SetXmpPageEmpty2}
\begin{paste}{SetXmpPageEmpty2}{SetXmpPagePatch2}
\pastebutton{SetXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{t := set [x**i - i+1 for i in 2..10 | prime? i]\bound{t }}
\end{paste}\end{patch}

\begin{patch}{SetXmpPagePatch3}
\begin{paste}{SetXmpPageFull3}{SetXmpPageEmpty3}
\pastebutton{SetXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{i := intersect(s,t)\free{s t }\bound{i }}
\indentrel{3}\begin{verbatim}
          2
   (3)  {x  - 1}
                           Type: Set Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SetXmpPageEmpty3}
\begin{paste}{SetXmpPageEmpty3}{SetXmpPagePatch3}
\pastebutton{SetXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{i := intersect(s,t)\free{s t }\bound{i }}
\end{paste}\end{patch}

\begin{patch}{SetXmpPagePatch4}
\begin{paste}{SetXmpPageFull4}{SetXmpPageEmpty4}
\pastebutton{SetXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{u := union(s,t)\free{s t }\bound{u }}
\indentrel{3}\begin{verbatim}
          2      3      5      7      2      2
   (4)  {x  - 1,x  - 2,x  - 4,x  - 6,y  - 1,z  - 1}
                           Type: Set Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SetXmpPageEmpty4}
\begin{paste}{SetXmpPageEmpty4}{SetXmpPagePatch4}
\pastebutton{SetXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{u := union(s,t)\free{s t }\bound{u }}
\end{paste}\end{patch}

\begin{patch}{SetXmpPagePatch5}
\begin{paste}{SetXmpPageFull5}{SetXmpPageEmpty5}
\pastebutton{SetXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{difference(s,t)\free{s t }}
\indentrel{3}\begin{verbatim}
          2      2
   (5)  {y  - 1,z  - 1}
                           Type: Set Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SetXmpPageEmpty5}
\begin{paste}{SetXmpPageEmpty5}{SetXmpPagePatch5}
\pastebutton{SetXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{difference(s,t)\free{s t }}
\end{paste}\end{patch}

\begin{patch}{SetXmpPagePatch6}
\begin{paste}{SetXmpPageFull6}{SetXmpPageEmpty6}
\pastebutton{SetXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{symmetricDifference(s,t)\free{s t }}
\indentrel{3}\begin{verbatim}
          3      5      7      2      2
   (6)  {x  - 2,x  - 4,x  - 6,y  - 1,z  - 1}
                           Type: Set Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SetXmpPageEmpty6}
\begin{paste}{SetXmpPageEmpty6}{SetXmpPagePatch6}
\pastebutton{SetXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{symmetricDifference(s,t)\free{s t }}
\end{paste}\end{patch}

\begin{patch}{SetXmpPagePatch7}
\begin{paste}{SetXmpPageFull7}{SetXmpPageEmpty7}
\pastebutton{SetXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{member?(y, s)\free{s }}
\indentrel{3}\begin{verbatim}
   (7)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SetXmpPageEmpty7}
\begin{paste}{SetXmpPageEmpty7}{SetXmpPagePatch7}
\pastebutton{SetXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{member?(y, s)\free{s }}
\end{paste}\end{patch}

\begin{patch}{SetXmpPagePatch8}
\begin{paste}{SetXmpPageFull8}{SetXmpPageEmpty8}
\pastebutton{SetXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{member?((y+1)*(y-1), s)\free{s }}
\indentrel{3}\begin{verbatim}
   (8)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SetXmpPageEmpty8}
\begin{paste}{SetXmpPageEmpty8}{SetXmpPagePatch8}
\pastebutton{SetXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{member?((y+1)*(y-1), s)\free{s }}
\end{paste}\end{patch}

\begin{patch}{SetXmpPagePatch9}
\begin{paste}{SetXmpPageFull9}{SetXmpPageEmpty9}
\pastebutton{SetXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{subset?(i, s)\free{i s }}
\indentrel{3}\begin{verbatim}
   (9)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SetXmpPageEmpty9}
\begin{paste}{SetXmpPageEmpty9}{SetXmpPagePatch9}
\pastebutton{SetXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{subset?(i, s)\free{i s }}
\end{paste}\end{patch}

\begin{patch}{SetXmpPagePatch10}
\begin{paste}{SetXmpPageFull10}{SetXmpPageEmpty10}
\pastebutton{SetXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{subset?(u, s)\free{u s }}
\indentrel{3}\begin{verbatim}
   (10)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SetXmpPageEmpty10}
\begin{paste}{SetXmpPageEmpty10}{SetXmpPagePatch10}
\pastebutton{SetXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{subset?(u, s)\free{u s }}
\end{paste}\end{patch}

\begin{patch}{SetXmpPagePatch11}
\begin{paste}{SetXmpPageFull11}{SetXmpPageEmpty11}
\pastebutton{SetXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{gs := set [g for i in 1..11 | primitive?(g := i::PF 11)]\bound{gs }}
\indentrel{3}\begin{verbatim}
   (11)  {2,6,7,8}
                                Type: Set PrimeField 11
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SetXmpPageEmpty11}
\begin{paste}{SetXmpPageEmpty11}{SetXmpPagePatch11}
\pastebutton{SetXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{gs := set [g for i in 1..11 | primitive?(g := i::PF 11)]\bound{gs }}
\end{paste}\end{patch}

\begin{patch}{SetXmpPagePatch12}
\begin{paste}{SetXmpPageFull12}{SetXmpPageEmpty12}
\pastebutton{SetXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{complement gs\free{gs }}
\indentrel{3}\begin{verbatim}
   (12)  {1,3,4,5,9,10,0}
                                Type: Set PrimeField 11
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SetXmpPageEmpty12}
\begin{paste}{SetXmpPageEmpty12}{SetXmpPagePatch12}
\pastebutton{SetXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{complement gs\free{gs }}
\end{paste}\end{patch}

\begin{patch}{SetXmpPagePatch13}
\begin{paste}{SetXmpPageFull13}{SetXmpPageEmpty13}
\pastebutton{SetXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{a := set [i**2 for i in 1..5]\bound{a }}
\indentrel{3}\begin{verbatim}
   (13)  {1,4,9,16,25}
                              Type: Set PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SetXmpPageEmpty13}
\begin{paste}{SetXmpPageEmpty13}{SetXmpPagePatch13}
\pastebutton{SetXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{a := set [i**2 for i in 1..5]\bound{a }}
\end{paste}\end{patch}

\begin{patch}{SetXmpPagePatch14}
\begin{paste}{SetXmpPageFull14}{SetXmpPageEmpty14}
\pastebutton{SetXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{insert!(32, a)\free{a }\bound{ainsert }}
\indentrel{3}\begin{verbatim}
   (14)  {1,4,9,16,25,32}
                              Type: Set PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SetXmpPageEmpty14}
\begin{paste}{SetXmpPageEmpty14}{SetXmpPagePatch14}
\pastebutton{SetXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{insert!(32, a)\free{a }\bound{ainsert }}
\end{paste}\end{patch}

\begin{patch}{SetXmpPagePatch15}
\begin{paste}{SetXmpPageFull15}{SetXmpPageEmpty15}
\pastebutton{SetXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{remove!(25, a)\free{a }\bound{aremove }}
\indentrel{3}\begin{verbatim}
   (15)  {1,4,9,16,32}
                              Type: Set PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SetXmpPageEmpty15}
\begin{paste}{SetXmpPageEmpty15}{SetXmpPagePatch15}
\pastebutton{SetXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{remove!(25, a)\free{a }\bound{aremove }}
\end{paste}\end{patch}

\begin{patch}{SetXmpPagePatch16}
\begin{paste}{SetXmpPageFull16}{SetXmpPageEmpty16}
\pastebutton{SetXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{a\free{aremove ainsert }}
\indentrel{3}\begin{verbatim}
   (16)  {1,4,9,16,32}
                              Type: Set PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SetXmpPageEmpty16}
\begin{paste}{SetXmpPageEmpty16}{SetXmpPagePatch16}
\pastebutton{SetXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{a\free{aremove ainsert }}
\end{paste}\end{patch}

\begin{patch}{SetXmpPagePatch17}
\begin{paste}{SetXmpPageFull17}{SetXmpPageEmpty17}
\pastebutton{SetXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{b := b0 := set [i**2 for i in 1..5]\bound{b }}
\indentrel{3}\begin{verbatim}
   (17)  {1,4,9,16,25}
                              Type: Set PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SetXmpPageEmpty17}
\begin{paste}{SetXmpPageEmpty17}{SetXmpPagePatch17}
\pastebutton{SetXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{b := b0 := set [i**2 for i in 1..5]\bound{b }}
\end{paste}\end{patch}

\begin{patch}{SetXmpPagePatch18}
\begin{paste}{SetXmpPageFull18}{SetXmpPageEmpty18}
\pastebutton{SetXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{b := union(b,32)\free{b }\bound{binsert }}
\indentrel{3}\begin{verbatim}
   (18)  {1,4,9,16,25,32}
                              Type: Set PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SetXmpPageEmpty18}
\begin{paste}{SetXmpPageEmpty18}{SetXmpPagePatch18}
\pastebutton{SetXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{b := union(b,32)\free{b }\bound{binsert }}
\end{paste}\end{patch}

\begin{patch}{SetXmpPagePatch19}
\begin{paste}{SetXmpPageFull19}{SetXmpPageEmpty19}
\pastebutton{SetXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{b := difference(b,25)\free{binsert }\bound{bremove }}
\indentrel{3}\begin{verbatim}
   (19)  {1,4,9,16,32}
                              Type: Set PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SetXmpPageEmpty19}
\begin{paste}{SetXmpPageEmpty19}{SetXmpPagePatch19}
\pastebutton{SetXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{b := difference(b,25)\free{binsert }\bound{bremove }}
\end{paste}\end{patch}

\begin{patch}{SetXmpPagePatch20}
\begin{paste}{SetXmpPageFull20}{SetXmpPageEmpty20}
\pastebutton{SetXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{b0\free{bremove }}
\indentrel{3}\begin{verbatim}
   (20)  {1,4,9,16,25}
                              Type: Set PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SetXmpPageEmpty20}
\begin{paste}{SetXmpPageEmpty20}{SetXmpPagePatch20}
\pastebutton{SetXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{b0\free{bremove }}
\end{paste}\end{patch}

\end{chunk}
\section{sint.ht}
\pagetitle{SingleIntegerXmpPage}{sint.ht}{SingleInteger}
\pagepic{ps/v71singleintegerxmppage.eps}{SingleIntegerXmpPage}{0.50}
\pagefrom{Axiom Number Types}{NumberPage}
\pageto{Declarations}{ugTypesDeclarePage}
\pageto{Package Calling and Target Types}{ugTypesPkgCallPage}
\pageto{Browse}{ugBrowsePage}
\begin{chunk}{sint.ht}
\begin{page}{SingleIntegerXmpPage}{SingleInteger}
\beginscroll
The \axiomType{SingleInteger} domain is intended to provide support in
Axiom for machine integer arithmetic.  It is generally much faster
than (bignum) \axiomType{Integer} arithmetic but suffers from a
limited range of values.  Since Axiom can be implemented on top of
various dialects of Lisp, the actual representation of small integers
may not correspond exactly to the host machines integer
representation.

In the CCL implementation of Axiom (Release 2.1 onwards) the
underlying representation of \axiomType{SingleInteger} is the same as
\axiomType{Integer}.  The underlying Lisp primitives treat
machine-word sized computations specially.

\xtc{
You can discover the minimum and maximum values in your implementation
by using \spadfunFrom{min}{SingleInteger} and \spadfunFrom{max}{SingleInteger}.
}{
\spadpaste{min()\$SingleInteger}
}
\xtc{
}{
\spadpaste{max()\$SingleInteger}
}
\xtc{
To avoid confusion with \axiomType{Integer}, which is the default
type for integers, you usually need to work with declared variables
(\downlink{``Declarations''}{ugTypesDeclarePage} 
in Section 2.3\ignore{ugTypesDeclare}) \ldots
}{
\spadpaste{a := 1234 :: SingleInteger \bound{a}}
}
\xtc{
or use package calling
(\downlink{``Package Calling and Target Types''}{ugTypesPkgCallPage} 
in Section 2.9\ignore{ugTypesPkgCall}).
}{
\spadpaste{b := 124\$SingleInteger \bound{b}}
}
\xtc{
You can add, multiply and subtract \axiomType{SingleInteger} objects,
and ask for the greatest common divisor (\spadfun{gcd}).
}{
\spadpaste{gcd(a,b) \free{a}\free{b}}
}
\xtc{
The least common multiple (\spadfun{lcm}) is also available.
}{
\spadpaste{lcm(a,b) \free{a}\free{b}}
}

\xtc{
Operations \spadfunFrom{mulmod}{SingleInteger},
\spadfunFrom{addmod}{SingleInteger},
\spadfunFrom{submod}{SingleInteger}, and
\spadfunFrom{invmod}{SingleInteger} are similar---they provide
arithmetic modulo a given small integer.
Here is \spad{5 * 6 {\tt mod} 13}.
}{
\spadpaste{mulmod(5,6,13)\$SingleInteger}
}
\xtc{
To reduce a small integer modulo a prime, use 
\spadfunFrom{positiveRemainder}{SingleInteger}.
}{
\spadpaste{positiveRemainder(37,13)\$SingleInteger}
}
\xtc{
Operations
\spadfunFrom{And}{SingleInteger},
\spadfunFrom{Or}{SingleInteger},
\spadfunFrom{xor}{SingleInteger},
and \spadfunFrom{Not}{SingleInteger}
provide bit level operations on small integers.
}{
\spadpaste{And(3,4)\$SingleInteger}
}
\xtc{
Use
\spad{shift(int,numToShift)} to shift bits, where
\spad{i} is shifted left if \spad{numToShift} is positive, right
if negative.
}{
\spadpaste{shift(1,4)\$SingleInteger}
}
\xtc{
}{
\spadpaste{shift(31,-1)\$SingleInteger}
}

Many other operations are available for small integers, including
many of those provided for \axiomType{Integer}.
To see the other operations, use the Browse Hyperdoc facility
(\downlink{``Browse''}{ugBrowsePage} in Section 14\ignore{ugBrowse}).
\showBlurb{SingleInteger}.
\endscroll
\autobuttons
\end{page}

\begin{patch}{SingleIntegerXmpPagePatch1}
\begin{paste}{SingleIntegerXmpPageFull1}{SingleIntegerXmpPageEmpty1}
\pastebutton{SingleIntegerXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{min()$SingleInteger}
\indentrel{3}\begin{verbatim}
   (1)  - 134217728
                                    Type: SingleInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SingleIntegerXmpPageEmpty1}
\begin{paste}{SingleIntegerXmpPageEmpty1}{SingleIntegerXmpPagePatch1}
\pastebutton{SingleIntegerXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{min()$SingleInteger}
\end{paste}\end{patch}

\begin{patch}{SingleIntegerXmpPagePatch2}
\begin{paste}{SingleIntegerXmpPageFull2}{SingleIntegerXmpPageEmpty2}
\pastebutton{SingleIntegerXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{max()$SingleInteger}
\indentrel{3}\begin{verbatim}
   (2)  134217727
                                    Type: SingleInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SingleIntegerXmpPageEmpty2}
\begin{paste}{SingleIntegerXmpPageEmpty2}{SingleIntegerXmpPagePatch2}
\pastebutton{SingleIntegerXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{max()$SingleInteger}
\end{paste}\end{patch}

\begin{patch}{SingleIntegerXmpPagePatch3}
\begin{paste}{SingleIntegerXmpPageFull3}{SingleIntegerXmpPageEmpty3}
\pastebutton{SingleIntegerXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{a := 1234 :: SingleInteger\bound{a }}
\indentrel{3}\begin{verbatim}
   (3)  1234
                                    Type: SingleInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SingleIntegerXmpPageEmpty3}
\begin{paste}{SingleIntegerXmpPageEmpty3}{SingleIntegerXmpPagePatch3}
\pastebutton{SingleIntegerXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{a := 1234 :: SingleInteger\bound{a }}
\end{paste}\end{patch}

\begin{patch}{SingleIntegerXmpPagePatch4}
\begin{paste}{SingleIntegerXmpPageFull4}{SingleIntegerXmpPageEmpty4}
\pastebutton{SingleIntegerXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{b := 124$SingleInteger\bound{b }}
\indentrel{3}\begin{verbatim}
   (4)  124
                                    Type: SingleInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SingleIntegerXmpPageEmpty4}
\begin{paste}{SingleIntegerXmpPageEmpty4}{SingleIntegerXmpPagePatch4}
\pastebutton{SingleIntegerXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{b := 124$SingleInteger\bound{b }}
\end{paste}\end{patch}

\begin{patch}{SingleIntegerXmpPagePatch5}
\begin{paste}{SingleIntegerXmpPageFull5}{SingleIntegerXmpPageEmpty5}
\pastebutton{SingleIntegerXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{gcd(a,b)\free{a }\free{b }}
\indentrel{3}\begin{verbatim}
   (5)  2
                                    Type: SingleInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SingleIntegerXmpPageEmpty5}
\begin{paste}{SingleIntegerXmpPageEmpty5}{SingleIntegerXmpPagePatch5}
\pastebutton{SingleIntegerXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{gcd(a,b)\free{a }\free{b }}
\end{paste}\end{patch}

\begin{patch}{SingleIntegerXmpPagePatch6}
\begin{paste}{SingleIntegerXmpPageFull6}{SingleIntegerXmpPageEmpty6}
\pastebutton{SingleIntegerXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{lcm(a,b)\free{a }\free{b }}
\indentrel{3}\begin{verbatim}
   (6)  76508
                                    Type: SingleInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SingleIntegerXmpPageEmpty6}
\begin{paste}{SingleIntegerXmpPageEmpty6}{SingleIntegerXmpPagePatch6}
\pastebutton{SingleIntegerXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{lcm(a,b)\free{a }\free{b }}
\end{paste}\end{patch}

\begin{patch}{SingleIntegerXmpPagePatch7}
\begin{paste}{SingleIntegerXmpPageFull7}{SingleIntegerXmpPageEmpty7}
\pastebutton{SingleIntegerXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{mulmod(5,6,13)$SingleInteger}
\indentrel{3}\begin{verbatim}
   (7)  4
                                    Type: SingleInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SingleIntegerXmpPageEmpty7}
\begin{paste}{SingleIntegerXmpPageEmpty7}{SingleIntegerXmpPagePatch7}
\pastebutton{SingleIntegerXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{mulmod(5,6,13)$SingleInteger}
\end{paste}\end{patch}

\begin{patch}{SingleIntegerXmpPagePatch8}
\begin{paste}{SingleIntegerXmpPageFull8}{SingleIntegerXmpPageEmpty8}
\pastebutton{SingleIntegerXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{positiveRemainder(37,13)$SingleInteger}
\indentrel{3}\begin{verbatim}
   (8)  11
                                    Type: SingleInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SingleIntegerXmpPageEmpty8}
\begin{paste}{SingleIntegerXmpPageEmpty8}{SingleIntegerXmpPagePatch8}
\pastebutton{SingleIntegerXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{positiveRemainder(37,13)$SingleInteger}
\end{paste}\end{patch}

\begin{patch}{SingleIntegerXmpPagePatch9}
\begin{paste}{SingleIntegerXmpPageFull9}{SingleIntegerXmpPageEmpty9}
\pastebutton{SingleIntegerXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{And(3,4)$SingleInteger}
\indentrel{3}\begin{verbatim}
   (9)  0
                                    Type: SingleInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SingleIntegerXmpPageEmpty9}
\begin{paste}{SingleIntegerXmpPageEmpty9}{SingleIntegerXmpPagePatch9}
\pastebutton{SingleIntegerXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{And(3,4)$SingleInteger}
\end{paste}\end{patch}

\begin{patch}{SingleIntegerXmpPagePatch10}
\begin{paste}{SingleIntegerXmpPageFull10}{SingleIntegerXmpPageEmpty10}
\pastebutton{SingleIntegerXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{shift(1,4)$SingleInteger}
\indentrel{3}\begin{verbatim}
   (10)  16
                                    Type: SingleInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SingleIntegerXmpPageEmpty10}
\begin{paste}{SingleIntegerXmpPageEmpty10}{SingleIntegerXmpPagePatch10}
\pastebutton{SingleIntegerXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{shift(1,4)$SingleInteger}
\end{paste}\end{patch}

\begin{patch}{SingleIntegerXmpPagePatch11}
\begin{paste}{SingleIntegerXmpPageFull11}{SingleIntegerXmpPageEmpty11}
\pastebutton{SingleIntegerXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{shift(31,-1)$SingleInteger}
\indentrel{3}\begin{verbatim}
   (11)  15
                                    Type: SingleInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SingleIntegerXmpPageEmpty11}
\begin{paste}{SingleIntegerXmpPageEmpty11}{SingleIntegerXmpPagePatch11}
\pastebutton{SingleIntegerXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{shift(31,-1)$SingleInteger}
\end{paste}\end{patch}

\end{chunk}
\section{sqmatrix.ht}
\pagetitle{SqMatrixXmpPage}{sqmatrix.ht}{SquareMatrix}
\pageto{notitle}{MatrixXmpPage}
\pageto{notitle}{ugTypesWritingModesPage}
\pageto{notitle}{ugTypesExposePage}
\begin{chunk}{sqmatrix.ht}
\begin{page}{SqMatrixXmpPage}{SquareMatrix}
\beginscroll
 
The top level matrix type in Axiom is \spadtype{Matrix} (see
\downlink{`Matrix'}{MatrixXmpPage}\ignore{Matrix}), which provides
basic arithmetic and linear algebra functions.  However, since the
matrices can be of any size it is not true that any pair can be added
or multiplied.  Thus \spadtype{Matrix} has little algebraic structure.
 
Sometimes you want to use matrices as coefficients for polynomials or
in other algebraic contexts.  In this case, \spadtype{SquareMatrix}
should be used.  The domain \spadtype{SquareMatrix(n,R)} gives the
ring of \spad{n} by \spad{n} square matrices over \spad{R}.
 
\xtc{
Since \spadtype{SquareMatrix} is not normally exposed at the top level,
you must expose it before it can be used.
}{
\spadpaste{)set expose add constructor SquareMatrix \bound{SQ}}
}
\xtc{
Once \spad{SQMATRIX} has been exposed,
values can be created using the \spadfunFrom{squareMatrix}{SquareMatrix}
function.
}{
\spadpaste{m := squareMatrix [[1,-\%i],[\%i,4]] \bound{m}\free{SQ}}
}
\xtc{
The usual arithmetic operations are available.
}{
\spadpaste{m*m - m \free{m}}
}
\xtc{
Square matrices can be used where ring elements are required.
For example, here is a matrix with matrix entries.
}{
\spadpaste{mm := squareMatrix [[m, 1], [1-m, m**2]] \free{m}\bound{mm}}
}
\xtc{
Or you can construct a polynomial with  square matrix coefficients.
}{
\spadpaste{p := (x + m)**2 \free{m}\bound{p}}
}
\xtc{
This value can be converted to a square matrix with polynomial 
coefficients.
}{
\spadpaste{p::SquareMatrix(2, ?) \free{p}}
}
 
For more information on related topics, see
\downlink{``Modes''}{ugTypesWritingModesPage} 
in Section 2.2.4\ignore{ugTypesWritingModes},
\downlink{``Exposing Domains and Packages''}{ugTypesExposePage} 
in Section 2.11\ignore{ugTypesExpose}, and
\downlink{`Matrix'}{MatrixXmpPage}\ignore{Matrix}.
\showBlurb{SquareMatrix}
\endscroll
\autobuttons
\end{page}

\begin{patch}{SqMatrixXmpPagePatch1}
\begin{paste}{SqMatrixXmpPageFull1}{SqMatrixXmpPageEmpty1}
\pastebutton{SqMatrixXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{)set expose add constructor SquareMatrix\bound{SQ }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqMatrixXmpPageEmpty1}
\begin{paste}{SqMatrixXmpPageEmpty1}{SqMatrixXmpPagePatch1}
\pastebutton{SqMatrixXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{)set expose add constructor SquareMatrix\bound{SQ }}
\end{paste}\end{patch}

\begin{patch}{SqMatrixXmpPagePatch2}
\begin{paste}{SqMatrixXmpPageFull2}{SqMatrixXmpPageEmpty2}
\pastebutton{SqMatrixXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{m := squareMatrix [[1,-\%i],[\%i,4]]\bound{m }\free{SQ }}
\indentrel{3}\begin{verbatim}
        Ú1   - %i¿
   (1)  ³        ³
        À%i   4  Ù
                  Type: SquareMatrix(2,Complex Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqMatrixXmpPageEmpty2}
\begin{paste}{SqMatrixXmpPageEmpty2}{SqMatrixXmpPagePatch2}
\pastebutton{SqMatrixXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{m := squareMatrix [[1,-\%i],[\%i,4]]\bound{m }\free{SQ }}
\end{paste}\end{patch}

\begin{patch}{SqMatrixXmpPagePatch3}
\begin{paste}{SqMatrixXmpPageFull3}{SqMatrixXmpPageEmpty3}
\pastebutton{SqMatrixXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{m*m - m\free{m }}
\indentrel{3}\begin{verbatim}
        Ú 1   - 4%i¿
   (2)  ³          ³
        À4%i   13  Ù
                  Type: SquareMatrix(2,Complex Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqMatrixXmpPageEmpty3}
\begin{paste}{SqMatrixXmpPageEmpty3}{SqMatrixXmpPagePatch3}
\pastebutton{SqMatrixXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{m*m - m\free{m }}
\end{paste}\end{patch}

\begin{patch}{SqMatrixXmpPagePatch4}
\begin{paste}{SqMatrixXmpPageFull4}{SqMatrixXmpPageEmpty4}
\pastebutton{SqMatrixXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{mm := squareMatrix [[m, 1], [1-m, m**2]]\free{m }\bound{mm }}
\indentrel{3}\begin{verbatim}
        ÚÚ1   - %i¿      Ú1  0¿   ¿
        ³³        ³      ³    ³   ³
        ³À%i   4  Ù      À0  1Ù   ³
   (3)  ³                         ³
        ³Ú 0    %i ¿  Ú 2   - 5%i¿³
        ³³         ³  ³          ³³
        ÀÀ- %i  - 3Ù  À5%i   17  ÙÙ
  Type: SquareMatrix(2,SquareMatrix(2,Complex Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqMatrixXmpPageEmpty4}
\begin{paste}{SqMatrixXmpPageEmpty4}{SqMatrixXmpPagePatch4}
\pastebutton{SqMatrixXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{mm := squareMatrix [[m, 1], [1-m, m**2]]\free{m }\bound{mm }}
\end{paste}\end{patch}

\begin{patch}{SqMatrixXmpPagePatch5}
\begin{paste}{SqMatrixXmpPageFull5}{SqMatrixXmpPageEmpty5}
\pastebutton{SqMatrixXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{p := (x + m)**2\free{m }\bound{p }}
\indentrel{3}\begin{verbatim}
         2   Ú 2   - 2%i¿    Ú 2   - 5%i¿
   (4)  x  + ³          ³x + ³          ³
             À2%i    8  Ù    À5%i   17  Ù
       Type: Polynomial SquareMatrix(2,Complex Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqMatrixXmpPageEmpty5}
\begin{paste}{SqMatrixXmpPageEmpty5}{SqMatrixXmpPagePatch5}
\pastebutton{SqMatrixXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{p := (x + m)**2\free{m }\bound{p }}
\end{paste}\end{patch}

\begin{patch}{SqMatrixXmpPagePatch6}
\begin{paste}{SqMatrixXmpPageFull6}{SqMatrixXmpPageEmpty6}
\pastebutton{SqMatrixXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{p::SquareMatrix(2, ?)\free{p }}
\indentrel{3}\begin{verbatim}
        Ú 2                        ¿
        ³x  + 2x + 2  - 2%i x - 5%i³
   (5)  ³                          ³
        ³              2           ³
        À2%i x + 5%i  x  + 8x + 17 Ù
       Type: SquareMatrix(2,Polynomial Complex Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqMatrixXmpPageEmpty6}
\begin{paste}{SqMatrixXmpPageEmpty6}{SqMatrixXmpPagePatch6}
\pastebutton{SqMatrixXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{p::SquareMatrix(2, ?)\free{p }}
\end{paste}\end{patch}

\end{chunk}
\section{sregset.ht}
\pagetitle{SqFreeRegTriangSetXmpPage}{sregset.ht}
{SquareFreeRegularTriangularSet}
\begin{chunk}{sregset.ht}
\begin{page}{SqFreeRegTriangSetXmpPage}
{SquareFreeRegularTriangularSet}
\beginscroll

The \spadtype{SquareFreeRegularTriangularSet} domain constructor
implements square-free regular triangular sets.  See the
\spadtype{RegularTriangularSet} domain constructor for general regular
triangular sets.  Let {\em T} be a regular triangular set consisting
of polynomials {\em t1, ..., tm} ordered by increasing main variables.
The regular triangular set {\em T} is square-free if {\em T} is empty
or if {\em t1, ..., tm-1} is square-free and if the polynomial {\em
tm} is square-free as a univariate polynomial with coefficients in the
tower of simple extensions associated with {\em t1, ..., tm-1}.

The main interest of square-free regular triangular sets is that their
associated towers of simple extensions are product of fields.
Consequently, the saturated ideal of a square-free regular triangular
set is radical.  This property simplifies some of the operations
related to regular triangular sets.  However, building square-free
regular triangular sets is generally more expensive than building
general regular triangular sets.

As the \spadtype{RegularTriangularSet} domain constructor, the
\spadtype{SquareFreeRegularTriangularSet} domain constructor also
implements a method for solving polynomial systems by means of regular
triangular sets.  This is in fact the same method with some
adaptations to take into account the fact that the computed regular
chains are square-free.  Note that it is also possible to pass from a
decomposition into general regular triangular sets to a decomposition
into square-free regular triangular sets.  This conversion is used
internally by the \spadtype{LazardSetSolvingPackage} package
constructor.

{\bf N.B.} When solving polynomial systems with the
\spadtype{SquareFreeRegularTriangularSet} domain constructor or the
\spadtype{LazardSetSolvingPackage} package constructor, decompositions
have no redundant components.  See also
\spadtype{LexTriangularPackage} and
\spadtype{ZeroDimensionalSolvePackage} for the case of algebraic
systems with a finite number of (complex) solutions.

We shall explain now how to use the constructor 
\spadtype{SquareFreeRegularTriangularSet}.

This constructor takes four arguments.  The first one, {\bf R}, is the
coefficient ring of the polynomials; it must belong to the category
\spadtype{GcdDomain}.  The second one, {\bf E}, is the exponent monoid
of the polynomials; it must belong to the category
\spadtype{OrderedAbelianMonoidSup}.  the third one, {\bf V}, is the
ordered set of variables; it must belong to the category
\spadtype{OrderedSet}.  The last one is the polynomial ring; it must
belong to the category \spadtype{RecursivePolynomialCategory(R,E,V)}.
The abbreviation for \spadtype{SquareFreeRegularTriangularSet} is
\spadtype{SREGSET}.

Note that the way of understanding triangular decompositions 
is detailed in the example of the \spadtype{RegularTriangularSet}
constructor.

\xtc{
Let us illustrate the use of this constructor 
with one example (Donati-Traverso).
Define the coefficient ring.
}{
\spadpaste{R := Integer \bound{R}}
}
\xtc{
Define the list of variables,
}{
\spadpaste{ls : List Symbol := [x,y,z,t] \bound{ls}}
}
\xtc{
and make it an ordered set;
}{
\spadpaste{V := OVAR(ls) \free{ls} \bound{V}}
}
\xtc{
then define the exponent monoid.
}{
\spadpaste{E := IndexedExponents V \free{V} \bound{E}}
}
\xtc{
Define the polynomial ring.
}{
\spadpaste{P := NSMP(R, V) \free{R} \free{V} \bound{P}}
}
\xtc{
Let the variables be polynomial.
}{
\spadpaste{x: P := 'x \free{P} \bound{x}}
}
\xtc{
}{
\spadpaste{y: P := 'y \free{P} \bound{y}}
}
\xtc{
}{
\spadpaste{z: P := 'z \free{P} \bound{z}}
}
\xtc{
}{
\spadpaste{t: P := 't \free{P} \bound{t}}
}
\xtc{
Now call the \spadtype{SquareFreeRegularTriangularSet} domain 
constructor.
}{
\spadpaste{ST := SREGSET(R,E,V,P) \free{R} \free{E} \free{V} 
\free{P} \bound{ST} }
}
\xtc{
Define a polynomial system.
}{
\spadpaste{p1 := x ** 31 - x ** 6 - x - y \free{x} \free{y} 
\bound{p1}}
}
\xtc{
}{
\spadpaste{p2 := x ** 8  - z \free{x} \free{z} \bound{p2}}
}
\xtc{
}{
\spadpaste{p3 := x ** 10 - t \free{x} \free{t} \bound{p3}}
}
\xtc{
}{
\spadpaste{lp := [p1, p2, p3] \free{p1} \free{p2} \free{p3} 
\bound{lp}}
}

\xtc{
First of all, let us solve this system in the sense of Kalkbrener.
}{
\spadpaste{zeroSetSplit(lp)$ST \free{lp} \free{ST}}
}
\xtc{
And now in the sense of Lazard (or Wu and other authors).
}{
\spadpaste{zeroSetSplit(lp,false)$ST \free{lp} \free{ST} 
\bound{lts}}
}

Now to see the difference with the \spadtype{RegularTriangularSet}
domain constructor,
\xtc{
we define:
}{
\spadpaste{T := REGSET(R,E,V,P) \free{R} \free{E} \free{V} 
\free{P} \bound{T} }
}
\xtc{
and compute:
}{
\spadpaste{lts := zeroSetSplit(lp,false)$T \free{lp} 
\free{T} \bound{lts}}
}

If you look at the second set in both decompositions in the sense of
Lazard, you will see that the polynomial with main variable {\bf y} is
not the same.

Let us understand what has happened.
\xtc{
We define:
}{
\spadpaste{ts := lts.2  \free{lts}  \bound{ts}}
}
\xtc{
}{
\spadpaste{pol := select(ts,'y)$T \free{ts} \free{y} \free{T} \bound{pol}}
}
\xtc{
}{
\spadpaste{tower := collectUnder(ts,'y)$T \free{ts} \free{y} 
\free{T} \bound{tower}}
}
\xtc{
}{
\spadpaste{pack := RegularTriangularSetGcdPackage(R,E,V,P,T) 
\free{R} \free{E} \free{V} \free{P} \free{T} \bound{pack}}
}
\xtc{
Then we compute:
}{
\spadpaste{toseSquareFreePart(pol,tower)$pack \free{pol} 
\free{tower} \free{pack}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch1}
\begin{paste}{SqFreeRegTriangSetXmpPageFull1}{SqFreeRegTriangSetXmpPageEmpty1}
\pastebutton{SqFreeRegTriangSetXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{R := Integer\bound{R }}
\indentrel{3}\begin{verbatim}
   (1)  Integer
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty1}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty1}{SqFreeRegTriangSetXmpPagePatch1}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{R := Integer\bound{R }}
\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch2}
\begin{paste}{SqFreeRegTriangSetXmpPageFull2}{SqFreeRegTriangSetXmpPageEmpty2}
\pastebutton{SqFreeRegTriangSetXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{ls : List Symbol := [x,y,z,t]\bound{ls }}
\indentrel{3}\begin{verbatim}
   (2)  [x,y,z,t]
                                      Type: List Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty2}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty2}{SqFreeRegTriangSetXmpPagePatch2}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{ls : List Symbol := [x,y,z,t]\bound{ls }}
\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch3}
\begin{paste}{SqFreeRegTriangSetXmpPageFull3}{SqFreeRegTriangSetXmpPageEmpty3}
\pastebutton{SqFreeRegTriangSetXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{V := OVAR(ls)\free{ls }\bound{V }}
\indentrel{3}\begin{verbatim}
   (3)  OrderedVariableList [x,y,z,t]
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty3}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty3}{SqFreeRegTriangSetXmpPagePatch3}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{V := OVAR(ls)\free{ls }\bound{V }}
\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch4}
\begin{paste}{SqFreeRegTriangSetXmpPageFull4}{SqFreeRegTriangSetXmpPageEmpty4}
\pastebutton{SqFreeRegTriangSetXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{E := IndexedExponents V\free{V }\bound{E }}
\indentrel{3}\begin{verbatim}
   (4)  IndexedExponents OrderedVariableList [x,y,z,t]
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty4}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty4}{SqFreeRegTriangSetXmpPagePatch4}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{E := IndexedExponents V\free{V }\bound{E }}
\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch5}
\begin{paste}{SqFreeRegTriangSetXmpPageFull5}{SqFreeRegTriangSetXmpPageEmpty5}
\pastebutton{SqFreeRegTriangSetXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{P := NSMP(R, V)\free{R }\free{V }\bound{P }}
\indentrel{3}\begin{verbatim}
   (5)
  NewSparseMultivariatePolynomial(Integer,OrderedVariable
  List [x,y,z,t])
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty5}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty5}{SqFreeRegTriangSetXmpPagePatch5}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{P := NSMP(R, V)\free{R }\free{V }\bound{P }}
\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch6}
\begin{paste}{SqFreeRegTriangSetXmpPageFull6}{SqFreeRegTriangSetXmpPageEmpty6}
\pastebutton{SqFreeRegTriangSetXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{x: P := 'x\free{P }\bound{x }}
\indentrel{3}\begin{verbatim}
   (6)  x
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty6}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty6}{SqFreeRegTriangSetXmpPagePatch6}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{x: P := 'x\free{P }\bound{x }}
\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch7}
\begin{paste}{SqFreeRegTriangSetXmpPageFull7}{SqFreeRegTriangSetXmpPageEmpty7}
\pastebutton{SqFreeRegTriangSetXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{y: P := 'y\free{P }\bound{y }}
\indentrel{3}\begin{verbatim}
   (7)  y
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty7}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty7}{SqFreeRegTriangSetXmpPagePatch7}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{y: P := 'y\free{P }\bound{y }}
\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch8}
\begin{paste}{SqFreeRegTriangSetXmpPageFull8}{SqFreeRegTriangSetXmpPageEmpty8}
\pastebutton{SqFreeRegTriangSetXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{z: P := 'z\free{P }\bound{z }}
\indentrel{3}\begin{verbatim}
   (8)  z
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty8}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty8}{SqFreeRegTriangSetXmpPagePatch8}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{z: P := 'z\free{P }\bound{z }}
\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch9}
\begin{paste}{SqFreeRegTriangSetXmpPageFull9}{SqFreeRegTriangSetXmpPageEmpty9}
\pastebutton{SqFreeRegTriangSetXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{t: P := 't\free{P }\bound{t }}
\indentrel{3}\begin{verbatim}
   (9)  t
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty9}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty9}{SqFreeRegTriangSetXmpPagePatch9}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{t: P := 't\free{P }\bound{t }}
\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch10}
\begin{paste}{SqFreeRegTriangSetXmpPageFull10}{SqFreeRegTriangSetXmpPageEmpty10}
\pastebutton{SqFreeRegTriangSetXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{ST := SREGSET(R,E,V,P)\free{R }\free{E }\free{V }\free{P }\bound{ST }}
\indentrel{3}\begin{verbatim}
   (10)
  SquareFreeRegularTriangularSet(Integer,IndexedExponents
   OrderedVariableList [x,y,z,t],OrderedVariableList [x,y
  ,z,t],NewSparseMultivariatePolynomial(Integer,OrderedVa
  riableList [x,y,z,t]))
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty10}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty10}{SqFreeRegTriangSetXmpPagePatch10}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{ST := SREGSET(R,E,V,P)\free{R }\free{E }\free{V }\free{P }\bound{ST }}
\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch11}
\begin{paste}{SqFreeRegTriangSetXmpPageFull11}{SqFreeRegTriangSetXmpPageEmpty11}
\pastebutton{SqFreeRegTriangSetXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{p1 := x ** 31 - x ** 6 - x - y\free{x }\free{y }\bound{p1 }}
\indentrel{3}\begin{verbatim}
          31    6
   (11)  x   - x  - x - y
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty11}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty11}{SqFreeRegTriangSetXmpPagePatch11}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{p1 := x ** 31 - x ** 6 - x - y\free{x }\free{y }\bound{p1 }}
\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch12}
\begin{paste}{SqFreeRegTriangSetXmpPageFull12}{SqFreeRegTriangSetXmpPageEmpty12}
\pastebutton{SqFreeRegTriangSetXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{p2 := x ** 8 - z\free{x }\free{z }\bound{p2 }}
\indentrel{3}\begin{verbatim}
          8
   (12)  x  - z
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty12}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty12}{SqFreeRegTriangSetXmpPagePatch12}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{p2 := x ** 8 - z\free{x }\free{z }\bound{p2 }}
\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch13}
\begin{paste}{SqFreeRegTriangSetXmpPageFull13}{SqFreeRegTriangSetXmpPageEmpty13}
\pastebutton{SqFreeRegTriangSetXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{p3 := x ** 10 - t\free{x }\free{t }\bound{p3 }}
\indentrel{3}\begin{verbatim}
          10
   (13)  x   - t
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty13}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty13}{SqFreeRegTriangSetXmpPagePatch13}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{p3 := x ** 10 - t\free{x }\free{t }\bound{p3 }}
\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch14}
\begin{paste}{SqFreeRegTriangSetXmpPageFull14}{SqFreeRegTriangSetXmpPageEmpty14}
\pastebutton{SqFreeRegTriangSetXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{lp := [p1, p2, p3]\free{p1 }\free{p2 }\free{p3 }\bound{lp }}
\indentrel{3}\begin{verbatim}
           31    6          8      10
   (14)  [x   - x  - x - y,x  - z,x   - t]
Type: List NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty14}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty14}{SqFreeRegTriangSetXmpPagePatch14}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{lp := [p1, p2, p3]\free{p1 }\free{p2 }\free{p3 }\bound{lp }}
\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch15}
\begin{paste}{SqFreeRegTriangSetXmpPageFull15}{SqFreeRegTriangSetXmpPageEmpty15}
\pastebutton{SqFreeRegTriangSetXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{zeroSetSplit(lp)$ST\free{lp }\free{ST }}
\indentrel{3}\begin{verbatim}
   (15)
   [
       5    4       2     3     8     5    3    2
     {z  - t , t z y  + 2z y - t  + 2t  + t  - t ,
        4                2
      (t  - t)x - t y - z }
     ]
Type: List SquareFreeRegularTriangularSet(Integer,IndexedExponents OrderedVariableList [x,y,z,t],OrderedVariableList [x,y,z,t],NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t]))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty15}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty15}{SqFreeRegTriangSetXmpPagePatch15}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{zeroSetSplit(lp)$ST\free{lp }\free{ST }}
\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch16}
\begin{paste}{SqFreeRegTriangSetXmpPageFull16}{SqFreeRegTriangSetXmpPageEmpty16}
\pastebutton{SqFreeRegTriangSetXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{zeroSetSplit(lp,false)$ST\free{lp }\free{ST }\bound{lts }}
\indentrel{3}\begin{verbatim}
   (16)
   [
       5    4       2     3     8     5    3    2
     {z  - t , t z y  + 2z y - t  + 2t  + t  - t ,
        4                2
      (t  - t)x - t y - z }
     ,
      3      5            2    2
    {t  - 1,z  - t,t y + z ,z x  - t}, {t,z,y,x}]
Type: List SquareFreeRegularTriangularSet(Integer,IndexedExponents OrderedVariableList [x,y,z,t],OrderedVariableList [x,y,z,t],NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t]))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty16}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty16}{SqFreeRegTriangSetXmpPagePatch16}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{zeroSetSplit(lp,false)$ST\free{lp }\free{ST }\bound{lts }}
\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch17}
\begin{paste}{SqFreeRegTriangSetXmpPageFull17}{SqFreeRegTriangSetXmpPageEmpty17}
\pastebutton{SqFreeRegTriangSetXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{T := REGSET(R,E,V,P)\free{R }\free{E }\free{V }\free{P }\bound{T }}
\indentrel{3}\begin{verbatim}
   (17)
  RegularTriangularSet(Integer,IndexedExponents OrderedVa
  riableList [x,y,z,t],OrderedVariableList [x,y,z,t],NewS
  parseMultivariatePolynomial(Integer,OrderedVariableList
   [x,y,z,t]))
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty17}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty17}{SqFreeRegTriangSetXmpPagePatch17}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{T := REGSET(R,E,V,P)\free{R }\free{E }\free{V }\free{P }\bound{T }}
\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch18}
\begin{paste}{SqFreeRegTriangSetXmpPageFull18}{SqFreeRegTriangSetXmpPageEmpty18}
\pastebutton{SqFreeRegTriangSetXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{lts := zeroSetSplit(lp,false)$T\free{lp }\free{T }\bound{lts }}
\indentrel{3}\begin{verbatim}
   (18)
   [
       5    4       2     3     8     5    3    2
     {z  - t , t z y  + 2z y - t  + 2t  + t  - t ,
        4                2
      (t  - t)x - t y - z }
     ,
      3      5          2     3         2
    {t  - 1,z  - t,t z y  + 2z y + 1,z x  - t},
    {t,z,y,x}]
Type: List RegularTriangularSet(Integer,IndexedExponents OrderedVariableList [x,y,z,t],OrderedVariableList [x,y,z,t],NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t]))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty18}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty18}{SqFreeRegTriangSetXmpPagePatch18}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{lts := zeroSetSplit(lp,false)$T\free{lp }\free{T }\bound{lts }}
\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch19}
\begin{paste}{SqFreeRegTriangSetXmpPageFull19}{SqFreeRegTriangSetXmpPageEmpty19}
\pastebutton{SqFreeRegTriangSetXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{ts := lts.2\free{lts }\bound{ts }}
\indentrel{3}\begin{verbatim}
           3      5          2     3         2
   (19)  {t  - 1,z  - t,t z y  + 2z y + 1,z x  - t}
Type: RegularTriangularSet(Integer,IndexedExponents OrderedVariableList [x,y,z,t],OrderedVariableList [x,y,z,t],NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t]))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty19}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty19}{SqFreeRegTriangSetXmpPagePatch19}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{ts := lts.2\free{lts }\bound{ts }}
\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch20}
\begin{paste}{SqFreeRegTriangSetXmpPageFull20}{SqFreeRegTriangSetXmpPageEmpty20}
\pastebutton{SqFreeRegTriangSetXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{pol := select(ts,'y)$T\free{ts }\free{y }\free{T }\bound{pol }}
\indentrel{3}\begin{verbatim}
              2     3
   (20)  t z y  + 2z y + 1
Type: Union(NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t]),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty20}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty20}{SqFreeRegTriangSetXmpPagePatch20}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{pol := select(ts,'y)$T\free{ts }\free{y }\free{T }\bound{pol }}
\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch21}
\begin{paste}{SqFreeRegTriangSetXmpPageFull21}{SqFreeRegTriangSetXmpPageEmpty21}
\pastebutton{SqFreeRegTriangSetXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{tower := collectUnder(ts,'y)$T\free{ts }\free{y }\free{T }\bound{tower }}
\indentrel{3}\begin{verbatim}
           3      5
   (21)  {t  - 1,z  - t}
Type: RegularTriangularSet(Integer,IndexedExponents OrderedVariableList [x,y,z,t],OrderedVariableList [x,y,z,t],NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t]))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty21}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty21}{SqFreeRegTriangSetXmpPagePatch21}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{tower := collectUnder(ts,'y)$T\free{ts }\free{y }\free{T }\bound{tower }}
\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch22}
\begin{paste}{SqFreeRegTriangSetXmpPageFull22}{SqFreeRegTriangSetXmpPageEmpty22}
\pastebutton{SqFreeRegTriangSetXmpPageFull22}{\hidepaste}
\tab{5}\spadcommand{pack := RegularTriangularSetGcdPackage(R,E,V,P,T)\free{R }\free{E }\free{V }\free{P }\free{T }\bound{pack }}
\indentrel{3}\begin{verbatim}
   (22)
  RegularTriangularSetGcdPackage(Integer,IndexedExponents
   OrderedVariableList [x,y,z,t],OrderedVariableList [x,y
  ,z,t],NewSparseMultivariatePolynomial(Integer,OrderedVa
  riableList [x,y,z,t]),RegularTriangularSet(Integer,Inde
  xedExponents OrderedVariableList [x,y,z,t],OrderedVaria
  bleList [x,y,z,t],NewSparseMultivariatePolynomial(Integ
  er,OrderedVariableList [x,y,z,t])))
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty22}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty22}{SqFreeRegTriangSetXmpPagePatch22}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty22}{\showpaste}
\tab{5}\spadcommand{pack := RegularTriangularSetGcdPackage(R,E,V,P,T)\free{R }\free{E }\free{V }\free{P }\free{T }\bound{pack }}
\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPagePatch23}
\begin{paste}{SqFreeRegTriangSetXmpPageFull23}{SqFreeRegTriangSetXmpPageEmpty23}
\pastebutton{SqFreeRegTriangSetXmpPageFull23}{\hidepaste}
\tab{5}\spadcommand{toseSquareFreePart(pol,tower)$pack\free{pol }\free{tower }\free{pack }}
\indentrel{3}\begin{verbatim}
                       2          3      5
   (23)  [[val= t y + z ,tower= {t  - 1,z  - t}]]
Type: List Record(val: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t]),tower: RegularTriangularSet(Integer,IndexedExponents OrderedVariableList [x,y,z,t],OrderedVariableList [x,y,z,t],NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SqFreeRegTriangSetXmpPageEmpty23}
\begin{paste}{SqFreeRegTriangSetXmpPageEmpty23}{SqFreeRegTriangSetXmpPagePatch23}
\pastebutton{SqFreeRegTriangSetXmpPageEmpty23}{\showpaste}
\tab{5}\spadcommand{toseSquareFreePart(pol,tower)$pack\free{pol }\free{tower }\free{pack }}
\end{paste}\end{patch}

\end{chunk}
\section{stbl.ht}
\pagetitle{SparseTableXmpPage}{stbl.ht}{SparseTable}
\pageto{notitle}{TableXmpPage}
\pageto{notitle}{GeneralSparseTableXmpPage}
\begin{chunk}{stbl.ht}
\begin{page}{SparseTableXmpPage}{SparseTable}
\beginscroll
%
The \spadtype{SparseTable} domain provides a general purpose
table type with default entries.
\xtc{
Here we create a table to save strings under integer keys.
The value \spad{"Try again!"} is returned if no other value has been
stored for a key.
}{
\spadpaste{t: SparseTable(Integer, String, "Try again!") := table() 
\bound{t}}
}
\xtc{
Entries can be stored in the table.
}{
\spadpaste{t.3 := "Number three" \free{t}\bound{t1}}
}
\xtc{
}{
\spadpaste{t.4 := "Number four" \free{t}\bound{t2}}
}
\xtc{
These values can be retrieved as usual, but if a look up fails
the default entry will be returned.
}{
\spadpaste{t.3 \free{t1}}
}
\xtc{
}{
\spadpaste{t.2 \free{t}}
}
\xtc{
To see which values are explicitly stored, the
\spadfunFrom{keys}{SparseTable} and \spadfunFrom{entries}{SparseTable}
functions can be used.
}{
\spadpaste{keys t \free{t1 t2}}
}
\xtc{
}{
\spadpaste{entries t \free{t1 t2}}
}
If a specific table representation
is required, the \spadtype{GeneralSparseTable} constructor should be 
used. The domain \spadtype{SparseTable(K, E, dflt)} is equivalent to
\spadtype{GeneralSparseTable(K,E, Table(K,E), dflt)}.
For more information, see
\downlink{`Table'}{TableXmpPage}\ignore{Table} and
\downlink{`GeneralSparseTable'}{GeneralSparseTableXmpPage}
\ignore{GeneralSparseTable}.
\showBlurb{SparseTable}
\endscroll
\autobuttons
\end{page}

\begin{patch}{SparseTableXmpPagePatch1}
\begin{paste}{SparseTableXmpPageFull1}{SparseTableXmpPageEmpty1}
\pastebutton{SparseTableXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{t: SparseTable(Integer, String, "Try again!") := table()\bound{t }}
\indentrel{3}\begin{verbatim}
   (1)  table()
           Type: SparseTable(Integer,String,Try again!)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SparseTableXmpPageEmpty1}
\begin{paste}{SparseTableXmpPageEmpty1}{SparseTableXmpPagePatch1}
\pastebutton{SparseTableXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{t: SparseTable(Integer, String, "Try again!") := table()\bound{t }}
\end{paste}\end{patch}

\begin{patch}{SparseTableXmpPagePatch2}
\begin{paste}{SparseTableXmpPageFull2}{SparseTableXmpPageEmpty2}
\pastebutton{SparseTableXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{t.3 := "Number three"\free{t }\bound{t1 }}
\indentrel{3}\begin{verbatim}
   (2)  "Number three"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SparseTableXmpPageEmpty2}
\begin{paste}{SparseTableXmpPageEmpty2}{SparseTableXmpPagePatch2}
\pastebutton{SparseTableXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{t.3 := "Number three"\free{t }\bound{t1 }}
\end{paste}\end{patch}

\begin{patch}{SparseTableXmpPagePatch3}
\begin{paste}{SparseTableXmpPageFull3}{SparseTableXmpPageEmpty3}
\pastebutton{SparseTableXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{t.4 := "Number four"\free{t }\bound{t2 }}
\indentrel{3}\begin{verbatim}
   (3)  "Number four"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SparseTableXmpPageEmpty3}
\begin{paste}{SparseTableXmpPageEmpty3}{SparseTableXmpPagePatch3}
\pastebutton{SparseTableXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{t.4 := "Number four"\free{t }\bound{t2 }}
\end{paste}\end{patch}

\begin{patch}{SparseTableXmpPagePatch4}
\begin{paste}{SparseTableXmpPageFull4}{SparseTableXmpPageEmpty4}
\pastebutton{SparseTableXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{t.3\free{t1 }}
\indentrel{3}\begin{verbatim}
   (4)  "Number three"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SparseTableXmpPageEmpty4}
\begin{paste}{SparseTableXmpPageEmpty4}{SparseTableXmpPagePatch4}
\pastebutton{SparseTableXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{t.3\free{t1 }}
\end{paste}\end{patch}

\begin{patch}{SparseTableXmpPagePatch5}
\begin{paste}{SparseTableXmpPageFull5}{SparseTableXmpPageEmpty5}
\pastebutton{SparseTableXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{t.2\free{t }}
\indentrel{3}\begin{verbatim}
   (5)  "Try again!"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SparseTableXmpPageEmpty5}
\begin{paste}{SparseTableXmpPageEmpty5}{SparseTableXmpPagePatch5}
\pastebutton{SparseTableXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{t.2\free{t }}
\end{paste}\end{patch}

\begin{patch}{SparseTableXmpPagePatch6}
\begin{paste}{SparseTableXmpPageFull6}{SparseTableXmpPageEmpty6}
\pastebutton{SparseTableXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{keys t\free{t1 t2 }}
\indentrel{3}\begin{verbatim}
   (6)  [4,3]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SparseTableXmpPageEmpty6}
\begin{paste}{SparseTableXmpPageEmpty6}{SparseTableXmpPagePatch6}
\pastebutton{SparseTableXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{keys t\free{t1 t2 }}
\end{paste}\end{patch}

\begin{patch}{SparseTableXmpPagePatch7}
\begin{paste}{SparseTableXmpPageFull7}{SparseTableXmpPageEmpty7}
\pastebutton{SparseTableXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{entries t\free{t1 t2 }}
\indentrel{3}\begin{verbatim}
   (7)  ["Number four","Number three"]
                                      Type: List String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SparseTableXmpPageEmpty7}
\begin{paste}{SparseTableXmpPageEmpty7}{SparseTableXmpPagePatch7}
\pastebutton{SparseTableXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{entries t\free{t1 t2 }}
\end{paste}\end{patch}

\end{chunk}
\section{stream.ht}
\pagetitle{StreamXmpPage}{stream.ht}{Stream}
\pageto{notitle}{ugLangItsPage}
\pageto{notitle}{ugProblemSeriesPage}
\pageto{notitle}{ContinuedFractionXmpPage}
\pageto{notitle}{ListXmpPage}
\begin{chunk}{stream.ht}
\begin{page}{StreamXmpPage}{Stream}
\beginscroll

A \spadtype{Stream} object is represented as a list whose 
last element contains the
wherewithal to create the next element, should it ever be required.
\xtc{
Let \spad{ints} be the infinite stream of non-negative integers.
}{
\spadpaste{ints := [i for i in 0..] \bound{ints}}
}
By default, ten stream elements are calculated.
This number may be changed to something else by the system command
\spadcmd{)set streams calculate}.
For the display purposes of this book, we have chosen a smaller value.
\xtc{
More generally, you can construct a stream by specifying its initial
value and a function which, when given an element, creates the next 
element.
}{
\spadpaste{f : List INT -> List INT \bound{fdec}}
}
\xtc{
}{
\spadpaste{f x == [x.1 + x.2, x.1] \bound{f}\free{fdec}}
}
\xtc{
}{
\spadpaste{fibs := [i.2 for i in [generate(f,[1,1])]] \bound{fibs}\free{f}}
}
\xtc{
You can create the stream of odd non-negative integers by either
filtering them from the integers, or by evaluating an expression for
each integer.
}{
\spadpaste{[i for i in ints | odd? i] \free{ints}}
}
\xtc{
}{
\spadpaste{odds := [2*i+1 for i in ints]\bound{odds}\free{ints}}
}
\xtc{
You can accumulate the initial segments of a stream using the
\spadfunFrom{scan}{StreamFunctions2} operation.
}{
\spadpaste{scan(0,+,odds) \free{odds}}
}
\xtc{
The corresponding elements of
two or more streams can be combined in this way.
}{
\spadpaste{[i*j for i in ints for j in odds]\free{ints} \free{odds}}
}
\xtc{
}{
\spadpaste{map(*,ints,odds)\free{ints odds}}
}
\xtc{
Many operations similar to those applicable to lists are available for
streams.
}{
\spadpaste{first ints \free{ints}}
}
\xtc{
}{
\spadpaste{rest ints \free{ints}}
}
\xtc{
}{
\spadpaste{fibs 20 \free{fibs}}
}
The packages \spadtype{StreamFunctions1},
\spadtype{StreamFunctions2} and
\spadtype{StreamFunctions3} export some useful stream manipulation
operations.
For more information, see
\downlink{``Creating Lists and Streams with Iterators''}
{ugLangItsPage} in Section 5.5\ignore{ugLangIts},
\downlink{``Working with Power Series''}{ugProblemSeriesPage} 
in Section 8.9\ignore{ugProblemSeries},
\downlink{`ContinuedFraction'}{ContinuedFractionXmpPage}
\ignore{ContinuedFraction}, and
\downlink{`List'}{ListXmpPage}\ignore{List}.
%
\showBlurb{Stream}
\endscroll
\autobuttons
\end{page}

\begin{patch}{StreamXmpPagePatch1}
\begin{paste}{StreamXmpPageFull1}{StreamXmpPageEmpty1}
\pastebutton{StreamXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{ints := [i for i in 0..]\bound{ints }}
\indentrel{3}\begin{verbatim}
   (1)  [0,1,2,3,4,5,6,7,8,9,...]
                        Type: Stream NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StreamXmpPageEmpty1}
\begin{paste}{StreamXmpPageEmpty1}{StreamXmpPagePatch1}
\pastebutton{StreamXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{ints := [i for i in 0..]\bound{ints }}
\end{paste}\end{patch}

\begin{patch}{StreamXmpPagePatch2}
\begin{paste}{StreamXmpPageFull2}{StreamXmpPageEmpty2}
\pastebutton{StreamXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{f : List INT -> List INT\bound{fdec }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StreamXmpPageEmpty2}
\begin{paste}{StreamXmpPageEmpty2}{StreamXmpPagePatch2}
\pastebutton{StreamXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{f : List INT -> List INT\bound{fdec }}
\end{paste}\end{patch}

\begin{patch}{StreamXmpPagePatch3}
\begin{paste}{StreamXmpPageFull3}{StreamXmpPageEmpty3}
\pastebutton{StreamXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{f x == [x.1 + x.2, x.1]\bound{f }\free{fdec }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StreamXmpPageEmpty3}
\begin{paste}{StreamXmpPageEmpty3}{StreamXmpPagePatch3}
\pastebutton{StreamXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{f x == [x.1 + x.2, x.1]\bound{f }\free{fdec }}
\end{paste}\end{patch}

\begin{patch}{StreamXmpPagePatch4}
\begin{paste}{StreamXmpPageFull4}{StreamXmpPageEmpty4}
\pastebutton{StreamXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{fibs := [i.2 for i in [generate(f,[1,1])]]\bound{fibs }\free{f }}
\indentrel{3}\begin{verbatim}
   (4)  [1,1,2,3,5,8,13,21,34,55,...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StreamXmpPageEmpty4}
\begin{paste}{StreamXmpPageEmpty4}{StreamXmpPagePatch4}
\pastebutton{StreamXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{fibs := [i.2 for i in [generate(f,[1,1])]]\bound{fibs }\free{f }}
\end{paste}\end{patch}

\begin{patch}{StreamXmpPagePatch5}
\begin{paste}{StreamXmpPageFull5}{StreamXmpPageEmpty5}
\pastebutton{StreamXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{[i for i in ints | odd? i]\free{ints }}
\indentrel{3}\begin{verbatim}
   (5)  [1,3,5,7,9,11,13,15,17,19,...]
                        Type: Stream NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StreamXmpPageEmpty5}
\begin{paste}{StreamXmpPageEmpty5}{StreamXmpPagePatch5}
\pastebutton{StreamXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{[i for i in ints | odd? i]\free{ints }}
\end{paste}\end{patch}

\begin{patch}{StreamXmpPagePatch6}
\begin{paste}{StreamXmpPageFull6}{StreamXmpPageEmpty6}
\pastebutton{StreamXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{odds := [2*i+1 for i in ints]\bound{odds }\free{ints }}
\indentrel{3}\begin{verbatim}
   (6)  [1,3,5,7,9,11,13,15,17,19,...]
                        Type: Stream NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StreamXmpPageEmpty6}
\begin{paste}{StreamXmpPageEmpty6}{StreamXmpPagePatch6}
\pastebutton{StreamXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{odds := [2*i+1 for i in ints]\bound{odds }\free{ints }}
\end{paste}\end{patch}

\begin{patch}{StreamXmpPagePatch7}
\begin{paste}{StreamXmpPageFull7}{StreamXmpPageEmpty7}
\pastebutton{StreamXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{scan(0,+,odds)\free{odds }}
\indentrel{3}\begin{verbatim}
   (7)  [1,4,9,16,25,36,49,64,81,100,...]
                        Type: Stream NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StreamXmpPageEmpty7}
\begin{paste}{StreamXmpPageEmpty7}{StreamXmpPagePatch7}
\pastebutton{StreamXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{scan(0,+,odds)\free{odds }}
\end{paste}\end{patch}

\begin{patch}{StreamXmpPagePatch8}
\begin{paste}{StreamXmpPageFull8}{StreamXmpPageEmpty8}
\pastebutton{StreamXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{[i*j for i in ints for j in odds]\free{ints }\free{odds }}
\indentrel{3}\begin{verbatim}
   (8)  [0,3,10,21,36,55,78,105,136,171,...]
                        Type: Stream NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StreamXmpPageEmpty8}
\begin{paste}{StreamXmpPageEmpty8}{StreamXmpPagePatch8}
\pastebutton{StreamXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{[i*j for i in ints for j in odds]\free{ints }\free{odds }}
\end{paste}\end{patch}

\begin{patch}{StreamXmpPagePatch9}
\begin{paste}{StreamXmpPageFull9}{StreamXmpPageEmpty9}
\pastebutton{StreamXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{map(*,ints,odds)\free{ints odds }}
\indentrel{3}\begin{verbatim}
   (9)  [0,3,10,21,36,55,78,105,136,171,...]
                        Type: Stream NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StreamXmpPageEmpty9}
\begin{paste}{StreamXmpPageEmpty9}{StreamXmpPagePatch9}
\pastebutton{StreamXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{map(*,ints,odds)\free{ints odds }}
\end{paste}\end{patch}

\begin{patch}{StreamXmpPagePatch10}
\begin{paste}{StreamXmpPageFull10}{StreamXmpPageEmpty10}
\pastebutton{StreamXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{first ints\free{ints }}
\indentrel{3}\begin{verbatim}
   (10)  0
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StreamXmpPageEmpty10}
\begin{paste}{StreamXmpPageEmpty10}{StreamXmpPagePatch10}
\pastebutton{StreamXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{first ints\free{ints }}
\end{paste}\end{patch}

\begin{patch}{StreamXmpPagePatch11}
\begin{paste}{StreamXmpPageFull11}{StreamXmpPageEmpty11}
\pastebutton{StreamXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{rest ints\free{ints }}
\indentrel{3}\begin{verbatim}
   (11)  [1,2,3,4,5,6,7,8,9,10,...]
                        Type: Stream NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StreamXmpPageEmpty11}
\begin{paste}{StreamXmpPageEmpty11}{StreamXmpPagePatch11}
\pastebutton{StreamXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{rest ints\free{ints }}
\end{paste}\end{patch}

\begin{patch}{StreamXmpPagePatch12}
\begin{paste}{StreamXmpPageFull12}{StreamXmpPageEmpty12}
\pastebutton{StreamXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{fibs 20\free{fibs }}
\indentrel{3}\begin{verbatim}
   (12)  6765
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StreamXmpPageEmpty12}
\begin{paste}{StreamXmpPageEmpty12}{StreamXmpPagePatch12}
\pastebutton{StreamXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{fibs 20\free{fibs }}
\end{paste}\end{patch}

\end{chunk}
\section{string.ht}
\pagetitle{StringXmpPage}{string.ht}{String}
\pageto{notitle}{CharacterXmpPage}
\pageto{notitle}{CharacterClassXmpPage}
\begin{chunk}{string.ht}
\begin{page}{StringXmpPage}{String}
\beginscroll

The type \spadtype{String} provides character strings.  Character
strings provide all the operations for a one-dimensional array of
characters, plus additional operations for manipulating text.  For
more information on related topics, see
\downlink{`Character'}{CharacterXmpPage}\ignore{Character} and
\downlink{`CharacterClass'}{CharacterClassXmpPage}\ignore{CharacterClass}.
You can also issue the system command \spadcmd{)show String} to
display the full list of operations defined by \spadtype{String}.

\xtc{
String values can be created using double quotes.
}{
\spadpaste{hello := "Hello, I'm Axiom!" \bound{hello}}
}
\xtc{
Note, however, that double quotes and underscores must be preceded by
an extra underscore.
}{
\spadpaste{said  := "Jane said, _"Look!_"" \bound{said}}
}
\xtc{
}{
\spadpaste{saw   := "She saw exactly one underscore: __." \bound{saw}}
}
\xtc{
It is also possible to use \spadfunFrom{new}{String} to create a
string of any size filled with a given character.  Since there are
many \spadfun{new} functions it is necessary to indicate the desired
type.
}{
\spadpaste{gasp: String := new(32, char "x") \bound{gasp}}
}
\xtc{
The length of a string is given by \spadopFrom{\#}{List}.
}{
\spadpaste{\#gasp \free{gasp}}
}
\xtc{
Indexing operations allow characters to be extracted or replaced in 
strings. For any string \spad{s}, 
indices lie in the range \spad{1..\#s}.
}{
\spadpaste{hello.2 \free{hello}}
}
\xtc{
Indexing is really just the application of a string to a subscript,
so any application syntax works.
}{
\spadpaste{hello 2  \free{hello}}
}
\xtc{
}{
\spadpaste{hello(2) \free{hello}}
}
\xtc{
If it is important not to modify a given string, it should be copied
before any updating operations are used.
}{
\spadpaste{hullo := copy hello \free{hello}\bound{hullo0}}
}
\xtc{
}{
\spadpaste{hullo.2 := char "u"; [hello, hullo] \free{hullo0 hello}
\bound{hullo}}
}

\xtc{
Operations are provided to split and join strings.
The \spadfunFrom{concat}{String} operation allows several strings 
to be joined together.
}{
\spadpaste{saidsaw := concat ["alpha","---","omega"] \bound{saidsaw}}
}
\xtc{
There is a version of \spadfunFrom{concat}{String} that works with
two strings.
}{
\spadpaste{concat("hello ","goodbye")}
}
\xtc{
Juxtaposition can also be used to concatenate strings.
}{
\spadpaste{"This " "is " "several " "strings " "concatenated."}
}
\xtc{
Substrings are obtained by giving an index range.
}{
\spadpaste{hello(1..5) \free{hello}}
}
\xtc{
}{
\spadpaste{hello(8..) \free{hello}}
}
\xtc{
A string can be split into several substrings by giving a 
separation character or character class.
}{
\spadpaste{split(hello, char " ")              \free{hello}}
}
\xtc{
}{
\spadpaste{other := complement alphanumeric(); \bound{other}}
}
\xtc{
}{
\spadpaste{split(saidsaw, other)               \free{saidsaw other}}
}
\xtc{
Unwanted characters can be trimmed from the beginning or end of a
string using the operations \spadfunFrom{trim}{String},
\spadfunFrom{leftTrim}{String} and \spadfunFrom{rightTrim}{String}.
}{
\spadpaste{trim     ("\#\# ++ relax ++ \#\#", char "\#")}
}
\xtc{
Each of these functions takes a string and a second argument to specify
the characters to be discarded.
}{
\spadpaste{trim     ("\#\# ++ relax ++ \#\#", other) \free{other}}
}
\xtc{
The second argument can be given
either as a single character or as a character class.
}{
\spadpaste{leftTrim ("\#\# ++ relax ++ \#\#", other) \free{other}}
}
\xtc{
}{
\spadpaste{rightTrim("\#\# ++ relax ++ \#\#", other) \free{other}}
}

\xtc{
Strings can be changed to upper case or lower case using the operations
\spadfunFrom{upperCase}{String}, \spadfunFromX{upperCase}{String}, 
\spadfunFrom{lowerCase}{String} and
\spadfunFromX{lowerCase}{String}.
}{
\spadpaste{upperCase hello \free{hello}}
}
\xtc{
The versions with the exclamation mark
change the original string, while the others produce a copy.
}{
\spadpaste{lowerCase hello \free{hello}}
}

\xtc{
Some basic string matching is provided.
The function \spadfunFrom{prefix?}{String}
tests whether one string is an initial prefix of another.
}{
\spadpaste{prefix?("He", "Hello")}
}
\xtc{
}{
\spadpaste{prefix?("Her", "Hello")}
}
\xtc{
A similar function, \spadfunFrom{suffix?}{String}, tests for suffixes.
}{
\spadpaste{suffix?("", "Hello")}
}
\xtc{
}{
\spadpaste{suffix?("LO", "Hello")}
}
\xtc{
The function \spadfunFrom{substring?}{String} tests for a substring 
given a starting
position.
}{
\spadpaste{substring?("ll", "Hello", 3)}
}
\xtc{
}{
\spadpaste{substring?("ll", "Hello", 4)}
}

\xtc{
A number of \spadfunFrom{position}{String} functions locate things in
strings.  If the first argument to position is a string, then
\spad{position(s,t,i)} finds the location of \spad{s} as a substring
of \spad{t} starting the search at position \spad{i}.
}{
\spadpaste{n := position("nd", "underground",   1) \bound{n}}
}
\xtc{
}{
\spadpaste{n := position("nd", "underground", n+1) \free{n} \bound{n1}}
}
\xtc{
If \spad{s} is not found, then \spad{0} is returned (\spad{minIndex(s)-1}
in \spadtype{IndexedString}).
}{
\spadpaste{n := position("nd", "underground", n+1) \free{n1}\bound{n2}}
}
\xtc{
To search for a specific character or a member of a character class,
a different first argument is used.
}{
\spadpaste{position(char "d", "underground", 1)}
}
\xtc{
}{
\spadpaste{position(hexDigit(), "underground", 1)}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{StringXmpPagePatch1}
\begin{paste}{StringXmpPageFull1}{StringXmpPageEmpty1}
\pastebutton{StringXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{hello := "Hello, I'm AXIOM!"\bound{hello }}
\indentrel{3}\begin{verbatim}
   (1)  "Hello, I'm AXIOM!"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty1}
\begin{paste}{StringXmpPageEmpty1}{StringXmpPagePatch1}
\pastebutton{StringXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{hello := "Hello, I'm AXIOM!"\bound{hello }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch2}
\begin{paste}{StringXmpPageFull2}{StringXmpPageEmpty2}
\pastebutton{StringXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{said := "Jane said, _"Look!_""\bound{said }}
\indentrel{3}\begin{verbatim}
   (2)  "Jane said, "Look!""
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty2}
\begin{paste}{StringXmpPageEmpty2}{StringXmpPagePatch2}
\pastebutton{StringXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{said := "Jane said, _"Look!_""\bound{said }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch3}
\begin{paste}{StringXmpPageFull3}{StringXmpPageEmpty3}
\pastebutton{StringXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{saw := "She saw exactly one underscore: __."\bound{saw }}
\indentrel{3}\begin{verbatim}
   (3)  "She saw exactly one underscore: _."
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty3}
\begin{paste}{StringXmpPageEmpty3}{StringXmpPagePatch3}
\pastebutton{StringXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{saw := "She saw exactly one underscore: __."\bound{saw }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch4}
\begin{paste}{StringXmpPageFull4}{StringXmpPageEmpty4}
\pastebutton{StringXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{gasp: String := new(32, char "x")\bound{gasp }}
\indentrel{3}\begin{verbatim}
   (4)  "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty4}
\begin{paste}{StringXmpPageEmpty4}{StringXmpPagePatch4}
\pastebutton{StringXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{gasp: String := new(32, char "x")\bound{gasp }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch5}
\begin{paste}{StringXmpPageFull5}{StringXmpPageEmpty5}
\pastebutton{StringXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{\#gasp\free{gasp }}
\indentrel{3}\begin{verbatim}
   (5)  32
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty5}
\begin{paste}{StringXmpPageEmpty5}{StringXmpPagePatch5}
\pastebutton{StringXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{\#gasp\free{gasp }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch6}
\begin{paste}{StringXmpPageFull6}{StringXmpPageEmpty6}
\pastebutton{StringXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{hello.2\free{hello }}
\indentrel{3}\begin{verbatim}
   (6)  e
                                        Type: Character
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty6}
\begin{paste}{StringXmpPageEmpty6}{StringXmpPagePatch6}
\pastebutton{StringXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{hello.2\free{hello }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch7}
\begin{paste}{StringXmpPageFull7}{StringXmpPageEmpty7}
\pastebutton{StringXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{hello 2\free{hello }}
\indentrel{3}\begin{verbatim}
   (7)  e
                                        Type: Character
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty7}
\begin{paste}{StringXmpPageEmpty7}{StringXmpPagePatch7}
\pastebutton{StringXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{hello 2\free{hello }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch8}
\begin{paste}{StringXmpPageFull8}{StringXmpPageEmpty8}
\pastebutton{StringXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{hello(2)\free{hello }}
\indentrel{3}\begin{verbatim}
   (8)  e
                                        Type: Character
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty8}
\begin{paste}{StringXmpPageEmpty8}{StringXmpPagePatch8}
\pastebutton{StringXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{hello(2)\free{hello }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch9}
\begin{paste}{StringXmpPageFull9}{StringXmpPageEmpty9}
\pastebutton{StringXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{hullo := copy hello\free{hello }\bound{hullo0 }}
\indentrel{3}\begin{verbatim}
   (9)  "Hello, I'm AXIOM!"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty9}
\begin{paste}{StringXmpPageEmpty9}{StringXmpPagePatch9}
\pastebutton{StringXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{hullo := copy hello\free{hello }\bound{hullo0 }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch10}
\begin{paste}{StringXmpPageFull10}{StringXmpPageEmpty10}
\pastebutton{StringXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{hullo.2 := char "u"; [hello, hullo]\free{hullo0 hello }\bound{hullo }}
\indentrel{3}\begin{verbatim}
   (10)  ["Hello, I'm AXIOM!","Hullo, I'm AXIOM!"]
                                      Type: List String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty10}
\begin{paste}{StringXmpPageEmpty10}{StringXmpPagePatch10}
\pastebutton{StringXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{hullo.2 := char "u"; [hello, hullo]\free{hullo0 hello }\bound{hullo }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch11}
\begin{paste}{StringXmpPageFull11}{StringXmpPageEmpty11}
\pastebutton{StringXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{saidsaw := concat ["alpha","---","omega"]\bound{saidsaw }}
\indentrel{3}\begin{verbatim}
   (11)  "alpha---omega"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty11}
\begin{paste}{StringXmpPageEmpty11}{StringXmpPagePatch11}
\pastebutton{StringXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{saidsaw := concat ["alpha","---","omega"]\bound{saidsaw }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch12}
\begin{paste}{StringXmpPageFull12}{StringXmpPageEmpty12}
\pastebutton{StringXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{concat("hello ","goodbye")}
\indentrel{3}\begin{verbatim}
   (12)  "hello goodbye"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty12}
\begin{paste}{StringXmpPageEmpty12}{StringXmpPagePatch12}
\pastebutton{StringXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{concat("hello ","goodbye")}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch13}
\begin{paste}{StringXmpPageFull13}{StringXmpPageEmpty13}
\pastebutton{StringXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{"This " "is " "several " "strings " "concatenated."}
\indentrel{3}\begin{verbatim}
   (13)  "This is several strings concatenated."
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty13}
\begin{paste}{StringXmpPageEmpty13}{StringXmpPagePatch13}
\pastebutton{StringXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{"This " "is " "several " "strings " "concatenated."}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch14}
\begin{paste}{StringXmpPageFull14}{StringXmpPageEmpty14}
\pastebutton{StringXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{hello(1..5)\free{hello }}
\indentrel{3}\begin{verbatim}
   (14)  "Hello"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty14}
\begin{paste}{StringXmpPageEmpty14}{StringXmpPagePatch14}
\pastebutton{StringXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{hello(1..5)\free{hello }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch15}
\begin{paste}{StringXmpPageFull15}{StringXmpPageEmpty15}
\pastebutton{StringXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{hello(8..)\free{hello }}
\indentrel{3}\begin{verbatim}
   (15)  "I'm AXIOM!"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty15}
\begin{paste}{StringXmpPageEmpty15}{StringXmpPagePatch15}
\pastebutton{StringXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{hello(8..)\free{hello }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch16}
\begin{paste}{StringXmpPageFull16}{StringXmpPageEmpty16}
\pastebutton{StringXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{split(hello, char " ")\free{hello }}
\indentrel{3}\begin{verbatim}
   (16)  ["Hello,","I'm","AXIOM!"]
                                      Type: List String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty16}
\begin{paste}{StringXmpPageEmpty16}{StringXmpPagePatch16}
\pastebutton{StringXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{split(hello, char " ")\free{hello }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch17}
\begin{paste}{StringXmpPageFull17}{StringXmpPageEmpty17}
\pastebutton{StringXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{other := complement alphanumeric();\bound{other }}
\indentrel{3}\begin{verbatim}
                                   Type: CharacterClass
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty17}
\begin{paste}{StringXmpPageEmpty17}{StringXmpPagePatch17}
\pastebutton{StringXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{other := complement alphanumeric();\bound{other }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch18}
\begin{paste}{StringXmpPageFull18}{StringXmpPageEmpty18}
\pastebutton{StringXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{split(saidsaw, other)\free{saidsaw other }}
\indentrel{3}\begin{verbatim}
   (18)  ["alpha","omega"]
                                      Type: List String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty18}
\begin{paste}{StringXmpPageEmpty18}{StringXmpPagePatch18}
\pastebutton{StringXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{split(saidsaw, other)\free{saidsaw other }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch19}
\begin{paste}{StringXmpPageFull19}{StringXmpPageEmpty19}
\pastebutton{StringXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{trim ("\#\# ++ relax ++ \#\#", char "\#")}
\indentrel{3}\begin{verbatim}
   (19)  " ++ relax ++ "
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty19}
\begin{paste}{StringXmpPageEmpty19}{StringXmpPagePatch19}
\pastebutton{StringXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{trim ("\#\# ++ relax ++ \#\#", char "\#")}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch20}
\begin{paste}{StringXmpPageFull20}{StringXmpPageEmpty20}
\pastebutton{StringXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{trim ("\#\# ++ relax ++ \#\#", other)\free{other }}
\indentrel{3}\begin{verbatim}
   (20)  "relax"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty20}
\begin{paste}{StringXmpPageEmpty20}{StringXmpPagePatch20}
\pastebutton{StringXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{trim ("\#\# ++ relax ++ \#\#", other)\free{other }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch21}
\begin{paste}{StringXmpPageFull21}{StringXmpPageEmpty21}
\pastebutton{StringXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{leftTrim ("\#\# ++ relax ++ \#\#", other)\free{other }}
\indentrel{3}\begin{verbatim}
   (21)  "relax ++ ##"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty21}
\begin{paste}{StringXmpPageEmpty21}{StringXmpPagePatch21}
\pastebutton{StringXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{leftTrim ("\#\# ++ relax ++ \#\#", other)\free{other }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch22}
\begin{paste}{StringXmpPageFull22}{StringXmpPageEmpty22}
\pastebutton{StringXmpPageFull22}{\hidepaste}
\tab{5}\spadcommand{rightTrim("\#\# ++ relax ++ \#\#", other)\free{other }}
\indentrel{3}\begin{verbatim}
   (22)  "## ++ relax"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty22}
\begin{paste}{StringXmpPageEmpty22}{StringXmpPagePatch22}
\pastebutton{StringXmpPageEmpty22}{\showpaste}
\tab{5}\spadcommand{rightTrim("\#\# ++ relax ++ \#\#", other)\free{other }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch23}
\begin{paste}{StringXmpPageFull23}{StringXmpPageEmpty23}
\pastebutton{StringXmpPageFull23}{\hidepaste}
\tab{5}\spadcommand{upperCase hello\free{hello }}
\indentrel{3}\begin{verbatim}
   (23)  "HELLO, I'M AXIOM!"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty23}
\begin{paste}{StringXmpPageEmpty23}{StringXmpPagePatch23}
\pastebutton{StringXmpPageEmpty23}{\showpaste}
\tab{5}\spadcommand{upperCase hello\free{hello }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch24}
\begin{paste}{StringXmpPageFull24}{StringXmpPageEmpty24}
\pastebutton{StringXmpPageFull24}{\hidepaste}
\tab{5}\spadcommand{lowerCase hello\free{hello }}
\indentrel{3}\begin{verbatim}
   (24)  "hello, i'm axiom!"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty24}
\begin{paste}{StringXmpPageEmpty24}{StringXmpPagePatch24}
\pastebutton{StringXmpPageEmpty24}{\showpaste}
\tab{5}\spadcommand{lowerCase hello\free{hello }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch25}
\begin{paste}{StringXmpPageFull25}{StringXmpPageEmpty25}
\pastebutton{StringXmpPageFull25}{\hidepaste}
\tab{5}\spadcommand{prefix?("He", "Hello")}
\indentrel{3}\begin{verbatim}
   (25)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty25}
\begin{paste}{StringXmpPageEmpty25}{StringXmpPagePatch25}
\pastebutton{StringXmpPageEmpty25}{\showpaste}
\tab{5}\spadcommand{prefix?("He", "Hello")}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch26}
\begin{paste}{StringXmpPageFull26}{StringXmpPageEmpty26}
\pastebutton{StringXmpPageFull26}{\hidepaste}
\tab{5}\spadcommand{prefix?("Her", "Hello")}
\indentrel{3}\begin{verbatim}
   (26)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty26}
\begin{paste}{StringXmpPageEmpty26}{StringXmpPagePatch26}
\pastebutton{StringXmpPageEmpty26}{\showpaste}
\tab{5}\spadcommand{prefix?("Her", "Hello")}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch27}
\begin{paste}{StringXmpPageFull27}{StringXmpPageEmpty27}
\pastebutton{StringXmpPageFull27}{\hidepaste}
\tab{5}\spadcommand{suffix?("", "Hello")}
\indentrel{3}\begin{verbatim}
   (27)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty27}
\begin{paste}{StringXmpPageEmpty27}{StringXmpPagePatch27}
\pastebutton{StringXmpPageEmpty27}{\showpaste}
\tab{5}\spadcommand{suffix?("", "Hello")}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch28}
\begin{paste}{StringXmpPageFull28}{StringXmpPageEmpty28}
\pastebutton{StringXmpPageFull28}{\hidepaste}
\tab{5}\spadcommand{suffix?("LO", "Hello")}
\indentrel{3}\begin{verbatim}
   (28)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty28}
\begin{paste}{StringXmpPageEmpty28}{StringXmpPagePatch28}
\pastebutton{StringXmpPageEmpty28}{\showpaste}
\tab{5}\spadcommand{suffix?("LO", "Hello")}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch29}
\begin{paste}{StringXmpPageFull29}{StringXmpPageEmpty29}
\pastebutton{StringXmpPageFull29}{\hidepaste}
\tab{5}\spadcommand{substring?("ll", "Hello", 3)}
\indentrel{3}\begin{verbatim}
   (29)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty29}
\begin{paste}{StringXmpPageEmpty29}{StringXmpPagePatch29}
\pastebutton{StringXmpPageEmpty29}{\showpaste}
\tab{5}\spadcommand{substring?("ll", "Hello", 3)}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch30}
\begin{paste}{StringXmpPageFull30}{StringXmpPageEmpty30}
\pastebutton{StringXmpPageFull30}{\hidepaste}
\tab{5}\spadcommand{substring?("ll", "Hello", 4)}
\indentrel{3}\begin{verbatim}
   (30)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty30}
\begin{paste}{StringXmpPageEmpty30}{StringXmpPagePatch30}
\pastebutton{StringXmpPageEmpty30}{\showpaste}
\tab{5}\spadcommand{substring?("ll", "Hello", 4)}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch31}
\begin{paste}{StringXmpPageFull31}{StringXmpPageEmpty31}
\pastebutton{StringXmpPageFull31}{\hidepaste}
\tab{5}\spadcommand{n := position("nd", "underground", 1)\bound{n }}
\indentrel{3}\begin{verbatim}
   (31)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty31}
\begin{paste}{StringXmpPageEmpty31}{StringXmpPagePatch31}
\pastebutton{StringXmpPageEmpty31}{\showpaste}
\tab{5}\spadcommand{n := position("nd", "underground", 1)\bound{n }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch32}
\begin{paste}{StringXmpPageFull32}{StringXmpPageEmpty32}
\pastebutton{StringXmpPageFull32}{\hidepaste}
\tab{5}\spadcommand{n := position("nd", "underground", n+1)\free{n }\bound{n1 }}
\indentrel{3}\begin{verbatim}
   (32)  10
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty32}
\begin{paste}{StringXmpPageEmpty32}{StringXmpPagePatch32}
\pastebutton{StringXmpPageEmpty32}{\showpaste}
\tab{5}\spadcommand{n := position("nd", "underground", n+1)\free{n }\bound{n1 }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch33}
\begin{paste}{StringXmpPageFull33}{StringXmpPageEmpty33}
\pastebutton{StringXmpPageFull33}{\hidepaste}
\tab{5}\spadcommand{n := position("nd", "underground", n+1)\free{n1 }\bound{n2 }}
\indentrel{3}\begin{verbatim}
   (33)  0
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty33}
\begin{paste}{StringXmpPageEmpty33}{StringXmpPagePatch33}
\pastebutton{StringXmpPageEmpty33}{\showpaste}
\tab{5}\spadcommand{n := position("nd", "underground", n+1)\free{n1 }\bound{n2 }}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch34}
\begin{paste}{StringXmpPageFull34}{StringXmpPageEmpty34}
\pastebutton{StringXmpPageFull34}{\hidepaste}
\tab{5}\spadcommand{position(char "d", "underground", 1)}
\indentrel{3}\begin{verbatim}
   (34)  3
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty34}
\begin{paste}{StringXmpPageEmpty34}{StringXmpPagePatch34}
\pastebutton{StringXmpPageEmpty34}{\showpaste}
\tab{5}\spadcommand{position(char "d", "underground", 1)}
\end{paste}\end{patch}

\begin{patch}{StringXmpPagePatch35}
\begin{paste}{StringXmpPageFull35}{StringXmpPageEmpty35}
\pastebutton{StringXmpPageFull35}{\hidepaste}
\tab{5}\spadcommand{position(hexDigit(), "underground", 1)}
\indentrel{3}\begin{verbatim}
   (35)  3
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringXmpPageEmpty35}
\begin{paste}{StringXmpPageEmpty35}{StringXmpPagePatch35}
\pastebutton{StringXmpPageEmpty35}{\showpaste}
\tab{5}\spadcommand{position(hexDigit(), "underground", 1)}
\end{paste}\end{patch}

\end{chunk}
\section{strtbl.ht}
\pagetitle{StringTableXmpPage}{strtbl.ht}{StringTable}
\pageto{notitle}{TableXmpPage}
\begin{chunk}{strtbl.ht}
\begin{page}{StringTableXmpPage}{StringTable}
\beginscroll
%
This domain provides a table type in which the keys are known to
be strings so special techniques can be used.
Other than performance, the type \spadtype{StringTable(S)} should
behave exactly the same way as \spadtype{Table(String,S)}.
See \downlink{`Table'}{TableXmpPage}\ignore{Table} 
for general information about tables.
\showBlurb{StringTable}

\xtc{
This creates a new table whose keys are strings.
}{
\spadpaste{t: StringTable(Integer) := table()  \bound{t}}
}
\xtc{
The value associated with each string key is the number of
characters in the string.
}{
\begin{spadsrc}[\free{t}\bound{h}]
for s in split("My name is Ian Watt.",char " ")
  repeat
    t.s := #s
\end{spadsrc}
}
\xtc{
}{
\spadpaste{for key in keys t repeat output [key, t.key] \free{t h}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{StringTableXmpPagePatch1}
\begin{paste}{StringTableXmpPageFull1}{StringTableXmpPageEmpty1}
\pastebutton{StringTableXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{t: StringTable(Integer) := table()\bound{t }}
\indentrel{3}\begin{verbatim}
   (1)  table()
                              Type: StringTable Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringTableXmpPageEmpty1}
\begin{paste}{StringTableXmpPageEmpty1}{StringTableXmpPagePatch1}
\pastebutton{StringTableXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{t: StringTable(Integer) := table()\bound{t }}
\end{paste}\end{patch}

\begin{patch}{StringTableXmpPagePatch2}
\begin{paste}{StringTableXmpPageFull2}{StringTableXmpPageEmpty2}
\pastebutton{StringTableXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{for s in split("My name is Ian Watt.",char " ")
  repeat
    t.s := \#s
\free{t }\bound{h }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringTableXmpPageEmpty2}
\begin{paste}{StringTableXmpPageEmpty2}{StringTableXmpPagePatch2}
\pastebutton{StringTableXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{for s in split("My name is Ian Watt.",char " ")
  repeat
    t.s := \#s
\free{t }\bound{h }}
\end{paste}\end{patch}

\begin{patch}{StringTableXmpPagePatch3}
\begin{paste}{StringTableXmpPageFull3}{StringTableXmpPageEmpty3}
\pastebutton{StringTableXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{for key in keys t repeat output [key, t.key]\free{t h }}
\indentrel{3}\begin{verbatim}
   ["Ian",3]
   ["My",2]
   ["Watt.",5]
   ["name",4]
   ["is",2]
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{StringTableXmpPageEmpty3}
\begin{paste}{StringTableXmpPageEmpty3}{StringTableXmpPagePatch3}
\pastebutton{StringTableXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{for key in keys t repeat output [key, t.key]\free{t h }}
\end{paste}\end{patch}

\end{chunk}
\section{symbol.ht}
\pagetitle{SymbolXmpPage}{symbol.ht}{Symbol}
\begin{chunk}{symbol.ht}
\begin{page}{SymbolXmpPage}{Symbol}
\beginscroll
 
Symbols are one of the basic types manipulated by Axiom.
The \spadtype{Symbol} domain provides ways to create
symbols of many varieties.
\showBlurb{Symbol}
 
\xtc{
The simplest way to create a symbol is to ``single quote'' an identifier.
}{
\spadpaste{X: Symbol := 'x \bound{X}}
}
\xtc{
This gives the symbol even if \spad{x} has been assigned a value.
If \spad{x} has not been assigned a value, then it is possible to omit
the quote.
}{
\spadpaste{XX: Symbol := x}
}
\xtc{
Declarations must be used when working
with symbols, because otherwise the interpreter tries to place
values in a more specialized type \spadtype{Variable}.
}{
\spadpaste{A := 'a}
}
\xtc{
}{
\spadpaste{B := b}
}
\xtc{
The normal way of entering polynomials uses this fact.
}{
\spadpaste{x**2 + 1}
}
 
\xtc{
Another convenient way to create symbols is to convert a string.
This is useful when the name is to be constructed by a program.
}{
\spadpaste{"Hello"::Symbol}
}
\xtc{
Sometimes it is necessary to generate new unique symbols, for example, to
name constants of integration.
The expression \spad{new()} generates a symbol starting with \spad{\%}.
}{
\spadpaste{new()\$Symbol}
}
\xtc{
Successive calls to \spadfunFrom{new}{Symbol} produce different symbols.
}{
\spadpaste{new()\$Symbol}
}
\xtc{
The expression \spad{new("s")} produces a symbol starting with \spad{\%s}.
}{
\spadpaste{new("xyz")\$Symbol}
}
 
\xtc{
A symbol can be adorned in various ways.
The most basic thing is applying a symbol to a list
of subscripts.
}{
\spadpaste{X[i,j] \free{X}}
}
 
\xtc{
Somewhat less pretty is to attach subscripts, superscripts or arguments.
}{
\spadpaste{U := subscript(u, [1,2,1,2]) \bound{U}}
}
\xtc{
}{
\spadpaste{V := superscript(v, [n]) \bound{V}}
}
\xtc{
}{
\spadpaste{P := argscript(p, [t]) \bound{P}}
}
 
\xtc{
It is possible to test whether a symbol has scripts using the
\spadfunFrom{scripted?}{Symbol} test.
}{
\spadpaste{scripted? U \free{U}}
}
\xtc{
}{
\spadpaste{scripted? X \free{X}}
}
\xtc{
If a symbol is not scripted, then it may be converted to a string.
}{
\spadpaste{string X \free{X}}
}
\xtc{
The basic parts can always be extracted using the
\spadfunFrom{name}{Symbol} and \spadfunFrom{scripts}{Symbol} operations.
}{
\spadpaste{name U \free{U}}
}
\xtc{
}{
\spadpaste{scripts U \free{U}}
}
\xtc{
}{
\spadpaste{name X \free{X}}
}
\xtc{
}{
\spadpaste{scripts X \free{X}}
}
 
\xtc{
The most general form is obtained using the \spadfunFrom{script}{Symbol}
operation.
This operation takes an argument which is a list containing, in this order,
lists of subscripts, superscripts, presuperscripts, presubscripts and
arguments to a symbol.
}{
\spadpaste{M := script(Mammoth, [[i,j],[k,l],[0,1],[2],[u,v,w]]) 
\bound{M}}
}
\xtc{
}{
\spadpaste{scripts M \free{M}}
}
\xtc{
If trailing lists of scripts are omitted, they are assumed to be empty.
}{
\spadpaste{N := script(Nut, [[i,j],[k,l],[0,1]]) \bound{N}}
}
\xtc{
}{
\spadpaste{scripts N \free{N}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{SymbolXmpPagePatch1}
\begin{paste}{SymbolXmpPageFull1}{SymbolXmpPageEmpty1}
\pastebutton{SymbolXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{X: Symbol := 'x\bound{X }}
\indentrel{3}\begin{verbatim}
   (1)  x
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty1}
\begin{paste}{SymbolXmpPageEmpty1}{SymbolXmpPagePatch1}
\pastebutton{SymbolXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{X: Symbol := 'x\bound{X }}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch2}
\begin{paste}{SymbolXmpPageFull2}{SymbolXmpPageEmpty2}
\pastebutton{SymbolXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{XX: Symbol := x}
\indentrel{3}\begin{verbatim}
   (2)  x
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty2}
\begin{paste}{SymbolXmpPageEmpty2}{SymbolXmpPagePatch2}
\pastebutton{SymbolXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{XX: Symbol := x}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch3}
\begin{paste}{SymbolXmpPageFull3}{SymbolXmpPageEmpty3}
\pastebutton{SymbolXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{A := 'a}
\indentrel{3}\begin{verbatim}
   (3)  a
                                       Type: Variable a
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty3}
\begin{paste}{SymbolXmpPageEmpty3}{SymbolXmpPagePatch3}
\pastebutton{SymbolXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{A := 'a}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch4}
\begin{paste}{SymbolXmpPageFull4}{SymbolXmpPageEmpty4}
\pastebutton{SymbolXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{B := b}
\indentrel{3}\begin{verbatim}
   (4)  b
                                       Type: Variable b
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty4}
\begin{paste}{SymbolXmpPageEmpty4}{SymbolXmpPagePatch4}
\pastebutton{SymbolXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{B := b}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch5}
\begin{paste}{SymbolXmpPageFull5}{SymbolXmpPageEmpty5}
\pastebutton{SymbolXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{x**2 + 1}
\indentrel{3}\begin{verbatim}
         2
   (5)  x  + 1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty5}
\begin{paste}{SymbolXmpPageEmpty5}{SymbolXmpPagePatch5}
\pastebutton{SymbolXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{x**2 + 1}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch6}
\begin{paste}{SymbolXmpPageFull6}{SymbolXmpPageEmpty6}
\pastebutton{SymbolXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{"Hello"::Symbol}
\indentrel{3}\begin{verbatim}
   (6)  Hello
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty6}
\begin{paste}{SymbolXmpPageEmpty6}{SymbolXmpPagePatch6}
\pastebutton{SymbolXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{"Hello"::Symbol}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch7}
\begin{paste}{SymbolXmpPageFull7}{SymbolXmpPageEmpty7}
\pastebutton{SymbolXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{new()$Symbol}
\indentrel{3}\begin{verbatim}
   (7)  %A
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty7}
\begin{paste}{SymbolXmpPageEmpty7}{SymbolXmpPagePatch7}
\pastebutton{SymbolXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{new()$Symbol}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch8}
\begin{paste}{SymbolXmpPageFull8}{SymbolXmpPageEmpty8}
\pastebutton{SymbolXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{new()$Symbol}
\indentrel{3}\begin{verbatim}
   (8)  %B
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty8}
\begin{paste}{SymbolXmpPageEmpty8}{SymbolXmpPagePatch8}
\pastebutton{SymbolXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{new()$Symbol}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch9}
\begin{paste}{SymbolXmpPageFull9}{SymbolXmpPageEmpty9}
\pastebutton{SymbolXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{new("xyz")$Symbol}
\indentrel{3}\begin{verbatim}
   (9)  %xyz0
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty9}
\begin{paste}{SymbolXmpPageEmpty9}{SymbolXmpPagePatch9}
\pastebutton{SymbolXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{new("xyz")$Symbol}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch10}
\begin{paste}{SymbolXmpPageFull10}{SymbolXmpPageEmpty10}
\pastebutton{SymbolXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{X[i,j]\free{X }}
\indentrel{3}\begin{verbatim}
   (10)  x
          i,j
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty10}
\begin{paste}{SymbolXmpPageEmpty10}{SymbolXmpPagePatch10}
\pastebutton{SymbolXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{X[i,j]\free{X }}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch11}
\begin{paste}{SymbolXmpPageFull11}{SymbolXmpPageEmpty11}
\pastebutton{SymbolXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{U := subscript(u, [1,2,1,2])\bound{U }}
\indentrel{3}\begin{verbatim}
   (11)  u
          1,2,1,2
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty11}
\begin{paste}{SymbolXmpPageEmpty11}{SymbolXmpPagePatch11}
\pastebutton{SymbolXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{U := subscript(u, [1,2,1,2])\bound{U }}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch12}
\begin{paste}{SymbolXmpPageFull12}{SymbolXmpPageEmpty12}
\pastebutton{SymbolXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{V := superscript(v, [n])\bound{V }}
\indentrel{3}\begin{verbatim}
          n
   (12)  v
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty12}
\begin{paste}{SymbolXmpPageEmpty12}{SymbolXmpPagePatch12}
\pastebutton{SymbolXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{V := superscript(v, [n])\bound{V }}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch13}
\begin{paste}{SymbolXmpPageFull13}{SymbolXmpPageEmpty13}
\pastebutton{SymbolXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{P := argscript(p, [t])\bound{P }}
\indentrel{3}\begin{verbatim}
   (13)  p(t)
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty13}
\begin{paste}{SymbolXmpPageEmpty13}{SymbolXmpPagePatch13}
\pastebutton{SymbolXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{P := argscript(p, [t])\bound{P }}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch14}
\begin{paste}{SymbolXmpPageFull14}{SymbolXmpPageEmpty14}
\pastebutton{SymbolXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{scripted? U\free{U }}
\indentrel{3}\begin{verbatim}
   (14)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty14}
\begin{paste}{SymbolXmpPageEmpty14}{SymbolXmpPagePatch14}
\pastebutton{SymbolXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{scripted? U\free{U }}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch15}
\begin{paste}{SymbolXmpPageFull15}{SymbolXmpPageEmpty15}
\pastebutton{SymbolXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{scripted? X\free{X }}
\indentrel{3}\begin{verbatim}
   (15)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty15}
\begin{paste}{SymbolXmpPageEmpty15}{SymbolXmpPagePatch15}
\pastebutton{SymbolXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{scripted? X\free{X }}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch16}
\begin{paste}{SymbolXmpPageFull16}{SymbolXmpPageEmpty16}
\pastebutton{SymbolXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{string X\free{X }}
\indentrel{3}\begin{verbatim}
   (16)  "x"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty16}
\begin{paste}{SymbolXmpPageEmpty16}{SymbolXmpPagePatch16}
\pastebutton{SymbolXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{string X\free{X }}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch17}
\begin{paste}{SymbolXmpPageFull17}{SymbolXmpPageEmpty17}
\pastebutton{SymbolXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{name U\free{U }}
\indentrel{3}\begin{verbatim}
   (17)  u
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty17}
\begin{paste}{SymbolXmpPageEmpty17}{SymbolXmpPagePatch17}
\pastebutton{SymbolXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{name U\free{U }}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch18}
\begin{paste}{SymbolXmpPageFull18}{SymbolXmpPageEmpty18}
\pastebutton{SymbolXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{scripts U\free{U }}
\indentrel{3}\begin{verbatim}
   (18)
   [sub= [1,2,1,2],sup= [],presup= [],presub= [],args= []]
Type: Record(sub: List OutputForm,sup: List OutputForm,presup: List OutputForm,presub: List OutputForm,args: List OutputForm)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty18}
\begin{paste}{SymbolXmpPageEmpty18}{SymbolXmpPagePatch18}
\pastebutton{SymbolXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{scripts U\free{U }}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch19}
\begin{paste}{SymbolXmpPageFull19}{SymbolXmpPageEmpty19}
\pastebutton{SymbolXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{name X\free{X }}
\indentrel{3}\begin{verbatim}
   (19)  x
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty19}
\begin{paste}{SymbolXmpPageEmpty19}{SymbolXmpPagePatch19}
\pastebutton{SymbolXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{name X\free{X }}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch20}
\begin{paste}{SymbolXmpPageFull20}{SymbolXmpPageEmpty20}
\pastebutton{SymbolXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{scripts X\free{X }}
\indentrel{3}\begin{verbatim}
   (20)
   [sub= [],sup= [],presup= [],presub= [],args= []]
Type: Record(sub: List OutputForm,sup: List OutputForm,presup: List OutputForm,presub: List OutputForm,args: List OutputForm)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty20}
\begin{paste}{SymbolXmpPageEmpty20}{SymbolXmpPagePatch20}
\pastebutton{SymbolXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{scripts X\free{X }}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch21}
\begin{paste}{SymbolXmpPageFull21}{SymbolXmpPageEmpty21}
\pastebutton{SymbolXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{M := script(Mammoth, [[i,j],[k,l],[0,1],[2],[u,v,w]])\bound{M }}
\indentrel{3}\begin{verbatim}
         0,1       k,l
   (21)     Mammoth   (u,v,w)
           2       i,j
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty21}
\begin{paste}{SymbolXmpPageEmpty21}{SymbolXmpPagePatch21}
\pastebutton{SymbolXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{M := script(Mammoth, [[i,j],[k,l],[0,1],[2],[u,v,w]])\bound{M }}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch22}
\begin{paste}{SymbolXmpPageFull22}{SymbolXmpPageEmpty22}
\pastebutton{SymbolXmpPageFull22}{\hidepaste}
\tab{5}\spadcommand{scripts M\free{M }}
\indentrel{3}\begin{verbatim}
   (22)
   [sub= [i,j], sup= [k,l], presup= [0,1], presub= [2],
    args= [u,v,w]]
Type: Record(sub: List OutputForm,sup: List OutputForm,presup: List OutputForm,presub: List OutputForm,args: List OutputForm)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty22}
\begin{paste}{SymbolXmpPageEmpty22}{SymbolXmpPagePatch22}
\pastebutton{SymbolXmpPageEmpty22}{\showpaste}
\tab{5}\spadcommand{scripts M\free{M }}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch23}
\begin{paste}{SymbolXmpPageFull23}{SymbolXmpPageEmpty23}
\pastebutton{SymbolXmpPageFull23}{\hidepaste}
\tab{5}\spadcommand{N := script(Nut, [[i,j],[k,l],[0,1]])\bound{N }}
\indentrel{3}\begin{verbatim}
         0,1   k,l
   (23)     Nut
               i,j
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty23}
\begin{paste}{SymbolXmpPageEmpty23}{SymbolXmpPagePatch23}
\pastebutton{SymbolXmpPageEmpty23}{\showpaste}
\tab{5}\spadcommand{N := script(Nut, [[i,j],[k,l],[0,1]])\bound{N }}
\end{paste}\end{patch}

\begin{patch}{SymbolXmpPagePatch24}
\begin{paste}{SymbolXmpPageFull24}{SymbolXmpPageEmpty24}
\pastebutton{SymbolXmpPageFull24}{\hidepaste}
\tab{5}\spadcommand{scripts N\free{N }}
\indentrel{3}\begin{verbatim}
   (24)
   [sub= [i,j], sup= [k,l], presup= [0,1], presub= [],
    args= []]
Type: Record(sub: List OutputForm,sup: List OutputForm,presup: List OutputForm,presub: List OutputForm,args: List OutputForm)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{SymbolXmpPageEmpty24}
\begin{paste}{SymbolXmpPageEmpty24}{SymbolXmpPagePatch24}
\pastebutton{SymbolXmpPageEmpty24}{\showpaste}
\tab{5}\spadcommand{scripts N\free{N }}
\end{paste}\end{patch}

\end{chunk}
\section{table.ht}
\pagetitle{TableXmpPage}{table.ht}{Table}
\pageto{notitle}{AssociationListXmpPage}
\pageto{notitle}{EqTableXmpPage}
\pageto{notitle}{StringTableXmpPage}
\pageto{notitle}{SparseTableXmpPage}
\pageto{notitle}{KeyedAccessFileXmpPage}
\begin{chunk}{table.ht}
\begin{page}{TableXmpPage}{Table}
\beginscroll

The \spadtype{Table} constructor provides a general structure for
associative storage.  This type provides hash tables in which data
objects can be saved according to keys of any type.  For a given
table, specific types must be chosen for the keys and entries.

\xtc{
In this example the keys to the table are polynomials with
integer coefficients.
The entries in the table are strings.
}{
\spadpaste{t: Table(Polynomial Integer, String) := table() \bound{t}}
}
\xtc{
To save an entry in the table, the \spadfunFrom{setelt}{Table} 
operation is used.
This can be called directly, giving the table a key and an entry.
}{
\spadpaste{setelt(t, x**2 - 1, "Easy to factor") \bound{p1}\free{t}}
}
\xtc{
Alternatively, you can use assignment syntax.
}{
\spadpaste{t(x**3 + 1) := "Harder to factor" \bound{p2}\free{p1}}
}
\xtc{
}{
\spadpaste{t(x)        := "The easiest to factor" \bound{p3}\free{p2}}
}
\xtc{
Entries are retrieved from the table by calling the
\spadfunFrom{elt}{Table} operation.
}{
\spadpaste{elt(t, x) \free{p3}}
}
\xtc{
This operation is called when a table is ``applied'' to a key using
this or the following syntax.
}{
\spadpaste{t.x \free{p3}}
}
\xtc{
}{
\spadpaste{t x \free{p3}}
}
\xtc{
Parentheses are used only for grouping.  They are needed if the key is
an infixed expression.
}{
\spadpaste{t.(x**2 - 1) \free{p3}}
}
\xtc{
Note that the \spadfunFrom{elt}{Table} operation is used only when the
key is known to be in the table---otherwise an error is generated.
}{
\spadpaste{t (x**3 + 1) \free{p3}}
}

\xtc{
You can get a list of all the keys to a table using the
\spadfunFrom{keys}{Table} operation.
}{
\spadpaste{keys t \free{p3}}
}
\xtc{
If you wish to test whether a key is in a table, the
\spadfunFrom{search}{Table} operation is used.
This operation returns either an entry or \spad{"failed"}.
}{
\spadpaste{search(x, t) \free{p3}}
}
\xtc{
}{
\spadpaste{search(x**2, t) \free{p3}}
}
\xtc{
The return type is a union so the success of the search can be tested
using \spad{case}.
\spadkey{case}
}{
\spadpaste{search(x**2, t) case "failed" \free{p3}}
}
\xtc{
The \spadfunFromX{remove}{Table} operation is used to delete values from a
table.
}{
\spadpaste{remove!(x**2-1, t) \free{p3} \bound{p4}}
}
\xtc{
If an entry exists under the key, then it is returned.  Otherwise
\spadfunFromX{remove}{Table} returns \spad{"failed"}.
}{
\spadpaste{remove!(x-1, t) \free{p4}\bound{p5}}
}

\xtc{
The number of key-entry pairs can be found using the
\spadfunFrom{\#}{Table} operation.
}{
\spadpaste{\#t \free{p5}}
}
\xtc{
Just as \spadfunFrom{keys}{Table} returns a list of keys to the table, a
list of all the entries can be obtained using the
\spadfunFrom{members}{Table} operation.
}{
\spadpaste{members t \free{p5}}
}
\xtc{
A number of useful operations take functions and map them on to the
table to compute the result.  Here we count the entries which
have \spad{"Hard"} as a prefix.
}{
\spadpaste{count(s: String +-> prefix?("Hard", s), t) \free{p5}}
}

Other table types are provided to support various needs.
\indent{4}
\beginitems
\item[-] \spadtype{AssociationList} gives a list with a table view.
This allows new entries to be appended onto the front of the list to
cover up old entries.  This is useful when table entries need to be
stacked or when frequent list traversals are required.  See
\downlink{`AssociationList'}{AssociationListXmpPage}
\ignore{AssociationList} for more information.

\item[-] \spadtype{EqTable} gives tables in which keys are considered
equal only when they are in fact the same instance of a structure.
See \downlink{`EqTable'}{EqTableXmpPage}\ignore{EqTable} for more
information.

\item[-] \spadtype{StringTable} should be used when the keys are known 
to be strings.
See \downlink{`StringTable'}{StringTableXmpPage}\ignore{StringTable} 
for more information.

\item[-] \spadtype{SparseTable} provides tables with default entries,
so lookup never fails.  The \spadtype{GeneralSparseTable} constructor
can be used to make any table type behave this way.  See
\downlink{`SparseTable'}{SparseTableXmpPage}\ignore{SparseTable} for
more information.

\item[-] \spadtype{KeyedAccessFile} allows values to be saved in a
file, accessed as a table.  See
\downlink{`KeyedAccessFile'}{KeyedAccessFileXmpPage}
\ignore{KeyedAccessFile}
for more information.

\enditems
\indent{0}
%
\showBlurb{Table}
\endscroll
\autobuttons
\end{page}

\begin{patch}{TableXmpPagePatch1}
\begin{paste}{TableXmpPageFull1}{TableXmpPageEmpty1}
\pastebutton{TableXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{t: Table(Polynomial Integer, String) := table()\bound{t }}
\indentrel{3}\begin{verbatim}
   (1)  table()
                 Type: Table(Polynomial Integer,String)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TableXmpPageEmpty1}
\begin{paste}{TableXmpPageEmpty1}{TableXmpPagePatch1}
\pastebutton{TableXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{t: Table(Polynomial Integer, String) := table()\bound{t }}
\end{paste}\end{patch}

\begin{patch}{TableXmpPagePatch2}
\begin{paste}{TableXmpPageFull2}{TableXmpPageEmpty2}
\pastebutton{TableXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{setelt(t, x**2 - 1, "Easy to factor")\bound{p1 }\free{t }}
\indentrel{3}\begin{verbatim}
   (2)  "Easy to factor"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TableXmpPageEmpty2}
\begin{paste}{TableXmpPageEmpty2}{TableXmpPagePatch2}
\pastebutton{TableXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{setelt(t, x**2 - 1, "Easy to factor")\bound{p1 }\free{t }}
\end{paste}\end{patch}

\begin{patch}{TableXmpPagePatch3}
\begin{paste}{TableXmpPageFull3}{TableXmpPageEmpty3}
\pastebutton{TableXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{t(x**3 + 1) := "Harder to factor"\bound{p2 }\free{p1 }}
\indentrel{3}\begin{verbatim}
   (3)  "Harder to factor"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TableXmpPageEmpty3}
\begin{paste}{TableXmpPageEmpty3}{TableXmpPagePatch3}
\pastebutton{TableXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{t(x**3 + 1) := "Harder to factor"\bound{p2 }\free{p1 }}
\end{paste}\end{patch}

\begin{patch}{TableXmpPagePatch4}
\begin{paste}{TableXmpPageFull4}{TableXmpPageEmpty4}
\pastebutton{TableXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{t(x) := "The easiest to factor"\bound{p3 }\free{p2 }}
\indentrel{3}\begin{verbatim}
   (4)  "The easiest to factor"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TableXmpPageEmpty4}
\begin{paste}{TableXmpPageEmpty4}{TableXmpPagePatch4}
\pastebutton{TableXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{t(x) := "The easiest to factor"\bound{p3 }\free{p2 }}
\end{paste}\end{patch}

\begin{patch}{TableXmpPagePatch5}
\begin{paste}{TableXmpPageFull5}{TableXmpPageEmpty5}
\pastebutton{TableXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{elt(t, x)\free{p3 }}
\indentrel{3}\begin{verbatim}
   (5)  "The easiest to factor"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TableXmpPageEmpty5}
\begin{paste}{TableXmpPageEmpty5}{TableXmpPagePatch5}
\pastebutton{TableXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{elt(t, x)\free{p3 }}
\end{paste}\end{patch}

\begin{patch}{TableXmpPagePatch6}
\begin{paste}{TableXmpPageFull6}{TableXmpPageEmpty6}
\pastebutton{TableXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{t.x\free{p3 }}
\indentrel{3}\begin{verbatim}
   (6)  "The easiest to factor"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TableXmpPageEmpty6}
\begin{paste}{TableXmpPageEmpty6}{TableXmpPagePatch6}
\pastebutton{TableXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{t.x\free{p3 }}
\end{paste}\end{patch}

\begin{patch}{TableXmpPagePatch7}
\begin{paste}{TableXmpPageFull7}{TableXmpPageEmpty7}
\pastebutton{TableXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{t x\free{p3 }}
\indentrel{3}\begin{verbatim}
   (7)  "The easiest to factor"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TableXmpPageEmpty7}
\begin{paste}{TableXmpPageEmpty7}{TableXmpPagePatch7}
\pastebutton{TableXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{t x\free{p3 }}
\end{paste}\end{patch}

\begin{patch}{TableXmpPagePatch8}
\begin{paste}{TableXmpPageFull8}{TableXmpPageEmpty8}
\pastebutton{TableXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{t.(x**2 - 1)\free{p3 }}
\indentrel{3}\begin{verbatim}
   (8)  "Easy to factor"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TableXmpPageEmpty8}
\begin{paste}{TableXmpPageEmpty8}{TableXmpPagePatch8}
\pastebutton{TableXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{t.(x**2 - 1)\free{p3 }}
\end{paste}\end{patch}

\begin{patch}{TableXmpPagePatch9}
\begin{paste}{TableXmpPageFull9}{TableXmpPageEmpty9}
\pastebutton{TableXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{t (x**3 + 1)\free{p3 }}
\indentrel{3}\begin{verbatim}
   (9)  "Harder to factor"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TableXmpPageEmpty9}
\begin{paste}{TableXmpPageEmpty9}{TableXmpPagePatch9}
\pastebutton{TableXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{t (x**3 + 1)\free{p3 }}
\end{paste}\end{patch}

\begin{patch}{TableXmpPagePatch10}
\begin{paste}{TableXmpPageFull10}{TableXmpPageEmpty10}
\pastebutton{TableXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{keys t\free{p3 }}
\indentrel{3}\begin{verbatim}
             3      2
   (10)  [x,x  + 1,x  - 1]
                          Type: List Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TableXmpPageEmpty10}
\begin{paste}{TableXmpPageEmpty10}{TableXmpPagePatch10}
\pastebutton{TableXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{keys t\free{p3 }}
\end{paste}\end{patch}

\begin{patch}{TableXmpPagePatch11}
\begin{paste}{TableXmpPageFull11}{TableXmpPageEmpty11}
\pastebutton{TableXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{search(x, t)\free{p3 }}
\indentrel{3}\begin{verbatim}
   (11)  "The easiest to factor"
                                Type: Union(String,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TableXmpPageEmpty11}
\begin{paste}{TableXmpPageEmpty11}{TableXmpPagePatch11}
\pastebutton{TableXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{search(x, t)\free{p3 }}
\end{paste}\end{patch}

\begin{patch}{TableXmpPagePatch12}
\begin{paste}{TableXmpPageFull12}{TableXmpPageEmpty12}
\pastebutton{TableXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{search(x**2, t)\free{p3 }}
\indentrel{3}\begin{verbatim}
   (12)  "failed"
                              Type: Union("failed",...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TableXmpPageEmpty12}
\begin{paste}{TableXmpPageEmpty12}{TableXmpPagePatch12}
\pastebutton{TableXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{search(x**2, t)\free{p3 }}
\end{paste}\end{patch}

\begin{patch}{TableXmpPagePatch13}
\begin{paste}{TableXmpPageFull13}{TableXmpPageEmpty13}
\pastebutton{TableXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{search(x**2, t) case "failed"\free{p3 }}
\indentrel{3}\begin{verbatim}
   (13)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TableXmpPageEmpty13}
\begin{paste}{TableXmpPageEmpty13}{TableXmpPagePatch13}
\pastebutton{TableXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{search(x**2, t) case "failed"\free{p3 }}
\end{paste}\end{patch}

\begin{patch}{TableXmpPagePatch14}
\begin{paste}{TableXmpPageFull14}{TableXmpPageEmpty14}
\pastebutton{TableXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{remove!(x**2-1, t)\free{p3 }\bound{p4 }}
\indentrel{3}\begin{verbatim}
   (14)  "Easy to factor"
                                Type: Union(String,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TableXmpPageEmpty14}
\begin{paste}{TableXmpPageEmpty14}{TableXmpPagePatch14}
\pastebutton{TableXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{remove!(x**2-1, t)\free{p3 }\bound{p4 }}
\end{paste}\end{patch}

\begin{patch}{TableXmpPagePatch15}
\begin{paste}{TableXmpPageFull15}{TableXmpPageEmpty15}
\pastebutton{TableXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{remove!(x-1, t)\free{p4 }\bound{p5 }}
\indentrel{3}\begin{verbatim}
   (15)  "failed"
                              Type: Union("failed",...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TableXmpPageEmpty15}
\begin{paste}{TableXmpPageEmpty15}{TableXmpPagePatch15}
\pastebutton{TableXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{remove!(x-1, t)\free{p4 }\bound{p5 }}
\end{paste}\end{patch}

\begin{patch}{TableXmpPagePatch16}
\begin{paste}{TableXmpPageFull16}{TableXmpPageEmpty16}
\pastebutton{TableXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{\#t\free{p5 }}
\indentrel{3}\begin{verbatim}
   (16)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TableXmpPageEmpty16}
\begin{paste}{TableXmpPageEmpty16}{TableXmpPagePatch16}
\pastebutton{TableXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{\#t\free{p5 }}
\end{paste}\end{patch}

\begin{patch}{TableXmpPagePatch17}
\begin{paste}{TableXmpPageFull17}{TableXmpPageEmpty17}
\pastebutton{TableXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{members t\free{p5 }}
\indentrel{3}\begin{verbatim}
   (17)  ["The easiest to factor","Harder to factor"]
                                      Type: List String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TableXmpPageEmpty17}
\begin{paste}{TableXmpPageEmpty17}{TableXmpPagePatch17}
\pastebutton{TableXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{members t\free{p5 }}
\end{paste}\end{patch}

\begin{patch}{TableXmpPagePatch18}
\begin{paste}{TableXmpPageFull18}{TableXmpPageEmpty18}
\pastebutton{TableXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{count(s: String +-> prefix?("Hard", s), t)\free{p5 }}
\indentrel{3}\begin{verbatim}
   (18)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TableXmpPageEmpty18}
\begin{paste}{TableXmpPageEmpty18}{TableXmpPagePatch18}
\pastebutton{TableXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{count(s: String +-> prefix?("Hard", s), t)\free{p5 }}
\end{paste}\end{patch}

\end{chunk}
\section{textfile.ht}
\pagetitle{TextFileXmpPage}{textfile.ht}{TextFile}
\pageto{notitle}{FileXmpPage}
\pageto{notitle}{KeyedAccessFileXmpPage}
\pageto{notitle}{LibraryXmpPage}
\begin{chunk}{textfile.ht}
\begin{page}{TextFileXmpPage}{TextFile}
\beginscroll

The domain \spadtype{TextFile} allows Axiom to read and write
character data and exchange text with other programs.
This type behaves in Axiom much like a \spadtype{File} of strings,
with additional operations to cause new lines.
We give an example of how to produce an upper case copy of a file.
\xtc{
This is the file from which we read the text.
}{
\spadpaste{f1: TextFile := open("/etc/group", "input")   \bound{f1}}
}
\xtc{
This is the file to which we read the text.
}{
\spadpaste{f2: TextFile := open("/tmp/MOTD", "output")  \bound{f2}}
}
\xtc{
Entire lines are handled using the \spadfunFromX{readLine}{TextFile} and
\spadfunFromX{writeLine}{TextFile} operations.
}{
\spadpaste{l := readLine! f1 \free{f1}\bound{l}}
}
\xtc{
}{
\spadpaste{writeLine!(f2, upperCase l) \free{f2 l}}
}
\xtc{
Use the
\spadfunFrom{endOfFile?}{TextFile} operation to check if you have
reached the end of the file.
}{
\begin{spadsrc}[\free{f1 f2}\bound{Copied}]
while not endOfFile? f1 repeat
    s := readLine! f1
    writeLine!(f2, upperCase s)
\end{spadsrc}
}
\xtc{
The file \spad{f1} is exhausted and should be closed.
}{
\spadpaste{close! f1  \free{Copied}\bound{closed1}}
}

\xtc{
It is sometimes useful to write lines a bit at a time.
The \spadfunFromX{write}{TextFile} operation allows this.
}{
\spadpaste{write!(f2, "-The-")  \free{Copied}\bound{tthhee}}
}
\xtc{
}{
\spadpaste{write!(f2, "-End-")  \free{tthhee}\bound{eenndd}}
}
\xtc{
This ends the line.
This is done in a machine-dependent manner.
}{
\spadpaste{writeLine! f2        \free{eenndd}\bound{LastLine}}
}
\xtc{
}{
\spadpaste{close! f2              \free{LastLine}\bound{closed2}}
}
\noOutputXtc{
Finally, clean up.
}{
\spadpaste{)system rm /tmp/MOTD   \free{closed2}}
}

For more information on related topics,  see
\downlink{`File'}{FileXmpPage}\ignore{File},
\downlink{`KeyedAccessFile'}{KeyedAccessFileXmpPage}
\ignore{KeyedAccessFile}, and
\downlink{`Library'}{LibraryXmpPage}\ignore{Library}.
\showBlurb{TextFile}
\endscroll
\autobuttons
\end{page}

\begin{patch}{TextFileXmpPagePatch1}
\begin{paste}{TextFileXmpPageFull1}{TextFileXmpPageEmpty1}
\pastebutton{TextFileXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{f1: TextFile := open("/etc/group", "input")\bound{f1 }}
\indentrel{3}\begin{verbatim}
   (1)  "/etc/group"
                                         Type: TextFile
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TextFileXmpPageEmpty1}
\begin{paste}{TextFileXmpPageEmpty1}{TextFileXmpPagePatch1}
\pastebutton{TextFileXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{f1: TextFile := open("/etc/group", "input")\bound{f1 }}
\end{paste}\end{patch}

\begin{patch}{TextFileXmpPagePatch2}
\begin{paste}{TextFileXmpPageFull2}{TextFileXmpPageEmpty2}
\pastebutton{TextFileXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{f2: TextFile := open("/tmp/MOTD", "output")\bound{f2 }}
\indentrel{3}\begin{verbatim}
   (2)  "/tmp/MOTD"
                                         Type: TextFile
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TextFileXmpPageEmpty2}
\begin{paste}{TextFileXmpPageEmpty2}{TextFileXmpPagePatch2}
\pastebutton{TextFileXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{f2: TextFile := open("/tmp/MOTD", "output")\bound{f2 }}
\end{paste}\end{patch}

\begin{patch}{TextFileXmpPagePatch3}
\begin{paste}{TextFileXmpPageFull3}{TextFileXmpPageEmpty3}
\pastebutton{TextFileXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{l := readLine! f1\free{f1 }\bound{l }}
\indentrel{3}\begin{verbatim}
   (3)  "system:*:0:root"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TextFileXmpPageEmpty3}
\begin{paste}{TextFileXmpPageEmpty3}{TextFileXmpPagePatch3}
\pastebutton{TextFileXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{l := readLine! f1\free{f1 }\bound{l }}
\end{paste}\end{patch}

\begin{patch}{TextFileXmpPagePatch4}
\begin{paste}{TextFileXmpPageFull4}{TextFileXmpPageEmpty4}
\pastebutton{TextFileXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{writeLine!(f2, upperCase l)\free{f2 l }}
\indentrel{3}\begin{verbatim}
   (4)  "SYSTEM:*:0:ROOT"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TextFileXmpPageEmpty4}
\begin{paste}{TextFileXmpPageEmpty4}{TextFileXmpPagePatch4}
\pastebutton{TextFileXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{writeLine!(f2, upperCase l)\free{f2 l }}
\end{paste}\end{patch}

\begin{patch}{TextFileXmpPagePatch5}
\begin{paste}{TextFileXmpPageFull5}{TextFileXmpPageEmpty5}
\pastebutton{TextFileXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{while not endOfFile? f1 repeat
    s := readLine! f1
    writeLine!(f2, upperCase s)
\free{f1 f2 }\bound{Copied }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TextFileXmpPageEmpty5}
\begin{paste}{TextFileXmpPageEmpty5}{TextFileXmpPagePatch5}
\pastebutton{TextFileXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{while not endOfFile? f1 repeat
    s := readLine! f1
    writeLine!(f2, upperCase s)
\free{f1 f2 }\bound{Copied }}
\end{paste}\end{patch}

\begin{patch}{TextFileXmpPagePatch6}
\begin{paste}{TextFileXmpPageFull6}{TextFileXmpPageEmpty6}
\pastebutton{TextFileXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{close! f1\free{Copied }\bound{closed1 }}
\indentrel{3}\begin{verbatim}
   (6)  "/etc/group"
                                         Type: TextFile
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TextFileXmpPageEmpty6}
\begin{paste}{TextFileXmpPageEmpty6}{TextFileXmpPagePatch6}
\pastebutton{TextFileXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{close! f1\free{Copied }\bound{closed1 }}
\end{paste}\end{patch}

\begin{patch}{TextFileXmpPagePatch7}
\begin{paste}{TextFileXmpPageFull7}{TextFileXmpPageEmpty7}
\pastebutton{TextFileXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{write!(f2, "-The-")\free{Copied }\bound{tthhee }}
\indentrel{3}\begin{verbatim}
   (7)  "-The-"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TextFileXmpPageEmpty7}
\begin{paste}{TextFileXmpPageEmpty7}{TextFileXmpPagePatch7}
\pastebutton{TextFileXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{write!(f2, "-The-")\free{Copied }\bound{tthhee }}
\end{paste}\end{patch}

\begin{patch}{TextFileXmpPagePatch8}
\begin{paste}{TextFileXmpPageFull8}{TextFileXmpPageEmpty8}
\pastebutton{TextFileXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{write!(f2, "-End-")\free{tthhee }\bound{eenndd }}
\indentrel{3}\begin{verbatim}
   (8)  "-End-"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TextFileXmpPageEmpty8}
\begin{paste}{TextFileXmpPageEmpty8}{TextFileXmpPagePatch8}
\pastebutton{TextFileXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{write!(f2, "-End-")\free{tthhee }\bound{eenndd }}
\end{paste}\end{patch}

\begin{patch}{TextFileXmpPagePatch9}
\begin{paste}{TextFileXmpPageFull9}{TextFileXmpPageEmpty9}
\pastebutton{TextFileXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{writeLine! f2\free{eenndd }\bound{LastLine }}
\indentrel{3}\begin{verbatim}
   (9)  ""
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TextFileXmpPageEmpty9}
\begin{paste}{TextFileXmpPageEmpty9}{TextFileXmpPagePatch9}
\pastebutton{TextFileXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{writeLine! f2\free{eenndd }\bound{LastLine }}
\end{paste}\end{patch}

\begin{patch}{TextFileXmpPagePatch10}
\begin{paste}{TextFileXmpPageFull10}{TextFileXmpPageEmpty10}
\pastebutton{TextFileXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{close! f2\free{LastLine }\bound{closed2 }}
\indentrel{3}\begin{verbatim}
   (10)  "/tmp/MOTD"
                                         Type: TextFile
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TextFileXmpPageEmpty10}
\begin{paste}{TextFileXmpPageEmpty10}{TextFileXmpPagePatch10}
\pastebutton{TextFileXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{close! f2\free{LastLine }\bound{closed2 }}
\end{paste}\end{patch}

\begin{patch}{TextFileXmpPagePatch11}
\begin{paste}{TextFileXmpPageFull11}{TextFileXmpPageEmpty11}
\pastebutton{TextFileXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{)system rm /tmp/MOTD\free{closed2 }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{TextFileXmpPageEmpty11}
\begin{paste}{TextFileXmpPageEmpty11}{TextFileXmpPagePatch11}
\pastebutton{TextFileXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{)system rm /tmp/MOTD\free{closed2 }}
\end{paste}\end{patch}

\end{chunk}
\section{topics.ht}
\pagetitle{TopicPage}{page.ht}{Axiom Topics}
\pagepic{ps/v71topicpage.eps}{topics}{0.50}
\pagefrom{Root Page}{RootPage}
\pagefrom{Reference}{TopReferencePage}
\pageto{Numbers}{NumberPage}
\pageto{Polynomials}{PolynomialPage} 
\pageto{Functions}{FunctionPage} 
\pageto{Solving Equations}{EquationPage} 
\pageto{Calculus}{CalculusPage} 
\pageto{Linear Algebra}{LinAlgPage} 
\pageto{Graphics}{GraphicsPage} 
\pageto{Algebra}{AlgebraPage} 
\begin{chunk}{topics.ht}
\begin{page}{TopicPage}{Axiom Topics}
\beginscroll
Select a topic below: % or
%\lispmemolink{search}{(|htTutorialSearch| '|\stringvalue{pattern}|))}
%for string (use {\em *} for wild card):
%\newline\inputstring{pattern}{58}{}
\beginmenu
\menumemolink{Numbers}{NumberPage}\tab{18}
A look at different types of numbers

\menumemolink{Polynomials}{PolynomialPage}\tab{18}
Polynomials in Axiom
%
\menumemolink{Functions}{FunctionPage}\tab{18}
Built-in and user-defined functions
%
\menumemolink{Solving Equations}{EquationPage}\tab{18}
Facilities for solving equations
%
\menumemolink{Calculus}{CalculusPage}\tab{18}
Using Axiom to do calculus
%
\menumemolink{Linear Algebra}{LinAlgPage}\tab{18}
Axiom's linear algebra facilities
%
\menumemolink{Graphics}{GraphicsPage}\tab{18}
Axiom's graphics facilities
%
\menumemolink{Algebra}{AlgebraPage}\tab{18}
Axiom's abstract algebra facilities
%
\endmenu
\endscroll
\end{page}

\end{chunk}
\pagetitle{EquationPage}{topics.ht}{Solving Equations}
\pagepic{ps/v71equationpage.eps}{equationpage}{0.50}
\pagefrom{Topics}{TopicPage}
\pageto{Sol...Systems of Linear Equations}{ugxProblemLinSysPage}
\pageto{Sol...Single Polynomial Equation}{ugxProblemOnePolPage}
\pageto{Sol...Systems of Polynomial Equations}{ugxProblemPolSysPage}
\pageto{Sol...Differential Equations}{ugProblemDEQPage}
\begin{chunk}{topics.ht}
\begin{page}{EquationPage}{Solving Equations}
\beginscroll
Axiom lets you solve equations of various types:
\beginmenu
  \menulink{Solution of Systems of Linear Equations}
{ugxProblemLinSysPage}
    \newline Solve systems of linear equations.
  \menulink{Solution of a Single Polynomial Equation}
{ugxProblemOnePolPage}
    \newline Find roots of polynomials.
  \menulink{Solution of Systems of Polynomial Equations}
{ugxProblemPolSysPage}
  \newline Solve systems of polynomial equations.
  \menulink{Solution of Differential Equations}{ugProblemDEQPage}
  \newline Closed form and series solutions of differential equations.
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{LinAlgPage}{topics.ht}{Linear Algebra}
\pagepic{ps/v71linalgpage.eps}{linalgpage}{0.50}
\pagefrom{Topics}{TopicPage}
\pageto{Introduction}{ugIntroTwoDimPage} 
\pageto{Creating Matrices}{ugxMatrixCreatePage} 
\pageto{Operations on Matrices}{ugxMatrixOpsPage} 
\pageto{Eigenvalues and Eigenvectors}{ugProblemEigenPage} 
\pageto{Example: Determinant of a Hilbert Matrix}{ugxFloatHilbertPage} 
\pageto{Computing the Permanent}{PermanentXmpPage} 
\pageto{Working with Vectors}{VectorXmpPage} 
\pageto{Working with Square Matrices}{SqMatrixXmpPage} 
\pageto{Working with One-dimensional Arrays}{OneDimensionalArrayXmpPage} 
\pageto{Working with Two-dimensional Arrays}{TwoDimensionalArrayXmpPage} 
\pageto{Conversion (Polynomials of Matrices)}{ugTypesConvertPage} 
\begin{chunk}{topics.ht}
\begin{page}{LinAlgPage}{Linear Algebra}
\beginscroll
\beginmenu

\menulink{Introduction}{ugIntroTwoDimPage}\newline

Create and manipulate matrices.
Work with the entries of a matrix.
Perform matrix arithmetic.

\menulink{Creating Matrices}{ugxMatrixCreatePage} \newline

Create matrices from scratch and from other matrices.

\menulink{Operations on Matrices}{ugxMatrixOpsPage} \newline

Algebraic manipulations with matrices.
Compute the inverse, determinant and trace of a matrix.
Find the rank, nullspace and row echelon form of a matrix.

\menulink{Eigenvalues and Eigenvectors}{ugProblemEigenPage} \newline

How to compute eigenvalues and eigenvectors.
\endmenu
\horizontalline\newline
Additional Topics:
\beginmenu
\menulink{Example: Determinant of a Hilbert Matrix}{ugxFloatHilbertPage}
\menulink{Computing the Permanent}{PermanentXmpPage}
\menulink{Working with Vectors}{VectorXmpPage}
\menulink{Working with Square Matrices}{SqMatrixXmpPage}
\menulink{Working with One-Dimensional Arrays}{OneDimensionalArrayXmpPage}
\menulink{Working with Two-Dimensional Arrays}{TwoDimensionalArrayXmpPage}
\menulink{Conversion (Polynomials of Matrices)}{ugTypesConvertPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{CalculusPage}{topics.ht}{Calculus}
\pagepic{ps/v71calculuspage.eps}{calculuspage}{0.50}
\pagefrom{Topics}{TopicPage}
\pageto{Limits}{ugProblemLimitsPage}
\pageto{Derivatives}{ugIntroCalcDerivPage}
\pageto{Integrals}{ugIntroIntegratePage}
\pageto{More Integrals}{ugProblemIntegrationPage}
\pageto{Laplace}{ugProblemLaplacePage}
\pageto{Series}{ugProblemSeriesPage}
\pageto{Differential Eqns}{ugProblemDEQPage}
\begin{chunk}{topics.ht}
\begin{page}{CalculusPage}{Calculus}
\beginscroll
\beginmenu
\menulink{Limits}{ugProblemLimitsPage} \tab{17}
Compute limits of functional expressions.
\menulink{Derivatives}{ugIntroCalcDerivPage}\tab{17}
Compute derivatives and partial derivatives.
\menulink{Integrals}{ugIntroIntegratePage}\tab{17}
Introduction to Axiom's symbolic integrator.
\menulink{More Integrals}{ugProblemIntegrationPage}\tab{17}
More information about symbolic integration.
\menulink{Laplace}{ugProblemLaplacePage}\tab{17}
Computing Laplace transforms.
\menulink{Series}{ugProblemSeriesPage}\tab{17}
Compute series expansions of expressions.
\menulink{Differential Eqns}{ugProblemDEQPage}\tab{17}
Solve differential equations.
\endmenu
\endscroll
\autobuttons \end{page}

\end{chunk}
\section{type.ht}
\pagetitle{CategoryType}{type.ht}{Category {\bf Type}}
\begin{chunk}{type.ht}
\begin{page}{CategoryType}{Category {\em Type}}
\beginscroll
{\em Type} is a primitive category in Axiom,
one which is an ancestor of all Axiom categories.

{\em Type} is the root of Axiom's category hierarchy,
a category with no properties (exported operations 
and attributes) of which all other categories are descendants.
Two important children of {\em Type} are
\spadtype{SetCategory}, the category of all algebraic domains,
and \spadtype{Aggregate}, the category of all data structures.
\endscroll

\end{chunk}
\section{union.ht}
\pagetitle{DomainUnion}{union.ht}{Domain {\bf Union(a:A,...,b:B)}}
\pageto{Description}{LispFunctions}
\pageto{Operations}{LispFunctions}
\pageto{Exports}{LispFunctions}
\begin{chunk}{union.ht}
\begin{page}{DomainUnion}{Domain {\em Union(a:A,...,b:B)}}
\beginscroll
{\em Union} takes any number of "tag"-domain pairs of arguments:
\indentrel{2}
\newline \spad{a}, a tag, an element of domain \spadtype{Symbol}
\newline \spad{A}, a domain of category \spadtype{SetCategory}
\newline\tab{10}...
\newline \spad{b}, a tag, an element of domain \spadtype{Symbol}
\newline \spad{B}, a domain of category \spadtype{SetCategory}
\indentrel{-2}\newline
This constructor is a primitive in Axiom. 
\newline
\beginmenu
\item\menulispdownlink{Description}
{(|dbSpecialDescription| '|Union|)) }\tab{15}General description
\item\menulispdownlink{Operations}
{(|dbSpecialOperations| '|Union|)}
\tab{15}All exported operations of \spad{Union(a:A,b:B)}
%\item\menudownlink{Examples}   {UnionExamples}   
%\tab{15}Examples illustrating use
\item\menulispdownlink{Exports}{(|dbSpecialExports| '|Union|)}
\tab{15}Explicit categories and operations
\endmenu
\vspace{1}\newline
In this tagged \spad{Union}, tags \spad{a,...,b} must be distinct. 
\newline
For an alternate "untagged" form of \spad{Union}, see 
\downlink{Union(A,B)}{UntaggedUnion}.
\endscroll\end{page}
 
\end{chunk}
\pagetitle{UnionDescription}{union.ht}{Domain Constructor {\bf Union}}
\begin{chunk}{union.ht}
\begin{page}{UnionDescription}{Domain Constructor {\em Union}}
\beginscroll
\newline\menuitemstyle{}\tab{2}Union({\em a:A},{\em b:B})
\newline\tab{2}{\em Arguments:}\indent{17}\tab{-2}
{\em a}, a tag, an element of domain \spadtype{Symbol}
\newline\tab{-2}
{\em A}, a domain of category \spadtype{SetCategory}
\newline\tab{-2}
{\em b}, a tag, an element of domain \spadtype{Symbol}
\newline\tab{-2}
{\em B}, a domain of category \spadtype{SetCategory}
\indent{0}\newline\tab{2}{\em Returns:}\indent{17}\tab{-2}
the "union of {\em A} and {\em B}" as described below.
\indent{0}\newline\tab{2}{\em Description:}\indent{15}\tab{0}
{\em Union(a:A,b:B)} denotes the class of objects 
which are either members of domain {\em A} or of domain {\em B}.
The symbols {\em a} and {\em b} are called "tags" and 
are used to identify the two "branches"
of the union.
The {\em Union} constructor can take any number of arguments and
has an alternate form without {\em tags}.
This tagged {\em Union} type is necessary, for example, to disambiguate
two branches of a union where {\em A} and {\em B} denote the same type.
{\em Union} is a primitive domain of Axiom which cannot be
defined in the Axiom language. 
\endscroll\end{page}

\end{chunk}
\pagetitle{UntaggedUnion}{union.ht}{Domain {\bf Union(A,...,B)}}
\pageto{Description}{LispFunctions}
\pageto{Operations}{LispFunctions}
\begin{chunk}{union.ht}
\begin{page}{UntaggedUnion}{Domain {\em Union(A,...,B)}}
\beginscroll
{\em Union} takes any number of domain arguments:
\indentrel{2}
\newline \spad{A}, a domain of category \spadtype{SetCategory}
\newline\tab{10}...
\newline \spad{B}, a domain of category \spadtype{SetCategory}
\indentrel{-2}\newline
\spad{Union} is a primitive constructor in Axiom. 
\newline
\beginmenu
\item\menulispdownlink{Description}
{(|dbSpecialDescription| '|UntaggedUnion|)) }\tab{15}General description
\item\menulispdownlink{Operations}
{(|dbSpecialOperations| '|UntaggedUnion|)}
\tab{15}All exported operations of \spad{Union(A,B)}
%\item\menudownlink{Examples}   {UTUnionExamples}   
%\tab{15}Examples illustrating use
%\item\menudownlink{Exports}    {UTUnionExports}    
%\tab{15}Explicit categories and operations
\endmenu
\vspace{1}\newline
In this untagged form of \spad{Union}, domains \spad{A,...,B} 
must be distinct.
\endscroll\end{page}

\end{chunk}
\pagetitle{UTUnionDescription}{union.ht}{Domain Constructor {\bf Union}}
\begin{chunk}{union.ht}
\begin{page}{UTUnionDescription}{Domain Constructor {\em Union}}
\beginscroll
\newline\menuitemstyle{}\tab{2}Union({\em A},{\em B})
\newline\tab{2}{\em Arguments:}\indent{17}\tab{-2}
{\em A}, a domain of category \spadtype{SetCategory}
\newline\tab{-2}
{\em B}, a domain of category \spadtype{SetCategory}
\indent{0}\newline\tab{2}{\em Returns:}\indent{17}\tab{-2}
the "union of {\em A} and {\em B}" as described below.
\indent{0}\newline\tab{2}{\em Description:}\indent{15}\tab{0}
{\em Union(A,B)} denotes the class of objects which are
which are either members of domain {\em A} or of domain {\em B}.
The {\em Union} constructor can take any number of arguments and
has an alternate form using {\em tags}.
{\em Union} is a primitive domain of Axiom which cannot be
defined in the Axiom language. 
\endscroll\end{page}


\end{chunk}
\section{uniseg.ht}
\pagetitle{UniversalSegmentXmpPage}{uniseg.ht}{UniversalSegment}
\pageto{notitle}{SegmentXmpPage}
\pageto{notitle}{SegmentBindingXmpPage}
\pageto{notitle}{ListXmpPage}
\pageto{notitle}{StreamXmpPage}
\begin{chunk}{uniseg.ht}
\begin{page}{UniversalSegmentXmpPage}{UniversalSegment}
\beginscroll

The \spadtype{UniversalSegment} domain generalizes \spadtype{Segment}
by allowing segments without a ``hi'' end point.
\xtc{
}{
\spadpaste{pints  := 1..         \bound{pints}}
}
\xtc{
}{
\spadpaste{nevens := (0..) by -2 \bound{nevens}}
}
\xtc{
Values of type \spadtype{Segment} are automatically converted to
type \spadtype{UniversalSegment} when appropriate.
}{
\spadpaste{useg: UniversalSegment(Integer) := 3..10 \bound{useg}}
}
\xtc{
The operation \spadfunFrom{hasHi}{UniversalSegment} is used to test
whether a segment has a \spad{hi} end point.
}{
\spadpaste{hasHi pints  \free{pints}}
}
\xtc{
}{
\spadpaste{hasHi nevens \free{nevens}}
}
\xtc{
}{
\spadpaste{hasHi useg   \free{useg}}
}
\xtc{
All operations available on type \spadtype{Segment} apply to
\spadtype{UniversalSegment}, with the proviso that expansions produce
streams rather than lists.
This is to accommodate infinite expansions.
}{
\spadpaste{expand pints \free{pints}}
}
\xtc{
}{
\spadpaste{expand nevens \free{nevens}}
}
\xtc{
}{
\spadpaste{expand [1, 3, 10..15, 100..]}
}

For more information on related topics,  see
\downlink{`Segment'}{SegmentXmpPage}\ignore{Segment},
\downlink{`SegmentBinding'}{SegmentBindingXmpPage}\ignore{SegmentBinding},
\downlink{`List'}{ListXmpPage}\ignore{List}, and
\downlink{`Stream'}{StreamXmpPage}\ignore{Stream}.
\showBlurb{UniversalSegment}
\endscroll
\autobuttons
\end{page}

\begin{patch}{UniversalSegmentXmpPagePatch1}
\begin{paste}{UniversalSegmentXmpPageFull1}{UniversalSegmentXmpPageEmpty1}
\pastebutton{UniversalSegmentXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{pints := 1..\bound{pints }}
\indentrel{3}\begin{verbatim}
   (1)  1..
                 Type: UniversalSegment PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UniversalSegmentXmpPageEmpty1}
\begin{paste}{UniversalSegmentXmpPageEmpty1}{UniversalSegmentXmpPagePatch1}
\pastebutton{UniversalSegmentXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{pints := 1..\bound{pints }}
\end{paste}\end{patch}

\begin{patch}{UniversalSegmentXmpPagePatch2}
\begin{paste}{UniversalSegmentXmpPageFull2}{UniversalSegmentXmpPageEmpty2}
\pastebutton{UniversalSegmentXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{nevens := (0..) by -2\bound{nevens }}
\indentrel{3}\begin{verbatim}
   (2)  0.. by - 2
              Type: UniversalSegment NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UniversalSegmentXmpPageEmpty2}
\begin{paste}{UniversalSegmentXmpPageEmpty2}{UniversalSegmentXmpPagePatch2}
\pastebutton{UniversalSegmentXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{nevens := (0..) by -2\bound{nevens }}
\end{paste}\end{patch}

\begin{patch}{UniversalSegmentXmpPagePatch3}
\begin{paste}{UniversalSegmentXmpPageFull3}{UniversalSegmentXmpPageEmpty3}
\pastebutton{UniversalSegmentXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{useg: UniversalSegment(Integer) := 3..10\bound{useg }}
\indentrel{3}\begin{verbatim}
   (3)  3..10
                         Type: UniversalSegment Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UniversalSegmentXmpPageEmpty3}
\begin{paste}{UniversalSegmentXmpPageEmpty3}{UniversalSegmentXmpPagePatch3}
\pastebutton{UniversalSegmentXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{useg: UniversalSegment(Integer) := 3..10\bound{useg }}
\end{paste}\end{patch}

\begin{patch}{UniversalSegmentXmpPagePatch4}
\begin{paste}{UniversalSegmentXmpPageFull4}{UniversalSegmentXmpPageEmpty4}
\pastebutton{UniversalSegmentXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{hasHi pints\free{pints }}
\indentrel{3}\begin{verbatim}
   (4)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UniversalSegmentXmpPageEmpty4}
\begin{paste}{UniversalSegmentXmpPageEmpty4}{UniversalSegmentXmpPagePatch4}
\pastebutton{UniversalSegmentXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{hasHi pints\free{pints }}
\end{paste}\end{patch}

\begin{patch}{UniversalSegmentXmpPagePatch5}
\begin{paste}{UniversalSegmentXmpPageFull5}{UniversalSegmentXmpPageEmpty5}
\pastebutton{UniversalSegmentXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{hasHi nevens\free{nevens }}
\indentrel{3}\begin{verbatim}
   (5)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UniversalSegmentXmpPageEmpty5}
\begin{paste}{UniversalSegmentXmpPageEmpty5}{UniversalSegmentXmpPagePatch5}
\pastebutton{UniversalSegmentXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{hasHi nevens\free{nevens }}
\end{paste}\end{patch}

\begin{patch}{UniversalSegmentXmpPagePatch6}
\begin{paste}{UniversalSegmentXmpPageFull6}{UniversalSegmentXmpPageEmpty6}
\pastebutton{UniversalSegmentXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{hasHi useg\free{useg }}
\indentrel{3}\begin{verbatim}
   (6)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UniversalSegmentXmpPageEmpty6}
\begin{paste}{UniversalSegmentXmpPageEmpty6}{UniversalSegmentXmpPagePatch6}
\pastebutton{UniversalSegmentXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{hasHi useg\free{useg }}
\end{paste}\end{patch}

\begin{patch}{UniversalSegmentXmpPagePatch7}
\begin{paste}{UniversalSegmentXmpPageFull7}{UniversalSegmentXmpPageEmpty7}
\pastebutton{UniversalSegmentXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{expand pints\free{pints }}
\indentrel{3}\begin{verbatim}
   (7)  [1,2,3,4,5,6,7,8,9,10,...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UniversalSegmentXmpPageEmpty7}
\begin{paste}{UniversalSegmentXmpPageEmpty7}{UniversalSegmentXmpPagePatch7}
\pastebutton{UniversalSegmentXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{expand pints\free{pints }}
\end{paste}\end{patch}

\begin{patch}{UniversalSegmentXmpPagePatch8}
\begin{paste}{UniversalSegmentXmpPageFull8}{UniversalSegmentXmpPageEmpty8}
\pastebutton{UniversalSegmentXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{expand nevens\free{nevens }}
\indentrel{3}\begin{verbatim}
   (8)  [0,- 2,- 4,- 6,- 8,- 10,- 12,- 14,- 16,- 18,...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UniversalSegmentXmpPageEmpty8}
\begin{paste}{UniversalSegmentXmpPageEmpty8}{UniversalSegmentXmpPagePatch8}
\pastebutton{UniversalSegmentXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{expand nevens\free{nevens }}
\end{paste}\end{patch}

\begin{patch}{UniversalSegmentXmpPagePatch9}
\begin{paste}{UniversalSegmentXmpPageFull9}{UniversalSegmentXmpPageEmpty9}
\pastebutton{UniversalSegmentXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{expand [1, 3, 10..15, 100..]}
\indentrel{3}\begin{verbatim}
   (9)  [1,3,10,11,12,13,14,15,100,101,...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UniversalSegmentXmpPageEmpty9}
\begin{paste}{UniversalSegmentXmpPageEmpty9}{UniversalSegmentXmpPagePatch9}
\pastebutton{UniversalSegmentXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{expand [1, 3, 10..15, 100..]}
\end{paste}\end{patch}

\end{chunk}
\section{up.ht}
\pagetitle{UnivariatePolyXmpPage}{up.ht}{UnivariatePolynomial}
\pageto{notitle}{ugProblemFactorPage}
\pageto{notitle}{ugIntroVariablesPage}
\pageto{notitle}{ugTypesConvertPage}
\pageto{notitle}{PolynomialXmpPage}
\pageto{notitle}{MultivariatePolyXmpPage}
\pageto{notitle}{DistributedMultivariatePolyXmpPage}
\begin{chunk}{up.ht}
\begin{page}{UnivariatePolyXmpPage}{UnivariatePolynomial}
\beginscroll

The domain constructor \spadtype{UnivariatePolynomial}
(abbreviated \spadtype{UP})
creates domains of univariate polynomials in a specified variable.
For example, the domain
\spadtype{UP(a1,POLY FRAC INT)} provides polynomials in the single 
variable \spad{a1} whose coefficients are general polynomials with 
rational number coefficients.

\beginImportant
\noindent {\bf Restriction:}
\texht{\begin{quotation}\noindent}{\newline\indent{5}}
Axiom does not allow you to create types where
\spadtype{UnivariatePolynomial} is contained in the coefficient type of
\spadtype{Polynomial}. Therefore,
\spadtype{UP(x,POLY INT)} is legal but \spadtype{POLY UP(x,INT)} is not.
\texht{\end{quotation}}{\indent{0}}
\endImportant

\xtc{
\spadtype{UP(x,INT)} is the domain of polynomials in the single
variable \spad{x} with integer coefficients.
}{
\spadpaste{(p,q) : UP(x,INT) \bound{pdec}\bound{qdec}}
}
\xtc{
}{
\spadpaste{p := (3*x-1)**2 * (2*x + 8) \free{pdec}\bound{p}}
}
\xtc{
}{
\spadpaste{q := (1 - 6*x + 9*x**2)**2 \free{qdec}\bound{q}}
}
\xtc{
The usual arithmetic operations are available for univariate
polynomials.
}{
\spadpaste{p**2 + p*q  \free{p q}}
}
\xtc{
The operation \spadfunFrom{leadingCoefficient}{UnivariatePolynomial}
extracts the coefficient of the term of highest degree.
}{
\spadpaste{leadingCoefficient p \free{p}}
}
\xtc{
The operation \spadfunFrom{degree}{UnivariatePolynomial} returns
the degree of the polynomial.
Since the polynomial has only one variable, the variable is not supplied
to operations like \spadfunFrom{degree}{UnivariatePolynomial}.
}{
\spadpaste{degree p \free{p}}
}
\xtc{
The reductum of the polynomial, the polynomial obtained by
subtracting the term of highest order, is returned by
\spadfunFrom{reductum}{UnivariatePolynomial}.
}{
\spadpaste{reductum p \free{p}}
}
\xtc{
The operation \spadfunFrom{gcd}{UnivariatePolynomial} computes the
greatest common divisor of two polynomials.
}{
\spadpaste{gcd(p,q) \free{p q}}
}
\xtc{
The operation \spadfunFrom{lcm}{UnivariatePolynomial} computes the
least common multiple.
}{
\spadpaste{lcm(p,q) \free{p q}}
}
\xtc{
The operation \spadfunFrom{resultant}{UnivariatePolynomial}
computes the resultant of two univariate polynomials.
In the case of \spad{p} and \spad{q}, the resultant is \spad{0} because they
share a common root.
}{
\spadpaste{resultant(p,q) \free{p q}}
}
\xtc{
To compute the derivative of a univariate polynomial with respect to its
variable, use \spadfunFrom{D}{UnivariatePolynomial}.
}{
\spadpaste{D p \free{p}}
}
\xtc{
Univariate polynomials can also be used as if they were functions.
To evaluate a univariate polynomial at some point, apply
the polynomial to the point.
}{
\spadpaste{p(2) \free{p}}
}
\xtc{
The same syntax is used for composing two univariate polynomials, i.e.
substituting one polynomial for the variable in another.
This substitutes \spad{q} for the variable in \spad{p}.
}{
\spadpaste{p(q) \free{p q}}
}
\xtc{
This substitutes \spad{p} for the variable in \spad{q}.
}{
\spadpaste{q(p) \free{p q}}
}
\xtc{
To obtain a list of coefficients of the polynomial, use
\spadfunFrom{coefficients}{UnivariatePolynomial}.
}{
\spadpaste{l := coefficients p \free{p}\bound{l}}
}
\xtc{
From this you can use \spadfunFrom{gcd}{UnivariatePolynomial}
and \spadfunFrom{reduce}{List}
to compute the content of the polynomial.
}{
\spadpaste{reduce(gcd,l) \free{l}}
}
\xtc{
Alternatively (and more easily),
you can just call \spadfunFrom{content}{UnivariatePolynomial}.
}{
\spadpaste{content p \free{p}}
}

Note that the operation \spadfunFrom{coefficients}{UnivariatePolynomial}
omits the zero coefficients from the list.
Sometimes it is useful to convert a univariate polynomial
to a vector whose \eth{\spad{i }} position contains the degree \spad{i-1}
coefficient of the polynomial.
\xtc{
}{
\spadpaste{ux := (x**4+2*x+3)::UP(x,INT) \bound{ux}}
}
\xtc{
To get a complete vector of coefficients, use the operation
\spadfunFrom{vectorise}{UnivariatePolynomial}, which takes a
univariate polynomial and an integer denoting the length of the
desired vector.
}{
\spadpaste{vectorise(ux,5) \free{ux}}
}

It is common to want to do something to every term of a polynomial,
creating a new polynomial in the process.
\xtc{
This is a function for iterating across the terms of a polynomial,
squaring each term.
}{
\begin{spadsrc}[\bound{squareTerms}]
squareTerms(p) ==
  reduce(+,[t**2 for t in monomials p])
\end{spadsrc}
}
\xtc{
Recall what \spad{p} looked like.
}{
\spadpaste{p \free{p}}
}
\xtc{
We can demonstrate \userfun{squareTerms} on \spad{p}.
}{
\spadpaste{squareTerms p \free{p}\free{squareTerms}}
}

When the coefficients of the univariate polynomial belong to a
field,\footnote{For example, when the coefficients are rational
numbers, as opposed to integers.  The important property of
a field is that non-zero elements can be divided and produce
another element. The quotient of the integers 2 and 3 is not
another integer.}
it is possible to compute quotients and remainders.
\xtc{
}{
\spadpaste{(r,s) : UP(a1,FRAC INT) \bound{rdec}\bound{sdec}}
}
\xtc{
}{
\spadpaste{r := a1**2 - 2/3  \free{rdec}\bound{r}}
}
\xtc{
}{
\spadpaste{s := a1 + 4       \free{sdec}\bound{s}}
}
\xtc{
When the coefficients are rational numbers or rational expressions, the
operation \spadfunFrom{quo}{UnivariatePolynomial} computes the quotient
of two polynomials.
}{
\spadpaste{r quo s \free{r s}}
}
\xtc{
The operation
\spadfunFrom{rem}{UnivariatePolynomial} computes the remainder.
}{
\spadpaste{r rem s \free{r s}}
}
\xtc{
The operation \spadfunFrom{divide}{UnivariatePolynomial} can be used to
return a record of both components.
}{
\spadpaste{d := divide(r, s) \free{r s}\bound{d}}
}
\xtc{
Now we check the arithmetic!
}{
\spadpaste{r - (d.quotient * s + d.remainder) \free{r s d}}
}
\xtc{
It is also possible to integrate univariate polynomials when the
coefficients belong to a field.
}{
\spadpaste{integrate r \free{r}}
}
\xtc{
}{
\spadpaste{integrate s \free{s}}
}

One application of univariate polynomials is to see expressions in terms
of a specific variable.
%
\xtc{
We start with a polynomial in \spad{a1} whose coefficients
are quotients of polynomials in \spad{b1} and \spad{b2}.
}{
\spadpaste{t : UP(a1,FRAC POLY INT) \bound{tdec}}
}
\xtc{
Since in this case we are not talking about using multivariate
polynomials in only two variables, we use \spadtype{Polynomial}.
We also use \spadtype{Fraction} because we want fractions.
}{
\spadpaste{t := a1**2 - a1/b2 + (b1**2-b1)/(b2+3) \free{tdec}\bound{t}}
}
\xtc{
We push all the variables into a single quotient of polynomials.
}{
\spadpaste{u : FRAC POLY INT := t \bound{u}\free{t}}
}
\xtc{
Alternatively, we can view this as a polynomial in the variable
This is a {\it mode-directed} conversion: you indicate
as much of the structure as you care about and let Axiom
decide on the full type and how to do the transformation.
}{
\spadpaste{u :: UP(b1,?) \free{u}}
}

See \downlink{``Polynomial Factorization''}{ugProblemFactorPage} in 
Section 8.2\ignore{ugProblemFactor}
for a discussion of the factorization facilities
in Axiom for univariate polynomials.
For more information on related topics, see
\downlink{``Polynomials''}{ugIntroVariablesPage} in 
Section 1.9\ignore{ugIntroVariables},
\downlink{``Conversion''}{ugTypesConvertPage} in 
Section 2.7\ignore{ugTypesConvert},
\downlink{`Polynomial'}{PolynomialXmpPage}\ignore{Polynomial},
\downlink{`MultivariatePolynomial'}{MultivariatePolyXmpPage}
\ignore{MultivariatePolynomial}, and
\downlink{`DistributedMultivariatePoly'}
{DistributedMultivariatePolyXmpPage}
\ignore{DistributedMultivariatePoly}.
%
\showBlurb{UnivariatePolynomial}
\endscroll
\autobuttons
\end{page}

\begin{patch}{UnivariatePolyXmpPagePatch1}
\begin{paste}{UnivariatePolyXmpPageFull1}{UnivariatePolyXmpPageEmpty1}
\pastebutton{UnivariatePolyXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{(p,q) : UP(x,INT)\bound{pdec }\bound{qdec }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty1}
\begin{paste}{UnivariatePolyXmpPageEmpty1}{UnivariatePolyXmpPagePatch1}
\pastebutton{UnivariatePolyXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{(p,q) : UP(x,INT)\bound{pdec }\bound{qdec }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch2}
\begin{paste}{UnivariatePolyXmpPageFull2}{UnivariatePolyXmpPageEmpty2}
\pastebutton{UnivariatePolyXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{p := (3*x-1)**2 * (2*x + 8)\free{pdec }\bound{p }}
\indentrel{3}\begin{verbatim}
           3      2
   (2)  18x  + 60x  - 46x + 8
                  Type: UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty2}
\begin{paste}{UnivariatePolyXmpPageEmpty2}{UnivariatePolyXmpPagePatch2}
\pastebutton{UnivariatePolyXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{p := (3*x-1)**2 * (2*x + 8)\free{pdec }\bound{p }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch3}
\begin{paste}{UnivariatePolyXmpPageFull3}{UnivariatePolyXmpPageEmpty3}
\pastebutton{UnivariatePolyXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{q := (1 - 6*x + 9*x**2)**2\free{qdec }\bound{q }}
\indentrel{3}\begin{verbatim}
           4       3      2
   (3)  81x  - 108x  + 54x  - 12x + 1
                  Type: UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty3}
\begin{paste}{UnivariatePolyXmpPageEmpty3}{UnivariatePolyXmpPagePatch3}
\pastebutton{UnivariatePolyXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{q := (1 - 6*x + 9*x**2)**2\free{qdec }\bound{q }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch4}
\begin{paste}{UnivariatePolyXmpPageFull4}{UnivariatePolyXmpPageEmpty4}
\pastebutton{UnivariatePolyXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{p**2 + p*q\free{p q }}
\indentrel{3}\begin{verbatim}
   (4)
          7        6        5         4        3        2
     1458x  + 3240x  - 7074x  + 10584x  - 9282x  + 4120x
   + 
     - 878x + 72
                  Type: UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty4}
\begin{paste}{UnivariatePolyXmpPageEmpty4}{UnivariatePolyXmpPagePatch4}
\pastebutton{UnivariatePolyXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{p**2 + p*q\free{p q }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch5}
\begin{paste}{UnivariatePolyXmpPageFull5}{UnivariatePolyXmpPageEmpty5}
\pastebutton{UnivariatePolyXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{leadingCoefficient p\free{p }}
\indentrel{3}\begin{verbatim}
   (5)  18
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty5}
\begin{paste}{UnivariatePolyXmpPageEmpty5}{UnivariatePolyXmpPagePatch5}
\pastebutton{UnivariatePolyXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{leadingCoefficient p\free{p }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch6}
\begin{paste}{UnivariatePolyXmpPageFull6}{UnivariatePolyXmpPageEmpty6}
\pastebutton{UnivariatePolyXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{degree p\free{p }}
\indentrel{3}\begin{verbatim}
   (6)  3
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty6}
\begin{paste}{UnivariatePolyXmpPageEmpty6}{UnivariatePolyXmpPagePatch6}
\pastebutton{UnivariatePolyXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{degree p\free{p }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch7}
\begin{paste}{UnivariatePolyXmpPageFull7}{UnivariatePolyXmpPageEmpty7}
\pastebutton{UnivariatePolyXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{reductum p\free{p }}
\indentrel{3}\begin{verbatim}
           2
   (7)  60x  - 46x + 8
                  Type: UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty7}
\begin{paste}{UnivariatePolyXmpPageEmpty7}{UnivariatePolyXmpPagePatch7}
\pastebutton{UnivariatePolyXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{reductum p\free{p }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch8}
\begin{paste}{UnivariatePolyXmpPageFull8}{UnivariatePolyXmpPageEmpty8}
\pastebutton{UnivariatePolyXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{gcd(p,q)\free{p q }}
\indentrel{3}\begin{verbatim}
          2
   (8)  9x  - 6x + 1
                  Type: UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty8}
\begin{paste}{UnivariatePolyXmpPageEmpty8}{UnivariatePolyXmpPagePatch8}
\pastebutton{UnivariatePolyXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{gcd(p,q)\free{p q }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch9}
\begin{paste}{UnivariatePolyXmpPageFull9}{UnivariatePolyXmpPageEmpty9}
\pastebutton{UnivariatePolyXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{lcm(p,q)\free{p q }}
\indentrel{3}\begin{verbatim}
            5       4       3       2
   (9)  162x  + 432x  - 756x  + 408x  - 94x + 8
                  Type: UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty9}
\begin{paste}{UnivariatePolyXmpPageEmpty9}{UnivariatePolyXmpPagePatch9}
\pastebutton{UnivariatePolyXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{lcm(p,q)\free{p q }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch10}
\begin{paste}{UnivariatePolyXmpPageFull10}{UnivariatePolyXmpPageEmpty10}
\pastebutton{UnivariatePolyXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{resultant(p,q)\free{p q }}
\indentrel{3}\begin{verbatim}
   (10)  0
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty10}
\begin{paste}{UnivariatePolyXmpPageEmpty10}{UnivariatePolyXmpPagePatch10}
\pastebutton{UnivariatePolyXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{resultant(p,q)\free{p q }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch11}
\begin{paste}{UnivariatePolyXmpPageFull11}{UnivariatePolyXmpPageEmpty11}
\pastebutton{UnivariatePolyXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{D p\free{p }}
\indentrel{3}\begin{verbatim}
            2
   (11)  54x  + 120x - 46
                  Type: UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty11}
\begin{paste}{UnivariatePolyXmpPageEmpty11}{UnivariatePolyXmpPagePatch11}
\pastebutton{UnivariatePolyXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{D p\free{p }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch12}
\begin{paste}{UnivariatePolyXmpPageFull12}{UnivariatePolyXmpPageEmpty12}
\pastebutton{UnivariatePolyXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{p(2)\free{p }}
\indentrel{3}\begin{verbatim}
   (12)  300
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty12}
\begin{paste}{UnivariatePolyXmpPageEmpty12}{UnivariatePolyXmpPagePatch12}
\pastebutton{UnivariatePolyXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{p(2)\free{p }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch13}
\begin{paste}{UnivariatePolyXmpPageFull13}{UnivariatePolyXmpPageEmpty13}
\pastebutton{UnivariatePolyXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{p(q)\free{p q }}
\indentrel{3}\begin{verbatim}
   (13)
             12            11            10            9
     9565938x   - 38263752x   + 70150212x   - 77944680x
   + 
              8            7            6           5
     58852170x  - 32227632x  + 13349448x  - 4280688x
   + 
             4          3         2
     1058184x  - 192672x  + 23328x  - 1536x + 40
                  Type: UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty13}
\begin{paste}{UnivariatePolyXmpPageEmpty13}{UnivariatePolyXmpPagePatch13}
\pastebutton{UnivariatePolyXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{p(q)\free{p q }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch14}
\begin{paste}{UnivariatePolyXmpPageFull14}{UnivariatePolyXmpPageEmpty14}
\pastebutton{UnivariatePolyXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{q(p)\free{p q }}
\indentrel{3}\begin{verbatim}
   (14)
             12             11             10
     8503056x   + 113374080x   + 479950272x
   + 
               9              8             7
     404997408x  - 1369516896x  - 626146848x
   + 
                6              5              4
     2939858712x  - 2780728704x  + 1364312160x
   + 
                 3            2
     - 396838872x  + 69205896x  - 6716184x + 279841
                  Type: UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty14}
\begin{paste}{UnivariatePolyXmpPageEmpty14}{UnivariatePolyXmpPagePatch14}
\pastebutton{UnivariatePolyXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{q(p)\free{p q }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch15}
\begin{paste}{UnivariatePolyXmpPageFull15}{UnivariatePolyXmpPageEmpty15}
\pastebutton{UnivariatePolyXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{l := coefficients p\free{p }\bound{l }}
\indentrel{3}\begin{verbatim}
   (15)  [18,60,- 46,8]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty15}
\begin{paste}{UnivariatePolyXmpPageEmpty15}{UnivariatePolyXmpPagePatch15}
\pastebutton{UnivariatePolyXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{l := coefficients p\free{p }\bound{l }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch16}
\begin{paste}{UnivariatePolyXmpPageFull16}{UnivariatePolyXmpPageEmpty16}
\pastebutton{UnivariatePolyXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{reduce(gcd,l)\free{l }}
\indentrel{3}\begin{verbatim}
   (16)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty16}
\begin{paste}{UnivariatePolyXmpPageEmpty16}{UnivariatePolyXmpPagePatch16}
\pastebutton{UnivariatePolyXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{reduce(gcd,l)\free{l }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch17}
\begin{paste}{UnivariatePolyXmpPageFull17}{UnivariatePolyXmpPageEmpty17}
\pastebutton{UnivariatePolyXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{content p\free{p }}
\indentrel{3}\begin{verbatim}
   (17)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty17}
\begin{paste}{UnivariatePolyXmpPageEmpty17}{UnivariatePolyXmpPagePatch17}
\pastebutton{UnivariatePolyXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{content p\free{p }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch18}
\begin{paste}{UnivariatePolyXmpPageFull18}{UnivariatePolyXmpPageEmpty18}
\pastebutton{UnivariatePolyXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{ux := (x**4+2*x+3)::UP(x,INT)\bound{ux }}
\indentrel{3}\begin{verbatim}
          4
   (18)  x  + 2x + 3
                  Type: UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty18}
\begin{paste}{UnivariatePolyXmpPageEmpty18}{UnivariatePolyXmpPagePatch18}
\pastebutton{UnivariatePolyXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{ux := (x**4+2*x+3)::UP(x,INT)\bound{ux }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch19}
\begin{paste}{UnivariatePolyXmpPageFull19}{UnivariatePolyXmpPageEmpty19}
\pastebutton{UnivariatePolyXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{vectorise(ux,5)\free{ux }}
\indentrel{3}\begin{verbatim}
   (19)  [3,2,0,0,1]
                                   Type: Vector Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty19}
\begin{paste}{UnivariatePolyXmpPageEmpty19}{UnivariatePolyXmpPagePatch19}
\pastebutton{UnivariatePolyXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{vectorise(ux,5)\free{ux }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch20}
\begin{paste}{UnivariatePolyXmpPageFull20}{UnivariatePolyXmpPageEmpty20}
\pastebutton{UnivariatePolyXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{squareTerms(p) ==
  reduce(+,[t**2 for t in monomials p])
\bound{squareTerms }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty20}
\begin{paste}{UnivariatePolyXmpPageEmpty20}{UnivariatePolyXmpPagePatch20}
\pastebutton{UnivariatePolyXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{squareTerms(p) ==
  reduce(+,[t**2 for t in monomials p])
\bound{squareTerms }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch21}
\begin{paste}{UnivariatePolyXmpPageFull21}{UnivariatePolyXmpPageEmpty21}
\pastebutton{UnivariatePolyXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{p\free{p }}
\indentrel{3}\begin{verbatim}
            3      2
   (21)  18x  + 60x  - 46x + 8
                  Type: UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty21}
\begin{paste}{UnivariatePolyXmpPageEmpty21}{UnivariatePolyXmpPagePatch21}
\pastebutton{UnivariatePolyXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{p\free{p }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch22}
\begin{paste}{UnivariatePolyXmpPageFull22}{UnivariatePolyXmpPageEmpty22}
\pastebutton{UnivariatePolyXmpPageFull22}{\hidepaste}
\tab{5}\spadcommand{squareTerms p\free{p }\free{squareTerms }}
\indentrel{3}\begin{verbatim}
             6        4        2
   (22)  324x  + 3600x  + 2116x  + 64
                  Type: UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty22}
\begin{paste}{UnivariatePolyXmpPageEmpty22}{UnivariatePolyXmpPagePatch22}
\pastebutton{UnivariatePolyXmpPageEmpty22}{\showpaste}
\tab{5}\spadcommand{squareTerms p\free{p }\free{squareTerms }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch23}
\begin{paste}{UnivariatePolyXmpPageFull23}{UnivariatePolyXmpPageEmpty23}
\pastebutton{UnivariatePolyXmpPageFull23}{\hidepaste}
\tab{5}\spadcommand{(r,s) : UP(a1,FRAC INT)\bound{rdec }\bound{sdec }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty23}
\begin{paste}{UnivariatePolyXmpPageEmpty23}{UnivariatePolyXmpPagePatch23}
\pastebutton{UnivariatePolyXmpPageEmpty23}{\showpaste}
\tab{5}\spadcommand{(r,s) : UP(a1,FRAC INT)\bound{rdec }\bound{sdec }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch24}
\begin{paste}{UnivariatePolyXmpPageFull24}{UnivariatePolyXmpPageEmpty24}
\pastebutton{UnivariatePolyXmpPageFull24}{\hidepaste}
\tab{5}\spadcommand{r := a1**2 - 2/3\free{rdec }\bound{r }}
\indentrel{3}\begin{verbatim}
           2   2
   (24)  a1  - Ä
               3
        Type: UnivariatePolynomial(a1,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty24}
\begin{paste}{UnivariatePolyXmpPageEmpty24}{UnivariatePolyXmpPagePatch24}
\pastebutton{UnivariatePolyXmpPageEmpty24}{\showpaste}
\tab{5}\spadcommand{r := a1**2 - 2/3\free{rdec }\bound{r }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch25}
\begin{paste}{UnivariatePolyXmpPageFull25}{UnivariatePolyXmpPageEmpty25}
\pastebutton{UnivariatePolyXmpPageFull25}{\hidepaste}
\tab{5}\spadcommand{s := a1 + 4\free{sdec }\bound{s }}
\indentrel{3}\begin{verbatim}
   (25)  a1 + 4
        Type: UnivariatePolynomial(a1,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty25}
\begin{paste}{UnivariatePolyXmpPageEmpty25}{UnivariatePolyXmpPagePatch25}
\pastebutton{UnivariatePolyXmpPageEmpty25}{\showpaste}
\tab{5}\spadcommand{s := a1 + 4\free{sdec }\bound{s }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch26}
\begin{paste}{UnivariatePolyXmpPageFull26}{UnivariatePolyXmpPageEmpty26}
\pastebutton{UnivariatePolyXmpPageFull26}{\hidepaste}
\tab{5}\spadcommand{r quo s\free{r s }}
\indentrel{3}\begin{verbatim}
   (26)  a1 - 4
        Type: UnivariatePolynomial(a1,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty26}
\begin{paste}{UnivariatePolyXmpPageEmpty26}{UnivariatePolyXmpPagePatch26}
\pastebutton{UnivariatePolyXmpPageEmpty26}{\showpaste}
\tab{5}\spadcommand{r quo s\free{r s }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch27}
\begin{paste}{UnivariatePolyXmpPageFull27}{UnivariatePolyXmpPageEmpty27}
\pastebutton{UnivariatePolyXmpPageFull27}{\hidepaste}
\tab{5}\spadcommand{r rem s\free{r s }}
\indentrel{3}\begin{verbatim}
         46
   (27)  ÄÄ
          3
        Type: UnivariatePolynomial(a1,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty27}
\begin{paste}{UnivariatePolyXmpPageEmpty27}{UnivariatePolyXmpPagePatch27}
\pastebutton{UnivariatePolyXmpPageEmpty27}{\showpaste}
\tab{5}\spadcommand{r rem s\free{r s }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch28}
\begin{paste}{UnivariatePolyXmpPageFull28}{UnivariatePolyXmpPageEmpty28}
\pastebutton{UnivariatePolyXmpPageFull28}{\hidepaste}
\tab{5}\spadcommand{d := divide(r, s)\free{r s }\bound{d }}
\indentrel{3}\begin{verbatim}
                                      46
   (28)  [quotient= a1 - 4,remainder= ÄÄ]
                                       3
Type: Record(quotient: UnivariatePolynomial(a1,Fraction Integer),remainder: UnivariatePolynomial(a1,Fraction Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty28}
\begin{paste}{UnivariatePolyXmpPageEmpty28}{UnivariatePolyXmpPagePatch28}
\pastebutton{UnivariatePolyXmpPageEmpty28}{\showpaste}
\tab{5}\spadcommand{d := divide(r, s)\free{r s }\bound{d }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch29}
\begin{paste}{UnivariatePolyXmpPageFull29}{UnivariatePolyXmpPageEmpty29}
\pastebutton{UnivariatePolyXmpPageFull29}{\hidepaste}
\tab{5}\spadcommand{r - (d.quotient * s + d.remainder)\free{r s d }}
\indentrel{3}\begin{verbatim}
   (29)  0
        Type: UnivariatePolynomial(a1,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty29}
\begin{paste}{UnivariatePolyXmpPageEmpty29}{UnivariatePolyXmpPagePatch29}
\pastebutton{UnivariatePolyXmpPageEmpty29}{\showpaste}
\tab{5}\spadcommand{r - (d.quotient * s + d.remainder)\free{r s d }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch30}
\begin{paste}{UnivariatePolyXmpPageFull30}{UnivariatePolyXmpPageEmpty30}
\pastebutton{UnivariatePolyXmpPageFull30}{\hidepaste}
\tab{5}\spadcommand{integrate r\free{r }}
\indentrel{3}\begin{verbatim}
         1   3   2
   (30)  Ä a1  - Ä a1
         3       3
        Type: UnivariatePolynomial(a1,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty30}
\begin{paste}{UnivariatePolyXmpPageEmpty30}{UnivariatePolyXmpPagePatch30}
\pastebutton{UnivariatePolyXmpPageEmpty30}{\showpaste}
\tab{5}\spadcommand{integrate r\free{r }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch31}
\begin{paste}{UnivariatePolyXmpPageFull31}{UnivariatePolyXmpPageEmpty31}
\pastebutton{UnivariatePolyXmpPageFull31}{\hidepaste}
\tab{5}\spadcommand{integrate s\free{s }}
\indentrel{3}\begin{verbatim}
         1   2
   (31)  Ä a1  + 4a1
         2
        Type: UnivariatePolynomial(a1,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty31}
\begin{paste}{UnivariatePolyXmpPageEmpty31}{UnivariatePolyXmpPagePatch31}
\pastebutton{UnivariatePolyXmpPageEmpty31}{\showpaste}
\tab{5}\spadcommand{integrate s\free{s }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch32}
\begin{paste}{UnivariatePolyXmpPageFull32}{UnivariatePolyXmpPageEmpty32}
\pastebutton{UnivariatePolyXmpPageFull32}{\hidepaste}
\tab{5}\spadcommand{t : UP(a1,FRAC POLY INT)\bound{tdec }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty32}
\begin{paste}{UnivariatePolyXmpPageEmpty32}{UnivariatePolyXmpPagePatch32}
\pastebutton{UnivariatePolyXmpPageEmpty32}{\showpaste}
\tab{5}\spadcommand{t : UP(a1,FRAC POLY INT)\bound{tdec }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch33}
\begin{paste}{UnivariatePolyXmpPageFull33}{UnivariatePolyXmpPageEmpty33}
\pastebutton{UnivariatePolyXmpPageFull33}{\hidepaste}
\tab{5}\spadcommand{t := a1**2 - a1/b2 + (b1**2-b1)/(b2+3)\free{tdec }\bound{t }}
\indentrel{3}\begin{verbatim}
                         2
           2    1      b1  - b1
   (33)  a1  - ÄÄ a1 + ÄÄÄÄÄÄÄÄ
               b2       b2 + 3
Type: UnivariatePolynomial(a1,Fraction Polynomial Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty33}
\begin{paste}{UnivariatePolyXmpPageEmpty33}{UnivariatePolyXmpPagePatch33}
\pastebutton{UnivariatePolyXmpPageEmpty33}{\showpaste}
\tab{5}\spadcommand{t := a1**2 - a1/b2 + (b1**2-b1)/(b2+3)\free{tdec }\bound{t }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch34}
\begin{paste}{UnivariatePolyXmpPageFull34}{UnivariatePolyXmpPageEmpty34}
\pastebutton{UnivariatePolyXmpPageFull34}{\hidepaste}
\tab{5}\spadcommand{u : FRAC POLY INT := t\bound{u }\free{t }}
\indentrel{3}\begin{verbatim}
           2  2      2           2
         a1 b2  + (b1  - b1 + 3a1  - a1)b2 - 3a1
   (34)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                          2
                        b2  + 3b2
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty34}
\begin{paste}{UnivariatePolyXmpPageEmpty34}{UnivariatePolyXmpPagePatch34}
\pastebutton{UnivariatePolyXmpPageEmpty34}{\showpaste}
\tab{5}\spadcommand{u : FRAC POLY INT := t\bound{u }\free{t }}
\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPagePatch35}
\begin{paste}{UnivariatePolyXmpPageFull35}{UnivariatePolyXmpPageEmpty35}
\pastebutton{UnivariatePolyXmpPageFull35}{\hidepaste}
\tab{5}\spadcommand{u :: UP(b1,?)\free{u }}
\indentrel{3}\begin{verbatim}
                                    2
            1     2      1        a1 b2 - a1
   (35)  ÄÄÄÄÄÄ b1  - ÄÄÄÄÄÄ b1 + ÄÄÄÄÄÄÄÄÄÄ
         b2 + 3       b2 + 3          b2
Type: UnivariatePolynomial(b1,Fraction Polynomial Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UnivariatePolyXmpPageEmpty35}
\begin{paste}{UnivariatePolyXmpPageEmpty35}{UnivariatePolyXmpPagePatch35}
\pastebutton{UnivariatePolyXmpPageEmpty35}{\showpaste}
\tab{5}\spadcommand{u :: UP(b1,?)\free{u }}
\end{paste}\end{patch}

\end{chunk}
\section{oreup.ht}
\pagetitle{UnivariateSkewPolyXmpPage}{up.ht}{UnivariateSkewPolynomial}
\begin{chunk}{oreup.ht}
\begin{page}{UnivariateSkewPolyXmpPage}{UnivariateSkewPolynomial}
\beginscroll

Skew or Ore polynomial rings provide a unified framework to
compute with differential and difference equations.
\newline
In the following, let A be an integral domain, equipped with two
endomorphisms \sigma and \delta where:
\blankline
\begin{items}
\item \sigma: A -> A is an injective ring endomorphism
\item \delta: A -> A, the pseudo-derivation with respect to 
\sigma, is an additive endomorphism with 
\blankline
\delta(ab) = \sigma(a)\delta(b) + \delta(a)b
\blankline
for all a,b in A
\end{items}
\blankline
The skew polynomial ring 
[\Delta;\sigma,\delta] is the ring of 
polynomials in \delta with coefficients in A, with the 
usual addition, while the product is given by
\blankline
\delta a = \sigma(a)\delta + \delta(a) for a in A
\blankline
The two most important examples of skew polynomial rings are:
\blankline
K(x)[D,1,\delta]
\blankline
where 1 is the identity on K and \texht{$\delta$}{delta} is 
the usual derviative, is the ring of differential polynomials
\blankline
  \subscriptIt{K}{n} [E,n,n->n+1,0] 
\blankline
is the ring of linear recurrence operators with polynomial coefficients

\horizontalline
The UnivariateSkewPolynomialCategory (OREPCAT) provides a unified
framework for polynomial rings in a non-central indeterminate over
some coefficient ring R. The commutation relations between the
indeterminate x and the coefficient t is given by 
\blankline
   x r = \sigma(r) x + \delta(r)
\blankline
where \sigma is a ring endomorphism of R
and   \delta is a \sigma-derivation of R
which is an additive map from R to R such that
\blankline
   \delta(rs) = \sigma(r) \delta(s) + \delta(r) s
\blankline
In case \sigma is the identity map on R, a \sigma-derivation of R
is just called a derivation. 
\blankline
We start with a linear ordinary differential operator. First, we
define the coefficient ring to be expressions in one variable x
with fractional coefficients:
\blankline
   F := EXPR(FRAC(INT))
\blankline
Define Dx to be a derivative d/dx:
\blankline
   Dx: F->F := f+->D(f,['x])
\blankline
Define a skew polynomial ring over F with identity endomorphism as
\sigma and derivation d/dx as \delta:
\begin{verbatim}
   D0 := OREUP('d,F,1,Dx)
\end{verbatim}
\begin{verbatim}
   u:D0 := (operator 'u)(x)
\end{verbatim}
\begin{verbatim}
   d:D0 := 'd
\end{verbatim}
\begin{verbatim}
   a:D0:=u^3*d^3+u^2*d^2+u*d+1

            3 3       2 2
        u(x) d  + u(x) d  + u(x)d + 1
\end{verbatim}
\begin{verbatim}
   b:D0:=(u+1)*d^2+2*d

                   2
        (u(x) + 1)d  + 2d
\end{verbatim}
\begin{verbatim}
   r:=rightDivide(a,b)

                                 3 ,          3       2
                    3      - u(x) u (x) - u(x)  + u(x)
                u(x)
   [quotient= -------- d + ----------------------------,
              u(x) + 1               2
                                 u(x)  + 2u(x) + 1
                    3 ,           3
               2u(x) u (x) + 3u(x)  + u(x)

    remainder= --------------------------- d + 1]
                        2
                    u(x)  + 2u(x) + 1

\end{verbatim}
\begin{verbatim}
   r.quotient

                           3 ,          3       2
              3      - u(x) u (x) - u(x)  + u(x)
          u(x)
        -------- d + ----------------------------
        u(x) + 1               2
                           u(x)  + 2u(x) + 1

\end{verbatim}
\begin{verbatim}
   r.remainder

              3 ,           3
         2u(x) u (x) + 3u(x)  + u(x)

         --------------------------- d + 1
                  2
              u(x)  + 2u(x) + 1
\end{verbatim}

\horizontalline

   )clear all
\blankline
As a second example, we consider the so-called Weyl algebra.
\blankline
Define the coefficient ring to be an ordinary polynomial over integers
in one variable t
\blankline
\begin{verbatim}
   R := UP('t,INT)
\end{verbatim}
\blankline
Define a skew polynomial ring over R with identity map as 
\sigma
and derivation d/dt as \delta. 
The resulting algebra is then called a Weyl algebra:
\blankline
\begin{verbatim}
   W := OREUP('x,R,1,D)

   t:W := 't

   x:W := 'x
\end{verbatim}
\blankline
Let 
\begin{verbatim}
   a:W:=(t-1)*x^4+(t^3+3*t+1)*x^2+2*t*x+t^3

                4     3           2           3
        (t - 1)x  + (t  + 3t + 1)x  + 2t x + t
\end{verbatim}
\begin{verbatim}
   b:W:=(6*t^4+2*t^2)*x^3+3*t^2*x^2

           4     2  3     2 2
        (6t  + 2t )x  + 3t x
\end{verbatim}
\blankline
Then
\begin{verbatim}
   a*b
           5     4     3     2  7       4      3      2        6
        (6t  - 6t  + 2t  - 2t )x  + (96t  - 93t  + 13t  - 16t)x
      + 
           7      5     4       3       2       5
        (6t  + 20t  + 6t  + 438t  - 406t  - 24)x
      + 
            6      5       4      3       2              4
        (48t  + 15t  + 152t  + 61t  + 603t  - 532t - 36)x
      + 
           7      5      4       3       2               3
        (6t  + 74t  + 60t  + 226t  + 116t  + 168t - 140)x
      + 
           5     3      2            2
        (3t  + 6t  + 12t  + 18t + 6)x

   a^3
         3     2           12      5     4      3      2           10
       (t  - 3t  + 3t - 1)x   + (3t  - 6t  + 12t  - 15t  + 3t + 3)x
     + 
          3      2       9      7     6      5      4      3     2            8
       (6t  - 12t  + 6t)x  + (3t  - 3t  + 21t  - 18t  + 24t  - 9t  - 15t - 3)x
     + 
           5      4      3      2        7
       (12t  - 12t  + 36t  - 24t  - 12t)x
     + 
         9      7     6      5     4      3      2           6
       (t  + 15t  - 3t  + 45t  + 6t  + 36t  + 15t  + 9t + 1)x
     + 
          7      5      3      2       5
       (6t  + 48t  + 54t  + 36t  + 6t)x
     + 
          9      7     6      5      4      3      2  4
       (3t  + 21t  + 3t  + 39t  + 18t  + 39t  + 12t )x
     + 
           7      5      4     3  3      9     7     6      5  2     7     9
       (12t  + 36t  + 12t  + 8t )x  + (3t  + 9t  + 3t  + 12t )x  + 6t x + t
\end{verbatim}

\horizontalline
   )clear all 
\blankline
As a third example, we construct a difference operator algebra over
the ring of EXPR(INT) by using an automorphism S defined by a
"shift" operation S:EXPR(INT) -> EXPR(INT)
\blankline
\begin{verbatim}
   s(e)(n) = e(n+1)
\end{verbatim}
\blankline
and an S-derivation defined by DF:EXPR(INT) -> EXPR(INT) as
\blankline
\begin{verbatim}
   DF(e)(n) = e(n+1)-e(n)
\end{verbatim}
\blankline
Define S to be a "shift" operator, which acts on expressions with 
the discrete variable n:
\blankline
\begin{verbatim}
   S:EXPR(INT)->EXPR(INT):=e+->eval(e,[n],[n+1])
\end{verbatim}
\blankline
Define DF to be a "difference" operator, which acts on expressions
with a discrete variable n:
\blankline
\begin{verbatim}
   DF:EXPR(INT)->EXPR(INT):=e+->eval(e,[n],[n+1])-e
\end{verbatim}
\blankline
Then define the difference operator algebra D0:
\blankline
\begin{verbatim}
   D0:=OREUP('D,EXPR(INT),morphism S,DF)

   u:=(operator 'u)[n]

   L:D0:='D+u

        D + u(n)

   L^2

         2                2
        D  + 2u(n)D + u(n)
\end{verbatim}

\horizontalline
   )clear all
\blankline
As a fourth example, we construct a skew polynomial ring by using an
inner derivation \delta induced by a fixed y in R:
\blankline
   \delta(r) = yr - ry
\blankline
First we should expose the constructor SquareMatrix so it is visible
in the interpreter:
\blankline
   )set expose add constructor SquareMatrix
\blankline
Define R to be the square matrix with integer entries:
\blankline
\begin{verbatim}
   R:=SQMATRIX(2,INT)

   y:R:=matrix [[1,1],[0,1]]
        +1  1+
        |    |
        +0  1+
\end{verbatim}
\blankline
Define the inner derivative \delta:
\blankline
   delta:R->R:=r+->y*r-r*y
\blankline
Define S to be a skew polynomial determined by \sigma = 1
and \delta as an inner derivative:
\blankline
\begin{verbatim}
   S:=OREUP('x,R,1,delta)

   x:S:='x

   a:S:=matrix [[2,3],[1,1]]
        +2  3+
        |    |
        +1  1+

   x^2*a
        +2  3+ 2   +2  - 2+    +0  - 2+
        |    |x  + |      |x + |      |
        +1  1+     +0  - 2+    +0   0 +
\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\section{vector.ht}
\pagetitle{VectorXmpPage}{vector.ht}{Vector}
\pageto{notitle}{OneDimensionalArrayXmpPage}
\pageto{notitle}{ListXmpPage}
\pageto{notitle}{MatrixXmpPage}
\pageto{notitle}{OneDimensionalArrayXmpPage}
\pageto{notitle}{SetXmpPage}
\pageto{notitle}{TableXmpPage}
\pageto{notitle}{TwoDimensionalArrayXmpPage}
\begin{chunk}{vector.ht}
\begin{page}{VectorXmpPage}{Vector}
\beginscroll

The \spadtype{Vector} domain is used for storing data in a
one-dimensional indexed data structure.  A vector is a homogeneous
data structure in that all the components of the vector must belong to
the same Axiom domain.  Each vector has a fixed length specified by
the user; vectors are not extensible.  This domain is similar to the
\spadtype{OneDimensionalArray} domain, except that when the components
of a \spadtype{Vector} belong to a \spadtype{Ring}, arithmetic
operations are provided.  For more examples of operations that are
defined for both \spadtype{Vector} and \spadtype{OneDimensionalArray},
see \downlink{`OneDimensionalArray'}{OneDimensionalArrayXmpPage}
\ignore{OneDimensionalArray}.

As with the \spadtype{OneDimensionalArray} domain, a \spadtype{Vector}
can be created by calling the operation \spadfunFrom{new}{Vector}, its
components can be accessed by calling the operations
\spadfunFrom{elt}{Vector} and \spadfunFrom{qelt}{Vector}, and its
components can be reset by calling the operations
\spadfunFrom{setelt}{Vector} and \spadfunFromX{qsetelt}{Vector}.
\xtc{ This creates a vector of integers of length \spad{5} all of
whose components are \spad{12}.  }{ \spadpaste{u : VECTOR INT :=
new(5,12) \bound{u}} } \xtc{ This is how you create a vector from a
list of its components.  }{ \spadpaste{v : VECTOR INT :=
vector([1,2,3,4,5]) \bound{v}} }

\xtc{
Indexing for vectors begins at \spad{1}.
The last element has index equal to the length of the vector,
which is computed by \spadopFrom{\#}{Vector}.
}{
\spadpaste{\#(v) \free{v}}
}
\xtc{
This is the standard way to use \spadfunFrom{elt}{Vector} to extract an
element.
Functionally, it is the same as if you had typed \spad{elt(v,2)}.
}{
\spadpaste{v.2 \free{v}}
}
\xtc{
This is the standard way to use \spadfunFrom{setelt}{Vector} to change an
element.
It is the same as if you had typed \spad{setelt(v,3,99)}.
}{
\spadpaste{v.3 := 99 \free{v}\bound{vdelta}}
}
\xtc{
Now look at \spad{v} to see the change.  You can use
\spadfunFrom{qelt}{Vector} and \spadfunFromX{qsetelt}{Vector} (instead
of \spadfunFrom{elt}{Vector} and \spadfunFrom{setelt}{Vector},
respectively) but {\it only} when you know that the index is within
the valid range.
}{
\spadpaste{v \free{vdelta}}
}

\xtc{
When the components belong to a \spadtype{Ring}, Axiom
provides arithmetic operations for \spadtype{Vector}.
These include left and right scalar multiplication.
}{
\spadpaste{5 * v \free{vdelta}}
}
\xtc{
}{
\spadpaste{v * 7 \free{vdelta}}
}
\xtc{
}{
\spadpaste{w : VECTOR INT := vector([2,3,4,5,6]) \bound{w}}
}
\xtc{
Addition and subtraction are also available.
}{
\spadpaste{v + w \free{vdelta w}}
}
\xtc{
Of course, when adding or subtracting, the two vectors must have the same
length or an error message is displayed.
}{
\spadpaste{v - w \free{vdelta w}}
}

For more information about other aggregate domains,
see the following:
\downlink{`List'}{ListXmpPage}\ignore{List},
\downlink{`Matrix'}{MatrixXmpPage}\ignore{Matrix},
\downlink{`OneDimensionalArray'}{OneDimensionalArrayXmpPage}
\ignore{OneDimensionalArray},
\downlink{`Set'}{SetXmpPage}\ignore{Set},
\downlink{`Table'}{TableXmpPage}\ignore{Table}, and
\downlink{`TwoDimensionalArray'}{TwoDimensionalArrayXmpPage}
\ignore{TwoDimensionalArray}.
Issue the system command \spadcmd{)show Vector}
to display the full list of operations defined by
\spadtype{Vector}.

\endscroll
\autobuttons
\end{page}

\begin{patch}{VectorXmpPagePatch1}
\begin{paste}{VectorXmpPageFull1}{VectorXmpPageEmpty1}
\pastebutton{VectorXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{u : VECTOR INT := new(5,12)\bound{u }}
\indentrel{3}\begin{verbatim}
   (1)  [12,12,12,12,12]
                                   Type: Vector Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{VectorXmpPageEmpty1}
\begin{paste}{VectorXmpPageEmpty1}{VectorXmpPagePatch1}
\pastebutton{VectorXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{u : VECTOR INT := new(5,12)\bound{u }}
\end{paste}\end{patch}

\begin{patch}{VectorXmpPagePatch2}
\begin{paste}{VectorXmpPageFull2}{VectorXmpPageEmpty2}
\pastebutton{VectorXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{v : VECTOR INT := vector([1,2,3,4,5])\bound{v }}
\indentrel{3}\begin{verbatim}
   (2)  [1,2,3,4,5]
                                   Type: Vector Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{VectorXmpPageEmpty2}
\begin{paste}{VectorXmpPageEmpty2}{VectorXmpPagePatch2}
\pastebutton{VectorXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{v : VECTOR INT := vector([1,2,3,4,5])\bound{v }}
\end{paste}\end{patch}

\begin{patch}{VectorXmpPagePatch3}
\begin{paste}{VectorXmpPageFull3}{VectorXmpPageEmpty3}
\pastebutton{VectorXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{\#(v)\free{v }}
\indentrel{3}\begin{verbatim}
   (3)  5
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{VectorXmpPageEmpty3}
\begin{paste}{VectorXmpPageEmpty3}{VectorXmpPagePatch3}
\pastebutton{VectorXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{\#(v)\free{v }}
\end{paste}\end{patch}

\begin{patch}{VectorXmpPagePatch4}
\begin{paste}{VectorXmpPageFull4}{VectorXmpPageEmpty4}
\pastebutton{VectorXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{v.2\free{v }}
\indentrel{3}\begin{verbatim}
   (4)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{VectorXmpPageEmpty4}
\begin{paste}{VectorXmpPageEmpty4}{VectorXmpPagePatch4}
\pastebutton{VectorXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{v.2\free{v }}
\end{paste}\end{patch}

\begin{patch}{VectorXmpPagePatch5}
\begin{paste}{VectorXmpPageFull5}{VectorXmpPageEmpty5}
\pastebutton{VectorXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{v.3 := 99\free{v }\bound{vdelta }}
\indentrel{3}\begin{verbatim}
   (5)  99
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{VectorXmpPageEmpty5}
\begin{paste}{VectorXmpPageEmpty5}{VectorXmpPagePatch5}
\pastebutton{VectorXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{v.3 := 99\free{v }\bound{vdelta }}
\end{paste}\end{patch}

\begin{patch}{VectorXmpPagePatch6}
\begin{paste}{VectorXmpPageFull6}{VectorXmpPageEmpty6}
\pastebutton{VectorXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{v\free{vdelta }}
\indentrel{3}\begin{verbatim}
   (6)  [1,2,99,4,5]
                                   Type: Vector Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{VectorXmpPageEmpty6}
\begin{paste}{VectorXmpPageEmpty6}{VectorXmpPagePatch6}
\pastebutton{VectorXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{v\free{vdelta }}
\end{paste}\end{patch}

\begin{patch}{VectorXmpPagePatch7}
\begin{paste}{VectorXmpPageFull7}{VectorXmpPageEmpty7}
\pastebutton{VectorXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{5 * v\free{vdelta }}
\indentrel{3}\begin{verbatim}
   (7)  [5,10,495,20,25]
                                   Type: Vector Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{VectorXmpPageEmpty7}
\begin{paste}{VectorXmpPageEmpty7}{VectorXmpPagePatch7}
\pastebutton{VectorXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{5 * v\free{vdelta }}
\end{paste}\end{patch}

\begin{patch}{VectorXmpPagePatch8}
\begin{paste}{VectorXmpPageFull8}{VectorXmpPageEmpty8}
\pastebutton{VectorXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{v * 7\free{vdelta }}
\indentrel{3}\begin{verbatim}
   (8)  [7,14,693,28,35]
                                   Type: Vector Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{VectorXmpPageEmpty8}
\begin{paste}{VectorXmpPageEmpty8}{VectorXmpPagePatch8}
\pastebutton{VectorXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{v * 7\free{vdelta }}
\end{paste}\end{patch}

\begin{patch}{VectorXmpPagePatch9}
\begin{paste}{VectorXmpPageFull9}{VectorXmpPageEmpty9}
\pastebutton{VectorXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{w : VECTOR INT := vector([2,3,4,5,6])\bound{w }}
\indentrel{3}\begin{verbatim}
   (9)  [2,3,4,5,6]
                                   Type: Vector Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{VectorXmpPageEmpty9}
\begin{paste}{VectorXmpPageEmpty9}{VectorXmpPagePatch9}
\pastebutton{VectorXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{w : VECTOR INT := vector([2,3,4,5,6])\bound{w }}
\end{paste}\end{patch}

\begin{patch}{VectorXmpPagePatch10}
\begin{paste}{VectorXmpPageFull10}{VectorXmpPageEmpty10}
\pastebutton{VectorXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{v + w\free{vdelta w }}
\indentrel{3}\begin{verbatim}
   (10)  [3,5,103,9,11]
                                   Type: Vector Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{VectorXmpPageEmpty10}
\begin{paste}{VectorXmpPageEmpty10}{VectorXmpPagePatch10}
\pastebutton{VectorXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{v + w\free{vdelta w }}
\end{paste}\end{patch}

\begin{patch}{VectorXmpPagePatch11}
\begin{paste}{VectorXmpPageFull11}{VectorXmpPageEmpty11}
\pastebutton{VectorXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{v - w\free{vdelta w }}
\indentrel{3}\begin{verbatim}
   (11)  [- 1,- 1,95,- 1,- 1]
                                   Type: Vector Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{VectorXmpPageEmpty11}
\begin{paste}{VectorXmpPageEmpty11}{VectorXmpPagePatch11}
\pastebutton{VectorXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{v - w\free{vdelta w }}
\end{paste}\end{patch}

\end{chunk}
\section{void.ht}
\pagetitle{VoidXmpPage}{void.ht}{Void}
\begin{chunk}{void.ht}
\begin{page}{VoidXmpPage}{Void}
\beginscroll

When an expression is not in a value context, it is given 
type \spadtype{Void}. For example, in the expression
\begin{verbatim}
r := (a; b; if c then d else e; f)
\end{verbatim}
values are used only from the subexpressions \spad{c} and \spad{f}: 
all others are thrown away.
The subexpressions \spad{a}, \spad{b}, \spad{d} and \spad{e}
are evaluated for side-effects only and have type \spadtype{Void}.
There is a unique value of type \spadtype{Void}.

\xtc{
You will most often see results of type \spadtype{Void} when you
declare a variable.
}{
\spadpaste{a : Integer}
}
\noOutputXtc{
Usually no output is displayed for \spadtype{Void} results.
You can force the display of a rather ugly object by issuing
\spadcmd{)set message void on}.
}{
\spadpaste{)set message void on}
}
\xtc{
}{
\spadpaste{b : Fraction Integer}
}
\noOutputXtc{
}{
\spadpaste{)set message void off}
}
\xtc{
All values can be converted to type \spadtype{Void}.
}{
\spadpaste{3::Void \bound{prev}}
}
\xtc{
Once a value has been converted to \spadtype{Void}, it cannot be recovered.
}{
\spadpaste{\% :: PositiveInteger \free{prev}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{VoidXmpPagePatch1}
\begin{paste}{VoidXmpPageFull1}{VoidXmpPageEmpty1}
\pastebutton{VoidXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{a : Integer}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{VoidXmpPageEmpty1}
\begin{paste}{VoidXmpPageEmpty1}{VoidXmpPagePatch1}
\pastebutton{VoidXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{a : Integer}
\end{paste}\end{patch}

\begin{patch}{VoidXmpPagePatch2}
\begin{paste}{VoidXmpPageFull2}{VoidXmpPageEmpty2}
\pastebutton{VoidXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{)set message void on}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{VoidXmpPageEmpty2}
\begin{paste}{VoidXmpPageEmpty2}{VoidXmpPagePatch2}
\pastebutton{VoidXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{)set message void on}
\end{paste}\end{patch}

\begin{patch}{VoidXmpPagePatch3}
\begin{paste}{VoidXmpPageFull3}{VoidXmpPageEmpty3}
\pastebutton{VoidXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{b : Fraction Integer}
\indentrel{3}\begin{verbatim}
   (2)  "()"
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{VoidXmpPageEmpty3}
\begin{paste}{VoidXmpPageEmpty3}{VoidXmpPagePatch3}
\pastebutton{VoidXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{b : Fraction Integer}
\end{paste}\end{patch}

\begin{patch}{VoidXmpPagePatch4}
\begin{paste}{VoidXmpPageFull4}{VoidXmpPageEmpty4}
\pastebutton{VoidXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{)set message void off}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{VoidXmpPageEmpty4}
\begin{paste}{VoidXmpPageEmpty4}{VoidXmpPagePatch4}
\pastebutton{VoidXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{)set message void off}
\end{paste}\end{patch}

\begin{patch}{VoidXmpPagePatch5}
\begin{paste}{VoidXmpPageFull5}{VoidXmpPageEmpty5}
\pastebutton{VoidXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{3::Void\bound{prev }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{VoidXmpPageEmpty5}
\begin{paste}{VoidXmpPageEmpty5}{VoidXmpPagePatch5}
\pastebutton{VoidXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{3::Void\bound{prev }}
\end{paste}\end{patch}

\begin{patch}{VoidXmpPagePatch6}
\begin{paste}{VoidXmpPageFull6}{VoidXmpPageEmpty6}
\pastebutton{VoidXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{\% :: PositiveInteger\free{prev }}
\indentrel{3}\begin{verbatim}
   "()"
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{VoidXmpPageEmpty6}
\begin{paste}{VoidXmpPageEmpty6}{VoidXmpPagePatch6}
\pastebutton{VoidXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{\% :: PositiveInteger\free{prev }}
\end{paste}\end{patch}

\end{chunk}
\section{wutset.ht}
\pagetitle{WuWenTsunTriangularSetXmpPage}{wutset.ht}{WuWenTsunTriangularSet}
\begin{chunk}{wutset.ht}
\begin{page}{WuWenTsunTriangularSetXmpPage}{WuWenTsunTriangularSet}
\beginscroll
The \spadtype{WuWenTsunTriangularSet} domain constructor implements
the characteristic set method of Wu Wen Tsun.  This algorithm computes
a list of triangular sets from a list of polynomials such that the
algebraic variety defined by the given list of polynomials decomposes
into the union of the regular-zero sets of the computed triangular
sets.  The constructor takes four arguments.  The first one, {\bf R},
is the coefficient ring of the polynomials; it must belong to the
category \spadtype{IntegralDomain}.  The second one, {\bf E}, is the
exponent monoid of the polynomials; it must belong to the category
\spadtype{OrderedAbelianMonoidSup}.  The third one, {\bf V}, is the
ordered set of variables; it must belong to the category
\spadtype{OrderedSet}.  The last one is the polynomial ring; it must
belong to the category \spadtype{RecursivePolynomialCategory(R,E,V)}.
The abbreviation for \spadtype{WuWenTsunTriangularSet} is
\spadtype{WUTSET}.

Let us illustrate the facilities by an example.

\xtc{
Define the coefficient ring.
}{
\spadpaste{R := Integer \bound{R}}
}
\xtc{
Define the list of variables,
}{
\spadpaste{ls : List Symbol := [x,y,z,t] \bound{ls}}
}
\xtc{
and make it an ordered set;
}{
\spadpaste{V := OVAR(ls) \free{ls} \bound{V}}
}
\xtc{
then define the exponent monoid.
}{
\spadpaste{E := IndexedExponents V \free{V} \bound{E}}
}
\xtc{
Define the polynomial ring.
}{
\spadpaste{P := NSMP(R, V) \free{R} \free{V} \bound{P}}
}
\xtc{
Let the variables be polynomial.
}{
\spadpaste{x: P := 'x \free{P} \bound{x}}
}
\xtc{
}{
\spadpaste{y: P := 'y \free{P} \bound{y}}
}
\xtc{
}{
\spadpaste{z: P := 'z \free{P} \bound{z}}
}
\xtc{
}{
\spadpaste{t: P := 't \free{P} \bound{t}}
}
\xtc{
Now call the \spadtype{WuWenTsunTriangularSet} domain constructor.
}{
\spadpaste{T := WUTSET(R,E,V,P) \free{R} \free{E} \free{V} 
\free{P} \bound{T} }
}
\xtc{
Define a polynomial system.
}{
\spadpaste{p1 := x ** 31 - x ** 6 - x - y \free{x} \free{y} \bound{p1}}
}
\xtc{
}{
\spadpaste{p2 := x ** 8  - z \free{x} \free{z} \bound{p2}}
}
\xtc{
}{
\spadpaste{p3 := x ** 10 - t \free{x} \free{t} \bound{p3}}
}
\xtc{
}{
\spadpaste{lp := [p1, p2, p3] \free{p1} \free{p2} \free{p3} \bound{lp}}
}
\xtc{
Compute a characteristic set of the system.
}{
\spadpaste{characteristicSet(lp)$T \free{lp} \free{T}}
}
\xtc{
Solve the system.
}{
\spadpaste{zeroSetSplit(lp)$T \free{lp} \free{T}}
}


The \spadtype{RegularTriangularSet} and
\spadtype{SquareFreeRegularTriangularSet} domain constructors, and the
\spadtype{LazardSetSolvingPackage},
\spadtype{SquareFreeRegularTriangularSet} and
\spadtype{ZeroDimensionalSolvePackage} package constructors also
provide operations to compute triangular decompositions of algebraic
varieties.  These five constructor use a special kind of
characteristic sets, called regular triangular sets.  These special
characteristic sets have better properties than the general ones.
Regular triangular sets and their related concepts are presented in
the paper "On the Theories of Triangular sets" By P. Aubry, D. Lazard
and M. Moreno Maza (to appear in the Journal of Symbolic Computation).
The decomposition algorithm (due to the third author) available in the
four above constructors provide generally better timings than the
characteristic set method.  In fact, the \spadtype{WUTSET} constructor
remains interesting for the purpose of manipulating characteristic
sets whereas the other constructors are more convenient for solving
polynomial systems.

Note that the way of understanding triangular decompositions 
is detailed in the example of the \spadtype{RegularTriangularSet}
constructor.
\endscroll
\autobuttons
\end{page}

\begin{patch}{WuWenTsunTriangularSetXmpPagePatch1}
\begin{paste}{WuWenTsunTriangularSetXmpPageFull1}{WuWenTsunTriangularSetXmpPageEmpty1}
\pastebutton{WuWenTsunTriangularSetXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{R := Integer\bound{R }}
\indentrel{3}\begin{verbatim}
   (1)  Integer
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPageEmpty1}
\begin{paste}{WuWenTsunTriangularSetXmpPageEmpty1}{WuWenTsunTriangularSetXmpPagePatch1}
\pastebutton{WuWenTsunTriangularSetXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{R := Integer\bound{R }}
\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPagePatch2}
\begin{paste}{WuWenTsunTriangularSetXmpPageFull2}{WuWenTsunTriangularSetXmpPageEmpty2}
\pastebutton{WuWenTsunTriangularSetXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{ls : List Symbol := [x,y,z,t]\bound{ls }}
\indentrel{3}\begin{verbatim}
   (2)  [x,y,z,t]
                                      Type: List Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPageEmpty2}
\begin{paste}{WuWenTsunTriangularSetXmpPageEmpty2}{WuWenTsunTriangularSetXmpPagePatch2}
\pastebutton{WuWenTsunTriangularSetXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{ls : List Symbol := [x,y,z,t]\bound{ls }}
\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPagePatch3}
\begin{paste}{WuWenTsunTriangularSetXmpPageFull3}{WuWenTsunTriangularSetXmpPageEmpty3}
\pastebutton{WuWenTsunTriangularSetXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{V := OVAR(ls)\free{ls }\bound{V }}
\indentrel{3}\begin{verbatim}
   (3)  OrderedVariableList [x,y,z,t]
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPageEmpty3}
\begin{paste}{WuWenTsunTriangularSetXmpPageEmpty3}{WuWenTsunTriangularSetXmpPagePatch3}
\pastebutton{WuWenTsunTriangularSetXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{V := OVAR(ls)\free{ls }\bound{V }}
\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPagePatch4}
\begin{paste}{WuWenTsunTriangularSetXmpPageFull4}{WuWenTsunTriangularSetXmpPageEmpty4}
\pastebutton{WuWenTsunTriangularSetXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{E := IndexedExponents V\free{V }\bound{E }}
\indentrel{3}\begin{verbatim}
   (4)  IndexedExponents OrderedVariableList [x,y,z,t]
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPageEmpty4}
\begin{paste}{WuWenTsunTriangularSetXmpPageEmpty4}{WuWenTsunTriangularSetXmpPagePatch4}
\pastebutton{WuWenTsunTriangularSetXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{E := IndexedExponents V\free{V }\bound{E }}
\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPagePatch5}
\begin{paste}{WuWenTsunTriangularSetXmpPageFull5}{WuWenTsunTriangularSetXmpPageEmpty5}
\pastebutton{WuWenTsunTriangularSetXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{P := NSMP(R, V)\free{R }\free{V }\bound{P }}
\indentrel{3}\begin{verbatim}
   (5)
  NewSparseMultivariatePolynomial(Integer,OrderedVariable
  List [x,y,z,t])
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPageEmpty5}
\begin{paste}{WuWenTsunTriangularSetXmpPageEmpty5}{WuWenTsunTriangularSetXmpPagePatch5}
\pastebutton{WuWenTsunTriangularSetXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{P := NSMP(R, V)\free{R }\free{V }\bound{P }}
\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPagePatch6}
\begin{paste}{WuWenTsunTriangularSetXmpPageFull6}{WuWenTsunTriangularSetXmpPageEmpty6}
\pastebutton{WuWenTsunTriangularSetXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{x: P := 'x\free{P }\bound{x }}
\indentrel{3}\begin{verbatim}
   (6)  x
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPageEmpty6}
\begin{paste}{WuWenTsunTriangularSetXmpPageEmpty6}{WuWenTsunTriangularSetXmpPagePatch6}
\pastebutton{WuWenTsunTriangularSetXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{x: P := 'x\free{P }\bound{x }}
\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPagePatch7}
\begin{paste}{WuWenTsunTriangularSetXmpPageFull7}{WuWenTsunTriangularSetXmpPageEmpty7}
\pastebutton{WuWenTsunTriangularSetXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{y: P := 'y\free{P }\bound{y }}
\indentrel{3}\begin{verbatim}
   (7)  y
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPageEmpty7}
\begin{paste}{WuWenTsunTriangularSetXmpPageEmpty7}{WuWenTsunTriangularSetXmpPagePatch7}
\pastebutton{WuWenTsunTriangularSetXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{y: P := 'y\free{P }\bound{y }}
\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPagePatch8}
\begin{paste}{WuWenTsunTriangularSetXmpPageFull8}{WuWenTsunTriangularSetXmpPageEmpty8}
\pastebutton{WuWenTsunTriangularSetXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{z: P := 'z\free{P }\bound{z }}
\indentrel{3}\begin{verbatim}
   (8)  z
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPageEmpty8}
\begin{paste}{WuWenTsunTriangularSetXmpPageEmpty8}{WuWenTsunTriangularSetXmpPagePatch8}
\pastebutton{WuWenTsunTriangularSetXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{z: P := 'z\free{P }\bound{z }}
\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPagePatch9}
\begin{paste}{WuWenTsunTriangularSetXmpPageFull9}{WuWenTsunTriangularSetXmpPageEmpty9}
\pastebutton{WuWenTsunTriangularSetXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{t: P := 't\free{P }\bound{t }}
\indentrel{3}\begin{verbatim}
   (9)  t
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPageEmpty9}
\begin{paste}{WuWenTsunTriangularSetXmpPageEmpty9}{WuWenTsunTriangularSetXmpPagePatch9}
\pastebutton{WuWenTsunTriangularSetXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{t: P := 't\free{P }\bound{t }}
\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPagePatch10}
\begin{paste}{WuWenTsunTriangularSetXmpPageFull10}{WuWenTsunTriangularSetXmpPageEmpty10}
\pastebutton{WuWenTsunTriangularSetXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{T := WUTSET(R,E,V,P)\free{R }\free{E }\free{V }\free{P }\bound{T }}
\indentrel{3}\begin{verbatim}
   (10)
  WuWenTsunTriangularSet(Integer,IndexedExponents Ordered
  VariableList [x,y,z,t],OrderedVariableList [x,y,z,t],Ne
  wSparseMultivariatePolynomial(Integer,OrderedVariableLi
  st [x,y,z,t]))
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPageEmpty10}
\begin{paste}{WuWenTsunTriangularSetXmpPageEmpty10}{WuWenTsunTriangularSetXmpPagePatch10}
\pastebutton{WuWenTsunTriangularSetXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{T := WUTSET(R,E,V,P)\free{R }\free{E }\free{V }\free{P }\bound{T }}
\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPagePatch11}
\begin{paste}{WuWenTsunTriangularSetXmpPageFull11}{WuWenTsunTriangularSetXmpPageEmpty11}
\pastebutton{WuWenTsunTriangularSetXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{p1 := x ** 31 - x ** 6 - x - y\free{x }\free{y }\bound{p1 }}
\indentrel{3}\begin{verbatim}
          31    6
   (11)  x   - x  - x - y
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPageEmpty11}
\begin{paste}{WuWenTsunTriangularSetXmpPageEmpty11}{WuWenTsunTriangularSetXmpPagePatch11}
\pastebutton{WuWenTsunTriangularSetXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{p1 := x ** 31 - x ** 6 - x - y\free{x }\free{y }\bound{p1 }}
\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPagePatch12}
\begin{paste}{WuWenTsunTriangularSetXmpPageFull12}{WuWenTsunTriangularSetXmpPageEmpty12}
\pastebutton{WuWenTsunTriangularSetXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{p2 := x ** 8 - z\free{x }\free{z }\bound{p2 }}
\indentrel{3}\begin{verbatim}
          8
   (12)  x  - z
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPageEmpty12}
\begin{paste}{WuWenTsunTriangularSetXmpPageEmpty12}{WuWenTsunTriangularSetXmpPagePatch12}
\pastebutton{WuWenTsunTriangularSetXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{p2 := x ** 8 - z\free{x }\free{z }\bound{p2 }}
\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPagePatch13}
\begin{paste}{WuWenTsunTriangularSetXmpPageFull13}{WuWenTsunTriangularSetXmpPageEmpty13}
\pastebutton{WuWenTsunTriangularSetXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{p3 := x ** 10 - t\free{x }\free{t }\bound{p3 }}
\indentrel{3}\begin{verbatim}
          10
   (13)  x   - t
Type: NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPageEmpty13}
\begin{paste}{WuWenTsunTriangularSetXmpPageEmpty13}{WuWenTsunTriangularSetXmpPagePatch13}
\pastebutton{WuWenTsunTriangularSetXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{p3 := x ** 10 - t\free{x }\free{t }\bound{p3 }}
\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPagePatch14}
\begin{paste}{WuWenTsunTriangularSetXmpPageFull14}{WuWenTsunTriangularSetXmpPageEmpty14}
\pastebutton{WuWenTsunTriangularSetXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{lp := [p1, p2, p3]\free{p1 }\free{p2 }\free{p3 }\bound{lp }}
\indentrel{3}\begin{verbatim}
           31    6          8      10
   (14)  [x   - x  - x - y,x  - z,x   - t]
Type: List NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPageEmpty14}
\begin{paste}{WuWenTsunTriangularSetXmpPageEmpty14}{WuWenTsunTriangularSetXmpPagePatch14}
\pastebutton{WuWenTsunTriangularSetXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{lp := [p1, p2, p3]\free{p1 }\free{p2 }\free{p3 }\bound{lp }}
\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPagePatch15}
\begin{paste}{WuWenTsunTriangularSetXmpPageFull15}{WuWenTsunTriangularSetXmpPageEmpty15}
\pastebutton{WuWenTsunTriangularSetXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{characteristicSet(lp)$T\free{lp }\free{T }}
\indentrel{3}\begin{verbatim}
   (15)
     5    4   4 2 2     3 4        7     4      6    6
   {z  - t , t z y  + 2t z y + (- t  + 2t  - t)z  + t z,
      3      3     3     3
    (t  - 1)z x - z y - t }
Type: Union(WuWenTsunTriangularSet(Integer,IndexedExponents OrderedVariableList [x,y,z,t],OrderedVariableList [x,y,z,t],NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t])),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPageEmpty15}
\begin{paste}{WuWenTsunTriangularSetXmpPageEmpty15}{WuWenTsunTriangularSetXmpPagePatch15}
\pastebutton{WuWenTsunTriangularSetXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{characteristicSet(lp)$T\free{lp }\free{T }}
\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPagePatch16}
\begin{paste}{WuWenTsunTriangularSetXmpPageFull16}{WuWenTsunTriangularSetXmpPageEmpty16}
\pastebutton{WuWenTsunTriangularSetXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{zeroSetSplit(lp)$T\free{lp }\free{T }}
\indentrel{3}\begin{verbatim}
   (16)
                 3      5    4  3     3    2
   [{t,z,y,x}, {t  - 1,z  - t ,z y + t ,z x  - t},

       5    4
     {z  - t ,
       4 2 2     3 4        7     4      6    6
      t z y  + 2t z y + (- t  + 2t  - t)z  + t z,
        3      3     3     3
      (t  - 1)z x - z y - t }
     ]
Type: List WuWenTsunTriangularSet(Integer,IndexedExponents OrderedVariableList [x,y,z,t],OrderedVariableList [x,y,z,t],NewSparseMultivariatePolynomial(Integer,OrderedVariableList [x,y,z,t]))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{WuWenTsunTriangularSetXmpPageEmpty16}
\begin{paste}{WuWenTsunTriangularSetXmpPageEmpty16}{WuWenTsunTriangularSetXmpPagePatch16}
\pastebutton{WuWenTsunTriangularSetXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{zeroSetSplit(lp)$T\free{lp }\free{T }}
\end{paste}\end{patch}

\end{chunk}
\section{xmpexp.ht}
\pagetitle{ExamplesExposedPage}{xmpexp.ht}
{Some Examples of Domains and Packages}
\pagepic{ps/v71examplesexposedpage.eps}{examplesexposedpage}{0.50}
\pagefrom{Reference}{TopReferencePage}
\pageto{AssociationList}{AssociationListXmpPage}
\pageto{BalancedBinaryTree}{BalancedBinaryTreeXmpPage}
\pageto{BasicOperator}{BasicOperatorXmpPage}
\pageto{BinaryExpansion}{BinaryExpansionXmpPage}
\pageto{BinarySearchTree}{BinarySearchTreeXmpPage}
\pageto{CardinalNumber}{CardinalNumberXmpPage}
\pageto{CartesianTensor}{CartesianTensorXmpPage}
\pageto{Character}{CharacterXmpPage}
\pageto{CharacterClass}{CharacterClassXmpPage}
\pageto{CliffordAlgebra}{CliffordAlgebraXmpPage}
\pageto{Complex}{ComplexXmpPage}
\pageto{ContinuedFraction}{ContinuedFractionXmpPage}
\pageto{CycleIndicators}{CycleIndicatorsXmpPage}
\pageto{DeRhamComplex}{DeRhamComplexXmpPage}
\pageto{DecimalExpansion}{DecimalExpansionXmpPage}
\pageto{DistributedMultivariatePoly}
{DistributedMultivariatePolyXmpPage}
\pageto{DoubleFloat}{DoubleFloatXmpPage}
\pageto{EqTable}{EqTableXmpPage}
\pageto{Equation}{EquationXmpPage}
\pageto{Exit}{ExitXmpPage}
\pageto{Expression}{ExpressionXmpPage}
\pageto{Factored}{FactoredXmpPage}
\pageto{FactoredFunctionsTwo}{FactoredFnsTwoXmpPage}
\pageto{File}{FileXmpPage}
\pageto{FileName}{FileNameXmpPage}
\pageto{FlexibleArray}{FlexibleArrayXmpPage}
\pageto{Float}{FloatXmpPage}
\pageto{Fraction}{FractionXmpPage}
\pageto{FullPartialFracExpansion}{FullPartialFracExpansionXmpPage}
\pageto{GeneralSparseTable}{GeneralSparseTableXmpPage}
\pageto{GroebnerFactorizationPkg}{GroebnerFactorizationPkgXmpPage}
\pageto{Heap}{HeapXmpPage}
\pageto{HexadecimalExpansion}{HexExpansionXmpPage}
\pageto{Integer}{IntegerXmpPage}
\pageto{IntegerLinearDependence}{IntegerLinearDependenceXmpPage}
\pageto{IntegerNumberTheoryFunctions}{IntNumberTheoryFnsXmpPage}
\pageto{Kernel}{KernelXmpPage}
\pageto{KeyedAccessFile}{KeyedAccessFileXmpPage}
\pageto{LexTriangularPackage}{LexTriangularPkgXmpPage}
\pageto{LazardSetSolvingPackage}{LazardSetSolvingPackageXmpPage}
\pageto{Library}{LibraryXmpPage}
\pageto{LieExponentials}{LieExponentialsXmpPage}
\pageto{LiePolynomial}{LiePolynomialXmpPage}
\pageto{LinearOrdinaryDifferentialOperator}
{LinearOrdinaryDifferentialOperatorXmpPage}
\pageto{LinearOrdinaryDifferentialOperatorOne}
{LinearOrdinaryDifferentialOperatorOneXmpPage}
\pageto{LinearODEOperatorTwo}
{LinearODEOperatorTwoXmpPage}
\pageto{List}{ListXmpPage}
\pageto{LyndonWord}{LyndonWordXmpPage}
\pageto{Magma}{MagmaXmpPage}
\pageto{MakeFunction}{MakeFunctionXmpPage}
\pageto{MappingPackageOne}{MappingPackageOneXmpPage}
\pageto{Matrix}{MatrixXmpPage}
\pageto{MultiSet}{MultiSetXmpPage}
\pageto{MultivariatePolynomial}{MultivariatePolyXmpPage}
\pageto{None}{NoneXmpPage}
\pageto{Octonion}{OctonionXmpPage}
\pageto{OneDimensionalArray}{OneDimensionalArrayXmpPage}
\pageto{Operator}{OperatorXmpPage}
\pageto{OrderedVariableList}{OrderedVariableListXmpPage}
\pageto{OrderlyDifferentialPolynomial}{OrderlyDifferentialPolyXmpPage}
\pageto{PartialFraction}{PartialFractionXmpPage}
\pageto{Permanent}{PermanentXmpPage}
\pageto{Polynomial}{PolynomialXmpPage}
\pageto{Quaternion}{QuaternionXmpPage}
\pageto{RadixExpansion}{RadixExpansionXmpPage}
\pageto{RealClosure}{RealClosureXmpPage}
\pageto{RegularTriangularSet}{RegularTriangularSetXmpPage}
\pageto{RomanNumeral}{RomanNumeralXmpPage}
\pageto{Segment}{SegmentXmpPage}
\pageto{SegmentBinding}{SegmentBindingXmpPage}
\pageto{Set}{SetXmpPage}
\pageto{SingleInteger}{SingleIntegerXmpPage}
\pageto{SparseTable}{SparseTableXmpPage}
\pageto{SquareMatrix}{SqMatrixXmpPage}
\pageto{SquareFreeRegularTriangularSet}{SqFreeRegTriangSetXmpPage}
\pageto{Stream}{StreamXmpPage}
\pageto{String}{StringXmpPage}
\pageto{StringTable}{StringTableXmpPage}
\pageto{Symbol}{SymbolXmpPage}
\pageto{Table}{TableXmpPage}
\pageto{TextFile}{TextFileXmpPage}
\pageto{TwoDimensionalArray}{TwoDimensionalArrayXmpPage}
\pageto{UnivariatePolynomial}{UnivariatePolyXmpPage}
\pageto{UnivariateSkewPolynomial}{UnivariateSkewPolyXmpPage}
\pageto{UniversalSegment}{UniversalSegmentXmpPage}
\pageto{Vector}{VectorXmpPage}
\pageto{Void}{VoidXmpPage}
\pageto{WuWenTsunTriangularSet}{WuWenTsunTriangularSetXmpPage}
\pageto{XPBWPolynomial}{XPBWPolynomialXmpPage}
\pageto{XPolynomial}{XPolynomialXmpPage}
\pageto{XPolynomialRing}{XPolynomialRingXmpPage}
\pageto{ZeroDimensionalSolvePackage}{ZeroDimSolvePkgXmpPage}
\begin{chunk}{xmpexp.ht}
\begin{page}{ExamplesExposedPage}{Some Examples of Domains and Packages}
This is a menu of examples of some domains and packages.
Click on any item below to see that section.
\beginscroll
\table{
{ \downlink{AssociationList}{AssociationListXmpPage} }
{ \downlink{BalancedBinaryTree}{BalancedBinaryTreeXmpPage} }
{ \downlink{BasicOperator}{BasicOperatorXmpPage} }
{ \downlink{BinaryExpansion}{BinaryExpansionXmpPage} }
{ \downlink{BinarySearchTree}{BinarySearchTreeXmpPage} }
{ \downlink{CardinalNumber}{CardinalNumberXmpPage} }
{ \downlink{CartesianTensor}{CartesianTensorXmpPage} }
{ \downlink{Character}{CharacterXmpPage} }
{ \downlink{CharacterClass}{CharacterClassXmpPage} }
{ \downlink{CliffordAlgebra}{CliffordAlgebraXmpPage} }
{ \downlink{Complex}{ComplexXmpPage} }
{ \downlink{ContinuedFraction}{ContinuedFractionXmpPage} }
{ \downlink{CycleIndicators}{CycleIndicatorsXmpPage} }
{ \downlink{DeRhamComplex}{DeRhamComplexXmpPage} }
{ \downlink{DecimalExpansion}{DecimalExpansionXmpPage} }
{ \downlink{DistributedMultivariatePoly}
{DistributedMultivariatePolyXmpPage} }
{ \downlink{DoubleFloat}{DoubleFloatXmpPage} }
{ \downlink{EqTable}{EqTableXmpPage} }
{ \downlink{Equation}{EquationXmpPage} }
{ \downlink{Exit}{ExitXmpPage} }
{ \downlink{Expression}{ExpressionXmpPage} }
{ \downlink{Factored}{FactoredXmpPage} }
{ \downlink{FactoredFunctions2}{FactoredFnsTwoXmpPage} }
{ \downlink{File}{FileXmpPage} }
{ \downlink{FileName}{FileNameXmpPage} }
{ \downlink{FlexibleArray}{FlexibleArrayXmpPage} }
{ \downlink{Float}{FloatXmpPage} }
{ \downlink{Fraction}{FractionXmpPage} }
{ \downlink{FullPartialFracExpansion}
{FullPartialFracExpansionXmpPage} }
{ \downlink{GeneralSparseTable}{GeneralSparseTableXmpPage} }
{ \downlink{GroebnerFactorizationPkg}
{GroebnerFactorizationPkgXmpPage} }
{ \downlink{Heap}{HeapXmpPage} }
{ \downlink{HexadecimalExpansion}{HexExpansionXmpPage} }
{ \downlink{Integer}{IntegerXmpPage} }
{ \downlink{IntegerLinearDependence}{IntegerLinearDependenceXmpPage} }
{ \downlink{IntegerNumberTheoryFunctions}
{IntNumberTheoryFnsXmpPage} }
{ \downlink{Kernel}{KernelXmpPage} }
{ \downlink{KeyedAccessFile}{KeyedAccessFileXmpPage} }
{ \downlink{LexTriangularPackage}{LexTriangularPkgXmpPage} }
{ \downlink{LazardSetSolvingPackage}{LazardSetSolvingPackageXmpPage} }
{ \downlink{Library}{LibraryXmpPage} }
{ \downlink{LieExponentials}{LieExponentialsXmpPage} }
{ \downlink{LiePolynomial}{LiePolynomialXmpPage} }
{ \downlink{LinearOrdinaryDifferentialOperator}
{LinearOrdinaryDifferentialOperatorXmpPage} }
{ \downlink{LinearOrdinaryDifferentialOperator1}
{LinearOrdinaryDifferentialOperatorOneXmpPage} }
{ \downlink{LinearOrdinaryDifferentialOperator2}
{LinearODEOperatorTwoXmpPage} }
{ \downlink{List}{ListXmpPage} }
{ \downlink{LyndonWord}{LyndonWordXmpPage} }
{ \downlink{Magma}{MagmaXmpPage} }
{ \downlink{MakeFunction}{MakeFunctionXmpPage} }
{ \downlink{MappingPackage1}{MappingPackageOneXmpPage} }
{ \downlink{Matrix}{MatrixXmpPage} }
{ \downlink{MultiSet}{MultiSetXmpPage} }
{ \downlink{MultivariatePolynomial}{MultivariatePolyXmpPage} }
{ \downlink{None}{NoneXmpPage} }
{ \downlink{Octonion}{OctonionXmpPage} }
{ \downlink{OneDimensionalArray}{OneDimensionalArrayXmpPage} }
{ \downlink{Operator}{OperatorXmpPage} }
{ \downlink{OrderedVariableList}{OrderedVariableListXmpPage} }
{ \downlink{OrderlyDifferentialPolynomial}
{OrderlyDifferentialPolyXmpPage} }
{ \downlink{PartialFraction}{PartialFractionXmpPage} }
{ \downlink{Permanent}{PermanentXmpPage} }
{ \downlink{Polynomial}{PolynomialXmpPage} }
{ \downlink{Quaternion}{QuaternionXmpPage} }
{ \downlink{RadixExpansion}{RadixExpansionXmpPage} }
{ \downlink{RealClosure}{RealClosureXmpPage} }
{ \downlink{RegularTriangularSet}{RegularTriangularSetXmpPage} }
{ \downlink{RomanNumeral}{RomanNumeralXmpPage} }
{ \downlink{Segment}{SegmentXmpPage} }
{ \downlink{SegmentBinding}{SegmentBindingXmpPage} }
{ \downlink{Set}{SetXmpPage} }
{ \downlink{SingleInteger}{SingleIntegerXmpPage} }
{ \downlink{SparseTable}{SparseTableXmpPage} }
{ \downlink{SquareMatrix}{SqMatrixXmpPage} }
{ \downlink{SquareFreeRegularTriangularSet}
{SqFreeRegTriangSetXmpPage} }
{ \downlink{Stream}{StreamXmpPage} }
{ \downlink{String}{StringXmpPage} }
{ \downlink{StringTable}{StringTableXmpPage} }
{ \downlink{Symbol}{SymbolXmpPage} }
{ \downlink{Table}{TableXmpPage} }
{ \downlink{TextFile}{TextFileXmpPage} }
{ \downlink{TwoDimensionalArray}{TwoDimensionalArrayXmpPage} }
{ \downlink{UnivariatePolynomial}{UnivariatePolyXmpPage} }
{ \downlink{UnivariateSkewPolynomial}{UnivariateSkewPolyXmpPage} }
{ \downlink{UniversalSegment}{UniversalSegmentXmpPage} }
{ \downlink{Vector}{VectorXmpPage} }
{ \downlink{Void}{VoidXmpPage} }
{ \downlink{WuWenTsunTriangularSet}{WuWenTsunTriangularSetXmpPage} }
{ \downlink{XPBWPolynomial}{XPBWPolynomialXmpPage} }
{ \downlink{XPolynomial}{XPolynomialXmpPage} }
{ \downlink{XPolynomialRing}{XPolynomialRingXmpPage} }
{ \downlink{ZeroDimensionalSolvePackage}
{ZeroDimSolvePkgXmpPage} }
}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\section{xpbwpoly.ht}
\pagetitle{XPBWPolynomialXmpPage}{xpbwpoly.ht}{XPBWPolynomial}
\begin{chunk}{xpbwpoly.ht}
\begin{page}{XPBWPolynomialXmpPage}{XPBWPolynomial}
\beginscroll
Initialisations
\xtc{
}{
\spadpaste{a:Symbol := 'a \bound{a}}
}
\xtc{
}{
\spadpaste{b:Symbol := 'b \bound{b}}
}
\xtc{
}{
\spadpaste{RN    := Fraction(Integer) \bound{RN}}
}
\xtc{
}{
\spadpaste{word   := OrderedFreeMonoid Symbol \bound{word}}
}
\xtc{
}{
\spadpaste{lword := LyndonWord(Symbol) \bound{lword}}
}
\xtc{
}{
\spadpaste{base  := PoincareBirkhoffWittLyndonBasis Symbol \bound{base}}
}
\xtc{
}{
\spadpaste{dpoly := XDistributedPolynomial(Symbol, RN) \bound{dpoly} 
\free{RN}}
}
\xtc{
}{
\spadpaste{rpoly := XRecursivePolynomial(Symbol, RN) \bound{rpoly} 
\free{RN}}
}
\xtc{
}{
\spadpaste{lpoly := LiePolynomial(Symbol, RN) \bound{lpoly} \free{RN}}
}
\xtc{
}{
\spadpaste{poly  := XPBWPolynomial(Symbol, RN) \bound{poly} \free{RN}}
}
\xtc{
}{
\spadpaste{liste : List lword := LyndonWordsList([a,b], 6) 
\bound{liste} \free{lword a b }}
}

Let's make some polynomials
\xtc{
}{
\spadpaste{0$poly \free{poly}}
}
\xtc{
}{
\spadpaste{1$poly \free{poly}}
}
\xtc{
}{
\spadpaste{p : poly := a \free{a poly} \bound{p}}
}
\xtc{
}{
\spadpaste{q : poly := b \free{b poly} \bound{q}}
}
\xtc{
}{
\spadpaste{pq: poly := p*q \free{p q poly} \bound{pq}}
}
\xtc{
Coerce to distributed polynomial
}{
\spadpaste{pq :: dpoly \free{pq dpoly}}
}

Check some polynomial operations
\xtc{
}{
\spadpaste{mirror pq \free{pq}}
}
\xtc{
}{
\spadpaste{listOfTerms pq \free{pq}}
}
\xtc{
}{
\spadpaste{reductum pq \free{pq}}
}
\xtc{
}{
\spadpaste{leadingMonomial pq \free{pq}}
}
\xtc{
}{
\spadpaste{coefficients pq \free{pq}}
}
\xtc{
}{
\spadpaste{leadingTerm pq \free{pq}}
}
\xtc{
}{
\spadpaste{degree pq \free{pq}}
}
\xtc{
}{
\spadpaste{pq4:=exp(pq,4) \bound{pq4} \free{pq}}
}
\xtc{
}{
\spadpaste{log(pq4,4) - pq \free{pq4 pq} }
}

Calculations with verification in \axiomType{XDistributedPolynomial}.
\xtc{
}{
\spadpaste{lp1 :lpoly := LiePoly liste.10 \free{liste lpoly} \bound{lp1}}
}
\xtc{
}{
\spadpaste{lp2 :lpoly := LiePoly liste.11 \free{liste lpoly} \bound{lp2}}
}
\xtc{
}{
\spadpaste{lp  :lpoly := [lp1, lp2] \free{lp1 lp2 lpoly} \bound{lp}}
}
\xtc{
}{
\spadpaste{lpd1: dpoly := lp1 \free{lp1 dpoly} \bound{lpd1}}
}
\xtc{
}{
\spadpaste{lpd2: dpoly := lp2 \free{lp2 dpoly} \bound{lpd2}}
}
\xtc{
}{
\spadpaste{lpd : dpoly := lpd1 * lpd2 - lpd2 * lpd1 
\free{dpoly lpd1 lpd2} \bound{lpd}}
}
\xtc{
}{
\spadpaste{lp :: dpoly - lpd \free{lpd dpoly lp}}
}

Calculations with verification in \axiomType{XRecursivePolynomial}.
\xtc{
}{
\spadpaste{p := 3 * lp \free{lp} \bound{pp}}
}
\xtc{
}{
\spadpaste{q := lp1 \free{lp1} \bound{qq}}
}
\xtc{
}{
\spadpaste{pq:= p * q \free{pp qq} \bound{pqpq}}
}
\xtc{
}{
\spadpaste{pr:rpoly := p :: rpoly \free{rpoly pp} \bound{pr}}
}
\xtc{
}{
\spadpaste{qr:rpoly := q :: rpoly \free{rpoly qq} \bound{qr}}
}
\xtc{
}{
\spadpaste{pq :: rpoly - pr*qr \free{pr qr rpoly pqpq} }
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{XPBWPolynomialXmpPagePatch1}
\begin{paste}{XPBWPolynomialXmpPageFull1}{XPBWPolynomialXmpPageEmpty1}
\pastebutton{XPBWPolynomialXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{a:Symbol := 'a\bound{a }}
\indentrel{3}\begin{verbatim}
   (1)  a
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty1}
\begin{paste}{XPBWPolynomialXmpPageEmpty1}{XPBWPolynomialXmpPagePatch1}
\pastebutton{XPBWPolynomialXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{a:Symbol := 'a\bound{a }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch2}
\begin{paste}{XPBWPolynomialXmpPageFull2}{XPBWPolynomialXmpPageEmpty2}
\pastebutton{XPBWPolynomialXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{b:Symbol := 'b\bound{b }}
\indentrel{3}\begin{verbatim}
   (2)  b
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty2}
\begin{paste}{XPBWPolynomialXmpPageEmpty2}{XPBWPolynomialXmpPagePatch2}
\pastebutton{XPBWPolynomialXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{b:Symbol := 'b\bound{b }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch3}
\begin{paste}{XPBWPolynomialXmpPageFull3}{XPBWPolynomialXmpPageEmpty3}
\pastebutton{XPBWPolynomialXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{RN := Fraction(Integer)\bound{RN }}
\indentrel{3}\begin{verbatim}
   (3)  Fraction Integer
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty3}
\begin{paste}{XPBWPolynomialXmpPageEmpty3}{XPBWPolynomialXmpPagePatch3}
\pastebutton{XPBWPolynomialXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{RN := Fraction(Integer)\bound{RN }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch4}
\begin{paste}{XPBWPolynomialXmpPageFull4}{XPBWPolynomialXmpPageEmpty4}
\pastebutton{XPBWPolynomialXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{word := OrderedFreeMonoid Symbol\bound{word }}
\indentrel{3}\begin{verbatim}
   (4)  OrderedFreeMonoid Symbol
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty4}
\begin{paste}{XPBWPolynomialXmpPageEmpty4}{XPBWPolynomialXmpPagePatch4}
\pastebutton{XPBWPolynomialXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{word := OrderedFreeMonoid Symbol\bound{word }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch5}
\begin{paste}{XPBWPolynomialXmpPageFull5}{XPBWPolynomialXmpPageEmpty5}
\pastebutton{XPBWPolynomialXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{lword := LyndonWord(Symbol)\bound{lword }}
\indentrel{3}\begin{verbatim}
   (5)  LyndonWord Symbol
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty5}
\begin{paste}{XPBWPolynomialXmpPageEmpty5}{XPBWPolynomialXmpPagePatch5}
\pastebutton{XPBWPolynomialXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{lword := LyndonWord(Symbol)\bound{lword }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch6}
\begin{paste}{XPBWPolynomialXmpPageFull6}{XPBWPolynomialXmpPageEmpty6}
\pastebutton{XPBWPolynomialXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{base := PoincareBirkhoffWittLyndonBasis Symbol\bound{base }}
\indentrel{3}\begin{verbatim}
   (6)  PoincareBirkhoffWittLyndonBasis Symbol
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty6}
\begin{paste}{XPBWPolynomialXmpPageEmpty6}{XPBWPolynomialXmpPagePatch6}
\pastebutton{XPBWPolynomialXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{base := PoincareBirkhoffWittLyndonBasis Symbol\bound{base }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch7}
\begin{paste}{XPBWPolynomialXmpPageFull7}{XPBWPolynomialXmpPageEmpty7}
\pastebutton{XPBWPolynomialXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{dpoly := XDistributedPolynomial(Symbol, RN)\bound{dpoly }\free{RN }}
\indentrel{3}\begin{verbatim}
   (7)  XDistributedPolynomial(Symbol,Fraction Integer)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty7}
\begin{paste}{XPBWPolynomialXmpPageEmpty7}{XPBWPolynomialXmpPagePatch7}
\pastebutton{XPBWPolynomialXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{dpoly := XDistributedPolynomial(Symbol, RN)\bound{dpoly }\free{RN }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch8}
\begin{paste}{XPBWPolynomialXmpPageFull8}{XPBWPolynomialXmpPageEmpty8}
\pastebutton{XPBWPolynomialXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{rpoly := XRecursivePolynomial(Symbol, RN)\bound{rpoly }\free{RN }}
\indentrel{3}\begin{verbatim}
   (8)  XRecursivePolynomial(Symbol,Fraction Integer)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty8}
\begin{paste}{XPBWPolynomialXmpPageEmpty8}{XPBWPolynomialXmpPagePatch8}
\pastebutton{XPBWPolynomialXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{rpoly := XRecursivePolynomial(Symbol, RN)\bound{rpoly }\free{RN }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch9}
\begin{paste}{XPBWPolynomialXmpPageFull9}{XPBWPolynomialXmpPageEmpty9}
\pastebutton{XPBWPolynomialXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{lpoly := LiePolynomial(Symbol, RN)\bound{lpoly }\free{RN }}
\indentrel{3}\begin{verbatim}
   (9)  LiePolynomial(Symbol,Fraction Integer)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty9}
\begin{paste}{XPBWPolynomialXmpPageEmpty9}{XPBWPolynomialXmpPagePatch9}
\pastebutton{XPBWPolynomialXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{lpoly := LiePolynomial(Symbol, RN)\bound{lpoly }\free{RN }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch10}
\begin{paste}{XPBWPolynomialXmpPageFull10}{XPBWPolynomialXmpPageEmpty10}
\pastebutton{XPBWPolynomialXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{poly := XPBWPolynomial(Symbol, RN)\bound{poly }\free{RN }}
\indentrel{3}\begin{verbatim}
   (10)  XPBWPolynomial(Symbol,Fraction Integer)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty10}
\begin{paste}{XPBWPolynomialXmpPageEmpty10}{XPBWPolynomialXmpPagePatch10}
\pastebutton{XPBWPolynomialXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{poly := XPBWPolynomial(Symbol, RN)\bound{poly }\free{RN }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch11}
\begin{paste}{XPBWPolynomialXmpPageFull11}{XPBWPolynomialXmpPageEmpty11}
\pastebutton{XPBWPolynomialXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{liste : List lword := LyndonWordsList([a,b], 6)\bound{liste }\free{lword a b }}
\indentrel{3}\begin{verbatim}
   (11)
                       2        2     3      2 2
   [[a], [b], [a b], [a b], [a b ], [a b], [a b ],
        3     4      3 2     2          2 3           2
    [a b ], [a b], [a b ], [a b a b], [a b ], [a b a b ],
        4     5      4 2     3          3 3     2     2
    [a b ], [a b], [a b ], [a b a b], [a b ], [a b a b ],
      2 2        2 4           3       5
    [a b a b], [a b ], [a b a b ], [a b ]]
                           Type: List LyndonWord Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty11}
\begin{paste}{XPBWPolynomialXmpPageEmpty11}{XPBWPolynomialXmpPagePatch11}
\pastebutton{XPBWPolynomialXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{liste : List lword := LyndonWordsList([a,b], 6)\bound{liste }\free{lword a b }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch12}
\begin{paste}{XPBWPolynomialXmpPageFull12}{XPBWPolynomialXmpPageEmpty12}
\pastebutton{XPBWPolynomialXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{0$poly\free{poly }}
\indentrel{3}\begin{verbatim}
   (12)  0
          Type: XPBWPolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty12}
\begin{paste}{XPBWPolynomialXmpPageEmpty12}{XPBWPolynomialXmpPagePatch12}
\pastebutton{XPBWPolynomialXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{0$poly\free{poly }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch13}
\begin{paste}{XPBWPolynomialXmpPageFull13}{XPBWPolynomialXmpPageEmpty13}
\pastebutton{XPBWPolynomialXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{1$poly\free{poly }}
\indentrel{3}\begin{verbatim}
   (13)  1
          Type: XPBWPolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty13}
\begin{paste}{XPBWPolynomialXmpPageEmpty13}{XPBWPolynomialXmpPagePatch13}
\pastebutton{XPBWPolynomialXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{1$poly\free{poly }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch14}
\begin{paste}{XPBWPolynomialXmpPageFull14}{XPBWPolynomialXmpPageEmpty14}
\pastebutton{XPBWPolynomialXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{p : poly := a\free{a poly }\bound{p }}
\indentrel{3}\begin{verbatim}
   (14)  [a]
          Type: XPBWPolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty14}
\begin{paste}{XPBWPolynomialXmpPageEmpty14}{XPBWPolynomialXmpPagePatch14}
\pastebutton{XPBWPolynomialXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{p : poly := a\free{a poly }\bound{p }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch15}
\begin{paste}{XPBWPolynomialXmpPageFull15}{XPBWPolynomialXmpPageEmpty15}
\pastebutton{XPBWPolynomialXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{q : poly := b\free{b poly }\bound{q }}
\indentrel{3}\begin{verbatim}
   (15)  [b]
          Type: XPBWPolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty15}
\begin{paste}{XPBWPolynomialXmpPageEmpty15}{XPBWPolynomialXmpPagePatch15}
\pastebutton{XPBWPolynomialXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{q : poly := b\free{b poly }\bound{q }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch16}
\begin{paste}{XPBWPolynomialXmpPageFull16}{XPBWPolynomialXmpPageEmpty16}
\pastebutton{XPBWPolynomialXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{pq: poly := p*q\free{p q poly }\bound{pq }}
\indentrel{3}\begin{verbatim}
   (16)  [a b] + [b][a]
          Type: XPBWPolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty16}
\begin{paste}{XPBWPolynomialXmpPageEmpty16}{XPBWPolynomialXmpPagePatch16}
\pastebutton{XPBWPolynomialXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{pq: poly := p*q\free{p q poly }\bound{pq }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch17}
\begin{paste}{XPBWPolynomialXmpPageFull17}{XPBWPolynomialXmpPageEmpty17}
\pastebutton{XPBWPolynomialXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{pq :: dpoly\free{pq dpoly }}
\indentrel{3}\begin{verbatim}
   (17)  a b
  Type: XDistributedPolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty17}
\begin{paste}{XPBWPolynomialXmpPageEmpty17}{XPBWPolynomialXmpPagePatch17}
\pastebutton{XPBWPolynomialXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{pq :: dpoly\free{pq dpoly }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch18}
\begin{paste}{XPBWPolynomialXmpPageFull18}{XPBWPolynomialXmpPageEmpty18}
\pastebutton{XPBWPolynomialXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{mirror pq\free{pq }}
\indentrel{3}\begin{verbatim}
   (18)  [b][a]
          Type: XPBWPolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty18}
\begin{paste}{XPBWPolynomialXmpPageEmpty18}{XPBWPolynomialXmpPagePatch18}
\pastebutton{XPBWPolynomialXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{mirror pq\free{pq }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch19}
\begin{paste}{XPBWPolynomialXmpPageFull19}{XPBWPolynomialXmpPageEmpty19}
\pastebutton{XPBWPolynomialXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{listOfTerms pq\free{pq }}
\indentrel{3}\begin{verbatim}
   (19)  [[k= [b][a],c= 1],[k= [a b],c= 1]]
Type: List Record(k: PoincareBirkhoffWittLyndonBasis Symbol,c: Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty19}
\begin{paste}{XPBWPolynomialXmpPageEmpty19}{XPBWPolynomialXmpPagePatch19}
\pastebutton{XPBWPolynomialXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{listOfTerms pq\free{pq }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch20}
\begin{paste}{XPBWPolynomialXmpPageFull20}{XPBWPolynomialXmpPageEmpty20}
\pastebutton{XPBWPolynomialXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{reductum pq\free{pq }}
\indentrel{3}\begin{verbatim}
   (20)  [a b]
          Type: XPBWPolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty20}
\begin{paste}{XPBWPolynomialXmpPageEmpty20}{XPBWPolynomialXmpPagePatch20}
\pastebutton{XPBWPolynomialXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{reductum pq\free{pq }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch21}
\begin{paste}{XPBWPolynomialXmpPageFull21}{XPBWPolynomialXmpPageEmpty21}
\pastebutton{XPBWPolynomialXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{leadingMonomial pq\free{pq }}
\indentrel{3}\begin{verbatim}
   (21)  [b][a]
           Type: PoincareBirkhoffWittLyndonBasis Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty21}
\begin{paste}{XPBWPolynomialXmpPageEmpty21}{XPBWPolynomialXmpPagePatch21}
\pastebutton{XPBWPolynomialXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{leadingMonomial pq\free{pq }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch22}
\begin{paste}{XPBWPolynomialXmpPageFull22}{XPBWPolynomialXmpPageEmpty22}
\pastebutton{XPBWPolynomialXmpPageFull22}{\hidepaste}
\tab{5}\spadcommand{coefficients pq\free{pq }}
\indentrel{3}\begin{verbatim}
   (22)  [1,1]
                            Type: List Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty22}
\begin{paste}{XPBWPolynomialXmpPageEmpty22}{XPBWPolynomialXmpPagePatch22}
\pastebutton{XPBWPolynomialXmpPageEmpty22}{\showpaste}
\tab{5}\spadcommand{coefficients pq\free{pq }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch23}
\begin{paste}{XPBWPolynomialXmpPageFull23}{XPBWPolynomialXmpPageEmpty23}
\pastebutton{XPBWPolynomialXmpPageFull23}{\hidepaste}
\tab{5}\spadcommand{leadingTerm pq\free{pq }}
\indentrel{3}\begin{verbatim}
   (23)  [k= [b][a],c= 1]
Type: Record(k: PoincareBirkhoffWittLyndonBasis Symbol,c: Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty23}
\begin{paste}{XPBWPolynomialXmpPageEmpty23}{XPBWPolynomialXmpPagePatch23}
\pastebutton{XPBWPolynomialXmpPageEmpty23}{\showpaste}
\tab{5}\spadcommand{leadingTerm pq\free{pq }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch24}
\begin{paste}{XPBWPolynomialXmpPageFull24}{XPBWPolynomialXmpPageEmpty24}
\pastebutton{XPBWPolynomialXmpPageFull24}{\hidepaste}
\tab{5}\spadcommand{degree pq\free{pq }}
\indentrel{3}\begin{verbatim}
   (24)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty24}
\begin{paste}{XPBWPolynomialXmpPageEmpty24}{XPBWPolynomialXmpPagePatch24}
\pastebutton{XPBWPolynomialXmpPageEmpty24}{\showpaste}
\tab{5}\spadcommand{degree pq\free{pq }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch25}
\begin{paste}{XPBWPolynomialXmpPageFull25}{XPBWPolynomialXmpPageEmpty25}
\pastebutton{XPBWPolynomialXmpPageFull25}{\hidepaste}
\tab{5}\spadcommand{pq4:=exp(pq,4)\bound{pq4 }\free{pq }}
\indentrel{3}\begin{verbatim}
   (25)
                          1              1     2
     1 + [a b] + [b][a] + Ä [a b][a b] + Ä [a b ][a]
                          2              2
   + 
     1      2     3               1
     Ä [b][a b] + Ä [b][a b][a] + Ä [b][b][a][a]
     2            2               2
          Type: XPBWPolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty25}
\begin{paste}{XPBWPolynomialXmpPageEmpty25}{XPBWPolynomialXmpPagePatch25}
\pastebutton{XPBWPolynomialXmpPageEmpty25}{\showpaste}
\tab{5}\spadcommand{pq4:=exp(pq,4)\bound{pq4 }\free{pq }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch26}
\begin{paste}{XPBWPolynomialXmpPageFull26}{XPBWPolynomialXmpPageEmpty26}
\pastebutton{XPBWPolynomialXmpPageFull26}{\hidepaste}
\tab{5}\spadcommand{log(pq4,4) - pq\free{pq4 pq }}
\indentrel{3}\begin{verbatim}
   (26)  0
          Type: XPBWPolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty26}
\begin{paste}{XPBWPolynomialXmpPageEmpty26}{XPBWPolynomialXmpPagePatch26}
\pastebutton{XPBWPolynomialXmpPageEmpty26}{\showpaste}
\tab{5}\spadcommand{log(pq4,4) - pq\free{pq4 pq }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch27}
\begin{paste}{XPBWPolynomialXmpPageFull27}{XPBWPolynomialXmpPageEmpty27}
\pastebutton{XPBWPolynomialXmpPageFull27}{\hidepaste}
\tab{5}\spadcommand{lp1 :lpoly := LiePoly liste.10\free{liste lpoly }\bound{lp1 }}
\indentrel{3}\begin{verbatim}
           3 2
   (27)  [a b ]
           Type: LiePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty27}
\begin{paste}{XPBWPolynomialXmpPageEmpty27}{XPBWPolynomialXmpPagePatch27}
\pastebutton{XPBWPolynomialXmpPageEmpty27}{\showpaste}
\tab{5}\spadcommand{lp1 :lpoly := LiePoly liste.10\free{liste lpoly }\bound{lp1 }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch28}
\begin{paste}{XPBWPolynomialXmpPageFull28}{XPBWPolynomialXmpPageEmpty28}
\pastebutton{XPBWPolynomialXmpPageFull28}{\hidepaste}
\tab{5}\spadcommand{lp2 :lpoly := LiePoly liste.11\free{liste lpoly }\bound{lp2 }}
\indentrel{3}\begin{verbatim}
           2
   (28)  [a b a b]
           Type: LiePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty28}
\begin{paste}{XPBWPolynomialXmpPageEmpty28}{XPBWPolynomialXmpPagePatch28}
\pastebutton{XPBWPolynomialXmpPageEmpty28}{\showpaste}
\tab{5}\spadcommand{lp2 :lpoly := LiePoly liste.11\free{liste lpoly }\bound{lp2 }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch29}
\begin{paste}{XPBWPolynomialXmpPageFull29}{XPBWPolynomialXmpPageEmpty29}
\pastebutton{XPBWPolynomialXmpPageFull29}{\hidepaste}
\tab{5}\spadcommand{lp :lpoly := [lp1, lp2]\free{lp1 lp2 lpoly }\bound{lp }}
\indentrel{3}\begin{verbatim}
           3 2 2
   (29)  [a b a b a b]
           Type: LiePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty29}
\begin{paste}{XPBWPolynomialXmpPageEmpty29}{XPBWPolynomialXmpPagePatch29}
\pastebutton{XPBWPolynomialXmpPageEmpty29}{\showpaste}
\tab{5}\spadcommand{lp :lpoly := [lp1, lp2]\free{lp1 lp2 lpoly }\bound{lp }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch30}
\begin{paste}{XPBWPolynomialXmpPageFull30}{XPBWPolynomialXmpPageEmpty30}
\pastebutton{XPBWPolynomialXmpPageFull30}{\hidepaste}
\tab{5}\spadcommand{lpd1: dpoly := lp1\free{lp1 dpoly }\bound{lpd1 }}
\indentrel{3}\begin{verbatim}
   (30)
      3 2     2         2 2                    2 2
     a b  - 2a b a b - a b a + 4a b a b a - a b a
   + 
               2    2 3
     - 2b a b a  + b a
  Type: XDistributedPolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty30}
\begin{paste}{XPBWPolynomialXmpPageEmpty30}{XPBWPolynomialXmpPagePatch30}
\pastebutton{XPBWPolynomialXmpPageEmpty30}{\showpaste}
\tab{5}\spadcommand{lpd1: dpoly := lp1\free{lp1 dpoly }\bound{lpd1 }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch31}
\begin{paste}{XPBWPolynomialXmpPageFull31}{XPBWPolynomialXmpPageEmpty31}
\pastebutton{XPBWPolynomialXmpPageFull31}{\hidepaste}
\tab{5}\spadcommand{lpd2: dpoly := lp2\free{lp2 dpoly }\bound{lpd2 }}
\indentrel{3}\begin{verbatim}
   (31)
      2         2 2          2                    2 2
     a b a b - a b a - 3a b a b + 4a b a b a - a b a
   + 
         3        2             2
     2b a b - 3b a b a + b a b a
  Type: XDistributedPolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty31}
\begin{paste}{XPBWPolynomialXmpPageEmpty31}{XPBWPolynomialXmpPagePatch31}
\pastebutton{XPBWPolynomialXmpPageEmpty31}{\showpaste}
\tab{5}\spadcommand{lpd2: dpoly := lp2\free{lp2 dpoly }\bound{lpd2 }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch32}
\begin{paste}{XPBWPolynomialXmpPageFull32}{XPBWPolynomialXmpPageEmpty32}
\pastebutton{XPBWPolynomialXmpPageFull32}{\hidepaste}
\tab{5}\spadcommand{lpd : dpoly := lpd1 * lpd2 - lpd2 * lpd1\free{dpoly lpd1 lpd2 }\bound{lpd }}
\indentrel{3}\begin{verbatim}
   (32)
      3 2 2         3 2 2 2      3 2     2
     a b a b a b - a b a b a - 3a b a b a b
   + 
       3 2             3 2   2 2     3 3 3      3 3 2
     4a b a b a b a - a b a b a  + 2a b a b - 3a b a b a
   + 
      3 3     2    2       3 2     2       2 2
     a b a b a  - a b a b a b  + 3a b a b a b a
   + 
       2           2       2
     6a b a b a b a b - 12a b a b a b a b a
   + 
       2         2 2     2     2 3      2     2 2
     3a b a b a b a  - 4a b a b a b + 6a b a b a b a
   + 
        2     3 3    2 2 4 2     2 2 3          2 2 2   2
     - a b a b a  + a b a b  - 3a b a b a b + 3a b a b a b
   + 
         2 2     3      2 2     2        2 2         2
     - 2a b a b a b + 3a b a b a b a - 3a b a b a b a
   + 
      2 2   2 3         2   3 2         2   2
     a b a b a  + 3a b a b a b  - 6a b a b a b a b
   + 
             2   2 2           2
     - 3a b a b a b a + 12a b a b a b a b a
   + 
             2     2 2         2 2     2         2 3 3
     - 3a b a b a b a  - 6a b a b a b a  + 3a b a b a
   + 
                 4 2              3
     - 4a b a b a b  + 12a b a b a b a b
   + 
                  2   2                  3
     - 12a b a b a b a b + 8a b a b a b a b
   + 
                      2                         2
     - 12a b a b a b a b a + 12a b a b a b a b a
   + 
                   2 3      2 5 2       2 4
     - 4a b a b a b a  + a b a b  - 3a b a b a b
   + 
         2 3   2        2 2   3        2 2   2
     3a b a b a b - 2a b a b a b + 3a b a b a b a
   + 
           2 2       2      2 2 2 3       3   3 2
     - 3a b a b a b a  + a b a b a  - 2b a b a b
   + 
         3   2            3   2 2        3
     4b a b a b a b + 2b a b a b a - 8b a b a b a b a
   + 
         3     2 2       3 2     2       3 3 3
     2b a b a b a  + 4b a b a b a  - 2b a b a
   + 
         2   4 2       2   3            2   3 2
     3b a b a b  - 6b a b a b a b - 3b a b a b a
   + 
          2   2              2   2 2 2       2           2
     12b a b a b a b a - 3b a b a b a  - 6b a b a b a b a
   + 
         2     2 3          5 2           4 2
     3b a b a b a  - b a b a b  + 3b a b a b a
   + 
             3   2             3                  3 2 2
     6b a b a b a b - 12b a b a b a b a + 3b a b a b a
   + 
               2   3            2   2             2 2 3
     - 4b a b a b a b + 6b a b a b a b a - b a b a b a
   + 
      2 5         2 5 2      2 4   2      2 4
     b a b a b - b a b a - 3b a b a b + 4b a b a b a
   + 
      2 4 2 2     2 3   3      2 3   2       2 3       2
   - b a b a  + 2b a b a b - 3b a b a b a + b a b a b a
  Type: XDistributedPolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty32}
\begin{paste}{XPBWPolynomialXmpPageEmpty32}{XPBWPolynomialXmpPagePatch32}
\pastebutton{XPBWPolynomialXmpPageEmpty32}{\showpaste}
\tab{5}\spadcommand{lpd : dpoly := lpd1 * lpd2 - lpd2 * lpd1\free{dpoly lpd1 lpd2 }\bound{lpd }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch33}
\begin{paste}{XPBWPolynomialXmpPageFull33}{XPBWPolynomialXmpPageEmpty33}
\pastebutton{XPBWPolynomialXmpPageFull33}{\hidepaste}
\tab{5}\spadcommand{lp :: dpoly - lpd\free{lpd dpoly lp }}
\indentrel{3}\begin{verbatim}
   (33)  0
  Type: XDistributedPolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty33}
\begin{paste}{XPBWPolynomialXmpPageEmpty33}{XPBWPolynomialXmpPagePatch33}
\pastebutton{XPBWPolynomialXmpPageEmpty33}{\showpaste}
\tab{5}\spadcommand{lp :: dpoly - lpd\free{lpd dpoly lp }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch34}
\begin{paste}{XPBWPolynomialXmpPageFull34}{XPBWPolynomialXmpPageEmpty34}
\pastebutton{XPBWPolynomialXmpPageFull34}{\hidepaste}
\tab{5}\spadcommand{p := 3 * lp\free{lp }\bound{pp }}
\indentrel{3}\begin{verbatim}
            3 2 2
   (34)  3[a b a b a b]
          Type: XPBWPolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty34}
\begin{paste}{XPBWPolynomialXmpPageEmpty34}{XPBWPolynomialXmpPagePatch34}
\pastebutton{XPBWPolynomialXmpPageEmpty34}{\showpaste}
\tab{5}\spadcommand{p := 3 * lp\free{lp }\bound{pp }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch35}
\begin{paste}{XPBWPolynomialXmpPageFull35}{XPBWPolynomialXmpPageEmpty35}
\pastebutton{XPBWPolynomialXmpPageFull35}{\hidepaste}
\tab{5}\spadcommand{q := lp1\free{lp1 }\bound{qq }}
\indentrel{3}\begin{verbatim}
           3 2
   (35)  [a b ]
          Type: XPBWPolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty35}
\begin{paste}{XPBWPolynomialXmpPageEmpty35}{XPBWPolynomialXmpPagePatch35}
\pastebutton{XPBWPolynomialXmpPageEmpty35}{\showpaste}
\tab{5}\spadcommand{q := lp1\free{lp1 }\bound{qq }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch36}
\begin{paste}{XPBWPolynomialXmpPageFull36}{XPBWPolynomialXmpPageEmpty36}
\pastebutton{XPBWPolynomialXmpPageFull36}{\hidepaste}
\tab{5}\spadcommand{pq:= p * q\free{pp qq }\bound{pqpq }}
\indentrel{3}\begin{verbatim}
            3 2 2        3 2
   (36)  3[a b a b a b][a b ]
          Type: XPBWPolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty36}
\begin{paste}{XPBWPolynomialXmpPageEmpty36}{XPBWPolynomialXmpPagePatch36}
\pastebutton{XPBWPolynomialXmpPageEmpty36}{\showpaste}
\tab{5}\spadcommand{pq:= p * q\free{pp qq }\bound{pqpq }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch37}
\begin{paste}{XPBWPolynomialXmpPageFull37}{XPBWPolynomialXmpPageEmpty37}
\pastebutton{XPBWPolynomialXmpPageFull37}{\hidepaste}
\tab{5}\spadcommand{pr:rpoly := p :: rpoly\free{rpoly pp }\bound{pr }}
\indentrel{3}\begin{verbatim}
   (37)
       a
    *
           a
        *
               a b b
            *
                   a
                *
                     a b(a b 3 + b a(- 3))
                   + 
                     b(a(a b(- 9) + b a 12) + b a a(- 3))
               + 
                 b a(a(a b 6 + b a(- 9)) + b a a 3)
           + 
               b
            *
                   a b
                *
                       a
                    *
                         a(a b b(- 3) + b b a 9)
                       + 
                       b(a(a b 18 + b a(- 36)) + b a a 9)
                   + 
                       b
                    *
                         a a(a b(- 12) + b a 18)
                       + 
                         b a a a(- 3)
               + 
                   b a
                *
                       a
                    *
                     (a(a b b 3 + b a b(- 9)) + b a a b 9)
                   + 
                       b
                    *
                           a
                        *
                             a(a b(- 6) + b a 9)
                           + 
                             b a a(- 9)
                       + 
                         b a a a 3
       + 
           b
        *
               a
            *
                   a b
                *
                       a
                    *
                           a
                        *
                             a b b 9
                           + 
                             b(a b(- 18) + b a(- 9))
                       + 
                         b(a b a 36 + b a a(- 9))
                   + 
                     b(a b a a(- 18) + b a a a 9)
               + 
                   b a
                *
                       a
                    *
                         a(a b b(- 12) + b a b 36)
                       + 
                         b a a b(- 36)
                   + 
                       b
                    *
                           a
                        *
                             a(a b 24 + b a(- 36))
                           + 
                             b a a 36
                       + 
                         b a a a(- 12)
           + 
               b a a
            *
                 a(a(a b b 3 + b a b(- 9)) + b a a b 9)
               + 
                   b
                *
                     a(a(a b(- 6) + b a 9) + b a a(- 9))
                   + 
                     b a a a 3
   + 
       b
    *
           a
        *
               a
            *
                   a b
                *
                       a
                    *
                         a(a b b(- 6) + b(a b 12 + b a 6))
                       + 
                         b(a b a(- 24) + b a a 6)
                   + 
                     b(a b a a 12 + b a a a(- 6))
               + 
                   b a
                *
                       a
                    *
                           a
                        *
                             a b b 9
                           + 
                             b(a b(- 18) + b a(- 9))
                       + 
                         b(a b a 36 + b a a(- 9))
                   + 
                     b(a b a a(- 18) + b a a a 9)
           + 
               b a a
            *
                   a
                *
                     a(a b b(- 3) + b b a 9)
                   + 
                     b(a(a b 18 + b a(- 36)) + b a a 9)
               + 
               b(a a(a b(- 12) + b a 18) + b a a a(- 3))
       + 
           b a a a
        *
               a
            *
                 a b(a b 3 + b a(- 3))
               + 
                 b(a(a b(- 9) + b a 12) + b a a(- 3))
           + 
             b a(a(a b 6 + b a(- 9)) + b a a 3)
    Type: XRecursivePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty37}
\begin{paste}{XPBWPolynomialXmpPageEmpty37}{XPBWPolynomialXmpPagePatch37}
\pastebutton{XPBWPolynomialXmpPageEmpty37}{\showpaste}
\tab{5}\spadcommand{pr:rpoly := p :: rpoly\free{rpoly pp }\bound{pr }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch38}
\begin{paste}{XPBWPolynomialXmpPageFull38}{XPBWPolynomialXmpPageEmpty38}
\pastebutton{XPBWPolynomialXmpPageFull38}{\hidepaste}
\tab{5}\spadcommand{qr:rpoly := q :: rpoly\free{rpoly qq }\bound{qr }}
\indentrel{3}\begin{verbatim}
   (38)
       a
    *
         a(a b b 1 + b(a b(- 2) + b a(- 1)))
       + 
         b(a b a 4 + b a a(- 1))
   + 
     b(a b a a(- 2) + b a a a 1)
    Type: XRecursivePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty38}
\begin{paste}{XPBWPolynomialXmpPageEmpty38}{XPBWPolynomialXmpPagePatch38}
\pastebutton{XPBWPolynomialXmpPageEmpty38}{\showpaste}
\tab{5}\spadcommand{qr:rpoly := q :: rpoly\free{rpoly qq }\bound{qr }}
\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPagePatch39}
\begin{paste}{XPBWPolynomialXmpPageFull39}{XPBWPolynomialXmpPageEmpty39}
\pastebutton{XPBWPolynomialXmpPageFull39}{\hidepaste}
\tab{5}\spadcommand{pq :: rpoly - pr*qr\free{pr qr rpoly pqpq }}
\indentrel{3}\begin{verbatim}
   (39)  0
    Type: XRecursivePolynomial(Symbol,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPBWPolynomialXmpPageEmpty39}
\begin{paste}{XPBWPolynomialXmpPageEmpty39}{XPBWPolynomialXmpPagePatch39}
\pastebutton{XPBWPolynomialXmpPageEmpty39}{\showpaste}
\tab{5}\spadcommand{pq :: rpoly - pr*qr\free{pr qr rpoly pqpq }}
\end{paste}\end{patch}

\end{chunk}
\section{xpoly.ht}
\pagetitle{XPolynomialXmpPage}{xpoly.ht}{XPolynomial}
\begin{chunk}{xpoly.ht}
\begin{page}{XPolynomialXmpPage}{XPolynomial}
\beginscroll
The \spadtype{XPolynomial} domain constructor implements 
multivariate polynomials
whose set of variables is \spadtype{Symbol}.
These variables do not commute.
The only parameter of this construtor is 
the coefficient ring which may be non-commutative.
However, coefficients and variables commute.
The representation of the polynomials is recursive.
The abbreviation for \spadtype{XPolynomial} is \spadtype{XPOLY}.

Other constructors like \spadtype{XPolynomialRing}, 
\spadtype{XRecursivePolynomial} 
\spadtype{XDistributedPolynomial},
\spadtype{LiePolynomial} and
\spadtype{XPBWPolynomial}
implement multivariate polynomials
in non-commutative variables.

We illustrate now some of the facilities of the \spadtype{XPOLY}
domain constructor.


\xtc{
Define a polynomial ring over the integers.
}{
\spadpaste{poly := XPolynomial(Integer) \bound{poly}}
}

\xtc{
Define a first polynomial,
}{
\spadpaste{pr: poly := 2*x + 3*y-5  \free{poly} \bound{pr}}
}


\xtc{
and a second one.
}{
\spadpaste{pr2: poly := pr*pr  \free{poly} \bound{pr2}}
}

\xtc{
Rewrite {\bf pr} in a distributive way,
}{
\spadpaste{pd  := expand pr   \free{pr} \bound{pd}}
}

\xtc{
compute its square,
}{
\spadpaste{pd2 := pd*pd   \free{pd} \bound{pd2}}
}

\xtc{
and checks that:
}{
\spadpaste{expand(pr2) - pd2 \free{pr2} \free{pd2}}
}


\xtc{
We define:
}{
\spadpaste{qr :=  pr**3 \free{pr} \bound{qr}}
}

\xtc{
and:
}{
\spadpaste{qd :=  pd**3 \free{pd} \bound{qd}}
}

\xtc{
We truncate {\bf qd} at degree {\bf 3}:
}{
\spadpaste{ trunc(qd,2) \free{qd}}
}

\xtc{
The same for {\bf qr}:
}{
\spadpaste{trunc(qr,2) \free{qr}}
}

\xtc{
We define:
}{
\spadpaste{Word := OrderedFreeMonoid Symbol \bound{Word}}
}

\xtc{
and:
}{
\spadpaste{w: Word := x*y**2 \free{Word} \bound{w}}
}

\xtc{
The we can compute the right-quotient of {\bf qr} by {\bf r}:
}{
\spadpaste{rquo(qr,w) \free{qr} \free{w}}
}

\xtc{
and the shuffle-product of {\bf pr} by {\bf r}:
}{
\spadpaste{sh(pr,w::poly) \free{pr} \free{w}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{XPolynomialXmpPagePatch1}
\begin{paste}{XPolynomialXmpPageFull1}{XPolynomialXmpPageEmpty1}
\pastebutton{XPolynomialXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{poly := XPolynomial(Integer)\bound{poly }}
\indentrel{3}\begin{verbatim}
   (1)  XPolynomial Integer
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPageEmpty1}
\begin{paste}{XPolynomialXmpPageEmpty1}{XPolynomialXmpPagePatch1}
\pastebutton{XPolynomialXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{poly := XPolynomial(Integer)\bound{poly }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPagePatch2}
\begin{paste}{XPolynomialXmpPageFull2}{XPolynomialXmpPageEmpty2}
\pastebutton{XPolynomialXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{pr: poly := 2*x + 3*y-5\free{poly }\bound{pr }}
\indentrel{3}\begin{verbatim}
   (2)  - 5 + x 2 + y 3
                              Type: XPolynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPageEmpty2}
\begin{paste}{XPolynomialXmpPageEmpty2}{XPolynomialXmpPagePatch2}
\pastebutton{XPolynomialXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{pr: poly := 2*x + 3*y-5\free{poly }\bound{pr }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPagePatch3}
\begin{paste}{XPolynomialXmpPageFull3}{XPolynomialXmpPageEmpty3}
\pastebutton{XPolynomialXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{pr2: poly := pr*pr\free{poly }\bound{pr2 }}
\indentrel{3}\begin{verbatim}
   (3)  25 + x(- 20 + x 4 + y 6) + y(- 30 + x 6 + y 9)
                              Type: XPolynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPageEmpty3}
\begin{paste}{XPolynomialXmpPageEmpty3}{XPolynomialXmpPagePatch3}
\pastebutton{XPolynomialXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{pr2: poly := pr*pr\free{poly }\bound{pr2 }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPagePatch4}
\begin{paste}{XPolynomialXmpPageFull4}{XPolynomialXmpPageEmpty4}
\pastebutton{XPolynomialXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{pd := expand pr\free{pr }\bound{pd }}
\indentrel{3}\begin{verbatim}
   (4)  - 5 + 2x + 3y
           Type: XDistributedPolynomial(Symbol,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPageEmpty4}
\begin{paste}{XPolynomialXmpPageEmpty4}{XPolynomialXmpPagePatch4}
\pastebutton{XPolynomialXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{pd := expand pr\free{pr }\bound{pd }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPagePatch5}
\begin{paste}{XPolynomialXmpPageFull5}{XPolynomialXmpPageEmpty5}
\pastebutton{XPolynomialXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{pd2 := pd*pd\free{pd }\bound{pd2 }}
\indentrel{3}\begin{verbatim}
                           2                   2
   (5)  25 - 20x - 30y + 4x  + 6x y + 6y x + 9y
           Type: XDistributedPolynomial(Symbol,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPageEmpty5}
\begin{paste}{XPolynomialXmpPageEmpty5}{XPolynomialXmpPagePatch5}
\pastebutton{XPolynomialXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{pd2 := pd*pd\free{pd }\bound{pd2 }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPagePatch6}
\begin{paste}{XPolynomialXmpPageFull6}{XPolynomialXmpPageEmpty6}
\pastebutton{XPolynomialXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{expand(pr2) - pd2\free{pr2 }\free{pd2 }}
\indentrel{3}\begin{verbatim}
   (6)  0
           Type: XDistributedPolynomial(Symbol,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPageEmpty6}
\begin{paste}{XPolynomialXmpPageEmpty6}{XPolynomialXmpPagePatch6}
\pastebutton{XPolynomialXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{expand(pr2) - pd2\free{pr2 }\free{pd2 }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPagePatch7}
\begin{paste}{XPolynomialXmpPageFull7}{XPolynomialXmpPageEmpty7}
\pastebutton{XPolynomialXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{qr := pr**3\free{pr }\bound{qr }}
\indentrel{3}\begin{verbatim}
   (7)
     - 125
   + 
     x(150 + x(- 60 + x 8 + y 12) + y(- 90 + x 12 + y 18))
   + 
   y(225 + x(- 90 + x 12 + y 18) + y(- 135 + x 18 + y 27))
                              Type: XPolynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPageEmpty7}
\begin{paste}{XPolynomialXmpPageEmpty7}{XPolynomialXmpPagePatch7}
\pastebutton{XPolynomialXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{qr := pr**3\free{pr }\bound{qr }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPagePatch8}
\begin{paste}{XPolynomialXmpPageFull8}{XPolynomialXmpPageEmpty8}
\pastebutton{XPolynomialXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{qd := pd**3\free{pd }\bound{qd }}
\indentrel{3}\begin{verbatim}
   (8)
                              2                       2
     - 125 + 150x + 225y - 60x  - 90x y - 90y x - 135y
   + 
       3      2                   2        2
     8x  + 12x y + 12x y x + 18x y  + 12y x  + 18y x y
   + 
        2       3
     18y x + 27y
           Type: XDistributedPolynomial(Symbol,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPageEmpty8}
\begin{paste}{XPolynomialXmpPageEmpty8}{XPolynomialXmpPagePatch8}
\pastebutton{XPolynomialXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{qd := pd**3\free{pd }\bound{qd }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPagePatch9}
\begin{paste}{XPolynomialXmpPageFull9}{XPolynomialXmpPageEmpty9}
\pastebutton{XPolynomialXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{ trunc(qd,2)\free{qd }}
\indentrel{3}\begin{verbatim}
   (9)
                            2                       2
   - 125 + 150x + 225y - 60x  - 90x y - 90y x - 135y
           Type: XDistributedPolynomial(Symbol,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPageEmpty9}
\begin{paste}{XPolynomialXmpPageEmpty9}{XPolynomialXmpPagePatch9}
\pastebutton{XPolynomialXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{ trunc(qd,2)\free{qd }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPagePatch10}
\begin{paste}{XPolynomialXmpPageFull10}{XPolynomialXmpPageEmpty10}
\pastebutton{XPolynomialXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{trunc(qr,2)\free{qr }}
\indentrel{3}\begin{verbatim}
   (10)
     - 125 + x(150 + x(- 60) + y(- 90))
   + 
     y(225 + x(- 90) + y(- 135))
                              Type: XPolynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPageEmpty10}
\begin{paste}{XPolynomialXmpPageEmpty10}{XPolynomialXmpPagePatch10}
\pastebutton{XPolynomialXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{trunc(qr,2)\free{qr }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPagePatch11}
\begin{paste}{XPolynomialXmpPageFull11}{XPolynomialXmpPageEmpty11}
\pastebutton{XPolynomialXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{Word := OrderedFreeMonoid Symbol\bound{Word }}
\indentrel{3}\begin{verbatim}
   (11)  OrderedFreeMonoid Symbol
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPageEmpty11}
\begin{paste}{XPolynomialXmpPageEmpty11}{XPolynomialXmpPagePatch11}
\pastebutton{XPolynomialXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{Word := OrderedFreeMonoid Symbol\bound{Word }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPagePatch12}
\begin{paste}{XPolynomialXmpPageFull12}{XPolynomialXmpPageEmpty12}
\pastebutton{XPolynomialXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{w: Word := x*y**2\free{Word }\bound{w }}
\indentrel{3}\begin{verbatim}
            2
   (12)  x y
                         Type: OrderedFreeMonoid Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPageEmpty12}
\begin{paste}{XPolynomialXmpPageEmpty12}{XPolynomialXmpPagePatch12}
\pastebutton{XPolynomialXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{w: Word := x*y**2\free{Word }\bound{w }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPagePatch13}
\begin{paste}{XPolynomialXmpPageFull13}{XPolynomialXmpPageEmpty13}
\pastebutton{XPolynomialXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{rquo(qr,w)\free{qr }\free{w }}
\indentrel{3}\begin{verbatim}
   (13)  18
                              Type: XPolynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPageEmpty13}
\begin{paste}{XPolynomialXmpPageEmpty13}{XPolynomialXmpPagePatch13}
\pastebutton{XPolynomialXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{rquo(qr,w)\free{qr }\free{w }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPagePatch14}
\begin{paste}{XPolynomialXmpPageFull14}{XPolynomialXmpPageEmpty14}
\pastebutton{XPolynomialXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{sh(pr,w::poly)\free{pr }\free{w }}
\indentrel{3}\begin{verbatim}
   (14)
   x(x y y 4 + y(x y 2 + y(- 5 + x 2 + y 9))) + y x y y 3
                              Type: XPolynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialXmpPageEmpty14}
\begin{paste}{XPolynomialXmpPageEmpty14}{XPolynomialXmpPagePatch14}
\pastebutton{XPolynomialXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{sh(pr,w::poly)\free{pr }\free{w }}
\end{paste}\end{patch}

\end{chunk}
\section{xpr.ht}
\pagetitle{XPolynomialRingXmpPage}{xpr.ht}{XPolynomialRing}
\begin{chunk}{xpr.ht}
\begin{page}{XPolynomialRingXmpPage}{XPolynomialRing}
\beginscroll
The \spadtype{XPolynomialRing} domain constructor implements
generalized polynomials with coefficients from an arbitrary \spadtype{Ring}
(not necessarily commutative) and whose exponents are
words from an arbitrary \spadtype{OrderedMonoid}
(not necessarily commutative too).
Thus these polynomials are (finite) linear combinations of words.

This constructor takes two arguments.
The first one is a \spadtype{Ring}
and the second is an \spadtype{OrderedMonoid}.
The abbreviation for \spadtype{XPolynomialRing} is \spadtype{XPR}.

Other constructors like \spadtype{XPolynomial}, 
\spadtype{XRecursivePolynomial} 
\spadtype{XDistributedPolynomial},
\spadtype{LiePolynomial} and
\spadtype{XPBWPolynomial}
implement multivariate polynomials
in non-commutative variables.

We illustrate now some of the facilities of the \spadtype{XPR} domain
constructor.

\xtc{
Define the free ordered monoid generated by the symbols.
}{
\spadpaste{Word := OrderedFreeMonoid(Symbol) \bound{Word}}
}

\xtc{
Define the linear combinations of these words with integer coefficients.
}{
\spadpaste{poly:= XPR(Integer,Word) \free{Word} \bound{poly}}
}


\xtc{
Then we define a first element from {\bf poly}.
}{
\spadpaste{p:poly := 2 * x - 3 * y + 1 \free{poly} \bound{p}}
}

\xtc{
And a second one.
}{
\spadpaste{q:poly := 2 * x + 1 \free{poly} \bound{q}}
}


\xtc{
We compute their sum,
}{
\spadpaste{p + q  \free{p}\free{q} }
}

\xtc{
their product,
}{
\spadpaste{p * q  \free{p}\free{q} }
}

\xtc{
and see that variables do not commute.
}{
\spadpaste{(p +q)^2 -p^2 -q^2 - 2*p*q  \free{p}\free{q} }
}



\xtc{
Now we define a ring of square matrices,
}{
\spadpaste{M := SquareMatrix(2,Fraction Integer)  \bound{M}}
}

\xtc{
and the linear combinations of words with these  matrices as coefficients.
}{
\spadpaste{poly1:= XPR(M,Word) \free{Word} \free{M} \bound{poly1}}
}


\xtc{
Define a first matrix,
}{
\spadpaste{m1:M := matrix [[i*j**2 for i in 1..2] for j in 1..2] 
\free{M} \bound{m1}}
}

\xtc{
a second one,
}{
\spadpaste{m2:M := m1 - 5/4 \free{M} \free{m1} \bound{m2}}
}

\xtc{
and a third one.
}{
\spadpaste{m3: M := m2**2 \free{M} \free{m2} \bound{m3}}
}

\xtc{
Define a polynomial,
}{
\spadpaste{pm:poly1   := m1*x + m2*y + m3*z - 2/3 \free{poly1} 
\free{m1} \free{m2} \free{m3} \bound{pm}}
}


\xtc{
a second one,
}{
\spadpaste{qm:poly1 := pm - m1*x \free{m1} \free{pm} \bound{qm}}
}

\xtc{
and the following power.
}{
\spadpaste{qm**3 \bound{qm}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{XPolynomialRingXmpPagePatch1}
\begin{paste}{XPolynomialRingXmpPageFull1}{XPolynomialRingXmpPageEmpty1}
\pastebutton{XPolynomialRingXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{Word := OrderedFreeMonoid(Symbol)\bound{Word }}
\indentrel{3}\begin{verbatim}
   (1)  OrderedFreeMonoid Symbol
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPageEmpty1}
\begin{paste}{XPolynomialRingXmpPageEmpty1}{XPolynomialRingXmpPagePatch1}
\pastebutton{XPolynomialRingXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{Word := OrderedFreeMonoid(Symbol)\bound{Word }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPagePatch2}
\begin{paste}{XPolynomialRingXmpPageFull2}{XPolynomialRingXmpPageEmpty2}
\pastebutton{XPolynomialRingXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{poly:= XPR(Integer,Word)\free{Word }\bound{poly }}
\indentrel{3}\begin{verbatim}
   (2)
   XPolynomialRing(Integer,OrderedFreeMonoid Symbol)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPageEmpty2}
\begin{paste}{XPolynomialRingXmpPageEmpty2}{XPolynomialRingXmpPagePatch2}
\pastebutton{XPolynomialRingXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{poly:= XPR(Integer,Word)\free{Word }\bound{poly }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPagePatch3}
\begin{paste}{XPolynomialRingXmpPageFull3}{XPolynomialRingXmpPageEmpty3}
\pastebutton{XPolynomialRingXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{p:poly := 2 * x - 3 * y + 1\free{poly }\bound{p }}
\indentrel{3}\begin{verbatim}
   (3)  1 + 2x - 3y
Type: XPolynomialRing(Integer,OrderedFreeMonoid Symbol)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPageEmpty3}
\begin{paste}{XPolynomialRingXmpPageEmpty3}{XPolynomialRingXmpPagePatch3}
\pastebutton{XPolynomialRingXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{p:poly := 2 * x - 3 * y + 1\free{poly }\bound{p }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPagePatch4}
\begin{paste}{XPolynomialRingXmpPageFull4}{XPolynomialRingXmpPageEmpty4}
\pastebutton{XPolynomialRingXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{q:poly := 2 * x + 1\free{poly }\bound{q }}
\indentrel{3}\begin{verbatim}
   (4)  1 + 2x
Type: XPolynomialRing(Integer,OrderedFreeMonoid Symbol)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPageEmpty4}
\begin{paste}{XPolynomialRingXmpPageEmpty4}{XPolynomialRingXmpPagePatch4}
\pastebutton{XPolynomialRingXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{q:poly := 2 * x + 1\free{poly }\bound{q }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPagePatch5}
\begin{paste}{XPolynomialRingXmpPageFull5}{XPolynomialRingXmpPageEmpty5}
\pastebutton{XPolynomialRingXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{p + q\free{p }\free{q }}
\indentrel{3}\begin{verbatim}
   (5)  2 + 4x - 3y
Type: XPolynomialRing(Integer,OrderedFreeMonoid Symbol)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPageEmpty5}
\begin{paste}{XPolynomialRingXmpPageEmpty5}{XPolynomialRingXmpPagePatch5}
\pastebutton{XPolynomialRingXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{p + q\free{p }\free{q }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPagePatch6}
\begin{paste}{XPolynomialRingXmpPageFull6}{XPolynomialRingXmpPageEmpty6}
\pastebutton{XPolynomialRingXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{p * q\free{p }\free{q }}
\indentrel{3}\begin{verbatim}
                        2
   (6)  1 + 4x - 3y + 4x  - 6y x
Type: XPolynomialRing(Integer,OrderedFreeMonoid Symbol)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPageEmpty6}
\begin{paste}{XPolynomialRingXmpPageEmpty6}{XPolynomialRingXmpPagePatch6}
\pastebutton{XPolynomialRingXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{p * q\free{p }\free{q }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPagePatch7}
\begin{paste}{XPolynomialRingXmpPageFull7}{XPolynomialRingXmpPageEmpty7}
\pastebutton{XPolynomialRingXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{(p +q)^2 -p^2 -q^2 - 2*p*q\free{p }\free{q }}
\indentrel{3}\begin{verbatim}
   (7)  - 6x y + 6y x
Type: XPolynomialRing(Integer,OrderedFreeMonoid Symbol)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPageEmpty7}
\begin{paste}{XPolynomialRingXmpPageEmpty7}{XPolynomialRingXmpPagePatch7}
\pastebutton{XPolynomialRingXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{(p +q)^2 -p^2 -q^2 - 2*p*q\free{p }\free{q }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPagePatch8}
\begin{paste}{XPolynomialRingXmpPageFull8}{XPolynomialRingXmpPageEmpty8}
\pastebutton{XPolynomialRingXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{M := SquareMatrix(2,Fraction Integer)\bound{M }}
\indentrel{3}\begin{verbatim}
   (8)  SquareMatrix(2,Fraction Integer)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPageEmpty8}
\begin{paste}{XPolynomialRingXmpPageEmpty8}{XPolynomialRingXmpPagePatch8}
\pastebutton{XPolynomialRingXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{M := SquareMatrix(2,Fraction Integer)\bound{M }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPagePatch9}
\begin{paste}{XPolynomialRingXmpPageFull9}{XPolynomialRingXmpPageEmpty9}
\pastebutton{XPolynomialRingXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{poly1:= XPR(M,Word)\free{Word }\free{M }\bound{poly1 }}
\indentrel{3}\begin{verbatim}
   (9)
  XPolynomialRing(SquareMatrix(2,Fraction Integer),Ordere
  dFreeMonoid Symbol)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPageEmpty9}
\begin{paste}{XPolynomialRingXmpPageEmpty9}{XPolynomialRingXmpPagePatch9}
\pastebutton{XPolynomialRingXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{poly1:= XPR(M,Word)\free{Word }\free{M }\bound{poly1 }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPagePatch10}
\begin{paste}{XPolynomialRingXmpPageFull10}{XPolynomialRingXmpPageEmpty10}
\pastebutton{XPolynomialRingXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{m1:M := matrix [[i*j**2 for i in 1..2] for j in 1..2]\free{M }\bound{m1 }}
\indentrel{3}\begin{verbatim}
         Ú1  2¿
   (10)  ³    ³
         À4  8Ù
                 Type: SquareMatrix(2,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPageEmpty10}
\begin{paste}{XPolynomialRingXmpPageEmpty10}{XPolynomialRingXmpPagePatch10}
\pastebutton{XPolynomialRingXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{m1:M := matrix [[i*j**2 for i in 1..2] for j in 1..2]\free{M }\bound{m1 }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPagePatch11}
\begin{paste}{XPolynomialRingXmpPageFull11}{XPolynomialRingXmpPageEmpty11}
\pastebutton{XPolynomialRingXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{m2:M := m1 - 5/4\free{M }\free{m1 }\bound{m2 }}
\indentrel{3}\begin{verbatim}
         Ú  1    ¿
         ³- Ä  2 ³
         ³  4    ³
   (11)  ³       ³
         ³     27³
         ³ 4   ÄÄ³
         À      4Ù
                 Type: SquareMatrix(2,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPageEmpty11}
\begin{paste}{XPolynomialRingXmpPageEmpty11}{XPolynomialRingXmpPagePatch11}
\pastebutton{XPolynomialRingXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{m2:M := m1 - 5/4\free{M }\free{m1 }\bound{m2 }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPagePatch12}
\begin{paste}{XPolynomialRingXmpPageFull12}{XPolynomialRingXmpPageEmpty12}
\pastebutton{XPolynomialRingXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{m3: M := m2**2\free{M }\free{m2 }\bound{m3 }}
\indentrel{3}\begin{verbatim}
         Ú129     ¿
         ³ÄÄÄ  13 ³
         ³ 16     ³
   (12)  ³        ³
         ³     857³
         ³26   ÄÄÄ³
         À      16Ù
                 Type: SquareMatrix(2,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPageEmpty12}
\begin{paste}{XPolynomialRingXmpPageEmpty12}{XPolynomialRingXmpPagePatch12}
\pastebutton{XPolynomialRingXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{m3: M := m2**2\free{M }\free{m2 }\bound{m3 }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPagePatch13}
\begin{paste}{XPolynomialRingXmpPageFull13}{XPolynomialRingXmpPageEmpty13}
\pastebutton{XPolynomialRingXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{pm:poly1 := m1*x + m2*y + m3*z - 2/3\free{poly1 }\free{m1 }\free{m2 }\free{m3 }\bound{pm }}
\indentrel{3}\begin{verbatim}
         Ú  2     ¿             Ú  1    ¿    Ú129     ¿
         ³- Ä   0 ³             ³- Ä  2 ³    ³ÄÄÄ  13 ³
         ³  3     ³   Ú1  2¿    ³  4    ³    ³ 16     ³
   (13)  ³        ³ + ³    ³x + ³       ³y + ³        ³z
         ³       2³   À4  8Ù    ³     27³    ³     857³
         ³ 0   - Ä³             ³ 4   ÄÄ³    ³26   ÄÄÄ³
         À       3Ù             À      4Ù    À      16Ù
Type: XPolynomialRing(SquareMatrix(2,Fraction Integer),OrderedFreeMonoid Symbol)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPageEmpty13}
\begin{paste}{XPolynomialRingXmpPageEmpty13}{XPolynomialRingXmpPagePatch13}
\pastebutton{XPolynomialRingXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{pm:poly1 := m1*x + m2*y + m3*z - 2/3\free{poly1 }\free{m1 }\free{m2 }\free{m3 }\bound{pm }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPagePatch14}
\begin{paste}{XPolynomialRingXmpPageFull14}{XPolynomialRingXmpPageEmpty14}
\pastebutton{XPolynomialRingXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{qm:poly1 := pm - m1*x\free{m1 }\free{pm }\bound{qm }}
\indentrel{3}\begin{verbatim}
         Ú  2     ¿   Ú  1    ¿    Ú129     ¿
         ³- Ä   0 ³   ³- Ä  2 ³    ³ÄÄÄ  13 ³
         ³  3     ³   ³  4    ³    ³ 16     ³
   (14)  ³        ³ + ³       ³y + ³        ³z
         ³       2³   ³     27³    ³     857³
         ³ 0   - Ä³   ³ 4   ÄÄ³    ³26   ÄÄÄ³
         À       3Ù   À      4Ù    À      16Ù
Type: XPolynomialRing(SquareMatrix(2,Fraction Integer),OrderedFreeMonoid Symbol)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPageEmpty14}
\begin{paste}{XPolynomialRingXmpPageEmpty14}{XPolynomialRingXmpPagePatch14}
\pastebutton{XPolynomialRingXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{qm:poly1 := pm - m1*x\free{m1 }\free{pm }\bound{qm }}
\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPagePatch15}
\begin{paste}{XPolynomialRingXmpPageFull15}{XPolynomialRingXmpPageEmpty15}
\pastebutton{XPolynomialRingXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{qm**3\bound{qm }}
\indentrel{3}\begin{verbatim}
   (15)
     Ú   8      ¿   Ú  1  8¿    Ú43   52 ¿
     ³- ÄÄ   0  ³   ³- Ä  Ä³    ³ÄÄ   ÄÄ ³
     ³  27      ³   ³  3  3³    ³ 4    3 ³
     ³          ³ + ³      ³y + ³        ³z
     ³         8³   ³16    ³    ³104  857³
     ³ 0    - ÄÄ³   ³ÄÄ   9³    ³ÄÄÄ  ÄÄÄ³
     À        27Ù   À 3    Ù    À 3    12Ù
   + 
     Ú  129       ¿     Ú  3199     831 ¿
     ³- ÄÄÄ  - 26 ³     ³- ÄÄÄÄ   - ÄÄÄ ³
     ³   8        ³ 2   ³   32       4  ³
     ³            ³y  + ³               ³y z
     ³         857³     ³  831     26467³
     ³- 52   - ÄÄÄ³     ³- ÄÄÄ   - ÄÄÄÄÄ³
     À          8 Ù     À   2        32 Ù
   + 
     Ú  3199     831 ¿      Ú  103169     6409 ¿
     ³- ÄÄÄÄ   - ÄÄÄ ³      ³- ÄÄÄÄÄÄ   - ÄÄÄÄ ³
     ³   32       4  ³      ³    128        4  ³ 2
     ³               ³z y + ³                  ³z
     ³  831     26467³      ³   6409     820977³
     ³- ÄÄÄ   - ÄÄÄÄÄ³      ³ - ÄÄÄÄ   - ÄÄÄÄÄÄ³
     À   2        32 Ù      À     2        128 Ù
   + 
     Ú3199   831 ¿     Ú103169   6409 ¿
     ³ÄÄÄÄ   ÄÄÄ ³     ³ÄÄÄÄÄÄ   ÄÄÄÄ ³
     ³ 64     8  ³ 3   ³  256      8  ³ 2
     ³           ³y  + ³              ³y z
     ³831   26467³     ³ 6409   820977³
     ³ÄÄÄ   ÄÄÄÄÄ³     ³ ÄÄÄÄ   ÄÄÄÄÄÄ³
     À 4      64 Ù     À   4      256 Ù
   + 
     Ú103169   6409 ¿        Ú3178239   795341 ¿
     ³ÄÄÄÄÄÄ   ÄÄÄÄ ³        ³ÄÄÄÄÄÄÄ   ÄÄÄÄÄÄ ³
     ³  256      8  ³        ³  1024      128  ³   2
     ³              ³y z y + ³                 ³y z
     ³ 6409   820977³        ³795341   25447787³
     ³ ÄÄÄÄ   ÄÄÄÄÄÄ³        ³ÄÄÄÄÄÄ   ÄÄÄÄÄÄÄÄ³
     À   4      256 Ù        À  64       1024  Ù
   + 
     Ú103169   6409 ¿       Ú3178239   795341 ¿
     ³ÄÄÄÄÄÄ   ÄÄÄÄ ³       ³ÄÄÄÄÄÄÄ   ÄÄÄÄÄÄ ³
     ³  256      8  ³   2   ³  1024      128  ³
     ³              ³z y  + ³                 ³z y z
     ³ 6409   820977³       ³795341   25447787³
     ³ ÄÄÄÄ   ÄÄÄÄÄÄ³       ³ÄÄÄÄÄÄ   ÄÄÄÄÄÄÄÄ³
     À   4      256 Ù       À  64       1024  Ù
   + 
     Ú3178239   795341 ¿      Ú98625409  12326223 ¿
     ³ÄÄÄÄÄÄÄ   ÄÄÄÄÄÄ ³      ³ÄÄÄÄÄÄÄÄ  ÄÄÄÄÄÄÄÄ ³
     ³  1024      128  ³ 2    ³  4096       256   ³ 3
     ³                 ³z y + ³                   ³z
     ³795341   25447787³      ³12326223  788893897³
     ³ÄÄÄÄÄÄ   ÄÄÄÄÄÄÄÄ³      ³ÄÄÄÄÄÄÄÄ  ÄÄÄÄÄÄÄÄÄ³
     À  64       1024  Ù      À   128       4096  Ù
Type: XPolynomialRing(SquareMatrix(2,Fraction Integer),OrderedFreeMonoid Symbol)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{XPolynomialRingXmpPageEmpty15}
\begin{paste}{XPolynomialRingXmpPageEmpty15}{XPolynomialRingXmpPagePatch15}
\pastebutton{XPolynomialRingXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{qm**3\bound{qm }}
\end{paste}\end{patch}

\end{chunk}
\section{zdsolve.ht}
\pagetitle{ZeroDimSolvePkgXmpPage}{zdsolve.ht}
{ZeroDimensionalSolvePackage}
\begin{chunk}{zdsolve.ht}
\begin{page}{ZeroDimSolvePkgXmpPage}{ZeroDimensionalSolvePackage}
\beginscroll
The \spadtype{ZeroDimensionalSolvePackage} package constructor
provides operations for computing symbolically the complex or real
roots of zero-dimensional algebraic systems.

The package provides {\bf no} multiplicity information (i.e. some
returned roots may be double or higher) but only distinct roots are
returned.

Complex roots are given by means of univariate representations of
irreducible regular chains.  These representations are computed by the
\axiomOpFrom{univariateSolve}{ZeroDimensionalSolvePackage} operation
(by calling the
\spadtype{InternalRationalUnivariateRepresentationPackage} package
constructor which does the job).

Real roots are given by means of tuples of coordinates lying in the
\spadtype{RealClosure} of the coefficient ring.  They are computed by
the \axiomOpFrom{realSolve}{ZeroDimensionalSolvePackage} and
\axiomOpFrom{positiveSolve}{ZeroDimensionalSolvePackage} operations.
The former computes all the solutions of the input system with real
coordinates whereas the later concentrate on the solutions with
(strictly) positive coordinates.  In both cases, the computations are
performed by the \spadtype{RealClosure} constructor.

Both computations of complex roots and real roots rely on triangular
decompositions.  These decompositions can be computed in two different
ways.  First, by a applying the
\axiomOpFrom{zeroSetSplit}{RegularTriangularSet} operation from the
\spadtype{REGSET} domain constructor.  In that case, no Groebner bases
are computed.  This strategy is used by default.  Secondly, by
applying the \axiomOpFrom{zeroSetSplit}{LexTriangularPackage} from
\spadtype{LEXTRIPK}.  To use this later strategy with the operations
\axiomOpFrom{univariateSolve}{ZeroDimensionalSolvePackage},
\axiomOpFrom{realSolve}{ZeroDimensionalSolvePackage} and
\axiomOpFrom{positiveSolve}{ZeroDimensionalSolvePackage} one just
needs to use an extra boolean argument.

Note that the way of understanding triangular decompositions 
is detailed in the example of the \spadtype{RegularTriangularSet}
constructor.

The \spadtype{ZeroDimensionalSolvePackage} constructor takes three
arguments.  The first one {\bf R} is the coefficient ring; it must
belong to the categories \spadtype{OrderedRing},
\spadtype{EuclideanDomain}, \spadtype{CharacteristicZero} and
\spadtype{RealConstant}.  This means essentially that {\bf R} is
\spadtype{Integer} or \spadtype{Fraction(Integer)}.  The second
argument {\bf ls} is the list of variables involved in the systems to
solve.  The third one MUST BE {\bf concat(ls,s)} where {\bf s} is an
additional symbol used for the univariate representations.  The
abbreviation for \spadtype{ZeroDimensionalSolvePackage} is
\spadtype{ZDSOLVE}.

We illustrate now how to use the constructor \spadtype{ZDSOLVE}
by two examples: the {\em Arnborg and Lazard} system and the 
{\em L-3} system (Aubry and Moreno Maza).
Note that the use of this package is also demonstrated in the example
of the \spadtype{LexTriangularPackage} constructor.

\xtc{
Define the coefficient ring.
}{
\spadpaste{R := Integer \bound{R}}
}

\xtc{
Define the lists of variables:
}{
\spadpaste{ls : List Symbol := [x,y,z,t] \bound{ls}}
}

\xtc{
and:
}{
\spadpaste{ls2 : List Symbol := [x,y,z,t,new()$Symbol] \bound{ls2}}
}

\xtc{
Call the package:
}{
\spadpaste{pack := ZDSOLVE(R,ls,ls2) \free{ls} \free{ls2} 
\free{R} \bound{pack}}
}

\xtc{
Define a polynomial system (Arnborg-Lazard)
}{
\spadpaste{p1 := x**2*y*z + x*y**2*z + x*y*z**2 + x*y*z + 
x*y + x*z + y*z \bound{p1}}
}
\xtc{
}{
\spadpaste{p2 := x**2*y**2*z + x*y**2*z**2 + x**2*y*z + 
x*y*z + y*z + x + z \bound{p2}}
}
\xtc{
}{
\spadpaste{p3 := x**2*y**2*z**2 + x**2*y**2*z + x*y**2*z + 
x*y*z + x*z + z + 1 \bound{p3}}
}
\xtc{
}{
\spadpaste{lp := [p1, p2, p3] \free{p1} \free{p2} \free{p3} \bound{lp}}
}
Note that these polynomials do not involve the variable {\bf t};
we will use it in the second example.

\xtc{
First compute a decomposition into regular chains 
(i.e. regular triangular sets).
}{
\spadpaste{triangSolve(lp)$pack \free{lp} \free{pack}}
}

We can see easily from this decomposition (consisting of a single
regular chain) that the input system has 20 complex roots.

\xtc{
Then we compute a univariate representation of this regular chain.
}{
\spadpaste{univariateSolve(lp)$pack \free{lp} \free{pack}}
}

We see that the zeros of our regular chain are split into three
components.  This is due to the use of univariate polynomial
factorization.

Each of these components consist of two parts.  The first one is an
irreducible univariate polynomial {\bf p(?)} which defines a simple
algebraic extension of the field of fractions of {\bf R}.  The second
one consists of multivariate polynomials {\bf pol1(x,\%A)}, {\bf
pol2(y,\%A)} and {\bf pol3(z,\%A)}.  Each of these polynomials involve
two variables: one is an indeterminate {\bf x}, {\bf y} or {\bf z} of
the input system {\bf lp} and the other is {\bf \%A} which represents
any root of {\bf p(?)}.  Recall that this {\bf \%A} is the last
element of the third parameter of \spadtype{ZDSOLVE}.  Thus any
complex root {\bf ?} of {\bf p(?)}  leads to a solution of the input
system {\bf lp} by replacing {\bf \%A} by this {\bf ?} in 
{\bf pol1(x,\%A)}, {\bf pol2(y,\%A)} and {\bf pol3(z,\%A)}.  Note that 
the polynomials {\bf pol1(x,\%A)}, {\bf pol2(y,\%A)} and {\bf pol3(z,\%A)}
have degree one w.r.t. {\bf x}, {\bf y} or {\bf z} respectively.  This
is always the case for all univariate representations.  Hence the
operation {\bf univariateSolve} replaces a system of multivariate
polynomials by a list of univariate polynomials, what justifies its
name.  Another example of univariate representations illustrates the
\spadtype{LexTriangularPackage} package constructor.

\xtc{
We now compute the solutions with real coordinates:
}{
\spadpaste{lr := realSolve(lp)$pack \free{lp} \free{pack} \bound{lr}}
}

\xtc{
The number of real solutions for the input system is:
}{
\spadpaste{\# lr \free{lr}}
}

Each of these real solutions is given by a list of elements in
\spadtype{RealClosure(R)}.  In these 8 lists, the first element is a
value of {\bf z}, the second of {\bf y} and the last of {\bf x}.  This
is logical since by setting the list of variables of the package to
{\bf [x,y,z,t]} we mean that the elimination ordering on the variables
is {\bf t < z < y < x }.  Note that each system treated by the
\spadtype{ZDSOLVE} package constructor needs only to be
zero-dimensional w.r.t. the variables involved in the system it-self
and not necessarily w.r.t. all the variables used to define the
package.

\xtc{
We can approximate these real numbers as follows. 
This computation takes between 30 sec. and 5 min, depending on your 
machine.
}{
\spadpaste{[[approximate(r,1/1000000) for r in point] for point in lr]
\free{lr}}
}

\xtc{
We can also concentrate on the solutions with real (strictly) 
positive coordinates:
}{
\spadpaste{lpr := positiveSolve(lp)$pack \free{lp} \free{pack} \bound{lpr}}
}

Thus we have checked that the input system has no solution with 
strictly positive coordinates.


\xtc{
Let us define another polynomial system ({\em L-3}).
}{
\spadpaste{f0 := x**3 + y + z + t- 1 \bound{f0}}
}
\xtc{
}{
\spadpaste{f1 := x + y**3 + z + t -1 \bound{f1}}
}
\xtc{
}{
\spadpaste{f2 := x + y + z**3 + t-1 \bound{f2}}
}
\xtc{
}{
\spadpaste{f3 := x + y + z + t**3 -1 \bound{f3}}
}
\xtc{
}{
\spadpaste{lf := [f0, f1, f2, f3] \free{f0} \free{f1} \free{f2} 
\free{f3} \bound{lf}}
}


\xtc{
First compute a decomposition into regular chains 
(i.e. regular triangular sets).
}{
\spadpaste{lts := triangSolve(lf)$pack \free{lf} \free{pack} \bound{lts}}
}


\xtc{
Then we compute a univariate representation.
}{
\spadpaste{univariateSolve(lf)$pack \free{lf} \free{pack}}
}

Note that this computation is made from the input system {\bf lf}.
\xtc{
However it is possible to reuse a pre-computed regular chain as follows:
}{
\spadpaste{ts := lts.1 \free{lts} \bound{ts}}
}
\xtc{
}{
\spadpaste{univariateSolve(ts)$pack \free{ts} \free{pack}}
}
\xtc{
}{
\spadpaste{realSolve(ts)$pack  \free{ts} \free{pack}}
}

\xtc{
We compute now the full set of points with real coordinates:
}{
\spadpaste{lr2 := realSolve(lf)$pack \free{lf} \free{pack}  \bound{lr2}}
}


\xtc{
The number of real solutions for the input system is:
}{
\spadpaste{\#lr2 \free{lr2}}
}
Another example of computation of real solutions illustrates
the \spadtype{LexTriangularPackage} package constructor.

\xtc{
We concentrate now on the solutions with real (strictly) positive 
coordinates:
}{
\spadpaste{lpr2 := positiveSolve(lf)$pack \free{lf} \free{pack} 
\bound{lpr2}}
}

\xtc{
Finally, we approximate the coordinates of this point with 20 exact 
digits:
}{
\spadpaste{[approximate(r,1/10**21)::Float for r in lpr2.1] \free{lpr2}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch1}
\begin{paste}{ZeroDimSolvePkgXmpPageFull1}{ZeroDimSolvePkgXmpPageEmpty1}
\pastebutton{ZeroDimSolvePkgXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{R := Integer\bound{R }}
\indentrel{3}\begin{verbatim}
   (1)  Integer
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty1}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty1}{ZeroDimSolvePkgXmpPagePatch1}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{R := Integer\bound{R }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch2}
\begin{paste}{ZeroDimSolvePkgXmpPageFull2}{ZeroDimSolvePkgXmpPageEmpty2}
\pastebutton{ZeroDimSolvePkgXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{ls : List Symbol := [x,y,z,t]\bound{ls }}
\indentrel{3}\begin{verbatim}
   (2)  [x,y,z,t]
                                      Type: List Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty2}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty2}{ZeroDimSolvePkgXmpPagePatch2}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{ls : List Symbol := [x,y,z,t]\bound{ls }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch3}
\begin{paste}{ZeroDimSolvePkgXmpPageFull3}{ZeroDimSolvePkgXmpPageEmpty3}
\pastebutton{ZeroDimSolvePkgXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{ls2 : List Symbol := [x,y,z,t,new()$Symbol]\bound{ls2 }}
\indentrel{3}\begin{verbatim}
   (3)  [x,y,z,t,%A]
                                      Type: List Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty3}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty3}{ZeroDimSolvePkgXmpPagePatch3}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{ls2 : List Symbol := [x,y,z,t,new()$Symbol]\bound{ls2 }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch4}
\begin{paste}{ZeroDimSolvePkgXmpPageFull4}{ZeroDimSolvePkgXmpPageEmpty4}
\pastebutton{ZeroDimSolvePkgXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{pack := ZDSOLVE(R,ls,ls2)\free{ls }\free{ls2 }\free{R }\bound{pack }}
\indentrel{3}\begin{verbatim}
   (4)
  ZeroDimensionalSolvePackage(Integer,[x,y,z,t],[x,y,z,t,
  %A])
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty4}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty4}{ZeroDimSolvePkgXmpPagePatch4}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{pack := ZDSOLVE(R,ls,ls2)\free{ls }\free{ls2 }\free{R }\bound{pack }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch5}
\begin{paste}{ZeroDimSolvePkgXmpPageFull5}{ZeroDimSolvePkgXmpPageEmpty5}
\pastebutton{ZeroDimSolvePkgXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{p1 := x**2*y*z + x*y**2*z + x*y*z**2 + x*y*z + x*y + x*z + y*z\bound{p1 }}
\indentrel{3}\begin{verbatim}
             2       2     2
   (5)  x y z  + (x y  + (x  + x + 1)y + x)z + x y
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty5}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty5}{ZeroDimSolvePkgXmpPagePatch5}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{p1 := x**2*y*z + x*y**2*z + x*y*z**2 + x*y*z + x*y + x*z + y*z\bound{p1 }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch6}
\begin{paste}{ZeroDimSolvePkgXmpPageFull6}{ZeroDimSolvePkgXmpPageEmpty6}
\pastebutton{ZeroDimSolvePkgXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{p2 := x**2*y**2*z + x*y**2*z**2 + x**2*y*z + x*y*z + y*z + x + z\bound{p2 }}
\indentrel{3}\begin{verbatim}
           2 2     2 2     2
   (6)  x y z  + (x y  + (x  + x + 1)y + 1)z + x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty6}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty6}{ZeroDimSolvePkgXmpPagePatch6}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{p2 := x**2*y**2*z + x*y**2*z**2 + x**2*y*z + x*y*z + y*z + x + z\bound{p2 }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch7}
\begin{paste}{ZeroDimSolvePkgXmpPageFull7}{ZeroDimSolvePkgXmpPageEmpty7}
\pastebutton{ZeroDimSolvePkgXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{p3 := x**2*y**2*z**2 + x**2*y**2*z + x*y**2*z + x*y*z + x*z + z + 1\bound{p3 }}
\indentrel{3}\begin{verbatim}
         2 2 2      2      2
   (7)  x y z  + ((x  + x)y  + x y + x + 1)z + 1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty7}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty7}{ZeroDimSolvePkgXmpPagePatch7}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{p3 := x**2*y**2*z**2 + x**2*y**2*z + x*y**2*z + x*y*z + x*z + z + 1\bound{p3 }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch8}
\begin{paste}{ZeroDimSolvePkgXmpPageFull8}{ZeroDimSolvePkgXmpPageEmpty8}
\pastebutton{ZeroDimSolvePkgXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{lp := [p1, p2, p3]\free{p1 }\free{p2 }\free{p3 }\bound{lp }}
\indentrel{3}\begin{verbatim}
   (8)
         2       2     2
   [x y z  + (x y  + (x  + x + 1)y + x)z + x y,
       2 2     2 2     2
    x y z  + (x y  + (x  + x + 1)y + 1)z + x,
     2 2 2      2      2
    x y z  + ((x  + x)y  + x y + x + 1)z + 1]
                          Type: List Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty8}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty8}{ZeroDimSolvePkgXmpPagePatch8}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{lp := [p1, p2, p3]\free{p1 }\free{p2 }\free{p3 }\bound{lp }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch9}
\begin{paste}{ZeroDimSolvePkgXmpPageFull9}{ZeroDimSolvePkgXmpPageEmpty9}
\pastebutton{ZeroDimSolvePkgXmpPageFull9}{\hidepaste}
\tab{5}\spadcommand{triangSolve(lp)$pack\free{lp }\free{pack }}
\indentrel{3}\begin{verbatim}
   (9)
   [
     {
          20     19      18      17       16      15
         z   - 6z   - 41z   + 71z   + 106z   + 92z
       + 
             14       13       12       11       10
         197z   + 145z   + 257z   + 278z   + 201z
       + 
             9       8       7       6      5       4
         278z  + 257z  + 145z  + 197z  + 92z  + 106z
       + 
            3      2
         71z  - 41z  - 6z + 1
       ,

                      19            18             17
             14745844z   + 50357474z   - 130948857z
           + 
                         16             15             14
             - 185261586z   - 180077775z   - 338007307z
           + 
                         13             12             11
             - 275379623z   - 453190404z   - 474597456z
           + 
                         10             9             8
             - 366147695z   - 481433567z  - 430613166z
           + 
                         7             6             5
             - 261878358z  - 326073537z  - 163008796z
           + 
                         4             3            2
             - 177213227z  - 104356755z  + 65241699z
           + 
             9237732z - 1567348
        *
           y
       + 
                 19           18            17
         1917314z   + 6508991z   - 16973165z
       + 
                    16            15            14
         - 24000259z   - 23349192z   - 43786426z
       + 
                    13            12            11
         - 35696474z   - 58724172z   - 61480792z
       + 
                    10            9            8
         - 47452440z   - 62378085z  - 55776527z
       + 
                    7            6            5
         - 33940618z  - 42233406z  - 21122875z
       + 
                    4            3           2
         - 22958177z  - 13504569z  + 8448317z  + 1195888z
       + 
         - 202934
       ,

               3       2       3    2               2
             (z  - 2z)y  + (- z  - z  - 2z - 1)y - z  - z
           + 
             1
        *
           x
       + 
          2
         z  - 1
       }
     ]
             Type: List RegularChain(Integer,[x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty9}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty9}{ZeroDimSolvePkgXmpPagePatch9}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty9}{\showpaste}
\tab{5}\spadcommand{triangSolve(lp)$pack\free{lp }\free{pack }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch10}
\begin{paste}{ZeroDimSolvePkgXmpPageFull10}{ZeroDimSolvePkgXmpPageEmpty10}
\pastebutton{ZeroDimSolvePkgXmpPageFull10}{\hidepaste}
\tab{5}\spadcommand{univariateSolve(lp)$pack\free{lp }\free{pack }}
\indentrel{3}\begin{verbatim}
   (10)
   [
     [
       complexRoots =
            12      11      10     9     8      7      6
           ?   - 12?   + 24?   + 4?  - 9?  + 27?  - 21?
         + 
              5     4     3      2
           27?  - 9?  + 4?  + 24?  - 12? + 1
       ,

       coordinates =
         [
                       11        10         9        8
             63x + 62%A   - 721%A   + 1220%A  + 705%A
           + 
                    7         6        5         4       3
             - 285%A  + 1512%A  - 735%A  + 1401%A  - 21%A
           + 
                  2
             215%A  + 1577%A - 142
           ,

                       11        10         9        8
             63y - 75%A   + 890%A   - 1682%A  - 516%A
           + 
                  7         6         5         4        3
             588%A  - 1953%A  + 1323%A  - 1815%A  + 426%A
           + 
                    2
             - 243%A  - 1801%A + 679
           ,
          z - %A]
       ]
     ,

                     6    5    4    3    2
     [complexRoots= ?  + ?  + ?  + ?  + ?  + ? + 1,
                          5       3
      coordinates= [x - %A ,y - %A ,z - %A]]
     ,

                     2
     [complexRoots= ?  + 5? + 1,
      coordinates= [x - 1,y - 1,z - %A]]
     ]
Type: List Record(complexRoots: SparseUnivariatePolynomial Integer,coordinates: List Polynomial Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty10}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty10}{ZeroDimSolvePkgXmpPagePatch10}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty10}{\showpaste}
\tab{5}\spadcommand{univariateSolve(lp)$pack\free{lp }\free{pack }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch11}
\begin{paste}{ZeroDimSolvePkgXmpPageFull11}{ZeroDimSolvePkgXmpPageEmpty11}
\pastebutton{ZeroDimSolvePkgXmpPageFull11}{\hidepaste}
\tab{5}\spadcommand{lr := realSolve(lp)$pack\free{lp }\free{pack }\bound{lr }}
\indentrel{3}\begin{verbatim}
   (11)
   [
     [%R1,

         1184459    19   2335702    18   5460230    17
         ÄÄÄÄÄÄÄ %R1   - ÄÄÄÄÄÄÄ %R1   - ÄÄÄÄÄÄÄ %R1
         1645371          548457          182819
       + 
         79900378    16   43953929    15   13420192    14
         ÄÄÄÄÄÄÄÄ %R1   + ÄÄÄÄÄÄÄÄ %R1   + ÄÄÄÄÄÄÄÄ %R1
          1645371          548457           182819
       + 
         553986    13   193381378    12   35978916    11
         ÄÄÄÄÄÄ %R1   + ÄÄÄÄÄÄÄÄÄ %R1   + ÄÄÄÄÄÄÄÄ %R1
          3731           1645371           182819
       + 
         358660781    10   271667666    9   118784873    8
         ÄÄÄÄÄÄÄÄÄ %R1   + ÄÄÄÄÄÄÄÄÄ %R1  + ÄÄÄÄÄÄÄÄÄ %R1
          1645371           1645371           548457
       + 
         337505020    7   1389370    6   688291    5
         ÄÄÄÄÄÄÄÄÄ %R1  + ÄÄÄÄÄÄÄ %R1  + ÄÄÄÄÄÄ %R1
          1645371          11193          4459
       + 
         3378002    4   140671876    3   32325724    2
         ÄÄÄÄÄÄÄ %R1  + ÄÄÄÄÄÄÄÄÄ %R1  + ÄÄÄÄÄÄÄÄ %R1
          42189          1645371          548457
       + 
           8270       9741532
         - ÄÄÄÄ %R1 - ÄÄÄÄÄÄÄ
            343       1645371
       ,

            91729    19   487915    18   4114333    17
         - ÄÄÄÄÄÄ %R1   + ÄÄÄÄÄÄ %R1   + ÄÄÄÄÄÄÄ %R1
           705159         705159          705159
       + 
           1276987    16   13243117    15   16292173    14
         - ÄÄÄÄÄÄÄ %R1   - ÄÄÄÄÄÄÄÄ %R1   - ÄÄÄÄÄÄÄÄ %R1
            235053          705159           705159
       + 
           26536060    13   722714    12   5382578    11
         - ÄÄÄÄÄÄÄÄ %R1   - ÄÄÄÄÄÄ %R1   - ÄÄÄÄÄÄÄ %R1
            705159           18081          100737
       + 
           15449995    10   14279770    9   6603890    8
         - ÄÄÄÄÄÄÄÄ %R1   - ÄÄÄÄÄÄÄÄ %R1  - ÄÄÄÄÄÄÄ %R1
            235053           235053          100737
       + 
           409930    7   37340389    6   34893715    5
         - ÄÄÄÄÄÄ %R1  - ÄÄÄÄÄÄÄÄ %R1  - ÄÄÄÄÄÄÄÄ %R1
            6027          705159          705159
       + 
           26686318    4   801511    3   17206178    2
         - ÄÄÄÄÄÄÄÄ %R1  - ÄÄÄÄÄÄ %R1  - ÄÄÄÄÄÄÄÄ %R1
            705159          26117         705159
       + 
           4406102       377534
         - ÄÄÄÄÄÄÄ %R1 + ÄÄÄÄÄÄ
            705159       705159
       ]
     ,

     [%R2,

         1184459    19   2335702    18   5460230    17
         ÄÄÄÄÄÄÄ %R2   - ÄÄÄÄÄÄÄ %R2   - ÄÄÄÄÄÄÄ %R2
         1645371          548457          182819
       + 
         79900378    16   43953929    15   13420192    14
         ÄÄÄÄÄÄÄÄ %R2   + ÄÄÄÄÄÄÄÄ %R2   + ÄÄÄÄÄÄÄÄ %R2
          1645371          548457           182819
       + 
         553986    13   193381378    12   35978916    11
         ÄÄÄÄÄÄ %R2   + ÄÄÄÄÄÄÄÄÄ %R2   + ÄÄÄÄÄÄÄÄ %R2
          3731           1645371           182819
       + 
         358660781    10   271667666    9   118784873    8
         ÄÄÄÄÄÄÄÄÄ %R2   + ÄÄÄÄÄÄÄÄÄ %R2  + ÄÄÄÄÄÄÄÄÄ %R2
          1645371           1645371           548457
       + 
         337505020    7   1389370    6   688291    5
         ÄÄÄÄÄÄÄÄÄ %R2  + ÄÄÄÄÄÄÄ %R2  + ÄÄÄÄÄÄ %R2
          1645371          11193          4459
       + 
         3378002    4   140671876    3   32325724    2
         ÄÄÄÄÄÄÄ %R2  + ÄÄÄÄÄÄÄÄÄ %R2  + ÄÄÄÄÄÄÄÄ %R2
          42189          1645371          548457
       + 
           8270       9741532
         - ÄÄÄÄ %R2 - ÄÄÄÄÄÄÄ
            343       1645371
       ,

            91729    19   487915    18   4114333    17
         - ÄÄÄÄÄÄ %R2   + ÄÄÄÄÄÄ %R2   + ÄÄÄÄÄÄÄ %R2
           705159         705159          705159
       + 
           1276987    16   13243117    15   16292173    14
         - ÄÄÄÄÄÄÄ %R2   - ÄÄÄÄÄÄÄÄ %R2   - ÄÄÄÄÄÄÄÄ %R2
            235053          705159           705159
       + 
           26536060    13   722714    12   5382578    11
         - ÄÄÄÄÄÄÄÄ %R2   - ÄÄÄÄÄÄ %R2   - ÄÄÄÄÄÄÄ %R2
            705159           18081          100737
       + 
           15449995    10   14279770    9   6603890    8
         - ÄÄÄÄÄÄÄÄ %R2   - ÄÄÄÄÄÄÄÄ %R2  - ÄÄÄÄÄÄÄ %R2
            235053           235053          100737
       + 
           409930    7   37340389    6   34893715    5
         - ÄÄÄÄÄÄ %R2  - ÄÄÄÄÄÄÄÄ %R2  - ÄÄÄÄÄÄÄÄ %R2
            6027          705159          705159
       + 
           26686318    4   801511    3   17206178    2
         - ÄÄÄÄÄÄÄÄ %R2  - ÄÄÄÄÄÄ %R2  - ÄÄÄÄÄÄÄÄ %R2
            705159          26117         705159
       + 
           4406102       377534
         - ÄÄÄÄÄÄÄ %R2 + ÄÄÄÄÄÄ
            705159       705159
       ]
     ,

     [%R3,

         1184459    19   2335702    18   5460230    17
         ÄÄÄÄÄÄÄ %R3   - ÄÄÄÄÄÄÄ %R3   - ÄÄÄÄÄÄÄ %R3
         1645371          548457          182819
       + 
         79900378    16   43953929    15   13420192    14
         ÄÄÄÄÄÄÄÄ %R3   + ÄÄÄÄÄÄÄÄ %R3   + ÄÄÄÄÄÄÄÄ %R3
          1645371          548457           182819
       + 
         553986    13   193381378    12   35978916    11
         ÄÄÄÄÄÄ %R3   + ÄÄÄÄÄÄÄÄÄ %R3   + ÄÄÄÄÄÄÄÄ %R3
          3731           1645371           182819
       + 
         358660781    10   271667666    9   118784873    8
         ÄÄÄÄÄÄÄÄÄ %R3   + ÄÄÄÄÄÄÄÄÄ %R3  + ÄÄÄÄÄÄÄÄÄ %R3
          1645371           1645371           548457
       + 
         337505020    7   1389370    6   688291    5
         ÄÄÄÄÄÄÄÄÄ %R3  + ÄÄÄÄÄÄÄ %R3  + ÄÄÄÄÄÄ %R3
          1645371          11193          4459
       + 
         3378002    4   140671876    3   32325724    2
         ÄÄÄÄÄÄÄ %R3  + ÄÄÄÄÄÄÄÄÄ %R3  + ÄÄÄÄÄÄÄÄ %R3
          42189          1645371          548457
       + 
           8270       9741532
         - ÄÄÄÄ %R3 - ÄÄÄÄÄÄÄ
            343       1645371
       ,

            91729    19   487915    18   4114333    17
         - ÄÄÄÄÄÄ %R3   + ÄÄÄÄÄÄ %R3   + ÄÄÄÄÄÄÄ %R3
           705159         705159          705159
       + 
           1276987    16   13243117    15   16292173    14
         - ÄÄÄÄÄÄÄ %R3   - ÄÄÄÄÄÄÄÄ %R3   - ÄÄÄÄÄÄÄÄ %R3
            235053          705159           705159
       + 
           26536060    13   722714    12   5382578    11
         - ÄÄÄÄÄÄÄÄ %R3   - ÄÄÄÄÄÄ %R3   - ÄÄÄÄÄÄÄ %R3
            705159           18081          100737
       + 
           15449995    10   14279770    9   6603890    8
         - ÄÄÄÄÄÄÄÄ %R3   - ÄÄÄÄÄÄÄÄ %R3  - ÄÄÄÄÄÄÄ %R3
            235053           235053          100737
       + 
           409930    7   37340389    6   34893715    5
         - ÄÄÄÄÄÄ %R3  - ÄÄÄÄÄÄÄÄ %R3  - ÄÄÄÄÄÄÄÄ %R3
            6027          705159          705159
       + 
           26686318    4   801511    3   17206178    2
         - ÄÄÄÄÄÄÄÄ %R3  - ÄÄÄÄÄÄ %R3  - ÄÄÄÄÄÄÄÄ %R3
            705159          26117         705159
       + 
           4406102       377534
         - ÄÄÄÄÄÄÄ %R3 + ÄÄÄÄÄÄ
            705159       705159
       ]
     ,

     [%R4,

         1184459    19   2335702    18   5460230    17
         ÄÄÄÄÄÄÄ %R4   - ÄÄÄÄÄÄÄ %R4   - ÄÄÄÄÄÄÄ %R4
         1645371          548457          182819
       + 
         79900378    16   43953929    15   13420192    14
         ÄÄÄÄÄÄÄÄ %R4   + ÄÄÄÄÄÄÄÄ %R4   + ÄÄÄÄÄÄÄÄ %R4
          1645371          548457           182819
       + 
         553986    13   193381378    12   35978916    11
         ÄÄÄÄÄÄ %R4   + ÄÄÄÄÄÄÄÄÄ %R4   + ÄÄÄÄÄÄÄÄ %R4
          3731           1645371           182819
       + 
         358660781    10   271667666    9   118784873    8
         ÄÄÄÄÄÄÄÄÄ %R4   + ÄÄÄÄÄÄÄÄÄ %R4  + ÄÄÄÄÄÄÄÄÄ %R4
          1645371           1645371           548457
       + 
         337505020    7   1389370    6   688291    5
         ÄÄÄÄÄÄÄÄÄ %R4  + ÄÄÄÄÄÄÄ %R4  + ÄÄÄÄÄÄ %R4
          1645371          11193          4459
       + 
         3378002    4   140671876    3   32325724    2
         ÄÄÄÄÄÄÄ %R4  + ÄÄÄÄÄÄÄÄÄ %R4  + ÄÄÄÄÄÄÄÄ %R4
          42189          1645371          548457
       + 
           8270       9741532
         - ÄÄÄÄ %R4 - ÄÄÄÄÄÄÄ
            343       1645371
       ,

            91729    19   487915    18   4114333    17
         - ÄÄÄÄÄÄ %R4   + ÄÄÄÄÄÄ %R4   + ÄÄÄÄÄÄÄ %R4
           705159         705159          705159
       + 
           1276987    16   13243117    15   16292173    14
         - ÄÄÄÄÄÄÄ %R4   - ÄÄÄÄÄÄÄÄ %R4   - ÄÄÄÄÄÄÄÄ %R4
            235053          705159           705159
       + 
           26536060    13   722714    12   5382578    11
         - ÄÄÄÄÄÄÄÄ %R4   - ÄÄÄÄÄÄ %R4   - ÄÄÄÄÄÄÄ %R4
            705159           18081          100737
       + 
           15449995    10   14279770    9   6603890    8
         - ÄÄÄÄÄÄÄÄ %R4   - ÄÄÄÄÄÄÄÄ %R4  - ÄÄÄÄÄÄÄ %R4
            235053           235053          100737
       + 
           409930    7   37340389    6   34893715    5
         - ÄÄÄÄÄÄ %R4  - ÄÄÄÄÄÄÄÄ %R4  - ÄÄÄÄÄÄÄÄ %R4
            6027          705159          705159
       + 
           26686318    4   801511    3   17206178    2
         - ÄÄÄÄÄÄÄÄ %R4  - ÄÄÄÄÄÄ %R4  - ÄÄÄÄÄÄÄÄ %R4
            705159          26117         705159
       + 
           4406102       377534
         - ÄÄÄÄÄÄÄ %R4 + ÄÄÄÄÄÄ
            705159       705159
       ]
     ,

     [%R5,

         1184459    19   2335702    18   5460230    17
         ÄÄÄÄÄÄÄ %R5   - ÄÄÄÄÄÄÄ %R5   - ÄÄÄÄÄÄÄ %R5
         1645371          548457          182819
       + 
         79900378    16   43953929    15   13420192    14
         ÄÄÄÄÄÄÄÄ %R5   + ÄÄÄÄÄÄÄÄ %R5   + ÄÄÄÄÄÄÄÄ %R5
          1645371          548457           182819
       + 
         553986    13   193381378    12   35978916    11
         ÄÄÄÄÄÄ %R5   + ÄÄÄÄÄÄÄÄÄ %R5   + ÄÄÄÄÄÄÄÄ %R5
          3731           1645371           182819
       + 
         358660781    10   271667666    9   118784873    8
         ÄÄÄÄÄÄÄÄÄ %R5   + ÄÄÄÄÄÄÄÄÄ %R5  + ÄÄÄÄÄÄÄÄÄ %R5
          1645371           1645371           548457
       + 
         337505020    7   1389370    6   688291    5
         ÄÄÄÄÄÄÄÄÄ %R5  + ÄÄÄÄÄÄÄ %R5  + ÄÄÄÄÄÄ %R5
          1645371          11193          4459
       + 
         3378002    4   140671876    3   32325724    2
         ÄÄÄÄÄÄÄ %R5  + ÄÄÄÄÄÄÄÄÄ %R5  + ÄÄÄÄÄÄÄÄ %R5
          42189          1645371          548457
       + 
           8270       9741532
         - ÄÄÄÄ %R5 - ÄÄÄÄÄÄÄ
            343       1645371
       ,

            91729    19   487915    18   4114333    17
         - ÄÄÄÄÄÄ %R5   + ÄÄÄÄÄÄ %R5   + ÄÄÄÄÄÄÄ %R5
           705159         705159          705159
       + 
           1276987    16   13243117    15   16292173    14
         - ÄÄÄÄÄÄÄ %R5   - ÄÄÄÄÄÄÄÄ %R5   - ÄÄÄÄÄÄÄÄ %R5
            235053          705159           705159
       + 
           26536060    13   722714    12   5382578    11
         - ÄÄÄÄÄÄÄÄ %R5   - ÄÄÄÄÄÄ %R5   - ÄÄÄÄÄÄÄ %R5
            705159           18081          100737
       + 
           15449995    10   14279770    9   6603890    8
         - ÄÄÄÄÄÄÄÄ %R5   - ÄÄÄÄÄÄÄÄ %R5  - ÄÄÄÄÄÄÄ %R5
            235053           235053          100737
       + 
           409930    7   37340389    6   34893715    5
         - ÄÄÄÄÄÄ %R5  - ÄÄÄÄÄÄÄÄ %R5  - ÄÄÄÄÄÄÄÄ %R5
            6027          705159          705159
       + 
           26686318    4   801511    3   17206178    2
         - ÄÄÄÄÄÄÄÄ %R5  - ÄÄÄÄÄÄ %R5  - ÄÄÄÄÄÄÄÄ %R5
            705159          26117         705159
       + 
           4406102       377534
         - ÄÄÄÄÄÄÄ %R5 + ÄÄÄÄÄÄ
            705159       705159
       ]
     ,

     [%R6,

         1184459    19   2335702    18   5460230    17
         ÄÄÄÄÄÄÄ %R6   - ÄÄÄÄÄÄÄ %R6   - ÄÄÄÄÄÄÄ %R6
         1645371          548457          182819
       + 
         79900378    16   43953929    15   13420192    14
         ÄÄÄÄÄÄÄÄ %R6   + ÄÄÄÄÄÄÄÄ %R6   + ÄÄÄÄÄÄÄÄ %R6
          1645371          548457           182819
       + 
         553986    13   193381378    12   35978916    11
         ÄÄÄÄÄÄ %R6   + ÄÄÄÄÄÄÄÄÄ %R6   + ÄÄÄÄÄÄÄÄ %R6
          3731           1645371           182819
       + 
         358660781    10   271667666    9   118784873    8
         ÄÄÄÄÄÄÄÄÄ %R6   + ÄÄÄÄÄÄÄÄÄ %R6  + ÄÄÄÄÄÄÄÄÄ %R6
          1645371           1645371           548457
       + 
         337505020    7   1389370    6   688291    5
         ÄÄÄÄÄÄÄÄÄ %R6  + ÄÄÄÄÄÄÄ %R6  + ÄÄÄÄÄÄ %R6
          1645371          11193          4459
       + 
         3378002    4   140671876    3   32325724    2
         ÄÄÄÄÄÄÄ %R6  + ÄÄÄÄÄÄÄÄÄ %R6  + ÄÄÄÄÄÄÄÄ %R6
          42189          1645371          548457
       + 
           8270       9741532
         - ÄÄÄÄ %R6 - ÄÄÄÄÄÄÄ
            343       1645371
       ,

            91729    19   487915    18   4114333    17
         - ÄÄÄÄÄÄ %R6   + ÄÄÄÄÄÄ %R6   + ÄÄÄÄÄÄÄ %R6
           705159         705159          705159
       + 
           1276987    16   13243117    15   16292173    14
         - ÄÄÄÄÄÄÄ %R6   - ÄÄÄÄÄÄÄÄ %R6   - ÄÄÄÄÄÄÄÄ %R6
            235053          705159           705159
       + 
           26536060    13   722714    12   5382578    11
         - ÄÄÄÄÄÄÄÄ %R6   - ÄÄÄÄÄÄ %R6   - ÄÄÄÄÄÄÄ %R6
            705159           18081          100737
       + 
           15449995    10   14279770    9   6603890    8
         - ÄÄÄÄÄÄÄÄ %R6   - ÄÄÄÄÄÄÄÄ %R6  - ÄÄÄÄÄÄÄ %R6
            235053           235053          100737
       + 
           409930    7   37340389    6   34893715    5
         - ÄÄÄÄÄÄ %R6  - ÄÄÄÄÄÄÄÄ %R6  - ÄÄÄÄÄÄÄÄ %R6
            6027          705159          705159
       + 
           26686318    4   801511    3   17206178    2
         - ÄÄÄÄÄÄÄÄ %R6  - ÄÄÄÄÄÄ %R6  - ÄÄÄÄÄÄÄÄ %R6
            705159          26117         705159
       + 
           4406102       377534
         - ÄÄÄÄÄÄÄ %R6 + ÄÄÄÄÄÄ
            705159       705159
       ]
     ,

     [%R7,

         1184459    19   2335702    18   5460230    17
         ÄÄÄÄÄÄÄ %R7   - ÄÄÄÄÄÄÄ %R7   - ÄÄÄÄÄÄÄ %R7
         1645371          548457          182819
       + 
         79900378    16   43953929    15   13420192    14
         ÄÄÄÄÄÄÄÄ %R7   + ÄÄÄÄÄÄÄÄ %R7   + ÄÄÄÄÄÄÄÄ %R7
          1645371          548457           182819
       + 
         553986    13   193381378    12   35978916    11
         ÄÄÄÄÄÄ %R7   + ÄÄÄÄÄÄÄÄÄ %R7   + ÄÄÄÄÄÄÄÄ %R7
          3731           1645371           182819
       + 
         358660781    10   271667666    9   118784873    8
         ÄÄÄÄÄÄÄÄÄ %R7   + ÄÄÄÄÄÄÄÄÄ %R7  + ÄÄÄÄÄÄÄÄÄ %R7
          1645371           1645371           548457
       + 
         337505020    7   1389370    6   688291    5
         ÄÄÄÄÄÄÄÄÄ %R7  + ÄÄÄÄÄÄÄ %R7  + ÄÄÄÄÄÄ %R7
          1645371          11193          4459
       + 
         3378002    4   140671876    3   32325724    2
         ÄÄÄÄÄÄÄ %R7  + ÄÄÄÄÄÄÄÄÄ %R7  + ÄÄÄÄÄÄÄÄ %R7
          42189          1645371          548457
       + 
           8270       9741532
         - ÄÄÄÄ %R7 - ÄÄÄÄÄÄÄ
            343       1645371
       ,

            91729    19   487915    18   4114333    17
         - ÄÄÄÄÄÄ %R7   + ÄÄÄÄÄÄ %R7   + ÄÄÄÄÄÄÄ %R7
           705159         705159          705159
       + 
           1276987    16   13243117    15   16292173    14
         - ÄÄÄÄÄÄÄ %R7   - ÄÄÄÄÄÄÄÄ %R7   - ÄÄÄÄÄÄÄÄ %R7
            235053          705159           705159
       + 
           26536060    13   722714    12   5382578    11
         - ÄÄÄÄÄÄÄÄ %R7   - ÄÄÄÄÄÄ %R7   - ÄÄÄÄÄÄÄ %R7
            705159           18081          100737
       + 
           15449995    10   14279770    9   6603890    8
         - ÄÄÄÄÄÄÄÄ %R7   - ÄÄÄÄÄÄÄÄ %R7  - ÄÄÄÄÄÄÄ %R7
            235053           235053          100737
       + 
           409930    7   37340389    6   34893715    5
         - ÄÄÄÄÄÄ %R7  - ÄÄÄÄÄÄÄÄ %R7  - ÄÄÄÄÄÄÄÄ %R7
            6027          705159          705159
       + 
           26686318    4   801511    3   17206178    2
         - ÄÄÄÄÄÄÄÄ %R7  - ÄÄÄÄÄÄ %R7  - ÄÄÄÄÄÄÄÄ %R7
            705159          26117         705159
       + 
           4406102       377534
         - ÄÄÄÄÄÄÄ %R7 + ÄÄÄÄÄÄ
            705159       705159
       ]
     ,

     [%R8,

         1184459    19   2335702    18   5460230    17
         ÄÄÄÄÄÄÄ %R8   - ÄÄÄÄÄÄÄ %R8   - ÄÄÄÄÄÄÄ %R8
         1645371          548457          182819
       + 
         79900378    16   43953929    15   13420192    14
         ÄÄÄÄÄÄÄÄ %R8   + ÄÄÄÄÄÄÄÄ %R8   + ÄÄÄÄÄÄÄÄ %R8
          1645371          548457           182819
       + 
         553986    13   193381378    12   35978916    11
         ÄÄÄÄÄÄ %R8   + ÄÄÄÄÄÄÄÄÄ %R8   + ÄÄÄÄÄÄÄÄ %R8
          3731           1645371           182819
       + 
         358660781    10   271667666    9   118784873    8
         ÄÄÄÄÄÄÄÄÄ %R8   + ÄÄÄÄÄÄÄÄÄ %R8  + ÄÄÄÄÄÄÄÄÄ %R8
          1645371           1645371           548457
       + 
         337505020    7   1389370    6   688291    5
         ÄÄÄÄÄÄÄÄÄ %R8  + ÄÄÄÄÄÄÄ %R8  + ÄÄÄÄÄÄ %R8
          1645371          11193          4459
       + 
         3378002    4   140671876    3   32325724    2
         ÄÄÄÄÄÄÄ %R8  + ÄÄÄÄÄÄÄÄÄ %R8  + ÄÄÄÄÄÄÄÄ %R8
          42189          1645371          548457
       + 
           8270       9741532
         - ÄÄÄÄ %R8 - ÄÄÄÄÄÄÄ
            343       1645371
       ,

            91729    19   487915    18   4114333    17
         - ÄÄÄÄÄÄ %R8   + ÄÄÄÄÄÄ %R8   + ÄÄÄÄÄÄÄ %R8
           705159         705159          705159
       + 
           1276987    16   13243117    15   16292173    14
         - ÄÄÄÄÄÄÄ %R8   - ÄÄÄÄÄÄÄÄ %R8   - ÄÄÄÄÄÄÄÄ %R8
            235053          705159           705159
       + 
           26536060    13   722714    12   5382578    11
         - ÄÄÄÄÄÄÄÄ %R8   - ÄÄÄÄÄÄ %R8   - ÄÄÄÄÄÄÄ %R8
            705159           18081          100737
       + 
           15449995    10   14279770    9   6603890    8
         - ÄÄÄÄÄÄÄÄ %R8   - ÄÄÄÄÄÄÄÄ %R8  - ÄÄÄÄÄÄÄ %R8
            235053           235053          100737
       + 
           409930    7   37340389    6   34893715    5
         - ÄÄÄÄÄÄ %R8  - ÄÄÄÄÄÄÄÄ %R8  - ÄÄÄÄÄÄÄÄ %R8
            6027          705159          705159
       + 
           26686318    4   801511    3   17206178    2
         - ÄÄÄÄÄÄÄÄ %R8  - ÄÄÄÄÄÄ %R8  - ÄÄÄÄÄÄÄÄ %R8
            705159          26117         705159
       + 
           4406102       377534
         - ÄÄÄÄÄÄÄ %R8 + ÄÄÄÄÄÄ
            705159       705159
       ]
     ]
           Type: List List RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty11}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty11}{ZeroDimSolvePkgXmpPagePatch11}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty11}{\showpaste}
\tab{5}\spadcommand{lr := realSolve(lp)$pack\free{lp }\free{pack }\bound{lr }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch12}
\begin{paste}{ZeroDimSolvePkgXmpPageFull12}{ZeroDimSolvePkgXmpPageEmpty12}
\pastebutton{ZeroDimSolvePkgXmpPageFull12}{\hidepaste}
\tab{5}\spadcommand{\# lr\free{lr }}
\indentrel{3}\begin{verbatim}
   (12)  8
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty12}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty12}{ZeroDimSolvePkgXmpPagePatch12}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty12}{\showpaste}
\tab{5}\spadcommand{\# lr\free{lr }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch13}
\begin{paste}{ZeroDimSolvePkgXmpPageFull13}{ZeroDimSolvePkgXmpPageEmpty13}
\pastebutton{ZeroDimSolvePkgXmpPageFull13}{\hidepaste}
\tab{5}\spadcommand{[[approximate(r,1/1000000) for r in point] for point in lr]\free{lr }}
\indentrel{3}\begin{verbatim}
   (13)
   [
        10048059
     [- ÄÄÄÄÄÄÄÄ,
         2097152

        450305731698538794352439791383896641459673197621_
         17682193358812083855163140589245671760914236296_
         95777403099833360761048898228916578137094309838_
         59733113720258484693913237615701950676035760116_
         59174549868153820987890948515234203928112931261_
         41329856546977145464661495487825919941188447041_
         72244049192156726354215802806143775884436463441_
         0045253024786561923163288214175
      /
        450305728302524548851651180698582663508310069375_
         73204652805547068656449495775099168672018894380_
         90408354817931718593862797624551518983570793048_
         77442429148870882984032418920030143612331486020_
         08214437337907553112436329198648954217042289495_
         71290016119498807957023663865443069392027148979_
         68826671232335604349152343406892427528041733857_
         4817381189277066143312396681216
       ,

        210626076882347507389479868048601659624960714869_
         06855387636837150206396808586496507900558895056_
         46893309447097099937802187329095325898785247249_
         02071750498366048207515661873872451468533306001_
         12029646351663813515432559822002503052839810868_
         37110614842307026091211297929876896285681830479_
         05476005638076266490561846205530604781619178201_
         15887037891389881895
      /
        210626060949846419247211380481647417534196295329_
         64341024139031423687579676852738885855909759652_
         11778862189872881953943640246297357061959812326_
         10365979902512686325867656720234210687703171018_
         42474841814232889218376812370627084702957062184_
         85928867400771937828499200923760593314168901000_
         66637389634759811822855673103707202647449677622_
         83837629939232800768
       ]
     ,

        2563013
     [- ÄÄÄÄÄÄÄ,
        2097152

       -
           261134617679192778969861769323775771923825996_
            30635417819227523304401898996680729283384907_
            68623593207442125925986733815932243504809294_
            83752303023733723680666816744617300172727135_
            3311571242897
         /
           116522540050522253058398191600458914375722661_
            02768589900087901348199149409224137539839713_
            94019523433320408139928153188829495755455163_
            96341761930839597754479714023146923426903492_
            1938055593984
       ,

        357259455027591722109658872961578827299851705467_
         56032395781981410060340917352828265906219023044_
         66963941971038923304526273329316373757450061978_
         9892286110976997087250466235373
      /
        103954826934559893687707124483402605580081455112_
         01705922005223665917594096594864423391410294529_
         50265179989960104811875822530205346505131581243_
         9017247289173865014702966308864
       ]
     ,

        1715967
     [- ÄÄÄÄÄÄÄ,
        2097152

       -
           421309353378430352108483951797708239037726150_
            39695862248289984366060306560763593745648137_
            73498376603121267822565801436206939519951465_
            18222580524697287410022543952491
         /
           944181414418537445864969203434922405243659747_
            09662536639306419607958058825854931998401916_
            99917659443264824641135187383583888147867340_
            19307857605820364195856822304768
       ,

        763583334711264422251562542441083122534747566900_
         85893388341621725019049943763467308768090428452_
         08919919925302105720971453918982731389072591403_
         5
      /
        262418876408609719978429761047806663393423046789_
         58516022785809785037845492057884990196406022669_
         66026891580103543567625039018629887141284916756_
         48
       ]
     ,

         437701
     [- ÄÄÄÄÄÄÄ,
        2097152

        168310690863834958832217233265422591356298631318_
         19510314527501614414974734553281507213648683555_
         79646781603507777199075077835213366484533654913_
         83623741304759
      /
        168310686809521338900170998270591363896307766873_
         12261111677851880049074252262986803258878109626_
         14140298597366984264887998908377068799998454233_
         81649008099328
       ,

        496155010983501018642268101342210873595871480100_
         37606397079680966469128267084728344431172391721_
         9104249213450966312411133
      /
        496154987275773831550919207821020902985289711861_
         10971262363840408293765926191431317025486746479_
         2718363492160482442215424
       ]
     ,

       222801
     [ÄÄÄÄÄÄÄ,
      2097152

       -
           899488488040242826510759512197069142713604569_
            25419782755730018652137599215881377166961263_
            49101655220195142994932299137183241705867672_
            383477
         /
           116788999866502637217776510069188858270896996_
            02299347696908357524570777794164352094737678_
            66507769405888942764587718542434255625992456_
            372224
       ,

       -
           238970488813315687832080154437380839561277150_
            92084910198474529918855095465195254678390166_
            13593999693886640036283570552321155037871291_
            458703265
         /
           535548727364509632609040328668993190598822544_
            46854114332215938336811929575628336714686542_
            90340746993656285925599117602120446183443145_
            479421952
       ]
     ,

       765693
     [ÄÄÄÄÄÄÄ,
      2097152

        855896921981671626787324476117819808872469895861_
         66701402137657543220023032516857861186783308402_
         03328837654339523418704917749518340772512899000_
         391009630373148561
      /
        294144244553301079097642841137639349981558021594_
         58569179064525354957230138568189417023302287798_
         90141296236721138154231997238917322156711965244_
         4639331719460159488
       ,

       -
           205761823058257210124765032486024256111130258_
            15435888088439236627675493822416593627122907_
            77612800192921420574408948085193743688582762_
            2246433251878894899015
         /
           267159820332573553809795235350145022057631375_
            98908350970917225206427101987719026671839489_
            06289863714759678360292483949204616471537777_
            775324180661095366656
       ]
     ,

      5743879
     [ÄÄÄÄÄÄÄ,
      2097152

        107628881696890684795554639477357020817145672494_
         26186140236631235747689608504342639713980725465_
         92772662158833449797698617455397887562900072984_
         76800060834355318980169340872720504761255988923_
         27575638305286889535354218094827710589175426028_
         90060941949620874083007858366669453501766248414_
         88732463225
      /
        313176895708031794664846194002355204419037661345_
         85849862285496319161966016162197817656155325322_
         94746529648276430583810894079374566460757823146_
         88858119555602920851521883888320031865840746939_
         94260632605898286123092315966691297079864813198_
         51571942927230340622934023923486703042068153044_
         0845099008
       ,

       -
           211328669918575091836412047556545843787017248_
            98654859943898281353352644446652845575264927_
            34931691731407872701432935503473348172076098_
            72054584900878007756416053431789468836611952_
            97399805029441626685500981279619504962102219_
            42878089359674925850594427768502251789758706_
            752831632503615
         /
           162761558493798758024290662434710458088914446_
            61684597180431538394083725255333098080703636_
            99585502216011211087103263609551026027769414_
            08739114812622116813978168258743807532259146_
            61319399754572005223498385689642856344480185_
            62038272378787354460106106141518010935617205_
            1706396253618176
       ]
     ,

      19739877
     [ÄÄÄÄÄÄÄÄ,
       2097152

       -
           299724993683270330379901580486152094921504038_
            75007071777012857667201925305794224789535660_
            24359860143101547801638082771611160372212874_
            84777803580987284314922548423836585801362934_
            17053217025823333509180096017899370239859353_
            04900460493389873837030853410347089908880814_
            85398113201846458245880061539477074169948729_
            58759602107502158919488144768548710315309312_
            95467332190133702671098200902282300510751860_
            71859284570302778073977965258138627622392869_
            96106809728023675
         /
           230843327485227859072891008119181102390650414_
            13214326461239367948739333192706089607021381_
            93417647898360620229519176632937631786851455_
            01476602720625902225250555174182368889688380_
            66366025744317604722402920931967294751602472_
            68834121141893318848728661844434927287285112_
            89708076755286489505658586403317856591038706_
            50061128015164035227410373609905560544769495_
            27059227070809593049491257519554708879259595_
            52929920110858560812556635485429471554031675_
            979542656381353984
       ,

       -
           512818926354822848909627639786894008060093841_
            06630804594079663358450092641094905204598253_
            16250084723010047035024497436523038925818959_
            28931293158470135392762143543439867426304729_
            39091228501338519906964902315660943719943337_
            95070782624011727587749989296611277318372294_
            62420711653791043655457414608288470130554391_
            26204193548854107359401577758966028223645758_
            64611831512943973974715166920465061850603762_
            87516256195847052412587282839139194642913955
         /
           228828193977843933053120879318129047118363109_
            24553689903863908242435094636442362497730806_
            47438987739144921607794682653851741189091711_
            74186814511497833728419182249767586835872948_
            66447308566225526872092037244118004814057028_
            37198310642291275676195774614443815996713502_
            62939174978359004147086012775237299648862774_
            26724876224800632688088893248918508424949343_
            47337603075939980268208482904859678177751444_
            65749979827872616963053217673201717237252096
       ]
     ]
                       Type: List List Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty13}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty13}{ZeroDimSolvePkgXmpPagePatch13}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty13}{\showpaste}
\tab{5}\spadcommand{[[approximate(r,1/1000000) for r in point] for point in lr]\free{lr }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch14}
\begin{paste}{ZeroDimSolvePkgXmpPageFull14}{ZeroDimSolvePkgXmpPageEmpty14}
\pastebutton{ZeroDimSolvePkgXmpPageFull14}{\hidepaste}
\tab{5}\spadcommand{lpr := positiveSolve(lp)$pack\free{lp }\free{pack }\bound{lpr }}
\indentrel{3}\begin{verbatim}
   (14)  []
           Type: List List RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty14}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty14}{ZeroDimSolvePkgXmpPagePatch14}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty14}{\showpaste}
\tab{5}\spadcommand{lpr := positiveSolve(lp)$pack\free{lp }\free{pack }\bound{lpr }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch15}
\begin{paste}{ZeroDimSolvePkgXmpPageFull15}{ZeroDimSolvePkgXmpPageEmpty15}
\pastebutton{ZeroDimSolvePkgXmpPageFull15}{\hidepaste}
\tab{5}\spadcommand{f0 := x**3 + y + z + t- 1\bound{f0 }}
\indentrel{3}\begin{verbatim}
                  3
   (15)  z + y + x  + t - 1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty15}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty15}{ZeroDimSolvePkgXmpPagePatch15}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty15}{\showpaste}
\tab{5}\spadcommand{f0 := x**3 + y + z + t- 1\bound{f0 }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch16}
\begin{paste}{ZeroDimSolvePkgXmpPageFull16}{ZeroDimSolvePkgXmpPageEmpty16}
\pastebutton{ZeroDimSolvePkgXmpPageFull16}{\hidepaste}
\tab{5}\spadcommand{f1 := x + y**3 + z + t -1\bound{f1 }}
\indentrel{3}\begin{verbatim}
              3
   (16)  z + y  + x + t - 1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty16}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty16}{ZeroDimSolvePkgXmpPagePatch16}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty16}{\showpaste}
\tab{5}\spadcommand{f1 := x + y**3 + z + t -1\bound{f1 }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch17}
\begin{paste}{ZeroDimSolvePkgXmpPageFull17}{ZeroDimSolvePkgXmpPageEmpty17}
\pastebutton{ZeroDimSolvePkgXmpPageFull17}{\hidepaste}
\tab{5}\spadcommand{f2 := x + y + z**3 + t-1\bound{f2 }}
\indentrel{3}\begin{verbatim}
          3
   (17)  z  + y + x + t - 1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty17}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty17}{ZeroDimSolvePkgXmpPagePatch17}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty17}{\showpaste}
\tab{5}\spadcommand{f2 := x + y + z**3 + t-1\bound{f2 }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch18}
\begin{paste}{ZeroDimSolvePkgXmpPageFull18}{ZeroDimSolvePkgXmpPageEmpty18}
\pastebutton{ZeroDimSolvePkgXmpPageFull18}{\hidepaste}
\tab{5}\spadcommand{f3 := x + y + z + t**3 -1\bound{f3 }}
\indentrel{3}\begin{verbatim}
                      3
   (18)  z + y + x + t  - 1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty18}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty18}{ZeroDimSolvePkgXmpPagePatch18}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty18}{\showpaste}
\tab{5}\spadcommand{f3 := x + y + z + t**3 -1\bound{f3 }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch19}
\begin{paste}{ZeroDimSolvePkgXmpPageFull19}{ZeroDimSolvePkgXmpPageEmpty19}
\pastebutton{ZeroDimSolvePkgXmpPageFull19}{\hidepaste}
\tab{5}\spadcommand{lf := [f0, f1, f2, f3]\free{f0 }\free{f1 }\free{f2 }\free{f3 }\bound{lf }}
\indentrel{3}\begin{verbatim}
   (19)
             3               3
   [z + y + x  + t - 1, z + y  + x + t - 1,
     3                               3
    z  + y + x + t - 1, z + y + x + t  - 1]
                          Type: List Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty19}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty19}{ZeroDimSolvePkgXmpPagePatch19}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty19}{\showpaste}
\tab{5}\spadcommand{lf := [f0, f1, f2, f3]\free{f0 }\free{f1 }\free{f2 }\free{f3 }\bound{lf }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch20}
\begin{paste}{ZeroDimSolvePkgXmpPageFull20}{ZeroDimSolvePkgXmpPageEmpty20}
\pastebutton{ZeroDimSolvePkgXmpPageFull20}{\hidepaste}
\tab{5}\spadcommand{lts := triangSolve(lf)$pack\free{lf }\free{pack }\bound{lts }}
\indentrel{3}\begin{verbatim}
   (20)
   [
       2           3        3
     {t  + t + 1, z  - z - t  + t,

                 3      2
         (3z + 3t  - 3)y
       + 
            2      3           6     3            3      2
         (3z  + (6t  - 6)z + 3t  - 6t  + 3)y + (3t  - 3)z
       + 
            6     3          9     6     3
         (3t  - 6t  + 3)z + t  - 3t  + 5t  - 3t
       ,
      x + y + z}
     ,

       16     13     10     7      4      2
     {t   - 6t   + 9t   + 4t  + 15t  - 54t  + 27,

                     15            14             13
             4907232t   + 40893984t   - 115013088t
           + 
                      12            11             10
             22805712t   + 36330336t   + 162959040t
           + 
                         9             8             7
             - 159859440t  - 156802608t  + 117168768t
           + 
                       6             5             4
             126282384t  - 129351600t  + 306646992t
           + 
                       3              2
             475302816t  - 1006837776t  - 237269088t
           + 
             480716208
        *
           z
       + 
            54       51        48      46         45
         48t   - 912t   + 8232t   - 72t   - 46848t
       + 
              43          42        40          39
         1152t   + 186324t   - 3780t   - 543144t
       + 
                38         37           36         35
         - 3168t   - 21384t   + 1175251t   + 41184t
       + 
                34           33          32           31
         278003t   - 1843242t   - 301815t   - 1440726t
       + 
                 30           29           28          27
         1912012t   + 1442826t   + 4696262t   - 922481t
       + 
                   26            25          24
         - 4816188t   - 10583524t   - 208751t
       + 
                  23            22          21
         11472138t   + 16762859t   - 857663t
       + 
                    20            19           18
         - 19328175t   - 18270421t   + 4914903t
       + 
                  17            16           15
         22483044t   + 12926517t   - 8605511t
       + 
                    14           13           12
         - 17455518t   - 5014597t   + 8108814t
       + 
                 11          10           9           8
         8465535t   + 190542t   - 4305624t  - 2226123t
       + 
                7           6          5          4
         661905t  + 1169775t  + 226260t  - 209952t
       + 
                  3
         - 141183t  + 27216t
       ,

                 3      2
         (3z + 3t  - 3)y
       + 
            2      3           6     3            3      2
         (3z  + (6t  - 6)z + 3t  - 6t  + 3)y + (3t  - 3)z
       + 
            6     3          9     6     3
         (3t  - 6t  + 3)z + t  - 3t  + 5t  - 3t
       ,
                   3
      x + y + z + t  - 1}
     ,
              2                       2
    {t,z - 1,y  - 1,x + y}, {t - 1,z,y  - 1,x + y},
            2
    {t - 1,z  - 1,z y + 1,x},

       16     13     10     7      4      2
     {t   - 6t   + 9t   + 4t  + 15t  - 54t  + 27,

                     29            28             27
             4907232t   + 40893984t   - 115013088t
           + 
                       26             25             24
             - 1730448t   - 168139584t   + 738024480t
           + 
                         23             22              21
             - 195372288t   + 315849456t   - 2567279232t
           + 
                       20              19              18
             937147968t   + 1026357696t   + 4780488240t
           + 
                          17              16
             - 2893767696t   - 5617160352t
           + 
                          15              14
             - 3427651728t   + 5001100848t
           + 
                        13              12             11
             8720098416t   + 2331732960t   - 499046544t
           + 
                           10              9
             - 16243306272t   - 9748123200t
           + 
                        8               7               6
             3927244320t  + 25257280896t  + 10348032096t
           + 
                           5               4             3
             - 17128672128t  - 14755488768t  + 544086720t
           + 
                         2
             10848188736t  + 1423614528t - 2884297248
        *
           z
       + 
              68        65         62       60          59
         - 48t   + 1152t   - 13560t   + 360t   + 103656t
       + 
                57          56         54           53
         - 7560t   - 572820t   + 71316t   + 2414556t
       + 
              52          51           50         49
         2736t   - 402876t   - 7985131t   - 49248t
       + 
                 48            47          46           45
         1431133t   + 20977409t   + 521487t   - 2697635t
       + 
                    44           43           42
         - 43763654t   - 3756573t   - 2093410t
       + 
                  41            40            39
         71546495t   + 19699032t   + 35025028t
       + 
                    38            37             36
         - 89623786t   - 77798760t   - 138654191t
       + 
                  35             34             33
         87596128t   + 235642497t   + 349607642t
       + 
                    32             31             30
         - 93299834t   - 551563167t   - 630995176t
       + 
                   29             28             27
         186818962t   + 995427468t   + 828416204t
       + 
                     26              25              24
         - 393919231t   - 1076617485t   - 1609479791t
       + 
                   23              22              21
         595738126t   + 1198787136t   + 4342832069t
       + 
                      20              19              18
         - 2075938757t   - 4390835799t   - 4822843033t
       + 
                    17              16              15
         6932747678t   + 6172196808t   + 1141517740t
       + 
                      14              13              12
         - 4981677585t   - 9819815280t   - 7404299976t
       + 
                     11               10               9
         - 157295760t   + 29124027630t   + 14856038208t
       + 
                       8               7              6
         - 16184101410t  - 26935440354t  - 3574164258t
       + 
                     5               4              3
         10271338974t  + 11191425264t  + 6869861262t
       + 
                      2
         - 9780477840t  - 3586674168t + 2884297248
       ,

               3      3      2      6      3           9
             3z  + (6t  - 6)z  + (6t  - 12t  + 3)z + 2t
           + 
                 6    3
             - 6t  + t  + 3t
        *
           y
       + 
            3      3      6      3      2
         (3t  - 3)z  + (6t  - 12t  + 6)z
       + 
            9      6      3          12     9     6     3
         (4t  - 12t  + 11t  - 3)z + t   - 4t  + 5t  - 2t
       ,
                   3
      x + y + z + t  - 1}
     ,
            2
    {t - 1,z  - 1,y,x + z},

       8    7    6     5     4     3      2
     {t  + t  + t  - 2t  - 2t  - 2t  + 19t  + 19t - 8,

                     7           6           5
             2395770t  + 3934440t  - 3902067t
           + 
                        4           3            2
             - 10084164t  - 1010448t  + 32386932t
           + 
             22413225t - 10432368
        *
           z
       + 
                  7           6           5           4
         - 463519t  + 3586833t  + 9494955t  - 8539305t
       + 
                    3            2
         - 33283098t  + 35479377t  + 46263256t - 17419896
       ,

               4      3      3       6      3      2
             3z  + (9t  - 9)z  + (12t  - 24t  + 9)z
           + 
                    3                    6      4      3
             (- 152t  + 219t - 67)z - 41t  + 57t  + 25t
           + 
             - 57t + 16
        *
           y
       + 
            3      4      6      3      3
         (3t  - 3)z  + (9t  - 18t  + 9)z
       + 
                3              2
         (- 181t  + 270t - 89)z
       + 
               6       4      3                    7
         (- 92t  + 135t  + 49t  - 135t + 43)z + 27t
       + 
              6      4       3
         - 27t  - 54t  + 396t  - 486t + 144
       ,
                   3
      x + y + z + t  - 1}
     ,
            3
    {t,z - t  + 1,y - 1,x - 1}, {t - 1,z,y,x},
    {t,z - 1,y,x}, {t,z,y - 1,x}, {t,z,y,x - 1}]
             Type: List RegularChain(Integer,[x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty20}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty20}{ZeroDimSolvePkgXmpPagePatch20}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty20}{\showpaste}
\tab{5}\spadcommand{lts := triangSolve(lf)$pack\free{lf }\free{pack }\bound{lts }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch21}
\begin{paste}{ZeroDimSolvePkgXmpPageFull21}{ZeroDimSolvePkgXmpPageEmpty21}
\pastebutton{ZeroDimSolvePkgXmpPageFull21}{\hidepaste}
\tab{5}\spadcommand{univariateSolve(lf)$pack\free{lf }\free{pack }}
\indentrel{3}\begin{verbatim}
   (21)
   [
     [complexRoots= ?,
      coordinates= [x - 1,y - 1,z + 1,t - %A]]
     ,
    [complexRoots= ?,coordinates= [x,y - 1,z,t - %A]],
    [complexRoots= ? - 1,coordinates= [x,y,z,t - %A]],
    [complexRoots= ?,coordinates= [x - 1,y,z,t - %A]],
    [complexRoots= ?,coordinates= [x,y,z - 1,t - %A]],

     [complexRoots= ? - 2,
      coordinates= [x - 1,y + 1,z,t - 1]]
     ,
    [complexRoots= ?,coordinates= [x + 1,y - 1,z,t - 1]],

     [complexRoots= ? - 1,
      coordinates= [x - 1,y + 1,z - 1,t]]
     ,

     [complexRoots= ? + 1,
      coordinates= [x + 1,y - 1,z - 1,t]]
     ,

                     6     3     2
     [complexRoots= ?  - 2?  + 3?  - 3,

       coordinates =
                 3                  3
         [2x + %A  + %A - 1, 2y + %A  + %A - 1, z - %A,
          t - %A]
       ]
     ,

                     5     3     2
     [complexRoots= ?  + 3?  - 2?  + 3? - 3,

       coordinates =
                              3
         [x - %A,y - %A,z + %A  + 2%A - 1,t - %A]
       ]
     ,

                     4    3     2
     [complexRoots= ?  - ?  - 2?  + 3,

       coordinates =
                3                 3
         [x + %A  - %A - 1, y + %A  - %A - 1,
                3
          z - %A  + 2%A + 1, t - %A]
       ]
     ,

     [complexRoots= ? + 1,
      coordinates= [x - 1,y - 1,z,t - %A]]
     ,

                     6     3     2
     [complexRoots= ?  + 2?  + 3?  - 3,

       coordinates =
                 3                          3
         [2x - %A  - %A - 1, y + %A, 2z - %A  - %A - 1,
          t + %A]
       ]
     ,

                     6      4      3      2
     [complexRoots= ?  + 12?  + 20?  - 45?  - 42? - 953,

       coordinates =
         [
                          5       4       3        2
             12609x + 23%A  + 49%A  - 46%A  + 362%A
           + 
             - 5015%A - 8239
           ,

                          5       4       3        2
             25218y + 23%A  + 49%A  - 46%A  + 362%A
           + 
             7594%A - 8239
           ,

                          5       4       3        2
             25218z + 23%A  + 49%A  - 46%A  + 362%A
           + 
             7594%A - 8239
           ,

                          5       4       3        2
             12609t + 23%A  + 49%A  - 46%A  + 362%A
           + 
             - 5015%A - 8239
           ]
       ]
     ,

                     5      3      2
     [complexRoots= ?  + 12?  - 16?  + 48? - 96,

       coordinates =
                 3
         [8x + %A  + 8%A - 8,2y - %A,2z - %A,2t - %A]
       ]
     ,

                     5    4     3     2
     [complexRoots= ?  + ?  - 5?  - 3?  + 9? + 3,

       coordinates =
                 3                   3
         [2x - %A  + 2%A - 1, 2y + %A  - 4%A + 1,
                 3                   3
          2z - %A  + 2%A - 1, 2t - %A  + 2%A - 1]
       ]
     ,

                     4     3     2
     [complexRoots= ?  - 3?  + 4?  - 6? + 13,

       coordinates =
                  3      2
         [9x - 2%A  + 4%A  - %A + 2,
                 3      2
          9y + %A  - 2%A  + 5%A - 1,
                 3      2
          9z + %A  - 2%A  + 5%A - 1,
                 3      2
          9t + %A  - 2%A  - 4%A - 1]
       ]
     ,

                     4      2
     [complexRoots= ?  - 11?  + 37,

       coordinates =
                 2             2                   2
         [3x - %A  + 7, 6y + %A  + 3%A - 7, 3z - %A  + 7,
                 2
          6t + %A  - 3%A - 7]
       ]
     ,

     [complexRoots= ? + 1,
      coordinates= [x - 1,y,z - 1,t + 1]]
     ,

     [complexRoots= ? + 2,
      coordinates= [x,y - 1,z - 1,t + 1]]
     ,

     [complexRoots= ? - 2,
      coordinates= [x,y - 1,z + 1,t - 1]]
     ,
    [complexRoots= ?,coordinates= [x,y + 1,z - 1,t - 1]],

     [complexRoots= ? - 2,
      coordinates= [x - 1,y,z + 1,t - 1]]
     ,
    [complexRoots= ?,coordinates= [x + 1,y,z - 1,t - 1]],

                     4     3      2
     [complexRoots= ?  + 5?  + 16?  + 30? + 57,

       coordinates =
                     3       2
         [151x + 15%A  + 54%A  + 104%A + 93,
                     3       2
          151y - 10%A  - 36%A  - 19%A - 62,
                    3       2
          151z - 5%A  - 18%A  - 85%A - 31,
                    3       2
          151t - 5%A  - 18%A  - 85%A - 31]
       ]
     ,

                     4    3     2
     [complexRoots= ?  - ?  - 2?  + 3,

       coordinates =
                3                  3
         [x - %A  + 2%A + 1, y + %A  - %A - 1, z - %A,
                3
          t + %A  - %A - 1]
       ]
     ,

                     4     3     2
     [complexRoots= ?  + 2?  - 8?  + 48,

       coordinates =
                 3
         [8x - %A  + 4%A - 8, 2y + %A,
                 3                   3
          8z + %A  - 8%A + 8, 8t - %A  + 4%A - 8]
       ]
     ,

                     5    4     3     2
     [complexRoots= ?  + ?  - 2?  - 4?  + 5? + 8,

       coordinates =
                 3            3            3
         [3x + %A  - 1,3y + %A  - 1,3z + %A  - 1,t - %A]
       ]
     ,

                     3
     [complexRoots= ?  + 3? - 1,
      coordinates= [x - %A,y - %A,z - %A,t - %A]]
     ]
Type: List Record(complexRoots: SparseUnivariatePolynomial Integer,coordinates: List Polynomial Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty21}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty21}{ZeroDimSolvePkgXmpPagePatch21}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty21}{\showpaste}
\tab{5}\spadcommand{univariateSolve(lf)$pack\free{lf }\free{pack }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch22}
\begin{paste}{ZeroDimSolvePkgXmpPageFull22}{ZeroDimSolvePkgXmpPageEmpty22}
\pastebutton{ZeroDimSolvePkgXmpPageFull22}{\hidepaste}
\tab{5}\spadcommand{ts := lts.1\free{lts }\bound{ts }}
\indentrel{3}\begin{verbatim}
   (22)
     2           3        3
   {t  + t + 1, z  - z - t  + t,

               3      2
       (3z + 3t  - 3)y
     + 
          2      3           6     3            3      2
       (3z  + (6t  - 6)z + 3t  - 6t  + 3)y + (3t  - 3)z
     + 
          6     3          9     6     3
       (3t  - 6t  + 3)z + t  - 3t  + 5t  - 3t
     ,
    x + y + z}
                  Type: RegularChain(Integer,[x,y,z,t])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty22}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty22}{ZeroDimSolvePkgXmpPagePatch22}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty22}{\showpaste}
\tab{5}\spadcommand{ts := lts.1\free{lts }\bound{ts }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch23}
\begin{paste}{ZeroDimSolvePkgXmpPageFull23}{ZeroDimSolvePkgXmpPageEmpty23}
\pastebutton{ZeroDimSolvePkgXmpPageFull23}{\hidepaste}
\tab{5}\spadcommand{univariateSolve(ts)$pack\free{ts }\free{pack }}
\indentrel{3}\begin{verbatim}
   (23)
   [
                     4     3      2
     [complexRoots= ?  + 5?  + 16?  + 30? + 57,

       coordinates =
                     3       2
         [151x + 15%A  + 54%A  + 104%A + 93,
                     3       2
          151y - 10%A  - 36%A  - 19%A - 62,
                    3       2
          151z - 5%A  - 18%A  - 85%A - 31,
                    3       2
          151t - 5%A  - 18%A  - 85%A - 31]
       ]
     ,

                     4    3     2
     [complexRoots= ?  - ?  - 2?  + 3,

       coordinates =
                3                  3
         [x - %A  + 2%A + 1, y + %A  - %A - 1, z - %A,
                3
          t + %A  - %A - 1]
       ]
     ,

                     4     3     2
     [complexRoots= ?  + 2?  - 8?  + 48,

       coordinates =
                 3
         [8x - %A  + 4%A - 8, 2y + %A,
                 3                   3
          8z + %A  - 8%A + 8, 8t - %A  + 4%A - 8]
       ]
     ]
Type: List Record(complexRoots: SparseUnivariatePolynomial Integer,coordinates: List Polynomial Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty23}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty23}{ZeroDimSolvePkgXmpPagePatch23}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty23}{\showpaste}
\tab{5}\spadcommand{univariateSolve(ts)$pack\free{ts }\free{pack }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch24}
\begin{paste}{ZeroDimSolvePkgXmpPageFull24}{ZeroDimSolvePkgXmpPageEmpty24}
\pastebutton{ZeroDimSolvePkgXmpPageFull24}{\hidepaste}
\tab{5}\spadcommand{realSolve(ts)$pack\free{ts }\free{pack }}
\indentrel{3}\begin{verbatim}
   (24)  []
           Type: List List RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty24}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty24}{ZeroDimSolvePkgXmpPagePatch24}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty24}{\showpaste}
\tab{5}\spadcommand{realSolve(ts)$pack\free{ts }\free{pack }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch25}
\begin{paste}{ZeroDimSolvePkgXmpPageFull25}{ZeroDimSolvePkgXmpPageEmpty25}
\pastebutton{ZeroDimSolvePkgXmpPageFull25}{\hidepaste}
\tab{5}\spadcommand{lr2 := realSolve(lf)$pack\free{lf }\free{pack }\bound{lr2 }}
\indentrel{3}\begin{verbatim}
   (25)
   [[0,- 1,1,1], [0,0,1,0], [1,0,0,0], [0,0,0,1],
    [0,1,0,0], [1,0,%R37,- %R37], [1,0,%R38,- %R38],
    [0,1,%R35,- %R35], [0,1,%R36,- %R36], [- 1,0,1,1],

     [%R32,

          1     15    2     14    1     13    4     12
         ÄÄ %R32   + ÄÄ %R32   + ÄÄ %R32   - ÄÄ %R32
         27          27          27          27
       + 
           11     11    4     10    1     9   14     8
         - ÄÄ %R32   - ÄÄ %R32   + ÄÄ %R32  + ÄÄ %R32
           27          27          27         27
       + 
          1     7   2     6   1     5   2     4       3
         ÄÄ %R32  + Ä %R32  + Ä %R32  + Ä %R32  + %R32
         27         9         3         9
       + 
         4     2
         Ä %R32  - %R32 - 2
         3
       ,

            1     15    1     14    1     13    2     12
         - ÄÄ %R32   - ÄÄ %R32   - ÄÄ %R32   + ÄÄ %R32
           54          27          54          27
       + 
         11     11    2     10    1     9    7     8
         ÄÄ %R32   + ÄÄ %R32   - ÄÄ %R32  - ÄÄ %R32
         54          27          54         27
       + 
            1     7   1     6   1     5   1     4       3
         - ÄÄ %R32  - Ä %R32  - Ä %R32  - Ä %R32  - %R32
           54         9         6         9
       + 
           2     2   1        3
         - Ä %R32  + Ä %R32 + Ä
           3         2        2
       ,

            1     15    1     14    1     13    2     12
         - ÄÄ %R32   - ÄÄ %R32   - ÄÄ %R32   + ÄÄ %R32
           54          27          54          27
       + 
         11     11    2     10    1     9    7     8
         ÄÄ %R32   + ÄÄ %R32   - ÄÄ %R32  - ÄÄ %R32
         54          27          54         27
       + 
            1     7   1     6   1     5   1     4       3
         - ÄÄ %R32  - Ä %R32  - Ä %R32  - Ä %R32  - %R32
           54         9         6         9
       + 
           2     2   1        3
         - Ä %R32  + Ä %R32 + Ä
           3         2        2
       ]
     ,

     [%R33,

          1     15    2     14    1     13    4     12
         ÄÄ %R33   + ÄÄ %R33   + ÄÄ %R33   - ÄÄ %R33
         27          27          27          27
       + 
           11     11    4     10    1     9   14     8
         - ÄÄ %R33   - ÄÄ %R33   + ÄÄ %R33  + ÄÄ %R33
           27          27          27         27
       + 
          1     7   2     6   1     5   2     4       3
         ÄÄ %R33  + Ä %R33  + Ä %R33  + Ä %R33  + %R33
         27         9         3         9
       + 
         4     2
         Ä %R33  - %R33 - 2
         3
       ,

            1     15    1     14    1     13    2     12
         - ÄÄ %R33   - ÄÄ %R33   - ÄÄ %R33   + ÄÄ %R33
           54          27          54          27
       + 
         11     11    2     10    1     9    7     8
         ÄÄ %R33   + ÄÄ %R33   - ÄÄ %R33  - ÄÄ %R33
         54          27          54         27
       + 
            1     7   1     6   1     5   1     4       3
         - ÄÄ %R33  - Ä %R33  - Ä %R33  - Ä %R33  - %R33
           54         9         6         9
       + 
           2     2   1        3
         - Ä %R33  + Ä %R33 + Ä
           3         2        2
       ,

            1     15    1     14    1     13    2     12
         - ÄÄ %R33   - ÄÄ %R33   - ÄÄ %R33   + ÄÄ %R33
           54          27          54          27
       + 
         11     11    2     10    1     9    7     8
         ÄÄ %R33   + ÄÄ %R33   - ÄÄ %R33  - ÄÄ %R33
         54          27          54         27
       + 
            1     7   1     6   1     5   1     4       3
         - ÄÄ %R33  - Ä %R33  - Ä %R33  - Ä %R33  - %R33
           54         9         6         9
       + 
           2     2   1        3
         - Ä %R33  + Ä %R33 + Ä
           3         2        2
       ]
     ,

     [%R34,

          1     15    2     14    1     13    4     12
         ÄÄ %R34   + ÄÄ %R34   + ÄÄ %R34   - ÄÄ %R34
         27          27          27          27
       + 
           11     11    4     10    1     9   14     8
         - ÄÄ %R34   - ÄÄ %R34   + ÄÄ %R34  + ÄÄ %R34
           27          27          27         27
       + 
          1     7   2     6   1     5   2     4       3
         ÄÄ %R34  + Ä %R34  + Ä %R34  + Ä %R34  + %R34
         27         9         3         9
       + 
         4     2
         Ä %R34  - %R34 - 2
         3
       ,

            1     15    1     14    1     13    2     12
         - ÄÄ %R34   - ÄÄ %R34   - ÄÄ %R34   + ÄÄ %R34
           54          27          54          27
       + 
         11     11    2     10    1     9    7     8
         ÄÄ %R34   + ÄÄ %R34   - ÄÄ %R34  - ÄÄ %R34
         54          27          54         27
       + 
            1     7   1     6   1     5   1     4       3
         - ÄÄ %R34  - Ä %R34  - Ä %R34  - Ä %R34  - %R34
           54         9         6         9
       + 
           2     2   1        3
         - Ä %R34  + Ä %R34 + Ä
           3         2        2
       ,

            1     15    1     14    1     13    2     12
         - ÄÄ %R34   - ÄÄ %R34   - ÄÄ %R34   + ÄÄ %R34
           54          27          54          27
       + 
         11     11    2     10    1     9    7     8
         ÄÄ %R34   + ÄÄ %R34   - ÄÄ %R34  - ÄÄ %R34
         54          27          54         27
       + 
            1     7   1     6   1     5   1     4       3
         - ÄÄ %R34  - Ä %R34  - Ä %R34  - Ä %R34  - %R34
           54         9         6         9
       + 
           2     2   1        3
         - Ä %R34  + Ä %R34 + Ä
           3         2        2
       ]
     ,
    [- 1,1,0,1], [- 1,1,1,0],

     [%R23,

            1     15    1     14    1     13    2     12
         - ÄÄ %R23   - ÄÄ %R23   - ÄÄ %R23   + ÄÄ %R23
           54          27          54          27
       + 
         11     11    2     10    1     9    7     8
         ÄÄ %R23   + ÄÄ %R23   - ÄÄ %R23  - ÄÄ %R23
         54          27          54         27
       + 
            1     7   1     6   1     5   1     4       3
         - ÄÄ %R23  - Ä %R23  - Ä %R23  - Ä %R23  - %R23
           54         9         6         9
       + 
           2     2   1        3
         - Ä %R23  + Ä %R23 + Ä
           3         2        2
       ,
      %R30,

                   1     15    1     14    1     13
         - %R30 + ÄÄ %R23   + ÄÄ %R23   + ÄÄ %R23
                  54          27          54
       + 
            2     12   11     11    2     10    1     9
         - ÄÄ %R23   - ÄÄ %R23   - ÄÄ %R23   + ÄÄ %R23
           27          54          27          54
       + 
          7     8    1     7   1     6   1     5   1     4
         ÄÄ %R23  + ÄÄ %R23  + Ä %R23  + Ä %R23  + Ä %R23
         27         54         9         6         9
       + 
         2     2   1        1
         Ä %R23  - Ä %R23 - Ä
         3         2        2
       ]
     ,

     [%R23,

            1     15    1     14    1     13    2     12
         - ÄÄ %R23   - ÄÄ %R23   - ÄÄ %R23   + ÄÄ %R23
           54          27          54          27
       + 
         11     11    2     10    1     9    7     8
         ÄÄ %R23   + ÄÄ %R23   - ÄÄ %R23  - ÄÄ %R23
         54          27          54         27
       + 
            1     7   1     6   1     5   1     4       3
         - ÄÄ %R23  - Ä %R23  - Ä %R23  - Ä %R23  - %R23
           54         9         6         9
       + 
           2     2   1        3
         - Ä %R23  + Ä %R23 + Ä
           3         2        2
       ,
      %R31,

                   1     15    1     14    1     13
         - %R31 + ÄÄ %R23   + ÄÄ %R23   + ÄÄ %R23
                  54          27          54
       + 
            2     12   11     11    2     10    1     9
         - ÄÄ %R23   - ÄÄ %R23   - ÄÄ %R23   + ÄÄ %R23
           27          54          27          54
       + 
          7     8    1     7   1     6   1     5   1     4
         ÄÄ %R23  + ÄÄ %R23  + Ä %R23  + Ä %R23  + Ä %R23
         27         54         9         6         9
       + 
         2     2   1        1
         Ä %R23  - Ä %R23 - Ä
         3         2        2
       ]
     ,

     [%R24,

            1     15    1     14    1     13    2     12
         - ÄÄ %R24   - ÄÄ %R24   - ÄÄ %R24   + ÄÄ %R24
           54          27          54          27
       + 
         11     11    2     10    1     9    7     8
         ÄÄ %R24   + ÄÄ %R24   - ÄÄ %R24  - ÄÄ %R24
         54          27          54         27
       + 
            1     7   1     6   1     5   1     4       3
         - ÄÄ %R24  - Ä %R24  - Ä %R24  - Ä %R24  - %R24
           54         9         6         9
       + 
           2     2   1        3
         - Ä %R24  + Ä %R24 + Ä
           3         2        2
       ,
      %R28,

                   1     15    1     14    1     13
         - %R28 + ÄÄ %R24   + ÄÄ %R24   + ÄÄ %R24
                  54          27          54
       + 
            2     12   11     11    2     10    1     9
         - ÄÄ %R24   - ÄÄ %R24   - ÄÄ %R24   + ÄÄ %R24
           27          54          27          54
       + 
          7     8    1     7   1     6   1     5   1     4
         ÄÄ %R24  + ÄÄ %R24  + Ä %R24  + Ä %R24  + Ä %R24
         27         54         9         6         9
       + 
         2     2   1        1
         Ä %R24  - Ä %R24 - Ä
         3         2        2
       ]
     ,

     [%R24,

            1     15    1     14    1     13    2     12
         - ÄÄ %R24   - ÄÄ %R24   - ÄÄ %R24   + ÄÄ %R24
           54          27          54          27
       + 
         11     11    2     10    1     9    7     8
         ÄÄ %R24   + ÄÄ %R24   - ÄÄ %R24  - ÄÄ %R24
         54          27          54         27
       + 
            1     7   1     6   1     5   1     4       3
         - ÄÄ %R24  - Ä %R24  - Ä %R24  - Ä %R24  - %R24
           54         9         6         9
       + 
           2     2   1        3
         - Ä %R24  + Ä %R24 + Ä
           3         2        2
       ,
      %R29,

                   1     15    1     14    1     13
         - %R29 + ÄÄ %R24   + ÄÄ %R24   + ÄÄ %R24
                  54          27          54
       + 
            2     12   11     11    2     10    1     9
         - ÄÄ %R24   - ÄÄ %R24   - ÄÄ %R24   + ÄÄ %R24
           27          54          27          54
       + 
          7     8    1     7   1     6   1     5   1     4
         ÄÄ %R24  + ÄÄ %R24  + Ä %R24  + Ä %R24  + Ä %R24
         27         54         9         6         9
       + 
         2     2   1        1
         Ä %R24  - Ä %R24 - Ä
         3         2        2
       ]
     ,

     [%R25,

            1     15    1     14    1     13    2     12
         - ÄÄ %R25   - ÄÄ %R25   - ÄÄ %R25   + ÄÄ %R25
           54          27          54          27
       + 
         11     11    2     10    1     9    7     8
         ÄÄ %R25   + ÄÄ %R25   - ÄÄ %R25  - ÄÄ %R25
         54          27          54         27
       + 
            1     7   1     6   1     5   1     4       3
         - ÄÄ %R25  - Ä %R25  - Ä %R25  - Ä %R25  - %R25
           54         9         6         9
       + 
           2     2   1        3
         - Ä %R25  + Ä %R25 + Ä
           3         2        2
       ,
      %R26,

                   1     15    1     14    1     13
         - %R26 + ÄÄ %R25   + ÄÄ %R25   + ÄÄ %R25
                  54          27          54
       + 
            2     12   11     11    2     10    1     9
         - ÄÄ %R25   - ÄÄ %R25   - ÄÄ %R25   + ÄÄ %R25
           27          54          27          54
       + 
          7     8    1     7   1     6   1     5   1     4
         ÄÄ %R25  + ÄÄ %R25  + Ä %R25  + Ä %R25  + Ä %R25
         27         54         9         6         9
       + 
         2     2   1        1
         Ä %R25  - Ä %R25 - Ä
         3         2        2
       ]
     ,

     [%R25,

            1     15    1     14    1     13    2     12
         - ÄÄ %R25   - ÄÄ %R25   - ÄÄ %R25   + ÄÄ %R25
           54          27          54          27
       + 
         11     11    2     10    1     9    7     8
         ÄÄ %R25   + ÄÄ %R25   - ÄÄ %R25  - ÄÄ %R25
         54          27          54         27
       + 
            1     7   1     6   1     5   1     4       3
         - ÄÄ %R25  - Ä %R25  - Ä %R25  - Ä %R25  - %R25
           54         9         6         9
       + 
           2     2   1        3
         - Ä %R25  + Ä %R25 + Ä
           3         2        2
       ,
      %R27,

                   1     15    1     14    1     13
         - %R27 + ÄÄ %R25   + ÄÄ %R25   + ÄÄ %R25
                  54          27          54
       + 
            2     12   11     11    2     10    1     9
         - ÄÄ %R25   - ÄÄ %R25   - ÄÄ %R25   + ÄÄ %R25
           27          54          27          54
       + 
          7     8    1     7   1     6   1     5   1     4
         ÄÄ %R25  + ÄÄ %R25  + Ä %R25  + Ä %R25  + Ä %R25
         27         54         9         6         9
       + 
         2     2   1        1
         Ä %R25  - Ä %R25 - Ä
         3         2        2
       ]
     ,
    [1,%R21,- %R21,0], [1,%R22,- %R22,0],
    [1,%R19,0,- %R19], [1,%R20,0,- %R20],
            1     3   1   1     3   1   1     3   1
    [%R17,- Ä %R17  + Ä,- Ä %R17  + Ä,- Ä %R17  + Ä],
            3         3   3         3   3         3
            1     3   1   1     3   1   1     3   1
    [%R18,- Ä %R18  + Ä,- Ä %R18  + Ä,- Ä %R18  + Ä]]
            3         3   3         3   3         3
           Type: List List RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty25}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty25}{ZeroDimSolvePkgXmpPagePatch25}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty25}{\showpaste}
\tab{5}\spadcommand{lr2 := realSolve(lf)$pack\free{lf }\free{pack }\bound{lr2 }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch26}
\begin{paste}{ZeroDimSolvePkgXmpPageFull26}{ZeroDimSolvePkgXmpPageEmpty26}
\pastebutton{ZeroDimSolvePkgXmpPageFull26}{\hidepaste}
\tab{5}\spadcommand{\#lr2\free{lr2 }}
\indentrel{3}\begin{verbatim}
   (26)  27
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty26}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty26}{ZeroDimSolvePkgXmpPagePatch26}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty26}{\showpaste}
\tab{5}\spadcommand{\#lr2\free{lr2 }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch27}
\begin{paste}{ZeroDimSolvePkgXmpPageFull27}{ZeroDimSolvePkgXmpPageEmpty27}
\pastebutton{ZeroDimSolvePkgXmpPageFull27}{\hidepaste}
\tab{5}\spadcommand{lpr2 := positiveSolve(lf)$pack\free{lf }\free{pack }\bound{lpr2 }}
\indentrel{3}\begin{verbatim}
   (27)
            1     3   1   1     3   1   1     3   1
   [[%R40,- Ä %R40  + Ä,- Ä %R40  + Ä,- Ä %R40  + Ä]]
            3         3   3         3   3         3
           Type: List List RealClosure Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty27}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty27}{ZeroDimSolvePkgXmpPagePatch27}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty27}{\showpaste}
\tab{5}\spadcommand{lpr2 := positiveSolve(lf)$pack\free{lf }\free{pack }\bound{lpr2 }}
\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPagePatch28}
\begin{paste}{ZeroDimSolvePkgXmpPageFull28}{ZeroDimSolvePkgXmpPageEmpty28}
\pastebutton{ZeroDimSolvePkgXmpPageFull28}{\hidepaste}
\tab{5}\spadcommand{[approximate(r,1/10**21)::Float for r in lpr2.1]\free{lpr2 }}
\indentrel{3}\begin{verbatim}
   (28)
   [0.3221853546 2608559291, 0.3221853546 2608559291,
    0.3221853546 2608559291, 0.3221853546 2608559291]
                                       Type: List Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ZeroDimSolvePkgXmpPageEmpty28}
\begin{paste}{ZeroDimSolvePkgXmpPageEmpty28}{ZeroDimSolvePkgXmpPagePatch28}
\pastebutton{ZeroDimSolvePkgXmpPageEmpty28}{\showpaste}
\tab{5}\spadcommand{[approximate(r,1/10**21)::Float for r in lpr2.1]\free{lpr2 }}
\end{paste}\end{patch}

\end{chunk}
\section{zlindep.ht}
\pagetitle{IntegerLinearDependenceXmpPage}{zlindep.ht}
{IntegerLinearDependence}
\begin{chunk}{zlindep.ht}
\begin{page}{IntegerLinearDependenceXmpPage}{IntegerLinearDependence}
\beginscroll

The elements \texht{$v_1, \dots,v_n$}{\spad{v1,...,vn}}
of a module \spad{M} over a ring \spad{R} are
said to be {\it linearly dependent over \spad{R}} if there exist
\texht{$c_1,\dots,c_n$}{\spad{c1, ..., cn}} in \spad{R},
not all \smath{0},
such that 
\texht{$c_1 v_1 + \dots c_n v_n = 0$}{\spad{c1*v1 + ... + cn*vn = 0}}.
If such \texht{$c_i$}{\spad{ci}}'s exist,
they form what is called a {\it linear dependence
relation over \spad{R}} for the \texht{$v_i$}{\spad{vi}}'s.

The package \spadtype{IntegerLinearDependence} provides functions
for testing whether some elements of a module over the integers are
linearly dependent over the integers, and to find the linear
dependence relations, if any.
%
\xtc{
Consider the domain of two by two square matrices with integer entries.
}{
\spadpaste{M := SQMATRIX(2,INT) \bound{M}}
}
%
%
\xtc{
Now create three such matrices.
}{
\spadpaste{m1: M := squareMatrix matrix [[1, 2], [0, -1]] 
\free{M}\bound{m1}}
}
\xtc{
}{
\spadpaste{m2: M := squareMatrix matrix [[2, 3], [1, -2]] 
\free{M}\bound{m2}}
}
\xtc{
}{
\spadpaste{m3: M := squareMatrix matrix [[3, 4], [2, -3]] 
\free{M}\bound{m3}}
}
%
%
\xtc{
This tells you whether \spad{m1}, \spad{m2} and \spad{m3} are linearly
dependent over the integers.
}{
\spadpaste{linearlyDependentOverZ? vector [m1, m2, m3] \free{m1 m2 m3}}
}
%
%
\xtc{
Since they are linearly dependent, you can ask for the dependence
relation.
}{
\spadpaste{c := linearDependenceOverZ vector [m1, m2, m3] 
\free{m1 m2 m3}\bound{c}}
}
%
%
\xtc{
This means that the following linear combination should be \spad{0}.
}{
\spadpaste{c.1 * m1 + c.2 * m2 + c.3 * m3 \free{c m1 m2 m3}}
}
%
When a given set of elements are linearly dependent over \spad{R}, this
also means that at least one of them can be rewritten as a linear
combination of the others with coefficients in the quotient field of
\spad{R}.
%
\xtc{
To express a given element in terms of other elements, use the operation
\spadfunFrom{solveLinearlyOverQ}{IntegerLinearDependence}.
}{
\spadpaste{solveLinearlyOverQ(vector [m1, m3], m2) \free{m1 m2 m3}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{IntegerLinearDependenceXmpPagePatch1}
\begin{paste}{IntegerLinearDependenceXmpPageFull1}{IntegerLinearDependenceXmpPageEmpty1}
\pastebutton{IntegerLinearDependenceXmpPageFull1}{\hidepaste}
\tab{5}\spadcommand{M := SQMATRIX(2,INT)\bound{M }}
\indentrel{3}\begin{verbatim}
   (1)  SquareMatrix(2,Integer)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerLinearDependenceXmpPageEmpty1}
\begin{paste}{IntegerLinearDependenceXmpPageEmpty1}{IntegerLinearDependenceXmpPagePatch1}
\pastebutton{IntegerLinearDependenceXmpPageEmpty1}{\showpaste}
\tab{5}\spadcommand{M := SQMATRIX(2,INT)\bound{M }}
\end{paste}\end{patch}

\begin{patch}{IntegerLinearDependenceXmpPagePatch2}
\begin{paste}{IntegerLinearDependenceXmpPageFull2}{IntegerLinearDependenceXmpPageEmpty2}
\pastebutton{IntegerLinearDependenceXmpPageFull2}{\hidepaste}
\tab{5}\spadcommand{m1: M := squareMatrix matrix [[1, 2], [0, -1]]\free{M }\bound{m1 }}
\indentrel{3}\begin{verbatim}
        Ú1   2 ¿
   (2)  ³      ³
        À0  - 1Ù
                          Type: SquareMatrix(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerLinearDependenceXmpPageEmpty2}
\begin{paste}{IntegerLinearDependenceXmpPageEmpty2}{IntegerLinearDependenceXmpPagePatch2}
\pastebutton{IntegerLinearDependenceXmpPageEmpty2}{\showpaste}
\tab{5}\spadcommand{m1: M := squareMatrix matrix [[1, 2], [0, -1]]\free{M }\bound{m1 }}
\end{paste}\end{patch}

\begin{patch}{IntegerLinearDependenceXmpPagePatch3}
\begin{paste}{IntegerLinearDependenceXmpPageFull3}{IntegerLinearDependenceXmpPageEmpty3}
\pastebutton{IntegerLinearDependenceXmpPageFull3}{\hidepaste}
\tab{5}\spadcommand{m2: M := squareMatrix matrix [[2, 3], [1, -2]]\free{M }\bound{m2 }}
\indentrel{3}\begin{verbatim}
        Ú2   3 ¿
   (3)  ³      ³
        À1  - 2Ù
                          Type: SquareMatrix(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerLinearDependenceXmpPageEmpty3}
\begin{paste}{IntegerLinearDependenceXmpPageEmpty3}{IntegerLinearDependenceXmpPagePatch3}
\pastebutton{IntegerLinearDependenceXmpPageEmpty3}{\showpaste}
\tab{5}\spadcommand{m2: M := squareMatrix matrix [[2, 3], [1, -2]]\free{M }\bound{m2 }}
\end{paste}\end{patch}

\begin{patch}{IntegerLinearDependenceXmpPagePatch4}
\begin{paste}{IntegerLinearDependenceXmpPageFull4}{IntegerLinearDependenceXmpPageEmpty4}
\pastebutton{IntegerLinearDependenceXmpPageFull4}{\hidepaste}
\tab{5}\spadcommand{m3: M := squareMatrix matrix [[3, 4], [2, -3]]\free{M }\bound{m3 }}
\indentrel{3}\begin{verbatim}
        Ú3   4 ¿
   (4)  ³      ³
        À2  - 3Ù
                          Type: SquareMatrix(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerLinearDependenceXmpPageEmpty4}
\begin{paste}{IntegerLinearDependenceXmpPageEmpty4}{IntegerLinearDependenceXmpPagePatch4}
\pastebutton{IntegerLinearDependenceXmpPageEmpty4}{\showpaste}
\tab{5}\spadcommand{m3: M := squareMatrix matrix [[3, 4], [2, -3]]\free{M }\bound{m3 }}
\end{paste}\end{patch}

\begin{patch}{IntegerLinearDependenceXmpPagePatch5}
\begin{paste}{IntegerLinearDependenceXmpPageFull5}{IntegerLinearDependenceXmpPageEmpty5}
\pastebutton{IntegerLinearDependenceXmpPageFull5}{\hidepaste}
\tab{5}\spadcommand{linearlyDependentOverZ? vector [m1, m2, m3]\free{m1 m2 m3 }}
\indentrel{3}\begin{verbatim}
   (5)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerLinearDependenceXmpPageEmpty5}
\begin{paste}{IntegerLinearDependenceXmpPageEmpty5}{IntegerLinearDependenceXmpPagePatch5}
\pastebutton{IntegerLinearDependenceXmpPageEmpty5}{\showpaste}
\tab{5}\spadcommand{linearlyDependentOverZ? vector [m1, m2, m3]\free{m1 m2 m3 }}
\end{paste}\end{patch}

\begin{patch}{IntegerLinearDependenceXmpPagePatch6}
\begin{paste}{IntegerLinearDependenceXmpPageFull6}{IntegerLinearDependenceXmpPageEmpty6}
\pastebutton{IntegerLinearDependenceXmpPageFull6}{\hidepaste}
\tab{5}\spadcommand{c := linearDependenceOverZ vector [m1, m2, m3]\free{m1 m2 m3 }\bound{c }}
\indentrel{3}\begin{verbatim}
   (6)  [1,- 2,1]
                        Type: Union(Vector Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerLinearDependenceXmpPageEmpty6}
\begin{paste}{IntegerLinearDependenceXmpPageEmpty6}{IntegerLinearDependenceXmpPagePatch6}
\pastebutton{IntegerLinearDependenceXmpPageEmpty6}{\showpaste}
\tab{5}\spadcommand{c := linearDependenceOverZ vector [m1, m2, m3]\free{m1 m2 m3 }\bound{c }}
\end{paste}\end{patch}

\begin{patch}{IntegerLinearDependenceXmpPagePatch7}
\begin{paste}{IntegerLinearDependenceXmpPageFull7}{IntegerLinearDependenceXmpPageEmpty7}
\pastebutton{IntegerLinearDependenceXmpPageFull7}{\hidepaste}
\tab{5}\spadcommand{c.1 * m1 + c.2 * m2 + c.3 * m3\free{c m1 m2 m3 }}
\indentrel{3}\begin{verbatim}
        Ú0  0¿
   (7)  ³    ³
        À0  0Ù
                          Type: SquareMatrix(2,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerLinearDependenceXmpPageEmpty7}
\begin{paste}{IntegerLinearDependenceXmpPageEmpty7}{IntegerLinearDependenceXmpPagePatch7}
\pastebutton{IntegerLinearDependenceXmpPageEmpty7}{\showpaste}
\tab{5}\spadcommand{c.1 * m1 + c.2 * m2 + c.3 * m3\free{c m1 m2 m3 }}
\end{paste}\end{patch}

\begin{patch}{IntegerLinearDependenceXmpPagePatch8}
\begin{paste}{IntegerLinearDependenceXmpPageFull8}{IntegerLinearDependenceXmpPageEmpty8}
\pastebutton{IntegerLinearDependenceXmpPageFull8}{\hidepaste}
\tab{5}\spadcommand{solveLinearlyOverQ(vector [m1, m3], m2)\free{m1 m2 m3 }}
\indentrel{3}\begin{verbatim}
         1 1
   (8)  [Ä,Ä]
         2 2
               Type: Union(Vector Fraction Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{IntegerLinearDependenceXmpPageEmpty8}
\begin{paste}{IntegerLinearDependenceXmpPageEmpty8}{IntegerLinearDependenceXmpPagePatch8}
\pastebutton{IntegerLinearDependenceXmpPageEmpty8}{\showpaste}
\tab{5}\spadcommand{solveLinearlyOverQ(vector [m1, m3], m2)\free{m1 m2 m3 }}
\end{paste}\end{patch}

\end{chunk}
\chapter{Users Guide Pages (ug.ht)}
\pagetitle{UsersGuidePage}{page.ht}{Users Guide}
\pagepic{ps/v71usersguidepage.eps}{usersguidepage}{0.50}
\pagefrom{Reference}{TopReferencePage}
\pageto{What's New in Axiom Version May 2008}{ugWhatsNewTwoTwoPage}
\pageto{An Overview of Axiom}{ugIntroPage} 
\pageto{Using Types and Modes}{ugTypesPage}
\pageto{Using HyperDoc}{ugHyperPage}
\pageto{Input Files and Output Styles}{ugInOutPage}
\pageto{Introduction to the Axiom Interactive Language}{ugLangPage}
\pageto{User-Defined Functions, ...}{ugUserPage}
\pageto{Graphics}{ugGraphPage}
\pageto{Advanced Problem Solving}{ugProblemPage}
\pageto{Some Examples for Domains and Packages}{ExamplesExposedPage}
\pageto{Interactive Programming}{ugIntProgPage}
\pageto{Packages}{ugPackagesPage}
\pageto{Categories}{ugCategoriesPage}
\pageto{Domains}{ugDomainsPage}
\pageto{Browse}{ugBrowsePage}
\pageto{What's New in Axiom Version 2.0}{ugWhatsNewPage}
\pageto{Axiom System Commands}{ugSysCmdPage}
\pageto{Programs for Axiom Images}{ugAppGraphicsPage}
\pageto{Glossary}{GlossaryPage}
\begin{chunk}{ug.ht}
\begin{page}{UsersGuidePage}{Users Guide}
This is the table of contents for the Users Guide.
Click on any item below to see that section.
\beginscroll
\indent{3}
\beginmenu
\menudownlink{{0. What's New in Axiom Version May 2008}}
{ugWhatsNewTwoTwoPage}
\endmenu
\indent{0}
Part I.   Basic Features of Axiom
\indent{3}
\beginmenu
\menudownlink{{1. An Overview of Axiom}}{ugIntroPage}
\menudownlink{{2. Using Types and Modes}}{ugTypesPage}
\menudownlink{{3. Using Hyperdoc}}{ugHyperPage}
\menudownlink{{4. Input Files and Output Styles}}{ugInOutPage}
\menudownlink{{5. Introduction to the Axiom Interactive Language}}
{ugLangPage}
\menudownlink{{6. User-Defined Functions, Macros and Rules}}{ugUserPage}
\menudownlink{{7. Graphics}}{ugGraphPage}
\endmenu
\indent{0}
Part II.  Advanced Problem Solving and Examples
\indent{3}
\beginmenu
\menudownlink{{8. Advanced Problem Solving}}{ugProblemPage}
\menudownlink{{9. Some Examples for Domains and Packages}}
{ExamplesExposedPage}
\endmenu
\indent{0}
Part III. Advanced Programming in Axiom
\indent{3}
\beginmenu
\menudownlink{{10. Interactive Programming}}{ugIntProgPage}
\menudownlink{{11. Packages}}{ugPackagesPage}
\menudownlink{{12. Categories}}{ugCategoriesPage}
\menudownlink{{13. Domains}}{ugDomainsPage}
\menudownlink{{14. Browse}}{ugBrowsePage}
\menudownlink{{15. What's New in Axiom Version 2.0}}{ugWhatsNewPage}
\endmenu
\indent{0}
Appendices.
\indent{3}
\beginmenu
\menudownlink{{A. Axiom System Commands}}{ugSysCmdPage}
\menudownlink{{F. Programs for Axiom Images}}{ugAppGraphicsPage}
\menudownlink{{G. Glossary}}{GlossaryPage}
\endmenu
\indent{0}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\chapter{Users Guide Chapter 0 (ug00.ht)}
\pagetitle{ugWhatsNewTwoTwoPage}{ug00.ht}
{What's New for May 2008}
No image here because the page changes every release.
\pagefrom{Reference}{TopReferencePage}
\pageto{New polynomial domains and algorithms}{ugTwoTwoPolynomialsPage}
\pageto{Enhancements to Hyperdoc...}{ugTwoTwoHyperdocPage}
\pageto{Enhancements to NAGLink}{ugTwoTwoNAGLinkPage}
\pageto{Enhancements to the Lisp system}{ugTwoTwoCCLPage}
\begin{chunk}{ug00.ht}
\begin{page}{ugWhatsNewTwoTwoPage}
{0. What's New for May 2008}
\beginscroll

\beginmenu
    \menudownlink{{0.2. New polynomial domains and algorithms}}
{ugTwoTwoPolynomialsPage}
    \menudownlink{{0.3. Enhancements to HyperDoc and Graphics}}
{ugTwoTwoHyperdocPage}
    \menudownlink{{0.4. Enhancements to NAGLink}}{ugTwoTwoNAGLinkPage}
    \menudownlink{{0.5. Enhancements to the Lisp system}}{ugTwoTwoCCLPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugTwoTwoPolynomialsPage}{ug00.ht}
{New polynomial domains and algorithms}
\begin{chunk}{ug00.ht}
\begin{page}{ugTwoTwoPolynomialsPage}
{0.2. New polynomial domains and algorithms}
\beginscroll

Univariate polynomial factorisation over the integers has been
enhanced by updates to the \spadtype{GaloisGroupFactorizer} type and
friends from Frederic Lehobey (Frederic.Lehobey@lifl.fr, University of
Lille I, France).

The package constructor \spadtype{PseudoRemainderSequence} provides
efficient algorithms by Lionel Ducos
(Lionel.Ducos@mathlabo.univ-poitiers.fr, University of Poitiers,
France) for computing sub-resultants.  This leads to a speed up in
many places in Axiom where sub-resultants are computed (polynomial
system solving, algebraic factorization, integration).

Based on this package, the domain constructor
\spadtype{NewSparseUnivariatePolynomial} extends the constructor
\spadtype{SparseUnivariatePolynomial}.  In a similar way, the
\spadtype{NewSparseMultivariatePolynomial} extends the constructor
\spadtype{SparseUnivariatePolynomial}; it also provides some
additional operations related to polynomial system solving by means of
triangular sets.

Several domain constructors implement regular triangular sets (or
regular chains).  Among them \spadtype{RegularTriangularSet} and
\spadtype{SquareFreeRegularTriangularSet}.  They also implement an
algorithm by Marc Moreno Maza (marc@nag.co.uk, NAG) for computing
triangular decompositions of polynomial systems.  This method is
refined in the package \spadtype{LazardSetSolvingPackage} in order to
produce decompositions by means of Lazard triangular sets.  For the
case of polynomial systems with finitely many solutions, these
decompositions can also be computed by the package
\spadtype{LexTriangularPackage}.

The domain constructor \spadtype{RealClosure} by Renaud Rioboo
(Renaud.Rioboo@lip6.fr, University of Paris 6, France) provides the
real closure of an ordered field.  The implementation is based on
interval arithmetic.  Moreover, the design of this constructor and its
related packages allows an easy use of other codings for real
algebraic numbers.

Based on triangular decompositions and the \spadtype{RealClosure}
constructor, the package \spadtype{ZeroDimensionalSolvePackage}
provides operations for computing symbolically the real or complex
roots of polynomial systems with finitely many solutions.

Polynomial arithmetic with non-commutative variables has been improved
too by a contribution of Michel Petitot (Michel.Petitot@lifl.fr,
University of Lille I, France).  The domain constructors
\spadtype{XRecursivePolynomial} and \spadtype{XDistributedPolynomial}
provide recursive and distributed representations for these
polynomials.  They are the non-commutative equivalents for the
\spadtype{SparseMultivariatePolynomial} and
\spadtype{DistributedMultivariatePoly} constructors.  The
constructor \spadtype{LiePolynomial} implement Lie polynomials in the
Lyndon basis.  The constructor \spadtype{XPBWPolynomial} manage
polynomials with non-commutative variables in the
\texht{Poincar\'e}{Poincare\space{-1}'}-Birkhoff-Witt basis from the
Lyndon basis.  This allows to compute in the Lie Group associated with
a free nilpotent Lie algebra by using the \spadtype{LieExponentials}
domain constructor.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugTwoTwoHyperdocPage}{ug00.ht}
{Enhancements to HyperDoc and Graphics}
\begin{chunk}{ug00.ht}
\begin{page}{ugTwoTwoHyperdocPage}
{0.3. Enhancements to HyperDoc and Graphics}
\beginscroll

From this version of Axiom onwards, the pixmap format used to save
graphics images in color and to display them in HyperDoc has been
changed to the industry-standard XPM format. See 
{\tt http://koala.ilog.fr/ftp/pub/xpm}.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugTwoTwoNAGLinkPage}{ug00.ht}{Enhancements to NAGLink}
\begin{chunk}{ug00.ht}
\begin{page}{ugTwoTwoNAGLinkPage}{0.4. Enhancements to NAGLink}
\beginscroll

This version of Axiom incorporates the Axiom/NAG Numerical Analyst
(ANNA) software developed in the University of Bath. ANNA is an expert
system which uses Axiom algebra functionality in choosing the most
appropriate NAG Fortran Library routine for a particular
problem. Documentation is provided on-line on the main HyperDoc page.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugTwoTwoCCLPage}{ug00.ht}{Enhancements to the Lisp system}
\begin{chunk}{ug00.ht}
\begin{page}{ugTwoTwoCCLPage}{0.5. Enhancements to the Lisp system}
\beginscroll

In this version of Axiom, certain Library operations have been
accelerated by converting their Lisp implementations into kernel
operations implemented directly in C. Here is a list of the
accelerated operations. The given names encode the abbreviated type
the operation comes from, the name of the operation and, in the case
of exported functions, an encoded signature and numerical index.

\begin{verbatim}
|A1AGG-;=;2AB;28|
|A1AGG-;copy;2A;19|
|A1AGG-;sort!;M2A;2|
|ABELGRP-;*;Nni2S;3|
|ABELGRP-;-;3S;1|
|ABELMON-;*;Pi2S;2|
|ABELMON-;zero?;SB;1|
|AGG-;empty?;SB;3|
|AGG-;size?;SNniB;6|
|ALIST;keys;$L;6|
|ALIST;search;Key$U;15|
|ARR2CAT-;copy;2S;10|
|BOP;<;2$B;29|
|BOP;=;2$B;27|
|BOP;has?;$SB;9|
|BOP;is?;$SB;1|
|BOP;name;$S;2|
|BOP;properties;$Al;3|
|BOP;property;$SU;7|
|BOP;weight;$Nni;28|
|COMPCAT-;*;R2S;18|
|COMPCAT-;-;2S;17|
|COMPCAT-;=;2SB;15|
|COMPCAT-;exquo;SRU;46|
|COMPCAT-;recip;SU;48|
|COMPCAT-;rem;3S;53|
|COMPCAT-;unitNormal;SR;49|
|COMPLEX;*;3$;10|
|COMPLEX;+;3$;9|
|COMPLEX;coerce;R$;5|
|COMPLEX;exquo;2$U;11|
|COMPLEX;one?;$B;4|
|COMPLEX;zero?;$B;3|
|DIRPROD;<;2$B;18|
|DIRPROD;subtractIfCan;2$U;14|
|ELAGG-;removeDuplicates;2A;12|
|ELTAGG-;qelt;SDomIm;1|
|ELTAGG-;qsetelt!;SDom2Im;2|
|EUCDOM-;gcd;3S;5|
|EUCDOM-;unitNormalizeIdealElt|
|EXPR;*;3$;11|
|EXPR;+;3$;12|
|EXPR;-;2$;8|
|EXPR;/;3$;14|
|EXPR;=;2$B;21|
|EXPR;algkernels!0|
|EXPR;algkernels|
|EXPR;coerce;I$;10|
|EXPR;coerce;Smp$;24|
|EXPR;commonk0|
|EXPR;commonk|
|EXPR;denom;$Smp;23|
|EXPR;numer;$Smp;22|
|EXPR;reduc|
|EXPR;zero?;$B;7|
|FACUTIL;lowerPolynomial;SupSup;1|
|FAMR-;coefficients;SL;4|
|FAMR-;ground;SR;2|
|FFP;*;3$;21|
|FFP;+;3$;22|
|FFP;-;3$;23|
|FFP;=;2$B;24|
|FIELD-;/;3S;11|
|FIELD-;inv;2S;4|
|FLAGG-;sort!;2A;8|
|FLAGG-;sort;M2A;6|
|FLASORT;QuickSort|
|FLASORT;partition|
|FLASORT;quickSort;M2V;1|
|FM;*;R2$;1|
|FRAC;*;3$;18|
|FRAC;*;I2$;19|
|FRAC;+;3$;16|
|FRAC;=;2$B;22|
|FRAC;cancelGcd|
|FRAC;coerce;S$;1|
|FRAC;normalize|
|FRAC;one?;$B;23|
|FRAC;recip;$U;13|
|FRAC;zero?;$B;2|
|FSAGG-;brace;LA;3|
|GDMP;univariate;$OvlSup;21|
|HDP;<;2$B;1|
|IARRAY1;#;$Nni;1|
|IARRAY1;elt;$IS;16|
|IARRAY1;fill!;$S$;2|
|IARRAY1;map;M3$;8|
|IARRAY1;maxIndex;$I;13|
|IARRAY1;minIndex;$I;3|
|IARRAY1;new;NniS$;5|
|IARRAY1;qelt;$IS;14|
|IARRAY1;qsetelt!;$I2S;15|
|IARRAY1;setelt;$I2S;17|
|IDPAM;+;3$;4|
|IDPAM;map;M2$;7|
|IDPAM;monomial;AS$;6|
|IDPO;=;2$B;1|
|IFARRAY;#;$Nni;4|
|IFARRAY;concat!;$S$;21|
|IFARRAY;elt;$IS;17|
|IFARRAY;empty;$;3|
|IFARRAY;growAndFill|
|IFARRAY;growWith|
|IFARRAY;maxIndex;$I;6|
|IFARRAY;minIndex;$I;7|
|IFARRAY;new;NniS$;8|
|IFARRAY;removeDuplicates!;2$;30|
|IFARRAY;setelt;$I2S;18|
|IIARRAY2;elt;$2IR;11|
|IIARRAY2;empty?;$B;1|
|IIARRAY2;maxColIndex;$I;7|
|IIARRAY2;maxRowIndex;$I;6|
|IIARRAY2;minColIndex;$I;5|
|IIARRAY2;minRowIndex;$I;4|
|IIARRAY2;ncols;$Nni;9|
|IIARRAY2;nrows;$Nni;8|
|IIARRAY2;qelt;$2IR;10|
|IIARRAY2;qsetelt!;$2I2R;12|
|ILIST;concat!;3$;25|
|ILIST;copy;2$;20|
|ILIST;empty;$;6|
|ILIST;first;$S;4|
|ILIST;member?;S$B;24|
|ILIST;mergeSort|
|ILIST;minIndex;$I;18|
|ILIST;removeDuplicates!;2$;26|
|ILIST;rest;$Nni$;19|
|ILIST;sort!;M2$;27|
|ILIST;split!;$I$;29|
|IMATLIN;rowEchelon;2M;3|
|INS-;symmetricRemainder;3S;27|
|INT;exquo;2$U;44|
|INT;one?;$B;2|
|INT;positiveRemainder;3$;23|
|INT;unitNormal;$R;47|
|INTDOM-;unitCanonical;2S;2|
|ISTRING;<;2$B;6|
|KDAGG-;key?;KeySB;1|
|KERNEL;<;2$B;14|
|KERNEL;=;2$B;13|
|KERNEL;B2Z|
|KERNEL;argument;$L;6|
|KERNEL;operator;$Bo;5|
|KERNEL;position;$Nni;7|
|KERNEL;triage|
|LO;-;2$;3|
|LO;=;2$B;4|
|LSAGG-;<;2AB;25|
|LSAGG-;reduce;MA2S;16|
|LSAGG-;select!;M2A;5|
|MATCAT-;*;3S;29|
|MATCAT-;*;S2Col;32|
|MDDFACT;reduction!0|
|MDDFACT;reduction|
|MODRING;reduce;RMod$;6|
|MODRING;zero?;$B;10|
|MONOID-;one?;SB;2|
|NNI;subtractIfCan;2$U;3|
|NSMP;mvar;$VarSet;5|
|OVAR;<;2$B;10|
|PERMGRP;inv|
|PERMGRP;orbitWithSvc|
|PERMGRP;testIdentity|
|PERMGRP;times|
|PGCD;better|
|PGCD;gcd;3P;15|
|PGCD;gcdTermList|
|POLYCATQ;variables;FL;5|
|PR;*;3$;20|
|PR;addm!|
|PR;coerce;R$;12|
|PR;degree;$E;4|
|PR;leadingCoefficient;$R;6|
|PR;reductum;2$;8|
|PRIMARR;#;$Nni;1|
|PRIMARR;fill!;$S$;9|
|PRIMARR;new;NniS$;4|
|PRTITION;<;2$B;5|
|REPSQ;expt;SPiS;1|
|RING-;coerce;IS;1|
|SAE;*;3$;15|
|SAE;+;3$;13|
|SAE;-;2$;14|
|SAE;=;2$B;12|
|SAE;reduce;UP$;11|
|SCACHE;enterInCache;SMS;5|
|SET;construct;L$;19|
|SET;empty;$;4|
|SGROUP-;**;SPiS;1|
|SINT;zero?;$B;33|
|SMP;*;3$;29|
|SMP;*;R2$;25|
|SMP;+;3$;26|
|SMP;-;2$;23|
|SMP;=;2$B;28|
|SMP;coerce;R$;20|
|SMP;coerce;VarSet$;7|
|SMP;exquo;2$U;35|
|SMP;exquo;2$U;36|
|SMP;gcd;3$;41|
|SMP;gcd;3$;44|
|SMP;gcd;3$;48|
|SMP;gcd;3$;51|
|SMP;ground?;$B;15|
|SMP;leadingCoefficient;$R;73|
|SMP;mainVariable;$U;59|
|SMP;one?;$B;4|
|SMP;retract;$R;55|
|SMP;unitNormal;$R;31|
|SMP;variables;$L;58|
|SMP;zero?;$B;3|
|STAGG-;c2|
|STAGG-;concat;3A;7|
|STAGG-;elt;AIS;5|
|STAGG-;first;ANniA;3|
|STREAM2;map;MSS;2|
|STREAM2;mapp!0|
|STREAM2;mapp|
|STREAM;empty;$;33|
|STREAM;lazyEval|
|STREAM;setfrst!|
|STREAM;setrst!|
|STTAYLOR;+;3S;2|
|SUP;exquo;2$U;19|
|SUP;exquo;2$U;20|
|SUP;fmecg;$NniR2$;21|
|SUP;ground?;$B;3|
|SUP;monicDivide;2$R;28|
|URAGG-;tail;2A;16|
|ZMOD;*;3$;30|
|ZMOD;+;3$;32|
|ZMOD;-;2$;36|
|ZMOD;-;3$;33|
\end{verbatim}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\chapter{Users Guide Chapter 1 (ug01.ht)}
\pagetitle{ugIntroPage}{ug01.ht}{An Overview of Axiom}
\pagefrom{Numeric Functions}{ugProblemNumericPage}
\pageto{Starting Up and Winding Down}{ugIntroStartPage}
\pageto{Typographic Conventions}{ugIntroTypoPage}
\pageto{The Axiom Language}{ugIntroExpressionsPage}
\pageto{Graphics}{ugIntroGraphicsPage}
\pageto{Numbers}{ugIntroNumbersPage}
\pageto{Data Structures}{ugIntroCollectPage}
\pageto{Expanding to Higher Dimensions}{ugIntroTwoDimPage}
\pageto{Writing Your Own Functions}{ugIntroYouPage}
\pageto{Polynomials}{ugIntroVariablesPage}
\pageto{Limits}{ugIntroCalcLimitsPage}
\pageto{Series}{ugIntroSeriesPage}
\pageto{Derivatives}{ugIntroCalcDerivPage}
\pageto{Integration}{ugIntroIntegratePage}
\pageto{Differential Equations}{ugIntroDiffEqnsPage}
\pageto{Solution of Equations}{ugIntroSolutionPage}
\pageto{System Commands}{ugIntroSysCmmandsPage}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroPage}{1. An Overview of Axiom}

\beginscroll

Welcome to the Axiom environment for interactive computation and
problem solving.  Consider this chapter a brief, whirlwind tour of the
Axiom world.  We introduce you to Axiom's graphics and the Axiom
language.  Then we give a sampling of the large variety of facilities
in the Axiom system, ranging from the various kinds of numbers, to
data types (like lists, arrays, and sets) and mathematical objects
(like matrices, integrals, and differential equations).  We conclude
with the discussion of system commands and an interactive ``undo.''

Before embarking on the tour, we need to brief those readers
working interactively with Axiom on some details.
Others can skip right immediately to
\downlink{``Typographic Conventions''}{ugIntroTypoPage} in 
Section 1.2\ignore{ugIntroTypo}.

\beginmenu
    \menudownlink{{1.1. Starting Up and Winding Down}}{ugIntroStartPage}
    \menudownlink{{1.2. Typographic Conventions}}{ugIntroTypoPage}
    \menudownlink{{1.3. The Axiom Language}}{ugIntroExpressionsPage}
    \menudownlink{{1.4. Graphics}}{ugIntroGraphicsPage}
    \menudownlink{{1.5. Numbers}}{ugIntroNumbersPage}
    \menudownlink{{1.6. Data Structures}}{ugIntroCollectPage}
    \menudownlink{{1.7. Expanding to Higher Dimensions}}{ugIntroTwoDimPage}
    \menudownlink{{1.8. Writing Your Own Functions}}{ugIntroYouPage}
    \menudownlink{{1.9. Polynomials}}{ugIntroVariablesPage}
    \menudownlink{{1.10. Limits}}{ugIntroCalcLimitsPage}
    \menudownlink{{1.11. Series}}{ugIntroSeriesPage}
    \menudownlink{{1.12. Derivatives}}{ugIntroCalcDerivPage}
    \menudownlink{{1.13. Integration}}{ugIntroIntegratePage}
    \menudownlink{{1.14. Differential Equations}}{ugIntroDiffEqnsPage}
    \menudownlink{{1.15. Solution of Equations}}{ugIntroSolutionPage}
    \menudownlink{{1.16. System Commands}}{ugIntroSysCmmandsPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugIntroStartPage}{ug01.ht}{Starting Up and Winding Down}
\pageto{notitle}{ugHyperPage}
\pageto{notitle}{ugSysCmdPage}
\pageto{notitle}{ugAvailCLEFPage}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroStartPage}{1.1. Starting Up and Winding Down}
\beginscroll

You need to know how to start the Axiom system and how to stop it.  
We assume that Axiom has been correctly installed on your machine (as
described in another Axiom document).

To begin using Axiom, issue the command {\bf axiom} to the operating
system shell.  There is a brief pause, some start-up messages, and
then one or more windows appear.

If you are not running Axiom under the X Window System, there is only
one window (the console).  At the lower left of the screen there is a
prompt that looks like
\begin{verbatim}
(1) ->
\end{verbatim}

When you want to enter input to Axiom, you do so on the same line
after the prompt.  The ``1'' in ``(1)'' is the computation step number
and is incremented after you enter Axiom statements.  Note, however,
that a system command such as \spadsys{)clear all} may change the step
number in other ways.  We talk about step numbers more when we discuss
system commands and the workspace history facility.

If you are running Axiom under the X Window System, there may be two
windows: the console window (as just described) and the Hyperdoc main
menu.  Hyperdoc is a multiple-window hypertext system that lets you
view Axiom documentation and examples on-line, execute Axiom
expressions, and generate graphics.  If you are in a graphical
windowing environment, it is usually started automatically when Axiom
begins.  If it is not running, issue \spadsys{)hd} to start it.  We
discuss the basics of Hyperdoc in
\downlink{``Using Hyperdoc''}{ugHyperPage} in Chapter 3\ignore{ugHyper}.

To interrupt an Axiom computation, hold down the
\texht{\fbox{\bf Ctrl}}{{\bf Ctrl}} (control) key and press
\texht{\fbox{\bf c}}{{\bf c}}.
This  brings you back to the Axiom prompt.

\beginImportant

To exit from Axiom, move to the console window, type \spadsys{)quit}
at the input prompt and press the \texht{\fbox{\bf Enter}}
{{\bf Enter}} key.  You will probably be prompted with the following
message: \centerline{{Please enter {\bf y} or {\bf yes} if you really
want to leave the }} \centerline{{interactive environment and return
to the operating system}} You should respond {\bf yes}, for example,
to exit Axiom.
\endImportant

We are purposely vague in describing exactly what your screen looks
like or what messages Axiom displays.  Axiom runs on a number of
different machines, operating systems and window environments, and
these differences all affect the physical look of the system.  You can
also change the way that Axiom behaves via \spadgloss{system commands}
described later in this chapter and in
\downlink{``Axiom System Commands''}{ugSysCmdPage} in Appendix B
\ignore{ugSysCmd}.  System commands are special
commands, like \spadcmd{)set}, that begin with a closing parenthesis
and are used to change your environment.  For example, you can set a
system variable so that you are not prompted for confirmation when you
want to leave Axiom.

\beginmenu
    \menudownlink{{1.1.1. \Clef{}}}{ugAvailCLEFPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugAvailCLEFPage}{ug01.ht}{Clef}
\pagepic{ps/v71ugavailclefpage.eps}{ugAvailCLEFPage}{0.50}
\pagefrom{Computation of Galois Groups}{ugProblemGaloisPage}
\begin{chunk}{ug01.ht}
\begin{page}{ugAvailCLEFPage}{1.1.1. \Clef{}}
\beginscroll
%

If you are using Axiom under the X Window System, the \Clef{} command
line editor is probably available and installed.  With this editor you
can recall previous lines with the up and down arrow keys\texht{
(\fbox{$\uparrow$} and \fbox{$\downarrow$})}{}.  To move forward and
backward on a line, use the right and left arrows
\texht{(\fbox{$\rightarrow$} and \fbox{$\leftarrow$})}{}.  You can use the
\texht{\fbox{\bf Insert}}{{\bf Insert}} key to toggle insert mode on
or off.  When you are in insert mode, the cursor appears as a large
block and if you type anything, the characters are inserted into the
line without deleting the previous ones.

If you press the \texht{\fbox{\bf Home}}{{\bf Home}} key, the cursor
moves to the beginning of the line and if you press the
\texht{\fbox{\bf End}}{{\bf End}} key, the cursor moves to the end of
the line.  Pressing 
\texht{\fbox{\bf Ctrl}--\fbox{\bf End}}{{\bf Ctrl-End}} 
deletes all the text from the cursor to the end of the line.

\Clef{} also provides Axiom operation name completion for a limited
set of operations.  If you enter a few letters and then press the
\texht{\fbox{\bf Tab}}{{\bf Tab}} key, \Clef{} tries to use those
letters as the prefix of an Axiom operation name.  If a name appears
and it is not what you want, press \texht{\fbox{\bf Tab}}{{\bf Tab}}
again to see another name.

You are ready to begin your journey into the world of Axiom.
Proceed to the first stop.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugIntroTypoPage}{ug01.ht}{Typographic Conventions}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroTypoPage}{1.2. Typographic Conventions}
\beginscroll

In this book we have followed these typographical conventions:
\indent{4}
\beginitems
%
\item[-] Categories, domains and packages are displayed in
\texht{a sans-serif typeface:}{this font:}
\axiomType{Ring}, \axiomType{Integer}, 
\axiomType{DiophantineSolutionPackage}.
%
\item[-] Prefix operators, infix operators, and 
punctuation symbols in the Axiom
language are displayed in the text like this:
\axiomOp{+}, \axiomSyntax{\$}, \axiomSyntax{+->}.
%
\item[-] Axiom expressions or expression fragments are displayed in
\texht{a mon\-o\-space typeface:}{this font:}
\axiom{inc(x) == x + 1}.
%
\item[-] For clarity of presentation, \TeX{} is often
used to format expressions\texht{: $g(x)=x^2+1.$}{.}
%
\item[-] Function names and Hyperdoc button names
are displayed in the text in
\texht{a bold typeface:}{this font:}
\axiomFun{factor}, \axiomFun{integrate},  {\bf Lighting}.
%
\item[-] Italics are used for emphasis and for words defined in the
glossary: \spadgloss{category}.
\enditems
\indent{0}

This book contains over 2500 examples of Axiom input and output.
All examples were run though Axiom and their output was
created in \texht{\TeX{}}{TeX} form for this book by the Axiom
\axiomType{TexFormat} package.
We have deleted system messages from the example output if those
messages are not important for the discussions in which the examples
appear.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugIntroExpressionsPage}{ug01.ht}{The Axiom Language}
\pageto{notitle}{ugIntroArithmeticPage}
\pageto{notitle}{ugIntroPreviousPage}
\pageto{notitle}{ugIntroTypesPage}
\pageto{notitle}{ugIntroAssignPage}
\pageto{notitle}{ugIntroConversionPage}
\pageto{notitle}{ugIntroCallFunPage}
\pageto{notitle}{ugIntroMacrosPage}
\pageto{notitle}{ugIntroLongPage}
\pageto{notitle}{ugIntroCommentsPage}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroExpressionsPage}{1.3. The Axiom Language}
\beginscroll
%

The Axiom language is a rich language for performing interactive
computations and for building components of the Axiom library.  Here
we present only some basic aspects of the language that you need to
know for the rest of this chapter.  Our discussion here is
intentionally informal, with details unveiled on an ``as needed''
basis.  For more information on a particular construct, we suggest you
consult the index at the back of the book.

\beginmenu
    \menudownlink{{1.3.1. Arithmetic Expressions}}{ugIntroArithmeticPage}
    \menudownlink{{1.3.2. Previous Results}}{ugIntroPreviousPage}
    \menudownlink{{1.3.3. Some Types}}{ugIntroTypesPage}
    \menudownlink{
{1.3.4. Symbols, Variables, Assignments, and Declarations}}
{ugIntroAssignPage}
    \menudownlink{{1.3.5. Conversion}}{ugIntroConversionPage}
    \menudownlink{{1.3.6. Calling Functions}}{ugIntroCallFunPage}
    \menudownlink{{1.3.7. Some Predefined Macros}}{ugIntroMacrosPage}
    \menudownlink{{1.3.8. Long Lines}}{ugIntroLongPage}
    \menudownlink{{1.3.9. Comments}}{ugIntroCommentsPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugIntroArithmeticPage}{ug01.ht}{Arithmetic Expressions}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroArithmeticPage}{1.3.1. Arithmetic Expressions}
\beginscroll

For arithmetic expressions, use the \spadop{+} and \spadop{-}
\spadglossSee{operators}{operator} as in mathematics.  Use \spadop{*}
for multiplication, and \spadop{**} for exponentiation.  To create a
fraction, use \spadop{/}.  When an expression contains several
operators, those of highest \spadgloss{precedence} are evaluated
first.  For arithmetic operators, \spadop{**} has highest precedence,
\spadop{*} and \spadop{/} have the next highest precedence, and
\spadop{+} and \spadop{-} have the lowest precedence.

\xtc{
Axiom puts implicit parentheses around operations of higher
precedence, and groups those of equal precedence from left to right.
}{
\spadpaste{1 + 2 - 3 / 4 * 3 ** 2 - 1}
}
\xtc{
The above expression is equivalent to this.
}{
\spadpaste{((1 + 2) - ((3 / 4) * (3 ** 2))) - 1}
}
\xtc{
If an expression contains subexpressions enclosed in parentheses,
the parenthesized subexpressions are evaluated first (from left to
right, from inside out).
}{
\spadpaste{1 + 2 - 3/ (4 * 3 ** (2 - 1))}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntroArithmeticPagePatch1}
\begin{paste}{ugIntroArithmeticPageFull1}{ugIntroArithmeticPageEmpty1}
\pastebutton{ugIntroArithmeticPageFull1}{\hidepaste}
\tab{5}\spadcommand{1 + 2 - 3 / 4 * 3 ** 2 - 1}
\indentrel{3}\begin{verbatim}
          19
   (1)  - ÄÄ
           4
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroArithmeticPageEmpty1}
\begin{paste}{ugIntroArithmeticPageEmpty1}{ugIntroArithmeticPagePatch1}
\pastebutton{ugIntroArithmeticPageEmpty1}{\showpaste}
\tab{5}\spadcommand{1 + 2 - 3 / 4 * 3 ** 2 - 1}
\end{paste}\end{patch}

\begin{patch}{ugIntroArithmeticPagePatch2}
\begin{paste}{ugIntroArithmeticPageFull2}{ugIntroArithmeticPageEmpty2}
\pastebutton{ugIntroArithmeticPageFull2}{\hidepaste}
\tab{5}\spadcommand{((1 + 2) - ((3 / 4) * (3 ** 2))) - 1}
\indentrel{3}\begin{verbatim}
          19
   (2)  - ÄÄ
           4
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroArithmeticPageEmpty2}
\begin{paste}{ugIntroArithmeticPageEmpty2}{ugIntroArithmeticPagePatch2}
\pastebutton{ugIntroArithmeticPageEmpty2}{\showpaste}
\tab{5}\spadcommand{((1 + 2) - ((3 / 4) * (3 ** 2))) - 1}
\end{paste}\end{patch}

\begin{patch}{ugIntroArithmeticPagePatch3}
\begin{paste}{ugIntroArithmeticPageFull3}{ugIntroArithmeticPageEmpty3}
\pastebutton{ugIntroArithmeticPageFull3}{\hidepaste}
\tab{5}\spadcommand{1 + 2 - 3/ (4 * 3 ** (2 - 1))}
\indentrel{3}\begin{verbatim}
        11
   (3)  ÄÄ
         4
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroArithmeticPageEmpty3}
\begin{paste}{ugIntroArithmeticPageEmpty3}{ugIntroArithmeticPagePatch3}
\pastebutton{ugIntroArithmeticPageEmpty3}{\showpaste}
\tab{5}\spadcommand{1 + 2 - 3/ (4 * 3 ** (2 - 1))}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntroPreviousPage}{ug01.ht}{Previous Results}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroPreviousPage}{1.3.2. Previous Results}
\beginscroll

Use the percent sign (\axiomSyntax{\%}) to refer to the last
result.
Also, use \axiomSyntax{\%\%} to refer to previous results.
\axiom{\%\%(-1)} is equivalent to \axiomSyntax{\%},
\axiom{\%\%(-2)} returns the next to the last result, and so on.
\axiom{\%\%(1)} returns the result from step number 1,
\axiom{\%\%(2)} returns the result from step number 2, and so on.
\axiom{\%\%(0)} is not defined.

\xtc{
This is ten to the tenth power.
}{
\spadpaste{10 ** 10 \bound{prev}}
}
\xtc{
This is the last result minus one.
}{
\spadpaste{\% - 1 \free{prev}\bound{prev1}}
}
\xtc{
This is the last result.
}{
\spadpaste{\%\%(-1) \free{prev1}\bound{prev2}}
}
\xtc{
This is the result from step number 1.
}{
\spadpaste{\%\%(1) \free{prev2}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntroPreviousPagePatch1}
\begin{paste}{ugIntroPreviousPageFull1}{ugIntroPreviousPageEmpty1}
\pastebutton{ugIntroPreviousPageFull1}{\hidepaste}
\tab{5}\spadcommand{10 ** 10\bound{prev }}
\indentrel{3}\begin{verbatim}
   (1)  10000000000
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroPreviousPageEmpty1}
\begin{paste}{ugIntroPreviousPageEmpty1}{ugIntroPreviousPagePatch1}
\pastebutton{ugIntroPreviousPageEmpty1}{\showpaste}
\tab{5}\spadcommand{10 ** 10\bound{prev }}
\end{paste}\end{patch}

\begin{patch}{ugIntroPreviousPagePatch2}
\begin{paste}{ugIntroPreviousPageFull2}{ugIntroPreviousPageEmpty2}
\pastebutton{ugIntroPreviousPageFull2}{\hidepaste}
\tab{5}\spadcommand{\% - 1\free{prev }\bound{prev1 }}
\indentrel{3}\begin{verbatim}
   (2)  9999999999
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroPreviousPageEmpty2}
\begin{paste}{ugIntroPreviousPageEmpty2}{ugIntroPreviousPagePatch2}
\pastebutton{ugIntroPreviousPageEmpty2}{\showpaste}
\tab{5}\spadcommand{\% - 1\free{prev }\bound{prev1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroPreviousPagePatch3}
\begin{paste}{ugIntroPreviousPageFull3}{ugIntroPreviousPageEmpty3}
\pastebutton{ugIntroPreviousPageFull3}{\hidepaste}
\tab{5}\spadcommand{\%\%(-1)\free{prev1 }\bound{prev2 }}
\indentrel{3}\begin{verbatim}
   (3)  9999999999
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroPreviousPageEmpty3}
\begin{paste}{ugIntroPreviousPageEmpty3}{ugIntroPreviousPagePatch3}
\pastebutton{ugIntroPreviousPageEmpty3}{\showpaste}
\tab{5}\spadcommand{\%\%(-1)\free{prev1 }\bound{prev2 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroPreviousPagePatch4}
\begin{paste}{ugIntroPreviousPageFull4}{ugIntroPreviousPageEmpty4}
\pastebutton{ugIntroPreviousPageFull4}{\hidepaste}
\tab{5}\spadcommand{\%\%(1)\free{prev2 }}
\indentrel{3}\begin{verbatim}
   (4)  10000000000
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroPreviousPageEmpty4}
\begin{paste}{ugIntroPreviousPageEmpty4}{ugIntroPreviousPagePatch4}
\pastebutton{ugIntroPreviousPageEmpty4}{\showpaste}
\tab{5}\spadcommand{\%\%(1)\free{prev2 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntroTypesPage}{ug01.ht}{Some Types}
\pageto{notitle}{ugTypesPage}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroTypesPage}{1.3.3. Some Types}
\beginscroll

Everything in Axiom has a type.
The type determines what operations you can perform on an object and
how the object can be used.
An entire chapter of this book (
\downlink{``Using Types and Modes''}{ugTypesPage} 
in Chapter 2\ignore{ugTypes}) is dedicated to
the interactive use of types.
Several of the final chapters discuss how types are built and how
they are organized in the Axiom library.

\xtc{
Positive integers are given type \spadtype{PositiveInteger}.
}{
\spadpaste{8}
}
\xtc{
Negative ones are given type \spadtype{Integer}.
This fine distinction is helpful to the
Axiom interpreter.
}{
\spadpaste{-8}
}
\xtc{
Here a positive integer exponent gives a polynomial result.
}{
\spadpaste{x**8}
}
\xtc{
Here a negative integer exponent produces a fraction.
}{
\spadpaste{x**(-8)}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntroTypesPagePatch1}
\begin{paste}{ugIntroTypesPageFull1}{ugIntroTypesPageEmpty1}
\pastebutton{ugIntroTypesPageFull1}{\hidepaste}
\tab{5}\spadcommand{8}
\indentrel{3}\begin{verbatim}
   (1)  8
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroTypesPageEmpty1}
\begin{paste}{ugIntroTypesPageEmpty1}{ugIntroTypesPagePatch1}
\pastebutton{ugIntroTypesPageEmpty1}{\showpaste}
\tab{5}\spadcommand{8}
\end{paste}\end{patch}

\begin{patch}{ugIntroTypesPagePatch2}
\begin{paste}{ugIntroTypesPageFull2}{ugIntroTypesPageEmpty2}
\pastebutton{ugIntroTypesPageFull2}{\hidepaste}
\tab{5}\spadcommand{-8}
\indentrel{3}\begin{verbatim}
   (2)  - 8
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroTypesPageEmpty2}
\begin{paste}{ugIntroTypesPageEmpty2}{ugIntroTypesPagePatch2}
\pastebutton{ugIntroTypesPageEmpty2}{\showpaste}
\tab{5}\spadcommand{-8}
\end{paste}\end{patch}

\begin{patch}{ugIntroTypesPagePatch3}
\begin{paste}{ugIntroTypesPageFull3}{ugIntroTypesPageEmpty3}
\pastebutton{ugIntroTypesPageFull3}{\hidepaste}
\tab{5}\spadcommand{x**8}
\indentrel{3}\begin{verbatim}
         8
   (3)  x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroTypesPageEmpty3}
\begin{paste}{ugIntroTypesPageEmpty3}{ugIntroTypesPagePatch3}
\pastebutton{ugIntroTypesPageEmpty3}{\showpaste}
\tab{5}\spadcommand{x**8}
\end{paste}\end{patch}

\begin{patch}{ugIntroTypesPagePatch4}
\begin{paste}{ugIntroTypesPageFull4}{ugIntroTypesPageEmpty4}
\pastebutton{ugIntroTypesPageFull4}{\hidepaste}
\tab{5}\spadcommand{x**(-8)}
\indentrel{3}\begin{verbatim}
         1
   (4)  ÄÄ
         8
        x
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroTypesPageEmpty4}
\begin{paste}{ugIntroTypesPageEmpty4}{ugIntroTypesPagePatch4}
\pastebutton{ugIntroTypesPageEmpty4}{\showpaste}
\tab{5}\spadcommand{x**(-8)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntroAssignPage}{ug01.ht}
{Symbols, Variables, Assignments, and Declarations}
\pageto{notitle}{ugLangAssignPage}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroAssignPage}
{1.3.4. Symbols, Variables, Assignments, and Declarations}
\beginscroll

A \spadgloss{symbol} is a literal used for the input of things like
the ``variables'' in polynomials and power series.

\labelSpace{2pc}
\xtc{
We use the three symbols \axiom{x}, \axiom{y}, and \axiom{z} in
entering this polynomial.
}{
\spadpaste{(x - y*z)**2}
}

A symbol has a name beginning with an uppercase or lowercase
alphabetic character, \axiomSyntax{\%}, or \axiomSyntax{!}.
Successive characters (if any) can be any of the above, digits, or
\axiomSyntax{?}.  Case is distinguished: the symbol \axiom{points} is
different from the symbol \axiom{Points}.

A symbol can also be used in Axiom as a \spadgloss{variable}.  A
variable refers to a value.  To \spadglossSee{assign}{assignment} a
value to a variable, the operator \axiomSyntax{:=} is
used.\footnote{Axiom actually has two forms of assignment: {\it
immediate} assignment, as discussed here, and {\it delayed
assignment}. See \downlink{``Immediate and Delayed Assignments''}
{ugLangAssignPage} in Section 5.1\ignore{ugLangAssign} for details.}
A variable initially has no restrictions on the kinds of values to
which it can refer.

\xtc{
This assignment gives the value \axiom{4} (an integer) to
a variable named \axiom{x}.
}{
\spadpaste{x := 4}
}
\xtc{
This gives the value \axiom{z + 3/5} (a polynomial)  to \axiom{x}.
}{
\spadpaste{x := z + 3/5}
}
\xtc{
To restrict the types of objects that can be assigned to a variable,
use a \spadgloss{declaration}
}{
\spadpaste{y : Integer \bound{y}}
}
\xtc{
After a variable is declared to be of some type, only values
of that type can be assigned to that variable.
}{
\spadpaste{y := 89\bound{y1}\free{y}}
}
\xtc{
The declaration for \axiom{y} forces values assigned to \axiom{y} to
be converted to integer values.
}{
\spadpaste{y := sin \%pi}
}
\xtc{
If no such conversion is possible,
Axiom refuses to assign a value to \axiom{y}.
}{
\spadpaste{y := 2/3}
}
\xtc{
A type declaration can also be given together with an assignment.
The declaration can assist Axiom in choosing the correct
operations to apply.
}{
\spadpaste{f : Float := 2/3}
}

Any number of expressions can be given on input line.
Just separate them by semicolons.
Only the result of evaluating the last expression is displayed.

\xtc{
These two expressions have the same effect as
the previous single expression.
}{
\spadpaste{f : Float; f := 2/3 \bound{fff}}
}

The type of a symbol is either \axiomType{Symbol}
or \axiomType{Variable({\it name})} where {\it name} is the name
of the symbol.

\xtc{
By default, the interpreter
gives this symbol the type \axiomType{Variable(q)}.
}{
\spadpaste{q}
}
\xtc{
When multiple symbols are involved, \axiomType{Symbol} is used.
}{
\spadpaste{[q, r]}
}

\xtc{
What happens when you try to use a symbol that is the name of a variable?
}{
\spadpaste{f \free{fff}}
}
\xtc{
Use a single quote (\axiomSyntax{'}) before
the name to get the symbol.
}{
\spadpaste{'f}
}

Quoting a name creates a symbol by
preventing evaluation of the name as a variable.
Experience will teach you when you are most likely going to need to use
a quote.
We try to point out the location of such trouble spots.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntroAssignPagePatch1}
\begin{paste}{ugIntroAssignPageFull1}{ugIntroAssignPageEmpty1}
\pastebutton{ugIntroAssignPageFull1}{\hidepaste}
\tab{5}\spadcommand{(x - y*z)**2}
\indentrel{3}\begin{verbatim}
         2 2             2
   (1)  y z  - 2x y z + x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPageEmpty1}
\begin{paste}{ugIntroAssignPageEmpty1}{ugIntroAssignPagePatch1}
\pastebutton{ugIntroAssignPageEmpty1}{\showpaste}
\tab{5}\spadcommand{(x - y*z)**2}
\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPagePatch2}
\begin{paste}{ugIntroAssignPageFull2}{ugIntroAssignPageEmpty2}
\pastebutton{ugIntroAssignPageFull2}{\hidepaste}
\tab{5}\spadcommand{x := 4}
\indentrel{3}\begin{verbatim}
   (2)  4
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPageEmpty2}
\begin{paste}{ugIntroAssignPageEmpty2}{ugIntroAssignPagePatch2}
\pastebutton{ugIntroAssignPageEmpty2}{\showpaste}
\tab{5}\spadcommand{x := 4}
\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPagePatch3}
\begin{paste}{ugIntroAssignPageFull3}{ugIntroAssignPageEmpty3}
\pastebutton{ugIntroAssignPageFull3}{\hidepaste}
\tab{5}\spadcommand{x := z + 3/5}
\indentrel{3}\begin{verbatim}
            3
   (3)  z + Ä
            5
                      Type: Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPageEmpty3}
\begin{paste}{ugIntroAssignPageEmpty3}{ugIntroAssignPagePatch3}
\pastebutton{ugIntroAssignPageEmpty3}{\showpaste}
\tab{5}\spadcommand{x := z + 3/5}
\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPagePatch4}
\begin{paste}{ugIntroAssignPageFull4}{ugIntroAssignPageEmpty4}
\pastebutton{ugIntroAssignPageFull4}{\hidepaste}
\tab{5}\spadcommand{y : Integer\bound{y }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPageEmpty4}
\begin{paste}{ugIntroAssignPageEmpty4}{ugIntroAssignPagePatch4}
\pastebutton{ugIntroAssignPageEmpty4}{\showpaste}
\tab{5}\spadcommand{y : Integer\bound{y }}
\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPagePatch5}
\begin{paste}{ugIntroAssignPageFull5}{ugIntroAssignPageEmpty5}
\pastebutton{ugIntroAssignPageFull5}{\hidepaste}
\tab{5}\spadcommand{y := 89\bound{y1 }\free{y }}
\indentrel{3}\begin{verbatim}
   (5)  89
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPageEmpty5}
\begin{paste}{ugIntroAssignPageEmpty5}{ugIntroAssignPagePatch5}
\pastebutton{ugIntroAssignPageEmpty5}{\showpaste}
\tab{5}\spadcommand{y := 89\bound{y1 }\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPagePatch6}
\begin{paste}{ugIntroAssignPageFull6}{ugIntroAssignPageEmpty6}
\pastebutton{ugIntroAssignPageFull6}{\hidepaste}
\tab{5}\spadcommand{y := sin \%pi}
\indentrel{3}\begin{verbatim}
   (6)  0
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPageEmpty6}
\begin{paste}{ugIntroAssignPageEmpty6}{ugIntroAssignPagePatch6}
\pastebutton{ugIntroAssignPageEmpty6}{\showpaste}
\tab{5}\spadcommand{y := sin \%pi}
\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPagePatch7}
\begin{paste}{ugIntroAssignPageFull7}{ugIntroAssignPageEmpty7}
\pastebutton{ugIntroAssignPageFull7}{\hidepaste}
\tab{5}\spadcommand{y := 2/3}
\indentrel{3}\begin{verbatim}
   2
   Ä
   3
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPageEmpty7}
\begin{paste}{ugIntroAssignPageEmpty7}{ugIntroAssignPagePatch7}
\pastebutton{ugIntroAssignPageEmpty7}{\showpaste}
\tab{5}\spadcommand{y := 2/3}
\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPagePatch8}
\begin{paste}{ugIntroAssignPageFull8}{ugIntroAssignPageEmpty8}
\pastebutton{ugIntroAssignPageFull8}{\hidepaste}
\tab{5}\spadcommand{f : Float := 2/3}
\indentrel{3}\begin{verbatim}
   (7)  0.6666666666 6666666667
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPageEmpty8}
\begin{paste}{ugIntroAssignPageEmpty8}{ugIntroAssignPagePatch8}
\pastebutton{ugIntroAssignPageEmpty8}{\showpaste}
\tab{5}\spadcommand{f : Float := 2/3}
\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPagePatch9}
\begin{paste}{ugIntroAssignPageFull9}{ugIntroAssignPageEmpty9}
\pastebutton{ugIntroAssignPageFull9}{\hidepaste}
\tab{5}\spadcommand{f : Float; f := 2/3\bound{fff }}
\indentrel{3}\begin{verbatim}
   (8)  0.6666666666 6666666667
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPageEmpty9}
\begin{paste}{ugIntroAssignPageEmpty9}{ugIntroAssignPagePatch9}
\pastebutton{ugIntroAssignPageEmpty9}{\showpaste}
\tab{5}\spadcommand{f : Float; f := 2/3\bound{fff }}
\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPagePatch10}
\begin{paste}{ugIntroAssignPageFull10}{ugIntroAssignPageEmpty10}
\pastebutton{ugIntroAssignPageFull10}{\hidepaste}
\tab{5}\spadcommand{q}
\indentrel{3}\begin{verbatim}
   (9)  q
                                       Type: Variable q
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPageEmpty10}
\begin{paste}{ugIntroAssignPageEmpty10}{ugIntroAssignPagePatch10}
\pastebutton{ugIntroAssignPageEmpty10}{\showpaste}
\tab{5}\spadcommand{q}
\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPagePatch11}
\begin{paste}{ugIntroAssignPageFull11}{ugIntroAssignPageEmpty11}
\pastebutton{ugIntroAssignPageFull11}{\hidepaste}
\tab{5}\spadcommand{[q, r]}
\indentrel{3}\begin{verbatim}
   (10)  [q,r]
                   Type: List OrderedVariableList [q,r]
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPageEmpty11}
\begin{paste}{ugIntroAssignPageEmpty11}{ugIntroAssignPagePatch11}
\pastebutton{ugIntroAssignPageEmpty11}{\showpaste}
\tab{5}\spadcommand{[q, r]}
\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPagePatch12}
\begin{paste}{ugIntroAssignPageFull12}{ugIntroAssignPageEmpty12}
\pastebutton{ugIntroAssignPageFull12}{\hidepaste}
\tab{5}\spadcommand{f\free{fff }}
\indentrel{3}\begin{verbatim}
   (11)  0.6666666666 6666666667
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPageEmpty12}
\begin{paste}{ugIntroAssignPageEmpty12}{ugIntroAssignPagePatch12}
\pastebutton{ugIntroAssignPageEmpty12}{\showpaste}
\tab{5}\spadcommand{f\free{fff }}
\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPagePatch13}
\begin{paste}{ugIntroAssignPageFull13}{ugIntroAssignPageEmpty13}
\pastebutton{ugIntroAssignPageFull13}{\hidepaste}
\tab{5}\spadcommand{'f}
\indentrel{3}\begin{verbatim}
   (12)  f
                                       Type: Variable f
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroAssignPageEmpty13}
\begin{paste}{ugIntroAssignPageEmpty13}{ugIntroAssignPagePatch13}
\pastebutton{ugIntroAssignPageEmpty13}{\showpaste}
\tab{5}\spadcommand{'f}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntroConversionPage}{ug01.ht}{Conversion}
\pageto{notitle}{ugTypesConvertPage}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroConversionPage}{1.3.5. Conversion}
\beginscroll

Objects of one type can usually be ``converted'' to objects of several
other types.  To \spadglossSee{convert}{conversion} an object to a new
type, use the \axiomSyntax{::} infix operator.\footnote{Conversion is
discussed in detail in
\downlink{``Conversion''}{ugTypesConvertPage} in Section
2.7\ignore{ugTypesConvert}.}  For example, to
display an object, it is necessary to convert the object to type
\spadtype{OutputForm}.

\xtc{
This produces a polynomial with rational number coefficients.
}{
\spadpaste{p := r**2 + 2/3 \bound{p}}
}
\xtc{
Create a quotient of polynomials with integer coefficients
by using \axiomSyntax{::}.
}{
\spadpaste{p :: Fraction Polynomial Integer \free{p}}
}

Some conversions can be performed automatically when
Axiom tries to evaluate your input.
Others conversions must be explicitly requested.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntroConversionPagePatch1}
\begin{paste}{ugIntroConversionPageFull1}{ugIntroConversionPageEmpty1}
\pastebutton{ugIntroConversionPageFull1}{\hidepaste}
\tab{5}\spadcommand{p := r**2 + 2/3\bound{p }}
\indentrel{3}\begin{verbatim}
         2   2
   (1)  r  + Ä
             3
                      Type: Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroConversionPageEmpty1}
\begin{paste}{ugIntroConversionPageEmpty1}{ugIntroConversionPagePatch1}
\pastebutton{ugIntroConversionPageEmpty1}{\showpaste}
\tab{5}\spadcommand{p := r**2 + 2/3\bound{p }}
\end{paste}\end{patch}

\begin{patch}{ugIntroConversionPagePatch2}
\begin{paste}{ugIntroConversionPageFull2}{ugIntroConversionPageEmpty2}
\pastebutton{ugIntroConversionPageFull2}{\hidepaste}
\tab{5}\spadcommand{p :: Fraction Polynomial Integer\free{p }}
\indentrel{3}\begin{verbatim}
          2
        3r  + 2
   (2)  ÄÄÄÄÄÄÄ
           3
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroConversionPageEmpty2}
\begin{paste}{ugIntroConversionPageEmpty2}{ugIntroConversionPagePatch2}
\pastebutton{ugIntroConversionPageEmpty2}{\showpaste}
\tab{5}\spadcommand{p :: Fraction Polynomial Integer\free{p }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntroCallFunPage}{ug01.ht}{Calling Functions}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroCallFunPage}{1.3.6. Calling Functions}
\beginscroll

As we saw earlier, when you want to add or subtract two values,
you place the arithmetic operator \spadop{+}
or \spadop{-} between the two
\spadglossSee{arguments}{argument} denoting the values.
To use most other Axiom operations, however, you use another syntax:
write the name
of the operation first, then an open parenthesis, then each of the
arguments separated by commas, and, finally, a closing parenthesis.
If the operation takes only one argument and the argument is a number
or a symbol, you can omit the parentheses.

\xtc{
This calls the operation \axiomFun{factor} with the single
integer argument \axiom{120}.
}{
\spadpaste{factor(120)}
}
\xtc{
This is a call to \axiomFun{divide} with the two integer arguments
\axiom{125} and \axiom{7}.
}{
\spadpaste{divide(125,7)}
}
\xtc{
This calls \axiomFun{quatern} with four floating-point arguments.
}{
\spadpaste{quatern(3.4,5.6,2.9,0.1)}
}
\xtc{
This is the same as \axiom{factorial(10)}.
}{
\spadpaste{factorial 10}
}

An operations that returns a \spadtype{Boolean} value (that is,
\spad{true} or \spad{false}) frequently has a name suffixed with
a question mark (``?'').  For example, the \spadfun{even?}
operation returns \spad{true} if its integer argument is an even
number, \spad{false} otherwise.

An operation that can be destructive on one or more arguments
usually has a name ending in a exclamation point (``!'').
This actually means that it is {\it allowed} to update its
arguments but it is not {\it required} to do so. For example,
the underlying representation of a collection type may not allow
the very last element to removed and so an empty object may be
returned instead. Therefore, it is important that you use the
object returned by the operation and not rely on a physical
change having occurred within the object. Usually, destructive
operations are provided for efficiency reasons.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntroCallFunPagePatch1}
\begin{paste}{ugIntroCallFunPageFull1}{ugIntroCallFunPageEmpty1}
\pastebutton{ugIntroCallFunPageFull1}{\hidepaste}
\tab{5}\spadcommand{factor(120)}
\indentrel{3}\begin{verbatim}
         3
   (1)  2 3 5
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCallFunPageEmpty1}
\begin{paste}{ugIntroCallFunPageEmpty1}{ugIntroCallFunPagePatch1}
\pastebutton{ugIntroCallFunPageEmpty1}{\showpaste}
\tab{5}\spadcommand{factor(120)}
\end{paste}\end{patch}

\begin{patch}{ugIntroCallFunPagePatch2}
\begin{paste}{ugIntroCallFunPageFull2}{ugIntroCallFunPageEmpty2}
\pastebutton{ugIntroCallFunPageFull2}{\hidepaste}
\tab{5}\spadcommand{divide(125,7)}
\indentrel{3}\begin{verbatim}
   (2)  [quotient= 17,remainder= 6]
     Type: Record(quotient: Integer,remainder: Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCallFunPageEmpty2}
\begin{paste}{ugIntroCallFunPageEmpty2}{ugIntroCallFunPagePatch2}
\pastebutton{ugIntroCallFunPageEmpty2}{\showpaste}
\tab{5}\spadcommand{divide(125,7)}
\end{paste}\end{patch}

\begin{patch}{ugIntroCallFunPagePatch3}
\begin{paste}{ugIntroCallFunPageFull3}{ugIntroCallFunPageEmpty3}
\pastebutton{ugIntroCallFunPageFull3}{\hidepaste}
\tab{5}\spadcommand{quatern(3.4,5.6,2.9,0.1)}
\indentrel{3}\begin{verbatim}
   (3)  3.4 + 5.6 i + 2.9 j + 0.1 k
                                 Type: Quaternion Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCallFunPageEmpty3}
\begin{paste}{ugIntroCallFunPageEmpty3}{ugIntroCallFunPagePatch3}
\pastebutton{ugIntroCallFunPageEmpty3}{\showpaste}
\tab{5}\spadcommand{quatern(3.4,5.6,2.9,0.1)}
\end{paste}\end{patch}

\begin{patch}{ugIntroCallFunPagePatch4}
\begin{paste}{ugIntroCallFunPageFull4}{ugIntroCallFunPageEmpty4}
\pastebutton{ugIntroCallFunPageFull4}{\hidepaste}
\tab{5}\spadcommand{factorial 10}
\indentrel{3}\begin{verbatim}
   (4)  3628800
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCallFunPageEmpty4}
\begin{paste}{ugIntroCallFunPageEmpty4}{ugIntroCallFunPagePatch4}
\pastebutton{ugIntroCallFunPageEmpty4}{\showpaste}
\tab{5}\spadcommand{factorial 10}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntroMacrosPage}{ug01.ht}{Some Predefined Macros}
\pageto{notitle}{ugUserMacrosPage}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroMacrosPage}{1.3.7. Some Predefined Macros}
\beginscroll

Axiom provides several \spadglossSee{macros}{macro} for your
convenience.\footnote{See \downlink{``Macros''}{ugUserMacrosPage} in
Section 6.2\ignore{ugUserMacros} for a discussion on how to write your
own macros.}  Macros are names (or forms) that expand to larger
expressions for commonly used values.

\texht{
\centerline{{\begin{tabular}{ll}}}
\centerline{{\spadgloss{\%i} &  The square root of -1. }}
\centerline{{\spadgloss{\%e} &  The base of the natural logarithm. }}
\centerline{{\spadgloss{\%pi}            &  $\pi$. }}
\centerline{{\spadgloss{\%infinity}      &  $\infty$. }}
\centerline{{\spadgloss{\%plusInfinity}  &  $+\infty$. }}
\centerline{{\spadgloss{\%minusInfinity} &  $-\infty$.}}
\centerline{{\end{tabular}}}
}{
\indent{0}
\beginitems
\item[\axiomSyntax{\%i}]     \tab{17} The square root of -1.
\item[\axiomSyntax{\%e}]     \tab{17} The base of the natural logarithm.
\item[\axiomSyntax{\%pi}]            \tab{17} Pi.
\item[\axiomSyntax{\%infinity}]      \tab{17} Infinity.
\item[\axiomSyntax{\%plusInfinity}]  \tab{17} Plus infinity.
\item[\axiomSyntax{\%minusInfinity}] \tab{17} Minus infinity.
\enditems
\indent{0}
}

%To display all the macros (along with anything you have
%defined in the workspace), issue the system command \spadsys{)display all}.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugIntroLongPage}{ug01.ht}{Long Lines}
\pageto{notitle}{ugInOutInPage}
\pageto{notitle}{ugLangBlocksPage}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroLongPage}{1.3.8. Long Lines}
\beginscroll

When you enter Axiom expressions from your keyboard, there
will be times when they are too long to fit on one line.
Axiom does not care how long your lines are, so you can let
them continue from the right margin to the left side of the
next line.

Alternatively, you may want to enter several shorter lines and
have Axiom glue them together.
To get this glue, put an underscore (\_) at the end of
each line you wish to continue.
\begin{verbatim}
2_
+_
3
\end{verbatim}
is the same as if you had entered
\begin{verbatim}
2+3
\end{verbatim}

If you are putting your Axiom statements in an input file
(see \downlink{``Input Files''}{ugInOutInPage} 
in Section 4.1\ignore{ugInOutIn}),
you can use indentation to indicate the structure of your program.
(see \downlink{``Blocks''}{ugLangBlocksPage} 
in Section 5.2\ignore{ugLangBlocks}).

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugIntroCommentsPage}{ug01.ht}{Comments}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroCommentsPage}{1.3.9. Comments}
\beginscroll

Comment statements begin with two consecutive hyphens or two
consecutive plus signs and continue until the end of the line.

\xtc{
The comment beginning with {\tt --} is ignored by Axiom.
}{
\spadpaste{2 + 3   -- this is rather simple, no?}
}

There is no way to write long multi-line comments
other than starting each line with \axiomSyntax{--} or
\axiomSyntax{++}.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntroCommentsPagePatch1}
\begin{paste}{ugIntroCommentsPageFull1}{ugIntroCommentsPageEmpty1}
\pastebutton{ugIntroCommentsPageFull1}{\hidepaste}
\tab{5}\spadcommand{2 + 3 -- this is rather simple, no?}
\indentrel{3}\begin{verbatim}
   (1)  5
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCommentsPageEmpty1}
\begin{paste}{ugIntroCommentsPageEmpty1}{ugIntroCommentsPagePatch1}
\pastebutton{ugIntroCommentsPageEmpty1}{\showpaste}
\tab{5}\spadcommand{2 + 3 -- this is rather simple, no?}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntroGraphicsPage}{ug01.ht}{Graphics}
\pageto{notitle}{ugProblemNumericPage}
\pageto{notitle}{ugAppGraphicsPage}
\pageto{notitle}{ugGraphPage}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroGraphicsPage}{1.4. Graphics}
\beginscroll
%

Axiom has a two- and three-dimensional drawing and rendering package
that allows you to draw, shade, color, rotate, translate, map, clip,
scale and combine graphic output of Axiom computations.  The graphics
interface is capable of plotting functions of one or more variables
and plotting parametric surfaces.  Once the graphics figure appears in
a window, move your mouse to the window and click.  A control panel
appears immediately and allows you to interactively transform the
object.

\psXtc{
This is an example of Axiom's two-dimensional plotting.  From the 2D
Control Panel you can rescale the plot, turn axes and units on and off
and save the image, among other things.  This PostScript image was
produced by clicking on the
\texht{\fbox{\bf PS}}{{\bf PS}} 2D Control Panel button.
}{
\graphpaste{draw(cos(5*t/8), t=0..16*\%pi, coordinates==polar)}
}{
\epsffile[72 72 300 300]{../ps/rose-1.ps}
}

\psXtc{
This is an example of Axiom's three-dimensional plotting.  It is a
monochrome graph of the complex arctangent function.  The image
displayed was rotated and had the ``shade'' and ``outline'' display
options set from the 3D Control Panel.  The PostScript output was
produced by clicking on the \texht{\fbox{\bf save}}{{\bf save}} 3D
Control Panel button and then clicking on the \texht{\fbox{\bf
PS}}{{\bf PS}} button.  See
\downlink{``Numeric Functions''}{ugProblemNumericPage} in Section
8.1\ignore{ugProblemNumeric} for more details and
examples of Axiom's numeric and graphics capabilities.
}{
\graphpaste{draw((x,y) +-> real atan complex(x,y), -\%pi..\%pi, 
-\%pi..\%pi, colorFunction == (x,y) +-> argument atan complex(x,y))}
}{
\epsffile[72 72 285 285]{../ps/atan-1.ps}
}

An exhibit of \Gallery{} is given in the center section of this book.
For a description of the commands and programs that produced these
figures, see 
\downlink{``Programs for Axiom Images''}{ugAppGraphicsPage} 
in Appendix G.\ignore{ugAppGraphics}.
PostScript output is available so that Axiom images can be
printed.\footnote{PostScript is a trademark of Adobe Systems
Incorporated, registered in the United States.}  See
\downlink{``Graphics''}{ugGraphPage} in Chapter 7
\ignore{ugGraph} for more examples and details about
using Axiom's graphics facilities.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntroGraphicsPagePatch1}
\begin{paste}{ugIntroGraphicsPageFull1}{ugIntroGraphicsPageEmpty1}
\pastebutton{ugIntroGraphicsPageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(cos(5*t/8), t=0..16*\%pi, coordinates==polar)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/ugintrographicspage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/ugintrographicspage1}}
\end{paste}\end{patch}

\begin{patch}{ugIntroGraphicsPageEmpty1}
\begin{paste}{ugIntroGraphicsPageEmpty1}{ugIntroGraphicsPagePatch1}
\pastebutton{ugIntroGraphicsPageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(cos(5*t/8), t=0..16*\%pi, coordinates==polar)}
\end{paste}\end{patch}

\begin{patch}{ugIntroGraphicsPagePatch2}
\begin{paste}{ugIntroGraphicsPageFull2}{ugIntroGraphicsPageEmpty2}
\pastebutton{ugIntroGraphicsPageFull2}{\hidepaste}
\tab{5}\spadgraph{draw((x,y) +-> real atan complex(x,y), -\%pi..\%pi, -\%pi..\%pi, colorFunction == (x,y) +-> argument atan complex(x,y))}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/ugintrographicspage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/ugintrographicspage2}}
\end{paste}\end{patch}

\begin{patch}{ugIntroGraphicsPageEmpty2}
\begin{paste}{ugIntroGraphicsPageEmpty2}{ugIntroGraphicsPagePatch2}
\pastebutton{ugIntroGraphicsPageEmpty2}{\showpaste}
\tab{5}\spadgraph{draw((x,y) +-> real atan complex(x,y), -\%pi..\%pi, -\%pi..\%pi, colorFunction == (x,y) +-> argument atan complex(x,y))}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntroNumbersPage}{ug01.ht}{Numbers}
\pagepic{ps/v71ugintronumberspage.eps}{ugIntroNumbersPage}{0.50}
\pagefrom{Integer}{IntegerXmpPage}
\pageto{Float}{FloatXmpPage}
\pageto{DoubleFloat}{DoubleFloatXmpPage}
\pageto{DecimalExpansion}{DecimalExpansionXmpPage}
\pageto{ContinuedFraction}{ContinuedFractionXmpPage}
\pageto{PartialFraction}{PartialFractionXmpPage}
\pageto{RadixExpansion}{RadixExpansionXmpPage}
\pageto{Modular Arithmetic and Prime Fields}{ugxProblemFinitePrimePage}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroNumbersPage}{1.5. Numbers}
\beginscroll
%

Axiom distinguishes very carefully between different kinds
of numbers, how they are represented and what their properties
are.
Here are a sampling of some of these kinds of numbers and some
things you can do with them.

\xtc{
Integer arithmetic is always exact.
}{
\spadpaste{11**13 * 13**11 * 17**7 - 19**5 * 23**3}
}
\xtc{
Integers can be represented in factored form.
}{
\spadpaste{factor 643238070748569023720594412551704344145570763243 
\bound{ex1}}
}
\xtc{
Results stay factored when you do arithmetic.
Note that the \axiom{12} is automatically factored for you.
}{
\spadpaste{\% * 12 \free{ex1}}
}
\xtc{
Integers can also be displayed to bases other than 10.
This is an integer in base 11.
}{
\spadpaste{radix(25937424601,11)}
}
\xtc{
Roman numerals are also available for those special occasions.
}{
\spadpaste{roman(1992)}
}
\xtc{
Rational number arithmetic is also exact.
}{
\spadpaste{r := 10 + 9/2 + 8/3 + 7/4 + 6/5 + 5/6 + 4/7 + 3/8 + 2/9
\bound{r}}
}
\xtc{
To factor fractions, you have to
map \axiomFun{factor} onto the numerator and denominator.
}{
\spadpaste{map(factor,r) \free{r}}
}
\xtc{
Type \spadtype{SingleInteger} refers to machine word-length
integers.
In English, this expression means ``\axiom{11} as a small
integer''.
}{
\spadpaste{11@SingleInteger}
}
\xtc{
Machine double-precision floating-point numbers are also
available for numeric and graphical
applications.
}{
\spadpaste{123.21@DoubleFloat}
}

The normal floating-point type in Axiom, \spadtype{Float},
is a software implementation of floating-point numbers in which
the exponent and the mantissa may have any number of
digits.\footnote{See 
\downlink{`Float'}{FloatXmpPage}\ignore{Float} and 
\downlink{`DoubleFloat'}{DoubleFloatXmpPage}\ignore{DoubleFloat} for
additional information on floating-point types.}
The types \spadtype{Complex(Float)} and
\spadtype{Complex(DoubleFloat)} are the corresponding software
implementations of complex floating-point numbers.

\xtc{
This is a floating-point approximation to about twenty digits.
The \axiomSyntax{::}
is used here to change from one kind of object
(here, a rational number) to another (a floating-point number).
}{
\spadpaste{r :: Float \free{r}}
}
\xtc{
Use \spadfunFrom{digits}{Float} to change the number of digits in
the representation.
This operation returns the previous value so you can reset it
later.
}{
\spadpaste{digits(22) \bound{fewerdigits}}
}
\xtc{
To \axiom{22} digits of precision, the number
\texht{$e^{\pi {\sqrt {163.0}}}$}{\axiom{exp(\%pi * sqrt 163.0)}}
appears to be an integer.
}{
\spadpaste{exp(\%pi * sqrt 163.0) \free{fewerdigits}}
}
\xtc{
Increase the precision to forty digits and try again.
}{
\spadpaste{digits(40);  exp(\%pi * sqrt 163.0) \free{moredigits}}
}
\xtc{
Here are complex numbers with rational numbers as real and
imaginary parts.
}{
\spadpaste{(2/3 + \%i)**3 \bound{gaussint}}
}
\xtc{
The standard operations on complex numbers are available.
}{
\spadpaste{conjugate \% \free{gaussint}}
}
\xtc{
You can factor complex integers.
}{
\spadpaste{factor(89 - 23 * \%i)}
}
\xtc{
Complex numbers with floating point parts are also available.
}{
\spadpaste{exp(\%pi/4.0 * \%i)}
}
\xtc{
Every rational number has an exact representation as a
repeating decimal expansion
(see \downlink{`DecimalExpansion'}{DecimalExpansionXmpPage}
\ignore{DecimalExpansion}).
}{
\spadpaste{decimal(1/352)}
}
\xtc{
A rational number can also be expressed as a continued fraction (see
\downlink{`ContinuedFraction'}{ContinuedFractionXmpPage}
\ignore{ContinuedFraction}).
}{
\spadpaste{continuedFraction(6543/210)}
}
\xtc{
Also, partial fractions can be used and can be displayed in a
compact \ldots
}{
\spadpaste{partialFraction(1,factorial(10)) \bound{partfrac}}
}
\xtc{
or expanded format (see 
\downlink{`PartialFraction'}{PartialFractionXmpPage}
\ignore{PartialFraction}).
}{
\spadpaste{padicFraction(\%) \free{partfrac}}
}
\xtc{
Like integers, bases (radices) other than ten can be used for rational
numbers (see 
\downlink{`RadixExpansion'}{RadixExpansionXmpPage}
\ignore{RadixExpansion}).
Here we use base eight.
}{
\spadpaste{radix(4/7, 8)\bound{rad}}
}
\xtc{
Of course, there are complex versions of these as well.
Axiom decides to make the result a complex rational number.
}{
\spadpaste{\% + 2/3*\%i\free{rad}}
}
\xtc{
You can also use Axiom to manipulate fractional powers.
}{
\spadpaste{(5 + sqrt 63 + sqrt 847)**(1/3)}
}
\xtc{
You can also compute with integers modulo a prime.
}{
\spadpaste{x : PrimeField 7 := 5 \bound{x}}
}
\xtc{
Arithmetic is then done modulo \mathOrSpad{7}.
}{
\spadpaste{x**3 \free{x}}
}
\xtc{
Since \mathOrSpad{7} is prime, you can invert nonzero values.
}{
\spadpaste{1/x \free{x}}
}
\xtc{
You can also compute modulo an integer that is not a prime.
}{
\spadpaste{y : IntegerMod 6 := 5 \bound{y}}
}
\xtc{
All of the usual arithmetic operations are available.
}{
\spadpaste{y**3 \free{y}}
}
\xtc{
Inversion is not available if the modulus is not a prime
number.
Modular arithmetic and prime fields are discussed in
\downlink{``Modular Arithmetic and Prime Fields''}
{ugxProblemFinitePrimePage} 
in Section 8.11.1\ignore{ugxProblemFinitePrime}.
}{
\spadpaste{1/y \free{y}}
}
\xtc{
This defines \axiom{a} to be an algebraic number, that is,
a root of a polynomial equation.
}{
\spadpaste{a := rootOf(a**5 + a**3 + a**2 + 3,a) \bound{a}}
}
\xtc{
Computations with \axiom{a} are reduced according
to the polynomial equation.
}{
\spadpaste{(a + 1)**10\free{a}}
}
\xtc{
Define \axiom{b} to be an algebraic number involving \axiom{a}.
}{
\spadpaste{b := rootOf(b**4 + a,b) \bound{b}\free{a}}
}
\xtc{
Do some arithmetic.
}{
\spadpaste{2/(b - 1) \free{b}\bound{check}}
}
\xtc{
To expand and simplify this, call \axiomFun{ratDenom}
to rationalize the denominator.
}{
\spadpaste{ratDenom(\%) \free{check}\bound{check1}}
}
\xtc{
If we do this, we should get \axiom{b}.
}{
\spadpaste{2/\%+1 \free{check1}\bound{check2}}
}
\xtc{
But we need to rationalize the denominator again.
}{
\spadpaste{ratDenom(\%) \free{check2}}
}
\xtc{
Types \spadtype{Quaternion} and \spadtype{Octonion} are also available.
Multiplication of quaternions is non-commutative, as expected.
}{
\spadpaste{q:=quatern(1,2,3,4)*quatern(5,6,7,8) - 
quatern(5,6,7,8)*quatern(1,2,3,4)}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntroNumbersPagePatch1}
\begin{paste}{ugIntroNumbersPageFull1}{ugIntroNumbersPageEmpty1}
\pastebutton{ugIntroNumbersPageFull1}{\hidepaste}
\tab{5}\spadcommand{11**13 * 13**11 * 17**7 - 19**5 * 23**3}
\indentrel{3}\begin{verbatim}
   (1)  25387751112538918594666224484237298
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty1}
\begin{paste}{ugIntroNumbersPageEmpty1}{ugIntroNumbersPagePatch1}
\pastebutton{ugIntroNumbersPageEmpty1}{\showpaste}
\tab{5}\spadcommand{11**13 * 13**11 * 17**7 - 19**5 * 23**3}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch2}
\begin{paste}{ugIntroNumbersPageFull2}{ugIntroNumbersPageEmpty2}
\pastebutton{ugIntroNumbersPageFull2}{\hidepaste}
\tab{5}\spadcommand{factor 643238070748569023720594412551704344145570763243\bound{ex1 }}
\indentrel{3}\begin{verbatim}
          13  11  7  5  3  2
   (2)  11  13  17 19 23 29
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty2}
\begin{paste}{ugIntroNumbersPageEmpty2}{ugIntroNumbersPagePatch2}
\pastebutton{ugIntroNumbersPageEmpty2}{\showpaste}
\tab{5}\spadcommand{factor 643238070748569023720594412551704344145570763243\bound{ex1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch3}
\begin{paste}{ugIntroNumbersPageFull3}{ugIntroNumbersPageEmpty3}
\pastebutton{ugIntroNumbersPageFull3}{\hidepaste}
\tab{5}\spadcommand{\% * 12\free{ex1 }}
\indentrel{3}\begin{verbatim}
         2    13  11  7  5  3  2
   (3)  2 3 11  13  17 19 23 29
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty3}
\begin{paste}{ugIntroNumbersPageEmpty3}{ugIntroNumbersPagePatch3}
\pastebutton{ugIntroNumbersPageEmpty3}{\showpaste}
\tab{5}\spadcommand{\% * 12\free{ex1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch4}
\begin{paste}{ugIntroNumbersPageFull4}{ugIntroNumbersPageEmpty4}
\pastebutton{ugIntroNumbersPageFull4}{\hidepaste}
\tab{5}\spadcommand{radix(25937424601,11)}
\indentrel{3}\begin{verbatim}
   (4)  10000000000
                                Type: RadixExpansion 11
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty4}
\begin{paste}{ugIntroNumbersPageEmpty4}{ugIntroNumbersPagePatch4}
\pastebutton{ugIntroNumbersPageEmpty4}{\showpaste}
\tab{5}\spadcommand{radix(25937424601,11)}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch5}
\begin{paste}{ugIntroNumbersPageFull5}{ugIntroNumbersPageEmpty5}
\pastebutton{ugIntroNumbersPageFull5}{\hidepaste}
\tab{5}\spadcommand{roman(1992)}
\indentrel{3}\begin{verbatim}
   (5)  MCMXCII
                                     Type: RomanNumeral
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty5}
\begin{paste}{ugIntroNumbersPageEmpty5}{ugIntroNumbersPagePatch5}
\pastebutton{ugIntroNumbersPageEmpty5}{\showpaste}
\tab{5}\spadcommand{roman(1992)}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch6}
\begin{paste}{ugIntroNumbersPageFull6}{ugIntroNumbersPageEmpty6}
\pastebutton{ugIntroNumbersPageFull6}{\hidepaste}
\tab{5}\spadcommand{r := 10 + 9/2 + 8/3 + 7/4 + 6/5 + 5/6 + 4/7 + 3/8 + 2/9\bound{r }}
\indentrel{3}\begin{verbatim}
        55739
   (6)  ÄÄÄÄÄ
         2520
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty6}
\begin{paste}{ugIntroNumbersPageEmpty6}{ugIntroNumbersPagePatch6}
\pastebutton{ugIntroNumbersPageEmpty6}{\showpaste}
\tab{5}\spadcommand{r := 10 + 9/2 + 8/3 + 7/4 + 6/5 + 5/6 + 4/7 + 3/8 + 2/9\bound{r }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch7}
\begin{paste}{ugIntroNumbersPageFull7}{ugIntroNumbersPageEmpty7}
\pastebutton{ugIntroNumbersPageFull7}{\hidepaste}
\tab{5}\spadcommand{map(factor,r)\free{r }}
\indentrel{3}\begin{verbatim}
        139 401
   (7)  ÄÄÄÄÄÄÄ
         3 2
        2 3 5 7
                        Type: Fraction Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty7}
\begin{paste}{ugIntroNumbersPageEmpty7}{ugIntroNumbersPagePatch7}
\pastebutton{ugIntroNumbersPageEmpty7}{\showpaste}
\tab{5}\spadcommand{map(factor,r)\free{r }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch8}
\begin{paste}{ugIntroNumbersPageFull8}{ugIntroNumbersPageEmpty8}
\pastebutton{ugIntroNumbersPageFull8}{\hidepaste}
\tab{5}\spadcommand{11@SingleInteger}
\indentrel{3}\begin{verbatim}
   (8)  11
                                    Type: SingleInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty8}
\begin{paste}{ugIntroNumbersPageEmpty8}{ugIntroNumbersPagePatch8}
\pastebutton{ugIntroNumbersPageEmpty8}{\showpaste}
\tab{5}\spadcommand{11@SingleInteger}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch9}
\begin{paste}{ugIntroNumbersPageFull9}{ugIntroNumbersPageEmpty9}
\pastebutton{ugIntroNumbersPageFull9}{\hidepaste}
\tab{5}\spadcommand{123.21@DoubleFloat}
\indentrel{3}\begin{verbatim}
   (9)  123.21000000000001
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty9}
\begin{paste}{ugIntroNumbersPageEmpty9}{ugIntroNumbersPagePatch9}
\pastebutton{ugIntroNumbersPageEmpty9}{\showpaste}
\tab{5}\spadcommand{123.21@DoubleFloat}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch10}
\begin{paste}{ugIntroNumbersPageFull10}{ugIntroNumbersPageEmpty10}
\pastebutton{ugIntroNumbersPageFull10}{\hidepaste}
\tab{5}\spadcommand{r :: Float\free{r }}
\indentrel{3}\begin{verbatim}
   (10)  22.1186507936 50793651
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty10}
\begin{paste}{ugIntroNumbersPageEmpty10}{ugIntroNumbersPagePatch10}
\pastebutton{ugIntroNumbersPageEmpty10}{\showpaste}
\tab{5}\spadcommand{r :: Float\free{r }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch11}
\begin{paste}{ugIntroNumbersPageFull11}{ugIntroNumbersPageEmpty11}
\pastebutton{ugIntroNumbersPageFull11}{\hidepaste}
\tab{5}\spadcommand{digits(22)\bound{fewerdigits }}
\indentrel{3}\begin{verbatim}
   (11)  20
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty11}
\begin{paste}{ugIntroNumbersPageEmpty11}{ugIntroNumbersPagePatch11}
\pastebutton{ugIntroNumbersPageEmpty11}{\showpaste}
\tab{5}\spadcommand{digits(22)\bound{fewerdigits }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch12}
\begin{paste}{ugIntroNumbersPageFull12}{ugIntroNumbersPageEmpty12}
\pastebutton{ugIntroNumbersPageFull12}{\hidepaste}
\tab{5}\spadcommand{exp(\%pi * sqrt 163.0)\free{fewerdigits }}
\indentrel{3}\begin{verbatim}
   (12)  26253741 2640768744.0
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty12}
\begin{paste}{ugIntroNumbersPageEmpty12}{ugIntroNumbersPagePatch12}
\pastebutton{ugIntroNumbersPageEmpty12}{\showpaste}
\tab{5}\spadcommand{exp(\%pi * sqrt 163.0)\free{fewerdigits }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch13}
\begin{paste}{ugIntroNumbersPageFull13}{ugIntroNumbersPageEmpty13}
\pastebutton{ugIntroNumbersPageFull13}{\hidepaste}
\tab{5}\spadcommand{digits(40); exp(\%pi * sqrt 163.0)\free{moredigits }}
\indentrel{3}\begin{verbatim}
   (13)  26253741 2640768743.9999999999 9925007259 76
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty13}
\begin{paste}{ugIntroNumbersPageEmpty13}{ugIntroNumbersPagePatch13}
\pastebutton{ugIntroNumbersPageEmpty13}{\showpaste}
\tab{5}\spadcommand{digits(40); exp(\%pi * sqrt 163.0)\free{moredigits }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch14}
\begin{paste}{ugIntroNumbersPageFull14}{ugIntroNumbersPageEmpty14}
\pastebutton{ugIntroNumbersPageFull14}{\hidepaste}
\tab{5}\spadcommand{(2/3 + \%i)**3\bound{gaussint }}
\indentrel{3}\begin{verbatim}
           46   1
   (14)  - ÄÄ + Ä %i
           27   3
                         Type: Complex Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty14}
\begin{paste}{ugIntroNumbersPageEmpty14}{ugIntroNumbersPagePatch14}
\pastebutton{ugIntroNumbersPageEmpty14}{\showpaste}
\tab{5}\spadcommand{(2/3 + \%i)**3\bound{gaussint }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch15}
\begin{paste}{ugIntroNumbersPageFull15}{ugIntroNumbersPageEmpty15}
\pastebutton{ugIntroNumbersPageFull15}{\hidepaste}
\tab{5}\spadcommand{conjugate \%\free{gaussint }}
\indentrel{3}\begin{verbatim}
           46   1
   (15)  - ÄÄ - Ä %i
           27   3
                         Type: Complex Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty15}
\begin{paste}{ugIntroNumbersPageEmpty15}{ugIntroNumbersPagePatch15}
\pastebutton{ugIntroNumbersPageEmpty15}{\showpaste}
\tab{5}\spadcommand{conjugate \%\free{gaussint }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch16}
\begin{paste}{ugIntroNumbersPageFull16}{ugIntroNumbersPageEmpty16}
\pastebutton{ugIntroNumbersPageFull16}{\hidepaste}
\tab{5}\spadcommand{factor(89 - 23 * \%i)}
\indentrel{3}\begin{verbatim}
                           2         2
   (16)  - (1 + %i)(2 + %i) (3 + 2%i)
                         Type: Factored Complex Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty16}
\begin{paste}{ugIntroNumbersPageEmpty16}{ugIntroNumbersPagePatch16}
\pastebutton{ugIntroNumbersPageEmpty16}{\showpaste}
\tab{5}\spadcommand{factor(89 - 23 * \%i)}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch17}
\begin{paste}{ugIntroNumbersPageFull17}{ugIntroNumbersPageEmpty17}
\pastebutton{ugIntroNumbersPageFull17}{\hidepaste}
\tab{5}\spadcommand{exp(\%pi/4.0 * \%i)}
\indentrel{3}\begin{verbatim}
   (17)
     0.7071067811 8654752440 0844362104 8490392849
   + 
     0.7071067811 8654752440 0844362104 8490392848 %i
                                    Type: Complex Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty17}
\begin{paste}{ugIntroNumbersPageEmpty17}{ugIntroNumbersPagePatch17}
\pastebutton{ugIntroNumbersPageEmpty17}{\showpaste}
\tab{5}\spadcommand{exp(\%pi/4.0 * \%i)}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch18}
\begin{paste}{ugIntroNumbersPageFull18}{ugIntroNumbersPageEmpty18}
\pastebutton{ugIntroNumbersPageFull18}{\hidepaste}
\tab{5}\spadcommand{decimal(1/352)}
\indentrel{3}\begin{verbatim}
                __
   (18)  0.0028409
                                 Type: DecimalExpansion
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty18}
\begin{paste}{ugIntroNumbersPageEmpty18}{ugIntroNumbersPagePatch18}
\pastebutton{ugIntroNumbersPageEmpty18}{\showpaste}
\tab{5}\spadcommand{decimal(1/352)}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch19}
\begin{paste}{ugIntroNumbersPageFull19}{ugIntroNumbersPageEmpty19}
\pastebutton{ugIntroNumbersPageFull19}{\hidepaste}
\tab{5}\spadcommand{continuedFraction(6543/210)}
\indentrel{3}\begin{verbatim}
                1 ³     1 ³     1 ³     1 ³
   (19)  31 + ÚÄÄÄÙ + ÚÄÄÄÙ + ÚÄÄÄÙ + ÚÄÄÄÙ
              ³ 6     ³ 2     ³ 1     ³ 3
                        Type: ContinuedFraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty19}
\begin{paste}{ugIntroNumbersPageEmpty19}{ugIntroNumbersPagePatch19}
\pastebutton{ugIntroNumbersPageEmpty19}{\showpaste}
\tab{5}\spadcommand{continuedFraction(6543/210)}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch20}
\begin{paste}{ugIntroNumbersPageFull20}{ugIntroNumbersPageEmpty20}
\pastebutton{ugIntroNumbersPageFull20}{\hidepaste}
\tab{5}\spadcommand{partialFraction(1,factorial(10))\bound{partfrac }}
\indentrel{3}\begin{verbatim}
         159   23   12   1
   (20)  ÄÄÄ - ÄÄ - ÄÄ + Ä
           8    4    2   7
          2    3    5
                          Type: PartialFraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty20}
\begin{paste}{ugIntroNumbersPageEmpty20}{ugIntroNumbersPagePatch20}
\pastebutton{ugIntroNumbersPageEmpty20}{\showpaste}
\tab{5}\spadcommand{partialFraction(1,factorial(10))\bound{partfrac }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch21}
\begin{paste}{ugIntroNumbersPageFull21}{ugIntroNumbersPageEmpty21}
\pastebutton{ugIntroNumbersPageFull21}{\hidepaste}
\tab{5}\spadcommand{padicFraction(\%)\free{partfrac }}
\indentrel{3}\begin{verbatim}
   (21)
   1    1    1    1    1    1    2    1    2   2    2   1
   Ä + ÄÄ + ÄÄ + ÄÄ + ÄÄ + ÄÄ - ÄÄ - ÄÄ - ÄÄ - Ä - ÄÄ + Ä
   2    4    5    6    7    8    2    3    4   5    2   7
       2    2    2    2    2    3    3    3        5
                          Type: PartialFraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty21}
\begin{paste}{ugIntroNumbersPageEmpty21}{ugIntroNumbersPagePatch21}
\pastebutton{ugIntroNumbersPageEmpty21}{\showpaste}
\tab{5}\spadcommand{padicFraction(\%)\free{partfrac }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch22}
\begin{paste}{ugIntroNumbersPageFull22}{ugIntroNumbersPageEmpty22}
\pastebutton{ugIntroNumbersPageFull22}{\hidepaste}
\tab{5}\spadcommand{radix(4/7, 8)\bound{rad }}
\indentrel{3}\begin{verbatim}
           _
   (22)  0.4
                                 Type: RadixExpansion 8
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty22}
\begin{paste}{ugIntroNumbersPageEmpty22}{ugIntroNumbersPagePatch22}
\pastebutton{ugIntroNumbersPageEmpty22}{\showpaste}
\tab{5}\spadcommand{radix(4/7, 8)\bound{rad }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch23}
\begin{paste}{ugIntroNumbersPageFull23}{ugIntroNumbersPageEmpty23}
\pastebutton{ugIntroNumbersPageFull23}{\hidepaste}
\tab{5}\spadcommand{\% + 2/3*\%i\free{rad }}
\indentrel{3}\begin{verbatim}
         4   2
   (23)  Ä + Ä %i
         7   3
                         Type: Complex Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty23}
\begin{paste}{ugIntroNumbersPageEmpty23}{ugIntroNumbersPagePatch23}
\pastebutton{ugIntroNumbersPageEmpty23}{\showpaste}
\tab{5}\spadcommand{\% + 2/3*\%i\free{rad }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch24}
\begin{paste}{ugIntroNumbersPageFull24}{ugIntroNumbersPageEmpty24}
\pastebutton{ugIntroNumbersPageFull24}{\hidepaste}
\tab{5}\spadcommand{(5 + sqrt 63 + sqrt 847)**(1/3)}
\indentrel{3}\begin{verbatim}
          ÚÄÄÄÄÄÄÄÄÄÄ¿
         3³   ÚÄ¿
   (24)  \³14\³7  + 5
                                  Type: AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty24}
\begin{paste}{ugIntroNumbersPageEmpty24}{ugIntroNumbersPagePatch24}
\pastebutton{ugIntroNumbersPageEmpty24}{\showpaste}
\tab{5}\spadcommand{(5 + sqrt 63 + sqrt 847)**(1/3)}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch25}
\begin{paste}{ugIntroNumbersPageFull25}{ugIntroNumbersPageEmpty25}
\pastebutton{ugIntroNumbersPageFull25}{\hidepaste}
\tab{5}\spadcommand{x : PrimeField 7 := 5\bound{x }}
\indentrel{3}\begin{verbatim}
   (25)  5
                                     Type: PrimeField 7
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty25}
\begin{paste}{ugIntroNumbersPageEmpty25}{ugIntroNumbersPagePatch25}
\pastebutton{ugIntroNumbersPageEmpty25}{\showpaste}
\tab{5}\spadcommand{x : PrimeField 7 := 5\bound{x }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch26}
\begin{paste}{ugIntroNumbersPageFull26}{ugIntroNumbersPageEmpty26}
\pastebutton{ugIntroNumbersPageFull26}{\hidepaste}
\tab{5}\spadcommand{x**3\free{x }}
\indentrel{3}\begin{verbatim}
   (26)  6
                                     Type: PrimeField 7
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty26}
\begin{paste}{ugIntroNumbersPageEmpty26}{ugIntroNumbersPagePatch26}
\pastebutton{ugIntroNumbersPageEmpty26}{\showpaste}
\tab{5}\spadcommand{x**3\free{x }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch27}
\begin{paste}{ugIntroNumbersPageFull27}{ugIntroNumbersPageEmpty27}
\pastebutton{ugIntroNumbersPageFull27}{\hidepaste}
\tab{5}\spadcommand{1/x\free{x }}
\indentrel{3}\begin{verbatim}
   (27)  3
                                     Type: PrimeField 7
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty27}
\begin{paste}{ugIntroNumbersPageEmpty27}{ugIntroNumbersPagePatch27}
\pastebutton{ugIntroNumbersPageEmpty27}{\showpaste}
\tab{5}\spadcommand{1/x\free{x }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch28}
\begin{paste}{ugIntroNumbersPageFull28}{ugIntroNumbersPageEmpty28}
\pastebutton{ugIntroNumbersPageFull28}{\hidepaste}
\tab{5}\spadcommand{y : IntegerMod 6 := 5\bound{y }}
\indentrel{3}\begin{verbatim}
   (28)  5
                                     Type: IntegerMod 6
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty28}
\begin{paste}{ugIntroNumbersPageEmpty28}{ugIntroNumbersPagePatch28}
\pastebutton{ugIntroNumbersPageEmpty28}{\showpaste}
\tab{5}\spadcommand{y : IntegerMod 6 := 5\bound{y }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch29}
\begin{paste}{ugIntroNumbersPageFull29}{ugIntroNumbersPageEmpty29}
\pastebutton{ugIntroNumbersPageFull29}{\hidepaste}
\tab{5}\spadcommand{y**3\free{y }}
\indentrel{3}\begin{verbatim}
   (29)  5
                                     Type: IntegerMod 6
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty29}
\begin{paste}{ugIntroNumbersPageEmpty29}{ugIntroNumbersPagePatch29}
\pastebutton{ugIntroNumbersPageEmpty29}{\showpaste}
\tab{5}\spadcommand{y**3\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch30}
\begin{paste}{ugIntroNumbersPageFull30}{ugIntroNumbersPageEmpty30}
\pastebutton{ugIntroNumbersPageFull30}{\hidepaste}
\tab{5}\spadcommand{1/y\free{y }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty30}
\begin{paste}{ugIntroNumbersPageEmpty30}{ugIntroNumbersPagePatch30}
\pastebutton{ugIntroNumbersPageEmpty30}{\showpaste}
\tab{5}\spadcommand{1/y\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch31}
\begin{paste}{ugIntroNumbersPageFull31}{ugIntroNumbersPageEmpty31}
\pastebutton{ugIntroNumbersPageFull31}{\hidepaste}
\tab{5}\spadcommand{a := rootOf(a**5 + a**3 + a**2 + 3,a)\bound{a }}
\indentrel{3}\begin{verbatim}
   (30)  a
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty31}
\begin{paste}{ugIntroNumbersPageEmpty31}{ugIntroNumbersPagePatch31}
\pastebutton{ugIntroNumbersPageEmpty31}{\showpaste}
\tab{5}\spadcommand{a := rootOf(a**5 + a**3 + a**2 + 3,a)\bound{a }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch32}
\begin{paste}{ugIntroNumbersPageFull32}{ugIntroNumbersPageEmpty32}
\pastebutton{ugIntroNumbersPageFull32}{\hidepaste}
\tab{5}\spadcommand{(a + 1)**10\free{a }}
\indentrel{3}\begin{verbatim}
              4       3       2
   (31)  - 85a  - 264a  - 378a  - 458a - 287
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty32}
\begin{paste}{ugIntroNumbersPageEmpty32}{ugIntroNumbersPagePatch32}
\pastebutton{ugIntroNumbersPageEmpty32}{\showpaste}
\tab{5}\spadcommand{(a + 1)**10\free{a }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch33}
\begin{paste}{ugIntroNumbersPageFull33}{ugIntroNumbersPageEmpty33}
\pastebutton{ugIntroNumbersPageFull33}{\hidepaste}
\tab{5}\spadcommand{b := rootOf(b**4 + a,b)\bound{b }\free{a }}
\indentrel{3}\begin{verbatim}
   (32)  b
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty33}
\begin{paste}{ugIntroNumbersPageEmpty33}{ugIntroNumbersPagePatch33}
\pastebutton{ugIntroNumbersPageEmpty33}{\showpaste}
\tab{5}\spadcommand{b := rootOf(b**4 + a,b)\bound{b }\free{a }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch34}
\begin{paste}{ugIntroNumbersPageFull34}{ugIntroNumbersPageEmpty34}
\pastebutton{ugIntroNumbersPageFull34}{\hidepaste}
\tab{5}\spadcommand{2/(b - 1)\free{b }\bound{check }}
\indentrel{3}\begin{verbatim}
           2
   (33)  ÄÄÄÄÄ
         b - 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty34}
\begin{paste}{ugIntroNumbersPageEmpty34}{ugIntroNumbersPagePatch34}
\pastebutton{ugIntroNumbersPageEmpty34}{\showpaste}
\tab{5}\spadcommand{2/(b - 1)\free{b }\bound{check }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch35}
\begin{paste}{ugIntroNumbersPageFull35}{ugIntroNumbersPageEmpty35}
\pastebutton{ugIntroNumbersPageFull35}{\hidepaste}
\tab{5}\spadcommand{ratDenom(\%)\free{check }\bound{check1 }}
\indentrel{3}\begin{verbatim}
   (34)
       4    3     2          3     4    3     2          2
     (a  - a  + 2a  - a + 1)b  + (a  - a  + 2a  - a + 1)b
   + 
       4    3     2              4    3     2
     (a  - a  + 2a  - a + 1)b + a  - a  + 2a  - a + 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty35}
\begin{paste}{ugIntroNumbersPageEmpty35}{ugIntroNumbersPagePatch35}
\pastebutton{ugIntroNumbersPageEmpty35}{\showpaste}
\tab{5}\spadcommand{ratDenom(\%)\free{check }\bound{check1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch36}
\begin{paste}{ugIntroNumbersPageFull36}{ugIntroNumbersPageEmpty36}
\pastebutton{ugIntroNumbersPageFull36}{\hidepaste}
\tab{5}\spadcommand{2/\%+1\free{check1 }\bound{check2 }}
\indentrel{3}\begin{verbatim}
   (35)
         4    3     2          3
       (a  - a  + 2a  - a + 1)b
     + 
         4    3     2          2
       (a  - a  + 2a  - a + 1)b
     + 
         4    3     2              4    3     2
       (a  - a  + 2a  - a + 1)b + a  - a  + 2a  - a + 3
  /
         4    3     2          3
       (a  - a  + 2a  - a + 1)b
     + 
         4    3     2          2
       (a  - a  + 2a  - a + 1)b
     + 
         4    3     2              4    3     2
       (a  - a  + 2a  - a + 1)b + a  - a  + 2a  - a + 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty36}
\begin{paste}{ugIntroNumbersPageEmpty36}{ugIntroNumbersPagePatch36}
\pastebutton{ugIntroNumbersPageEmpty36}{\showpaste}
\tab{5}\spadcommand{2/\%+1\free{check1 }\bound{check2 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch37}
\begin{paste}{ugIntroNumbersPageFull37}{ugIntroNumbersPageEmpty37}
\pastebutton{ugIntroNumbersPageFull37}{\hidepaste}
\tab{5}\spadcommand{ratDenom(\%)\free{check2 }}
\indentrel{3}\begin{verbatim}
   (36)  b
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty37}
\begin{paste}{ugIntroNumbersPageEmpty37}{ugIntroNumbersPagePatch37}
\pastebutton{ugIntroNumbersPageEmpty37}{\showpaste}
\tab{5}\spadcommand{ratDenom(\%)\free{check2 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPagePatch38}
\begin{paste}{ugIntroNumbersPageFull38}{ugIntroNumbersPageEmpty38}
\pastebutton{ugIntroNumbersPageFull38}{\hidepaste}
\tab{5}\spadcommand{q:=quatern(1,2,3,4)*quatern(5,6,7,8) - quatern(5,6,7,8)*quatern(1,2,3,4)}
\indentrel{3}\begin{verbatim}
   (37)  - 8i + 16j - 8k
                               Type: Quaternion Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroNumbersPageEmpty38}
\begin{paste}{ugIntroNumbersPageEmpty38}{ugIntroNumbersPagePatch38}
\pastebutton{ugIntroNumbersPageEmpty38}{\showpaste}
\tab{5}\spadcommand{q:=quatern(1,2,3,4)*quatern(5,6,7,8) - quatern(5,6,7,8)*quatern(1,2,3,4)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntroCollectPage}{ug01.ht}{Data Structures}
\pageto{notitle}{ListXmpPage}
\pageto{notitle}{ugLangItsPage}
\pageto{notitle}{StreamXmpPage}
\pageto{notitle}{ugLangItsPage}
\pageto{notitle}{OneDimensionalArrayXmpPage}
\pageto{notitle}{FlexibleArrayXmpPage}
\pageto{notitle}{HeapXmpPage}
\pageto{notitle}{BinarySearchTreeXmpPage}
\pageto{notitle}{BalancedBinaryTreeXmpPage}
\pageto{notitle}{SetXmpPage}
\pageto{notitle}{MultiSetXmpPage}
\pageto{notitle}{AssociationListXmpPage}
\pageto{notitle}{KeyedAccessFileXmpPage}
\pageto{notitle}{LibraryXmpPage}
\pageto{notitle}{SparseTableXmpPage}
\pageto{notitle}{StringTableXmpPage}
\pageto{notitle}{TableXmpPage}
\pageto{notitle}{ugTypesRecordsPage}
\pageto{notitle}{ugTypesUnionsPage}
\pageto{notitle}{ugDomainsPage}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroCollectPage}{1.6. Data Structures}
\beginscroll
%

Axiom has a large variety of data structures available.
Many data structures are particularly useful for interactive
computation and others are useful for building applications.
The data structures of Axiom are organized into
\spadglossSee{category hierarchies}{hierarchy} as shown on
the inside back cover.

A \spadgloss{list} is the most commonly used data structure in
Axiom for holding objects all of the same
type.\footnote{Lists are discussed in 
\downlink{`List'}{ListXmpPage}\ignore{List} and in
\downlink{``Creating Lists and Streams with Iterators''}
{ugLangItsPage} in Section 5.5\ignore{ugLangIts}.}
The name {\it list} is short for ``linked-list of nodes.'' Each
node consists of a value (\spadfunFrom{first}{List}) and a link
(\spadfunFrom{rest}{List}) that
\spadglossSee{points}{pointer} to the next node, or to a
distinguished value denoting the empty list.
To get to, say, the third element, Axiom starts at the front
of the list, then traverses across two links to the third node.

\xtc{
Write a list of elements using
square brackets with commas separating the elements.
}{
\spadpaste{u := [1,-7,11] \bound{u}}
}
\xtc{
This is the value at the third node.
Alternatively, you can say \axiom{u.3}.
}{
\spadpaste{first rest rest u\free{u}}
}

Many operations are defined on lists, such as:
\axiomFun{empty?}, to test that a list has no elements;
\axiomFun{cons}\axiom{(x,l)}, to create a new list with
\axiomFun{first} element \axiom{x} and \axiomFun{rest} \axiom{l};
\axiomFun{reverse}, to create a new list with elements in reverse
order; and \axiomFun{sort}, to arrange elements in order.

An important point about lists is that they are ``mutable'': their
constituent elements and links can be changed ``in place.''
To do this, use any of the operations whose names end with the
character \axiomSyntax{!}.

\xtc{
The operation \spadfunFromX{concat}{List}\axiom{(u,v)}
replaces the last link of the list
\axiom{u} to point to some other list \axiom{v}.
Since \axiom{u} refers to the original list,
this change is seen by \axiom{u}.
}{
\spadpaste{concat!(u,[9,1,3,-4]); u\free{u}\bound{u1}}
}
\xtc{
A {\it cyclic list} is a list with a ``cycle'':
a link pointing back to an earlier node of the list.
To create a cycle, first get a node somewhere down
the list.
}{
\spadpaste{lastnode := rest(u,3)\free{u1}\bound{u2}}
}
\xtc{
Use \spadfunFromX{setrest}{List} to
change the link emanating from that node to point back to an
earlier part of the list.
}{
\spadpaste{setrest!(lastnode,rest(u,2)); u\free{u2}}
}

A \spadgloss{stream}
is a structure that (potentially) has an infinite number of
distinct elements.\footnote{Streams are discussed in
\downlink{`Stream'}{StreamXmpPage}\ignore{Stream} and in 
\downlink{``Creating Lists and Streams with Iterators''}
{ugLangItsPage} in Section 5.5\ignore{ugLangIts}.}
Think of a stream as an ``infinite list'' where elements are
computed successively.

\xtc{
Create an infinite stream of factored integers.
Only a certain number of initial elements are computed
and displayed.
}{
\spadpaste{[factor(i) for i in 2.. by 2] \bound{stream1}}
}
\xtc{
Axiom represents streams by a collection of already-computed
elements together with a function to compute the next element
``on demand.''
Asking for the \eth{\axiom{n}} element causes elements \axiom{1} through
\axiom{n} to be evaluated.
}{
\spadpaste{\%.36 \free{stream1}}
}

Streams can also be finite or cyclic.
They are implemented by a linked list structure similar to lists
and have many of the same operations.
For example, \axiomFun{first} and \axiomFun{rest} are used to access
elements and successive nodes of a stream.
%%> reverse and sort do not exist for streams
%%Don't try to reverse or sort a stream: the
%%operation will generally run forever!

A \spadgloss{one-dimensional array} is another data structure used
to hold objects of the same type.\footnote{See 
\downlink{`OneDimensionalArray'}{OneDimensionalArrayXmpPage}
\ignore{OneDimensionalArray} for
details.}
Unlike lists, one-dimensional arrays are inflexible---they are
implemented using a fixed block of storage.
Their advantage is that they give quick and equal access time to
any element.

\xtc{
A simple way to create a one-dimensional array is to apply the
operation \axiomFun{oneDimensionalArray} to a list of elements.
}{
\spadpaste{a := oneDimensionalArray [1, -7, 3, 3/2]\bound{a}}
}
\xtc{
One-dimensional arrays are also mutable:
you can change their constituent elements ``in place.''
}{
\spadpaste{a.3 := 11; a\bound{a1}\free{a}}
}
\xtc{
However, one-dimensional arrays are not flexible structures.
You cannot destructively \spadfunX{concat} them together.
}{
\spadpaste{concat!(a,oneDimensionalArray [1,-2])\free{a1}}
}

Examples of datatypes similar to \spadtype{OneDimensionalArray}
are: \spadtype{Vector} (vectors are mathematical structures
implemented by one-dimensional arrays), \spadtype{String} (arrays
of ``characters,'' represented by byte vectors), and
\spadtype{Bits} (represented by ``bit vectors'').

\xtc{
A vector of 32 bits, 
each representing the \spadtype{Boolean} value \axiom{true}.
}{
\spadpaste{bits(32,true)}
}

A \spadgloss{flexible array} is a cross between a list
and a one-dimensional array.\footnote{See 
\downlink{`FlexibleArray'}{FlexibleArrayXmpPage}\ignore{FlexibleArray} for
details.}
Like a one-dimensional array, a flexible array occupies a fixed
block of storage.
Its block of storage, however, has room to expand!
When it gets full, it grows (a new, larger block of storage is
allocated); when it has too much room, it contracts.

\xtc{
Create a flexible array of three elements.
}{
\spadpaste{f := flexibleArray [2, 7, -5]\bound{f}}
}
\xtc{
Insert some elements between the second and third elements.
}{
\spadpaste{insert!(flexibleArray [11, -3],f,2)\free{f}}
}

Flexible arrays are used to implement ``heaps.'' A
\spadgloss{heap} is an example of a data structure called a
\spadgloss{priority queue}, where elements are ordered with
respect to one another.\footnote{See 
\downlink{`Heap'}{HeapXmpPage}\ignore{Heap} for more details.
Heaps are also examples of data structures called
\spadglossSee{bags}{bag}.
Other bag data structures are \spadtype{Stack}, \spadtype{Queue},
and \spadtype{Dequeue}.}
A heap is organized
so as to optimize insertion and extraction of maximum elements.
The \spadfunX{extract} operation
returns the maximum element of the heap, after destructively
removing that element and
reorganizing the heap
so that the next maximum element is ready to be delivered.

\xtc{
An easy way to create a heap is to apply the
operation \spadfun{heap} to a list of values.
}{
\spadpaste{h := heap [-4,7,11,3,4,-7]\bound{h}}
}
\xtc{
This loop extracts elements one-at-a-time from \spad{h}
until the heap is exhausted, returning the elements
as a list in the order they were extracted.
}{
\spadpaste{[extract!(h) while not empty?(h)]\free{h}}
}

A \spadgloss{binary tree} is a ``tree'' with at most two branches per
node: it is either empty, or else is a node consisting of a value, and
a left and right subtree (again, binary trees).\footnote{Example of
binary tree types are \spadtype{BinarySearchTree} (see
\downlink{`BinarySearchTree'}{BinarySearchTreeXmpPage}
\ignore{BinarySearchTree}, \spadtype{PendantTree},
\spadtype{TournamentTree}, and \spadtype{BalancedBinaryTree} (see
\downlink{`BalancedBinaryTree'}{BalancedBinaryTreeXmpPage}
\ignore{BalancedBinaryTree}).}

\xtc{
A {\it binary search tree} is a binary tree such that,
for each node, the value of the node is
greater than all values (if any) in the left subtree,
and less than or equal all values (if any) in the right subtree.
}{
\spadpaste{binarySearchTree [5,3,2,9,4,7,11]}
}

\xtc{
A {\it balanced binary tree} is useful for doing modular computations.
Given a list \axiom{lm} of moduli,
\axiomFun{modTree}\axiom{(a,lm)} produces a balanced binary
tree with the values \texht{$a \bmod m$}{a {\tt mod} m}
at its leaves.
}{
\spadpaste{modTree(8,[2,3,5,7])}
}

A \spadgloss{set} is a collection of elements where duplication
and order is irrelevant.\footnote{See 
\downlink{`Set'}{SetXmpPage}\ignore{Set} for more
details.}
Sets are always finite and have no corresponding
structure like streams for infinite collections.

\xtc{
%Create sets using braces (\axiomSyntax{\{} and \axiomSyntax{\}})
%rather than brackets.
}{
\spadpaste{fs := set [1/3,4/5,-1/3,4/5] \bound{fs}}
}

A \spadgloss{multiset}
is a set that keeps track of the number
of duplicate values.\footnote{See 
\downlink{`MultiSet'}{MultiSetXmpPage}\ignore{MultiSet} for details.}
\xtc{
For all the primes \axiom{p} between 2 and 1000, find the
distribution of \texht{$p \bmod 5$}{p mod 5}.
}{
\spadpaste{multiset [x rem 5 for x in primes(2,1000)]}
}

A \spadgloss{table}
is conceptually a set of ``key--value'' pairs and
is a generalization of a multiset.\footnote{For examples of tables, see
\spadtype{AssociationList} (
\downlink{`AssociationList'}{AssociationListXmpPage}
\ignore{AssociationList}),
\spadtype{HashTable},
\spadtype{KeyedAccessFile} (
\downlink{`KeyedAccessFile'}{KeyedAccessFileXmpPage}
\ignore{KeyedAccessFile}),
\spadtype{Library} (\downlink{`Library'}{LibraryXmpPage}
\ignore{Library}),
\spadtype{SparseTable} (
\downlink{`SparseTable'}{SparseTableXmpPage}\ignore{SparseTable}),
\spadtype{StringTable} (
\downlink{`StringTable'}{StringTableXmpPage}\ignore{StringTable}),
and \spadtype{Table} (\downlink{`Table'}{TableXmpPage}\ignore{Table}).}
The domain \spadtype{Table(Key, Entry)} provides a general-purpose
type for tables with {\it values} of type \axiom{Entry} indexed
by {\it keys} of type \axiom{Key}.

\xtc{
Compute the above distribution of primes using tables.
First, let \axiom{t} denote an empty table of keys and values,
each of type \spadtype{Integer}.
}{
\spadpaste{t : Table(Integer,Integer) := empty()\bound{t}}
}

We define a function \userfun{howMany} to return the number
of values of a given modulus \axiom{k} seen so far.
It calls \axiomFun{search}\axiom{(k,t)} which returns the number of
values stored under the key \axiom{k} in table \axiom{t}, or
\axiom{"failed"} if no such value is yet stored in \axiom{t} under
\axiom{k}.

\xtc{
In English, this says ``Define \axiom{howMany(k)} as follows.
First, let \smath{n} be the value of \axiomFun{search}\smath{(k,t)}.
Then, if \smath{n} has the value \smath{"failed"}, return the value
\smath{1}; otherwise return \smath{n + 1}.''
}{
\spadpaste{howMany(k) == (n:=search(k,t); n case "failed" => 1; n+1)
\bound{how}}
}
\xtc{
Run through the primes to create the table, then print the table.
The expression \axiom{t.m := howMany(m)} updates the value in table \axiom{t}
stored under key \axiom{m}.
}{
\spadpaste{for p in primes(2,1000) repeat (m:= p rem 5; t.m:= howMany(m)); 
t\free{how t}}
}

A {\it record}
is an example of an inhomogeneous collection
of objects.\footnote{See 
\downlink{``Records''}{ugTypesRecordsPage} 
in Section 2.4\ignore{ugTypesRecords} for details.}
A record consists of a set of named {\it selectors} that
can be used to access its components.

\xtc{
Declare that \axiom{daniel} can only be
assigned a record with two prescribed fields.
}{
\spadpaste{daniel : Record(age : Integer, salary : Float) \bound{danieldec}}
}
\xtc{
Give \axiom{daniel} a value, using square brackets to enclose the values of
the fields.
}{
\spadpaste{daniel := [28, 32005.12] \free{danieldec}\bound{daniel}}
}
\xtc{
Give \axiom{daniel} a raise.
}{
\spadpaste{daniel.salary := 35000; daniel \free{daniel}}
}

A {\it union}
is a data structure used when objects
have multiple types.\footnote{See 
\downlink{``Unions''}{ugTypesUnionsPage} 
in Section 2.5\ignore{ugTypesUnions} for details.}

\xtc{
Let \axiom{dog} be either an integer or a string value.
}{
\spadpaste{dog: Union(licenseNumber: Integer, name: String)\bound{xint}}
}
\xtc{
Give \axiom{dog} a name.
}{
\spadpaste{dog := "Whisper"\free{xint}}
}

All told, there are over forty different data structures in
Axiom.
Using the domain constructors described in 
\downlink{``Domains''}{ugDomainsPage} 
in Chapter 13\ignore{ugDomains}, you
can add your own data structure or extend an existing one.
Choosing the right data structure for your application may be the key
to obtaining good performance.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntroCollectPagePatch1}
\begin{paste}{ugIntroCollectPageFull1}{ugIntroCollectPageEmpty1}
\pastebutton{ugIntroCollectPageFull1}{\hidepaste}
\tab{5}\spadcommand{u := [1,-7,11]\bound{u }}
\indentrel{3}\begin{verbatim}
   (1)  [1,- 7,11]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty1}
\begin{paste}{ugIntroCollectPageEmpty1}{ugIntroCollectPagePatch1}
\pastebutton{ugIntroCollectPageEmpty1}{\showpaste}
\tab{5}\spadcommand{u := [1,-7,11]\bound{u }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch2}
\begin{paste}{ugIntroCollectPageFull2}{ugIntroCollectPageEmpty2}
\pastebutton{ugIntroCollectPageFull2}{\hidepaste}
\tab{5}\spadcommand{first rest rest u\free{u }}
\indentrel{3}\begin{verbatim}
   (2)  11
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty2}
\begin{paste}{ugIntroCollectPageEmpty2}{ugIntroCollectPagePatch2}
\pastebutton{ugIntroCollectPageEmpty2}{\showpaste}
\tab{5}\spadcommand{first rest rest u\free{u }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch3}
\begin{paste}{ugIntroCollectPageFull3}{ugIntroCollectPageEmpty3}
\pastebutton{ugIntroCollectPageFull3}{\hidepaste}
\tab{5}\spadcommand{concat!(u,[9,1,3,-4]); u\free{u }\bound{u1 }}
\indentrel{3}\begin{verbatim}
   (3)  [1,- 7,11,9,1,3,- 4]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty3}
\begin{paste}{ugIntroCollectPageEmpty3}{ugIntroCollectPagePatch3}
\pastebutton{ugIntroCollectPageEmpty3}{\showpaste}
\tab{5}\spadcommand{concat!(u,[9,1,3,-4]); u\free{u }\bound{u1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch4}
\begin{paste}{ugIntroCollectPageFull4}{ugIntroCollectPageEmpty4}
\pastebutton{ugIntroCollectPageFull4}{\hidepaste}
\tab{5}\spadcommand{lastnode := rest(u,3)\free{u1 }\bound{u2 }}
\indentrel{3}\begin{verbatim}
   (4)  [9,1,3,- 4]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty4}
\begin{paste}{ugIntroCollectPageEmpty4}{ugIntroCollectPagePatch4}
\pastebutton{ugIntroCollectPageEmpty4}{\showpaste}
\tab{5}\spadcommand{lastnode := rest(u,3)\free{u1 }\bound{u2 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch5}
\begin{paste}{ugIntroCollectPageFull5}{ugIntroCollectPageEmpty5}
\pastebutton{ugIntroCollectPageFull5}{\hidepaste}
\tab{5}\spadcommand{setrest!(lastnode,rest(u,2)); u\free{u2 }}
\indentrel{3}\begin{verbatim}
               ____
   (5)  [1,- 7,11,9]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty5}
\begin{paste}{ugIntroCollectPageEmpty5}{ugIntroCollectPagePatch5}
\pastebutton{ugIntroCollectPageEmpty5}{\showpaste}
\tab{5}\spadcommand{setrest!(lastnode,rest(u,2)); u\free{u2 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch6}
\begin{paste}{ugIntroCollectPageFull6}{ugIntroCollectPageEmpty6}
\pastebutton{ugIntroCollectPageFull6}{\hidepaste}
\tab{5}\spadcommand{[factor(i) for i in 2.. by 2]\bound{stream1 }}
\indentrel{3}\begin{verbatim}
            2      3      2       4    2  2
   (6)  [2,2 ,2 3,2 ,2 5,2 3,2 7,2 ,2 3 ,2 5,...]
                          Type: Stream Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty6}
\begin{paste}{ugIntroCollectPageEmpty6}{ugIntroCollectPagePatch6}
\pastebutton{ugIntroCollectPageEmpty6}{\showpaste}
\tab{5}\spadcommand{[factor(i) for i in 2.. by 2]\bound{stream1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch7}
\begin{paste}{ugIntroCollectPageFull7}{ugIntroCollectPageEmpty7}
\pastebutton{ugIntroCollectPageFull7}{\hidepaste}
\tab{5}\spadcommand{\%.36\free{stream1 }}
\indentrel{3}\begin{verbatim}
         3 2
   (7)  2 3
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty7}
\begin{paste}{ugIntroCollectPageEmpty7}{ugIntroCollectPagePatch7}
\pastebutton{ugIntroCollectPageEmpty7}{\showpaste}
\tab{5}\spadcommand{\%.36\free{stream1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch8}
\begin{paste}{ugIntroCollectPageFull8}{ugIntroCollectPageEmpty8}
\pastebutton{ugIntroCollectPageFull8}{\hidepaste}
\tab{5}\spadcommand{a := oneDimensionalArray [1, -7, 3, 3/2]\bound{a }}
\indentrel{3}\begin{verbatim}
                 3
   (8)  [1,- 7,3,Ä]
                 2
             Type: OneDimensionalArray Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty8}
\begin{paste}{ugIntroCollectPageEmpty8}{ugIntroCollectPagePatch8}
\pastebutton{ugIntroCollectPageEmpty8}{\showpaste}
\tab{5}\spadcommand{a := oneDimensionalArray [1, -7, 3, 3/2]\bound{a }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch9}
\begin{paste}{ugIntroCollectPageFull9}{ugIntroCollectPageEmpty9}
\pastebutton{ugIntroCollectPageFull9}{\hidepaste}
\tab{5}\spadcommand{a.3 := 11; a\bound{a1 }\free{a }}
\indentrel{3}\begin{verbatim}
                  3
   (9)  [1,- 7,11,Ä]
                  2
             Type: OneDimensionalArray Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty9}
\begin{paste}{ugIntroCollectPageEmpty9}{ugIntroCollectPagePatch9}
\pastebutton{ugIntroCollectPageEmpty9}{\showpaste}
\tab{5}\spadcommand{a.3 := 11; a\bound{a1 }\free{a }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch10}
\begin{paste}{ugIntroCollectPageFull10}{ugIntroCollectPageEmpty10}
\pastebutton{ugIntroCollectPageFull10}{\hidepaste}
\tab{5}\spadcommand{concat!(a,oneDimensionalArray [1,-2])\free{a1 }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty10}
\begin{paste}{ugIntroCollectPageEmpty10}{ugIntroCollectPagePatch10}
\pastebutton{ugIntroCollectPageEmpty10}{\showpaste}
\tab{5}\spadcommand{concat!(a,oneDimensionalArray [1,-2])\free{a1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch11}
\begin{paste}{ugIntroCollectPageFull11}{ugIntroCollectPageEmpty11}
\pastebutton{ugIntroCollectPageFull11}{\hidepaste}
\tab{5}\spadcommand{bits(32,true)}
\indentrel{3}\begin{verbatim}
   (10)  "11111111111111111111111111111111"
                                             Type: Bits
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty11}
\begin{paste}{ugIntroCollectPageEmpty11}{ugIntroCollectPagePatch11}
\pastebutton{ugIntroCollectPageEmpty11}{\showpaste}
\tab{5}\spadcommand{bits(32,true)}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch12}
\begin{paste}{ugIntroCollectPageFull12}{ugIntroCollectPageEmpty12}
\pastebutton{ugIntroCollectPageFull12}{\hidepaste}
\tab{5}\spadcommand{f := flexibleArray [2, 7, -5]\bound{f }}
\indentrel{3}\begin{verbatim}
   (11)  [2,7,- 5]
                            Type: FlexibleArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty12}
\begin{paste}{ugIntroCollectPageEmpty12}{ugIntroCollectPagePatch12}
\pastebutton{ugIntroCollectPageEmpty12}{\showpaste}
\tab{5}\spadcommand{f := flexibleArray [2, 7, -5]\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch13}
\begin{paste}{ugIntroCollectPageFull13}{ugIntroCollectPageEmpty13}
\pastebutton{ugIntroCollectPageFull13}{\hidepaste}
\tab{5}\spadcommand{insert!(flexibleArray [11, -3],f,2)\free{f }}
\indentrel{3}\begin{verbatim}
   (12)  [2,11,- 3,7,- 5]
                            Type: FlexibleArray Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty13}
\begin{paste}{ugIntroCollectPageEmpty13}{ugIntroCollectPagePatch13}
\pastebutton{ugIntroCollectPageEmpty13}{\showpaste}
\tab{5}\spadcommand{insert!(flexibleArray [11, -3],f,2)\free{f }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch14}
\begin{paste}{ugIntroCollectPageFull14}{ugIntroCollectPageEmpty14}
\pastebutton{ugIntroCollectPageFull14}{\hidepaste}
\tab{5}\spadcommand{h := heap [-4,7,11,3,4,-7]\bound{h }}
\indentrel{3}\begin{verbatim}
   (13)  [11,4,7,- 4,3,- 7]
                                     Type: Heap Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty14}
\begin{paste}{ugIntroCollectPageEmpty14}{ugIntroCollectPagePatch14}
\pastebutton{ugIntroCollectPageEmpty14}{\showpaste}
\tab{5}\spadcommand{h := heap [-4,7,11,3,4,-7]\bound{h }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch15}
\begin{paste}{ugIntroCollectPageFull15}{ugIntroCollectPageEmpty15}
\pastebutton{ugIntroCollectPageFull15}{\hidepaste}
\tab{5}\spadcommand{[extract!(h) while not empty?(h)]\free{h }}
\indentrel{3}\begin{verbatim}
   (14)  [11,7,4,3,- 4,- 7]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty15}
\begin{paste}{ugIntroCollectPageEmpty15}{ugIntroCollectPagePatch15}
\pastebutton{ugIntroCollectPageEmpty15}{\showpaste}
\tab{5}\spadcommand{[extract!(h) while not empty?(h)]\free{h }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch16}
\begin{paste}{ugIntroCollectPageFull16}{ugIntroCollectPageEmpty16}
\pastebutton{ugIntroCollectPageFull16}{\hidepaste}
\tab{5}\spadcommand{binarySearchTree [5,3,2,9,4,7,11]}
\indentrel{3}\begin{verbatim}
   (15)  [[2,3,4],5,[7,9,11]]
                 Type: BinarySearchTree PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty16}
\begin{paste}{ugIntroCollectPageEmpty16}{ugIntroCollectPagePatch16}
\pastebutton{ugIntroCollectPageEmpty16}{\showpaste}
\tab{5}\spadcommand{binarySearchTree [5,3,2,9,4,7,11]}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch17}
\begin{paste}{ugIntroCollectPageFull17}{ugIntroCollectPageEmpty17}
\pastebutton{ugIntroCollectPageFull17}{\hidepaste}
\tab{5}\spadcommand{modTree(8,[2,3,5,7])}
\indentrel{3}\begin{verbatim}
   (16)  [0,2,3,1]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty17}
\begin{paste}{ugIntroCollectPageEmpty17}{ugIntroCollectPagePatch17}
\pastebutton{ugIntroCollectPageEmpty17}{\showpaste}
\tab{5}\spadcommand{modTree(8,[2,3,5,7])}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch18}
\begin{paste}{ugIntroCollectPageFull18}{ugIntroCollectPageEmpty18}
\pastebutton{ugIntroCollectPageFull18}{\hidepaste}
\tab{5}\spadcommand{fs := set[1/3,4/5,-1/3,4/5]\bound{fs }}
\indentrel{3}\begin{verbatim}
            1 1 4
   (17)  {- Ä,Ä,Ä}
            3 3 5
                             Type: Set Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty18}
\begin{paste}{ugIntroCollectPageEmpty18}{ugIntroCollectPagePatch18}
\pastebutton{ugIntroCollectPageEmpty18}{\showpaste}
\tab{5}\spadcommand{fs := set[1/3,4/5,-1/3,4/5]\bound{fs }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch19}
\begin{paste}{ugIntroCollectPageFull19}{ugIntroCollectPageEmpty19}
\pastebutton{ugIntroCollectPageFull19}{\hidepaste}
\tab{5}\spadcommand{multiset [x rem 5 for x in primes(2,1000)]}
\indentrel{3}\begin{verbatim}
   (18)  {0,42: 3,40: 1,38: 4,47: 2}
                                 Type: Multiset Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty19}
\begin{paste}{ugIntroCollectPageEmpty19}{ugIntroCollectPagePatch19}
\pastebutton{ugIntroCollectPageEmpty19}{\showpaste}
\tab{5}\spadcommand{multiset [x rem 5 for x in primes(2,1000)]}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch20}
\begin{paste}{ugIntroCollectPageFull20}{ugIntroCollectPageEmpty20}
\pastebutton{ugIntroCollectPageFull20}{\hidepaste}
\tab{5}\spadcommand{t : Table(Integer,Integer) := empty()\bound{t }}
\indentrel{3}\begin{verbatim}
   (19)  table()
                           Type: Table(Integer,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty20}
\begin{paste}{ugIntroCollectPageEmpty20}{ugIntroCollectPagePatch20}
\pastebutton{ugIntroCollectPageEmpty20}{\showpaste}
\tab{5}\spadcommand{t : Table(Integer,Integer) := empty()\bound{t }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch21}
\begin{paste}{ugIntroCollectPageFull21}{ugIntroCollectPageEmpty21}
\pastebutton{ugIntroCollectPageFull21}{\hidepaste}
\tab{5}\spadcommand{howMany(k) == (n:=search(k,t); n case "failed" => 1; n+1)\bound{how }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty21}
\begin{paste}{ugIntroCollectPageEmpty21}{ugIntroCollectPagePatch21}
\pastebutton{ugIntroCollectPageEmpty21}{\showpaste}
\tab{5}\spadcommand{howMany(k) == (n:=search(k,t); n case "failed" => 1; n+1)\bound{how }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch22}
\begin{paste}{ugIntroCollectPageFull22}{ugIntroCollectPageEmpty22}
\pastebutton{ugIntroCollectPageFull22}{\hidepaste}
\tab{5}\spadcommand{for p in primes(2,1000) repeat (m:= p rem 5; t.m:= howMany(m)); t\free{how t }}
\indentrel{3}\begin{verbatim}
   (21)  table(2= 47,4= 38,1= 40,3= 42,0= 1)
                           Type: Table(Integer,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty22}
\begin{paste}{ugIntroCollectPageEmpty22}{ugIntroCollectPagePatch22}
\pastebutton{ugIntroCollectPageEmpty22}{\showpaste}
\tab{5}\spadcommand{for p in primes(2,1000) repeat (m:= p rem 5; t.m:= howMany(m)); t\free{how t }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch23}
\begin{paste}{ugIntroCollectPageFull23}{ugIntroCollectPageEmpty23}
\pastebutton{ugIntroCollectPageFull23}{\hidepaste}
\tab{5}\spadcommand{daniel : Record(age : Integer, salary : Float)\bound{danieldec }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty23}
\begin{paste}{ugIntroCollectPageEmpty23}{ugIntroCollectPagePatch23}
\pastebutton{ugIntroCollectPageEmpty23}{\showpaste}
\tab{5}\spadcommand{daniel : Record(age : Integer, salary : Float)\bound{danieldec }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch24}
\begin{paste}{ugIntroCollectPageFull24}{ugIntroCollectPageEmpty24}
\pastebutton{ugIntroCollectPageFull24}{\hidepaste}
\tab{5}\spadcommand{daniel := [28, 32005.12]\free{danieldec }\bound{daniel }}
\indentrel{3}\begin{verbatim}
   (23)  [age= 28,salary= 32005.12]
               Type: Record(age: Integer,salary: Float)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty24}
\begin{paste}{ugIntroCollectPageEmpty24}{ugIntroCollectPagePatch24}
\pastebutton{ugIntroCollectPageEmpty24}{\showpaste}
\tab{5}\spadcommand{daniel := [28, 32005.12]\free{danieldec }\bound{daniel }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch25}
\begin{paste}{ugIntroCollectPageFull25}{ugIntroCollectPageEmpty25}
\pastebutton{ugIntroCollectPageFull25}{\hidepaste}
\tab{5}\spadcommand{daniel.salary := 35000; daniel\free{daniel }}
\indentrel{3}\begin{verbatim}
   (24)  [age= 28,salary= 35000.0]
               Type: Record(age: Integer,salary: Float)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty25}
\begin{paste}{ugIntroCollectPageEmpty25}{ugIntroCollectPagePatch25}
\pastebutton{ugIntroCollectPageEmpty25}{\showpaste}
\tab{5}\spadcommand{daniel.salary := 35000; daniel\free{daniel }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch26}
\begin{paste}{ugIntroCollectPageFull26}{ugIntroCollectPageEmpty26}
\pastebutton{ugIntroCollectPageFull26}{\hidepaste}
\tab{5}\spadcommand{dog: Union(licenseNumber: Integer, name: String)\bound{xint }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty26}
\begin{paste}{ugIntroCollectPageEmpty26}{ugIntroCollectPagePatch26}
\pastebutton{ugIntroCollectPageEmpty26}{\showpaste}
\tab{5}\spadcommand{dog: Union(licenseNumber: Integer, name: String)\bound{xint }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPagePatch27}
\begin{paste}{ugIntroCollectPageFull27}{ugIntroCollectPageEmpty27}
\pastebutton{ugIntroCollectPageFull27}{\hidepaste}
\tab{5}\spadcommand{dog := "Whisper"\free{xint }}
\indentrel{3}\begin{verbatim}
   (26)  "Whisper"
                          Type: Union(name: String,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCollectPageEmpty27}
\begin{paste}{ugIntroCollectPageEmpty27}{ugIntroCollectPagePatch27}
\pastebutton{ugIntroCollectPageEmpty27}{\showpaste}
\tab{5}\spadcommand{dog := "Whisper"\free{xint }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntroTwoDimPage}{ug01.ht}{Expanding to Higher Dimensions}
\pageto{notitle}{TwoDimensionalArrayXmpPage}
\pageto{notitle}{MatrixXmpPage}
\pageto{notitle}{PermanentXmpPage}
\pageto{notitle}{SqMatrixXmpPage}
\pageto{notitle}{VectorXmpPage}
\pageto{notitle}{ugProblemEigenPage}
\pageto{notitle}{ugProblemLinPolEqnPage}
\pageto{notitle}{ugLangItsPage}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroTwoDimPage}{1.7. Expanding to Higher Dimensions}
\beginscroll
%

To get higher dimensional aggregates, you can create one-dimensional
aggregates with elements that are themselves aggregates, for example,
lists of lists, one-dimensional arrays of lists of multisets, and so
on.  For applications requiring two-dimensional homogeneous
aggregates, you will likely find {\it two-dimensional arrays} and {\it
matrices} most useful.

The entries in \spadtype{TwoDimensionalArray} and
\spadtype{Matrix} objects
are all the same type, except that those for
\spadtype{Matrix} must belong to a \spadtype{Ring}.
You create and access elements in roughly the same way.
Since matrices have an understood algebraic structure, certain algebraic
operations are available for matrices but not for arrays.
Because of this, we limit our discussion here to
\spadtype{Matrix}, that can be regarded as an extension of
\spadtype{TwoDimensionalArray}.\footnote{See
\downlink{`TwoDimensionalArray'}{TwoDimensionalArrayXmpPage}
\ignore{TwoDimensionalArray} for more information about arrays.
For more information about Axiom's linear algebra
facilities, see \downlink{`Matrix'}{MatrixXmpPage}\ignore{Matrix}, 
\downlink{`Permanent'}{PermanentXmpPage}\ignore{Permanent},
\downlink{`SquareMatrix'}{SqMatrixXmpPage}\ignore{SquareMatrix}, 
\downlink{`Vector'}{VectorXmpPage}\ignore{Vector},
\downlink{``Computation of Eigenvalues and Eigenvectors''}
{ugProblemEigenPage} in Section 8.4\ignore{ugProblemEigen}
\texht{(computation of eigenvalues and
eigenvectors)}{}, and
\downlink{``Solution of Linear and Polynomial Equations''}
{ugProblemLinPolEqnPage} in Section 8.5\ignore{ugProblemLinPolEqn}
\texht{(solution of linear and
polynomial equations)}{}.}

\xtc{
You can create a matrix from a list of lists,
where each of the inner lists represents a row of the matrix.
}{
\spadpaste{m := matrix([[1,2], [3,4]]) \bound{m}}
}
\xtc{
The ``collections'' construct (see 
\downlink{``Creating Lists and Streams with Iterators''}
{ugLangItsPage} in Section 5.5\ignore{ugLangIts}) is
useful for creating matrices whose entries are given by formulas.
}{
\spadpaste{matrix([[1/(i + j - x) for i in 1..4] for j in 1..4]) 
\bound{hilb}}
}
\xtc{
Let \axiom{vm} denote the three by three Vandermonde matrix.
}{
\spadpaste{vm := matrix [[1,1,1], [x,y,z], [x*x,y*y,z*z]] \bound{vm}}
}
\xtc{
Use this syntax to extract an entry in the matrix.
}{
\spadpaste{vm(3,3) \free{vm}}
}
\xtc{
You can also pull out a \axiomFun{row} or a \axiom{column}.
}{
\spadpaste{column(vm,2) \free{vm}}
}
\xtc{
You can do arithmetic.
}{
\spadpaste{vm * vm \free{vm}}
}
\xtc{
You can perform operations such as
\axiomFun{transpose}, \axiomFun{trace}, and \axiomFun{determinant}.
}{
\spadpaste{factor determinant vm \free{vm}\bound{d}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntroTwoDimPagePatch1}
\begin{paste}{ugIntroTwoDimPageFull1}{ugIntroTwoDimPageEmpty1}
\pastebutton{ugIntroTwoDimPageFull1}{\hidepaste}
\tab{5}\spadcommand{m := matrix([[1,2], [3,4]])\bound{m }}
\indentrel{3}\begin{verbatim}
        Ú1  2¿
   (1)  ³    ³
        À3  4Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroTwoDimPageEmpty1}
\begin{paste}{ugIntroTwoDimPageEmpty1}{ugIntroTwoDimPagePatch1}
\pastebutton{ugIntroTwoDimPageEmpty1}{\showpaste}
\tab{5}\spadcommand{m := matrix([[1,2], [3,4]])\bound{m }}
\end{paste}\end{patch}

\begin{patch}{ugIntroTwoDimPagePatch2}
\begin{paste}{ugIntroTwoDimPageFull2}{ugIntroTwoDimPageEmpty2}
\pastebutton{ugIntroTwoDimPageFull2}{\hidepaste}
\tab{5}\spadcommand{matrix([[1/(i + j - x) for i in 1..4] for j in 1..4])\bound{hilb }}
\indentrel{3}\begin{verbatim}
        Ú    1        1        1        1  ¿
        ³- ÄÄÄÄÄ  - ÄÄÄÄÄ  - ÄÄÄÄÄ  - ÄÄÄÄÄ³
        ³  x - 2    x - 3    x - 4    x - 5³
        ³                                  ³
        ³    1        1        1        1  ³
        ³- ÄÄÄÄÄ  - ÄÄÄÄÄ  - ÄÄÄÄÄ  - ÄÄÄÄÄ³
        ³  x - 3    x - 4    x - 5    x - 6³
   (2)  ³                                  ³
        ³    1        1        1        1  ³
        ³- ÄÄÄÄÄ  - ÄÄÄÄÄ  - ÄÄÄÄÄ  - ÄÄÄÄÄ³
        ³  x - 4    x - 5    x - 6    x - 7³
        ³                                  ³
        ³    1        1        1        1  ³
        ³- ÄÄÄÄÄ  - ÄÄÄÄÄ  - ÄÄÄÄÄ  - ÄÄÄÄÄ³
        À  x - 5    x - 6    x - 7    x - 8Ù
               Type: Matrix Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroTwoDimPageEmpty2}
\begin{paste}{ugIntroTwoDimPageEmpty2}{ugIntroTwoDimPagePatch2}
\pastebutton{ugIntroTwoDimPageEmpty2}{\showpaste}
\tab{5}\spadcommand{matrix([[1/(i + j - x) for i in 1..4] for j in 1..4])\bound{hilb }}
\end{paste}\end{patch}

\begin{patch}{ugIntroTwoDimPagePatch3}
\begin{paste}{ugIntroTwoDimPageFull3}{ugIntroTwoDimPageEmpty3}
\pastebutton{ugIntroTwoDimPageFull3}{\hidepaste}
\tab{5}\spadcommand{vm := matrix [[1,1,1], [x,y,z], [x*x,y*y,z*z]]\bound{vm }}
\indentrel{3}\begin{verbatim}
        Ú1   1   1 ¿
        ³          ³
   (3)  ³x   y   z ³
        ³          ³
        ³ 2   2   2³
        Àx   y   z Ù
                        Type: Matrix Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroTwoDimPageEmpty3}
\begin{paste}{ugIntroTwoDimPageEmpty3}{ugIntroTwoDimPagePatch3}
\pastebutton{ugIntroTwoDimPageEmpty3}{\showpaste}
\tab{5}\spadcommand{vm := matrix [[1,1,1], [x,y,z], [x*x,y*y,z*z]]\bound{vm }}
\end{paste}\end{patch}

\begin{patch}{ugIntroTwoDimPagePatch4}
\begin{paste}{ugIntroTwoDimPageFull4}{ugIntroTwoDimPageEmpty4}
\pastebutton{ugIntroTwoDimPageFull4}{\hidepaste}
\tab{5}\spadcommand{vm(3,3)\free{vm }}
\indentrel{3}\begin{verbatim}
         2
   (4)  z
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroTwoDimPageEmpty4}
\begin{paste}{ugIntroTwoDimPageEmpty4}{ugIntroTwoDimPagePatch4}
\pastebutton{ugIntroTwoDimPageEmpty4}{\showpaste}
\tab{5}\spadcommand{vm(3,3)\free{vm }}
\end{paste}\end{patch}

\begin{patch}{ugIntroTwoDimPagePatch5}
\begin{paste}{ugIntroTwoDimPageFull5}{ugIntroTwoDimPageEmpty5}
\pastebutton{ugIntroTwoDimPageFull5}{\hidepaste}
\tab{5}\spadcommand{column(vm,2)\free{vm }}
\indentrel{3}\begin{verbatim}
              2
   (5)  [1,y,y ]
                        Type: Vector Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroTwoDimPageEmpty5}
\begin{paste}{ugIntroTwoDimPageEmpty5}{ugIntroTwoDimPagePatch5}
\pastebutton{ugIntroTwoDimPageEmpty5}{\showpaste}
\tab{5}\spadcommand{column(vm,2)\free{vm }}
\end{paste}\end{patch}

\begin{patch}{ugIntroTwoDimPagePatch6}
\begin{paste}{ugIntroTwoDimPageFull6}{ugIntroTwoDimPageEmpty6}
\pastebutton{ugIntroTwoDimPageFull6}{\hidepaste}
\tab{5}\spadcommand{vm * vm\free{vm }}
\indentrel{3}\begin{verbatim}
   (6)
   Ú    2                2              2          ¿
   ³   x  + x + 1       y  + y + 1     z  + z + 1  ³
   ³                                               ³
   ³  2                 2     2        3           ³
   ³ x z + x y + x     y z + y  + x   z  + y z + x ³
   ³                                               ³
   ³ 2 2      2    2   2 2    3    2   4    2     2³
   Àx z  + x y  + x   y z  + y  + x   z  + y z + x Ù
                        Type: Matrix Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroTwoDimPageEmpty6}
\begin{paste}{ugIntroTwoDimPageEmpty6}{ugIntroTwoDimPagePatch6}
\pastebutton{ugIntroTwoDimPageEmpty6}{\showpaste}
\tab{5}\spadcommand{vm * vm\free{vm }}
\end{paste}\end{patch}

\begin{patch}{ugIntroTwoDimPagePatch7}
\begin{paste}{ugIntroTwoDimPageFull7}{ugIntroTwoDimPageEmpty7}
\pastebutton{ugIntroTwoDimPageFull7}{\hidepaste}
\tab{5}\spadcommand{factor determinant vm\free{vm }\bound{d }}
\indentrel{3}\begin{verbatim}
   (7)  (y - x)(z - y)(z - x)
                      Type: Factored Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroTwoDimPageEmpty7}
\begin{paste}{ugIntroTwoDimPageEmpty7}{ugIntroTwoDimPagePatch7}
\pastebutton{ugIntroTwoDimPageEmpty7}{\showpaste}
\tab{5}\spadcommand{factor determinant vm\free{vm }\bound{d }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntroYouPage}{ug01.ht}{Writing Your Own Functions}
\pageto{notitle}{ugUserPage}
\pageto{notitle}{ugInOutInPage}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroYouPage}{1.8. Writing Your Own Functions}
\beginscroll
%

Axiom provides you with a very large library of predefined operations
and objects to compute with.  You can use the Axiom library of
constructors to create new objects dynamically of quite arbitrary
complexity.  For example, you can make lists of matrices of fractions
of polynomials with complex floating point numbers as coefficients.
Moreover, the library provides a wealth of operations that allow you
to create and manipulate these objects.

For many applications, you need to interact with the interpreter and
write some Axiom programs to tackle your application.  Axiom allows
you to write functions interactively, thereby effectively extending
the system library.  Here we give a few simple examples, leaving the
details to \downlink{``User-Defined Functions, Macros and Rules''}
{ugUserPage} in Chapter 6\ignore{ugUser}.

We begin by looking at several ways that you can define the
``factorial'' function in Axiom.  The first way is to give a
piece-wise definition of the function.  This method is best for a
general recurrence relation since the pieces are gathered together and
compiled into an efficient iterative function.  Furthermore, enough
previously computed values are automatically saved so that a
subsequent call to the function can pick up from where it left off.

\xtc{
Define the value of \userfun{fact} at \axiom{0}.
}{
\spadpaste{fact(0) == 1 \bound{fact}}
}
\xtc{
Define the value of \axiom{fact(n)} for general \axiom{n}.
}{
\spadpaste{fact(n) == n*fact(n-1)\bound{facta}\free{fact}}
}
\xtc{
Ask for the value at \axiom{50}.
The resulting function created by Axiom
computes the value by iteration.
}{
\spadpaste{fact(50) \free{facta}}
}
\xtc{
A second definition uses an \axiom{if-then-else} and recursion.
}{
\spadpaste{fac(n) == if n < 3 then n else n * fac(n - 1) \bound{fac}}
}
\xtc{
This function is less efficient than the previous version since
each iteration involves a recursive function call.
}{
\spadpaste{fac(50) \free{fac}}
}
\xtc{
A third version directly uses iteration.
}{
\spadpaste{fa(n) == (a := 1; for i in 2..n repeat a := a*i; a) \bound{fa}}
}
\xtc{
This is the least space-consumptive version.
}{
\spadpaste{fa(50) \free{fa}}
}
\xtc{
A final version appears to construct a large list and then reduces over
it with multiplication.
}{
\spadpaste{f(n) == reduce(*,[i for i in 2..n]) \bound{f}}
}
\xtc{
In fact, the resulting computation is optimized into an efficient
iteration loop equivalent to that of the third version.
}{
\spadpaste{f(50) \free{f}}
}
\xtc{
The library version uses an algorithm that is different from the four
above because it highly optimizes the recurrence relation definition of
\axiomFun{factorial}.
}{
\spadpaste{factorial(50)}
}

You are not limited to one-line functions in Axiom.
If you place your function definitions in {\bf .input} files
(see \downlink{``Input Files''}{ugInOutInPage} 
in Section 4.1\ignore{ugInOutIn}), you can have
multi-line functions that use indentation for grouping.

Given \axiom{n} elements, \axiomFun{diagonalMatrix} creates an
\axiom{n} by \axiom{n} matrix with those elements down the diagonal.
This function uses a permutation matrix
that interchanges the \axiom{i}th and \axiom{j}th rows of a matrix
by which it is right-multiplied.

\xtc{
This function definition shows a style of definition that can be used
in {\bf .input} files.
Indentation is used to create \spadglossSee{blocks}{block}\texht{\/}{}:
sequences of expressions that are evaluated in sequence except as
modified by control statements such as \axiom{if-then-else} and \axiom{return}.
}{
\begin{spadsrc}[\bound{permMat}]
permMat(n, i, j) ==
  m := diagonalMatrix
    [(if i = k or j = k then 0 else 1)
      for k in 1..n]
  m(i,j) := 1
  m(j,i) := 1
  m
\end{spadsrc}
}
\xtc{
This creates a four by four matrix that interchanges the second and third
rows.
}{
\spadpaste{p := permMat(4,2,3) \free{permMat}\bound{p}}
}
\xtc{
Create an example matrix to permute.
}{
\spadpaste{m := matrix [[4*i + j for j in 1..4] for i in 0..3]\bound{m}}
}
\xtc{
Interchange the second and third rows of m.
}{
\spadpaste{permMat(4,2,3) * m \free{p m}}
}

A function can also be passed as an argument to another function,
which then applies the function or passes it off to some other
function that does.
You often have to declare the type of a function that has
functional arguments.

\xtc{
This declares \userfun{t} to be a two-argument function that
returns a \spadtype{Float}.
The first argument is a function that takes one \spadtype{Float}
argument and returns a \spadtype{Float}.
}{
\spadpaste{t : (Float -> Float, Float) -> Float \bound{tdecl}}
}
\xtc{
This is the definition of \userfun{t}.
}{
\spadpaste{t(fun, x) == fun(x)**2 + sin(x)**2 \free{tdecl}\bound{t}}
}
\xtc{
We have not defined a \axiomFun{cos} in the workspace. The one from the
Axiom library will do.
}{
\spadpaste{t(cos, 5.2058) \free{t}}
}
\xtc{
Here we define our own (user-defined) function.
}{
\spadpaste{cosinv(y) == cos(1/y) \bound{cosinv}}
}
\xtc{
Pass this function as an argument to \userfun{t}.
}{
\spadpaste{t(cosinv, 5.2058) \free{t}\free{cosinv}}
}

Axiom also has pattern matching capabilities for
simplification
of expressions and for defining new functions by rules.
For example, suppose that you want to apply regularly a transformation
that groups together products of radicals:
\texht{$$\sqrt{a}\:\sqrt{b} \mapsto \sqrt{ab}, \quad
(\forall a)(\forall b)$$}
{\axiom{sqrt(a) * sqrt(b) by sqrt(a*b)} for any \axiom{a} and \axiom{b}}
Note that such a transformation is not generally correct.
Axiom never uses it automatically.

\xtc{
Give this rule the name \userfun{groupSqrt}.
}{
\spadpaste{groupSqrt := rule(sqrt(a) * sqrt(b) == sqrt(a*b)) \bound{g}}
}
\xtc{
Here is a test expression.
}{
\spadpaste{a := (sqrt(x) + sqrt(y) + sqrt(z))**4 \bound{sxy}}
}
\xtc{
The rule
\userfun{groupSqrt} successfully simplifies the expression.
}{
\spadpaste{groupSqrt a \free{sxy} \free{g}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntroYouPagePatch1}
\begin{paste}{ugIntroYouPageFull1}{ugIntroYouPageEmpty1}
\pastebutton{ugIntroYouPageFull1}{\hidepaste}
\tab{5}\spadcommand{fact(0) == 1\bound{fact }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroYouPageEmpty1}
\begin{paste}{ugIntroYouPageEmpty1}{ugIntroYouPagePatch1}
\pastebutton{ugIntroYouPageEmpty1}{\showpaste}
\tab{5}\spadcommand{fact(0) == 1\bound{fact }}
\end{paste}\end{patch}

\begin{patch}{ugIntroYouPagePatch2}
\begin{paste}{ugIntroYouPageFull2}{ugIntroYouPageEmpty2}
\pastebutton{ugIntroYouPageFull2}{\hidepaste}
\tab{5}\spadcommand{fact(n) == n*fact(n-1)\bound{facta }\free{fact }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroYouPageEmpty2}
\begin{paste}{ugIntroYouPageEmpty2}{ugIntroYouPagePatch2}
\pastebutton{ugIntroYouPageEmpty2}{\showpaste}
\tab{5}\spadcommand{fact(n) == n*fact(n-1)\bound{facta }\free{fact }}
\end{paste}\end{patch}

\begin{patch}{ugIntroYouPagePatch3}
\begin{paste}{ugIntroYouPageFull3}{ugIntroYouPageEmpty3}
\pastebutton{ugIntroYouPageFull3}{\hidepaste}
\tab{5}\spadcommand{fact(50)\free{facta }}
\indentrel{3}\begin{verbatim}
   (3)
  304140932017133780436126081660647688443776415689605120_
   00000000000
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroYouPageEmpty3}
\begin{paste}{ugIntroYouPageEmpty3}{ugIntroYouPagePatch3}
\pastebutton{ugIntroYouPageEmpty3}{\showpaste}
\tab{5}\spadcommand{fact(50)\free{facta }}
\end{paste}\end{patch}

\begin{patch}{ugIntroYouPagePatch4}
\begin{paste}{ugIntroYouPageFull4}{ugIntroYouPageEmpty4}
\pastebutton{ugIntroYouPageFull4}{\hidepaste}
\tab{5}\spadcommand{fac(n) == if n < 3 then n else n * fac(n - 1)\bound{fac }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroYouPageEmpty4}
\begin{paste}{ugIntroYouPageEmpty4}{ugIntroYouPagePatch4}
\pastebutton{ugIntroYouPageEmpty4}{\showpaste}
\tab{5}\spadcommand{fac(n) == if n < 3 then n else n * fac(n - 1)\bound{fac }}
\end{paste}\end{patch}

\begin{patch}{ugIntroYouPagePatch5}
\begin{paste}{ugIntroYouPageFull5}{ugIntroYouPageEmpty5}
\pastebutton{ugIntroYouPageFull5}{\hidepaste}
\tab{5}\spadcommand{fac(50)\free{fac }}
\indentrel{3}\begin{verbatim}
   (5)
  304140932017133780436126081660647688443776415689605120_
   00000000000
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroYouPageEmpty5}
\begin{paste}{ugIntroYouPageEmpty5}{ugIntroYouPagePatch5}
\pastebutton{ugIntroYouPageEmpty5}{\showpaste}
\tab{5}\spadcommand{fac(50)\free{fac }}
\end{paste}\end{patch}

\begin{patch}{ugIntroYouPagePatch6}
\begin{paste}{ugIntroYouPageFull6}{ugIntroYouPageEmpty6}
\pastebutton{ugIntroYouPageFull6}{\hidepaste}
\tab{5}\spadcommand{fa(n) == (a := 1; for i in 2..n repeat a := a*i; a)\bound{fa }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroYouPageEmpty6}
\begin{paste}{ugIntroYouPageEmpty6}{ugIntroYouPagePatch6}
\pastebutton{ugIntroYouPageEmpty6}{\showpaste}
\tab{5}\spadcommand{fa(n) == (a := 1; for i in 2..n repeat a := a*i; a)\bound{fa }}
\end{paste}\end{patch}

\begin{patch}{ugIntroYouPagePatch7}
\begin{paste}{ugIntroYouPageFull7}{ugIntroYouPageEmpty7}
\pastebutton{ugIntroYouPageFull7}{\hidepaste}
\tab{5}\spadcommand{fa(50)\free{fa }}
\indentrel{3}\begin{verbatim}
   (7)
  304140932017133780436126081660647688443776415689605120_
   00000000000
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroYouPageEmpty7}
\begin{paste}{ugIntroYouPageEmpty7}{ugIntroYouPagePatch7}
\pastebutton{ugIntroYouPageEmpty7}{\showpaste}
\tab{5}\spadcommand{fa(50)\free{fa }}
\end{paste}\end{patch}

\begin{patch}{ugIntroYouPagePatch8}
\begin{paste}{ugIntroYouPageFull8}{ugIntroYouPageEmpty8}
\pastebutton{ugIntroYouPageFull8}{\hidepaste}
\tab{5}\spadcommand{f(n) == reduce(*,[i for i in 2..n])\bound{f }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroYouPageEmpty8}
\begin{paste}{ugIntroYouPageEmpty8}{ugIntroYouPagePatch8}
\pastebutton{ugIntroYouPageEmpty8}{\showpaste}
\tab{5}\spadcommand{f(n) == reduce(*,[i for i in 2..n])\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ugIntroYouPagePatch9}
\begin{paste}{ugIntroYouPageFull9}{ugIntroYouPageEmpty9}
\pastebutton{ugIntroYouPageFull9}{\hidepaste}
\tab{5}\spadcommand{f(50)\free{f }}
\indentrel{3}\begin{verbatim}
   (9)
  304140932017133780436126081660647688443776415689605120_
   00000000000
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroYouPageEmpty9}
\begin{paste}{ugIntroYouPageEmpty9}{ugIntroYouPagePatch9}
\pastebutton{ugIntroYouPageEmpty9}{\showpaste}
\tab{5}\spadcommand{f(50)\free{f }}
\end{paste}\end{patch}

\begin{patch}{ugIntroYouPagePatch10}
\begin{paste}{ugIntroYouPageFull10}{ugIntroYouPageEmpty10}
\pastebutton{ugIntroYouPageFull10}{\hidepaste}
\tab{5}\spadcommand{factorial(50)}
\indentrel{3}\begin{verbatim}
   (10)
  304140932017133780436126081660647688443776415689605120_
   00000000000
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroYouPageEmpty10}
\begin{paste}{ugIntroYouPageEmpty10}{ugIntroYouPagePatch10}
\pastebutton{ugIntroYouPageEmpty10}{\showpaste}
\tab{5}\spadcommand{factorial(50)}
\end{paste}\end{patch}

\begin{patch}{ugIntroYouPagePatch11}
\begin{paste}{ugIntroYouPageFull11}{ugIntroYouPageEmpty11}
\pastebutton{ugIntroYouPageFull11}{\hidepaste}
\tab{5}\spadcommand{permMat(n, i, j) ==
  m := diagonalMatrix
    [(if i = k or j = k then 0 else 1)
      for k in 1..n]
  m(i,j) := 1
  m(j,i) := 1
  m
\bound{permMat }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroYouPageEmpty11}
\begin{paste}{ugIntroYouPageEmpty11}{ugIntroYouPagePatch11}
\pastebutton{ugIntroYouPageEmpty11}{\showpaste}
\tab{5}\spadcommand{permMat(n, i, j) ==
  m := diagonalMatrix
    [(if i = k or j = k then 0 else 1)
      for k in 1..n]
  m(i,j) := 1
  m(j,i) := 1
  m
\bound{permMat }}
\end{paste}\end{patch}

\begin{patch}{ugIntroYouPagePatch12}
\begin{paste}{ugIntroYouPageFull12}{ugIntroYouPageEmpty12}
\pastebutton{ugIntroYouPageFull12}{\hidepaste}
\tab{5}\spadcommand{p := permMat(4,2,3)\free{permMat }\bound{p }}
\indentrel{3}\begin{verbatim}
         Ú1  0  0  0¿
         ³          ³
         ³0  0  1  0³
   (12)  ³          ³
         ³0  1  0  0³
         ³          ³
         À0  0  0  1Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroYouPageEmpty12}
\begin{paste}{ugIntroYouPageEmpty12}{ugIntroYouPagePatch12}
\pastebutton{ugIntroYouPageEmpty12}{\showpaste}
\tab{5}\spadcommand{p := permMat(4,2,3)\free{permMat }\bound{p }}
\end{paste}\end{patch}

\begin{patch}{ugIntroYouPagePatch13}
\begin{paste}{ugIntroYouPageFull13}{ugIntroYouPageEmpty13}
\pastebutton{ugIntroYouPageFull13}{\hidepaste}
\tab{5}\spadcommand{m := matrix [[4*i + j for j in 1..4] for i in 0..3]\bound{m }}
\indentrel{3}\begin{verbatim}
         Ú1   2   3   4 ¿
         ³              ³
         ³5   6   7   8 ³
   (13)  ³              ³
         ³9   10  11  12³
         ³              ³
         À13  14  15  16Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroYouPageEmpty13}
\begin{paste}{ugIntroYouPageEmpty13}{ugIntroYouPagePatch13}
\pastebutton{ugIntroYouPageEmpty13}{\showpaste}
\tab{5}\spadcommand{m := matrix [[4*i + j for j in 1..4] for i in 0..3]\bound{m }}
\end{paste}\end{patch}

\begin{patch}{ugIntroYouPagePatch14}
\begin{paste}{ugIntroYouPageFull14}{ugIntroYouPageEmpty14}
\pastebutton{ugIntroYouPageFull14}{\hidepaste}
\tab{5}\spadcommand{permMat(4,2,3) * m\free{p m }}
\indentrel{3}\begin{verbatim}
         Ú1   2   3   4 ¿
         ³              ³
         ³9   10  11  12³
   (14)  ³              ³
         ³5   6   7   8 ³
         ³              ³
         À13  14  15  16Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroYouPageEmpty14}
\begin{paste}{ugIntroYouPageEmpty14}{ugIntroYouPagePatch14}
\pastebutton{ugIntroYouPageEmpty14}{\showpaste}
\tab{5}\spadcommand{permMat(4,2,3) * m\free{p m }}
\end{paste}\end{patch}

\begin{patch}{ugIntroYouPagePatch15}
\begin{paste}{ugIntroYouPageFull15}{ugIntroYouPageEmpty15}
\pastebutton{ugIntroYouPageFull15}{\hidepaste}
\tab{5}\spadcommand{t : (Float -> Float, Float) -> Float\bound{tdecl }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroYouPageEmpty15}
\begin{paste}{ugIntroYouPageEmpty15}{ugIntroYouPagePatch15}
\pastebutton{ugIntroYouPageEmpty15}{\showpaste}
\tab{5}\spadcommand{t : (Float -> Float, Float) -> Float\bound{tdecl }}
\end{paste}\end{patch}

\begin{patch}{ugIntroYouPagePatch16}
\begin{paste}{ugIntroYouPageFull16}{ugIntroYouPageEmpty16}
\pastebutton{ugIntroYouPageFull16}{\hidepaste}
\tab{5}\spadcommand{t(fun, x) == fun(x)**2 + sin(x)**2\free{tdecl }\bound{t }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroYouPageEmpty16}
\begin{paste}{ugIntroYouPageEmpty16}{ugIntroYouPagePatch16}
\pastebutton{ugIntroYouPageEmpty16}{\showpaste}
\tab{5}\spadcommand{t(fun, x) == fun(x)**2 + sin(x)**2\free{tdecl }\bound{t }}
\end{paste}\end{patch}

\begin{patch}{ugIntroYouPagePatch17}
\begin{paste}{ugIntroYouPageFull17}{ugIntroYouPageEmpty17}
\pastebutton{ugIntroYouPageFull17}{\hidepaste}
\tab{5}\spadcommand{t(cos, 5.2058)\free{t }}
\indentrel{3}\begin{verbatim}
   (17)  1.0
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroYouPageEmpty17}
\begin{paste}{ugIntroYouPageEmpty17}{ugIntroYouPagePatch17}
\pastebutton{ugIntroYouPageEmpty17}{\showpaste}
\tab{5}\spadcommand{t(cos, 5.2058)\free{t }}
\end{paste}\end{patch}

\begin{patch}{ugIntroYouPagePatch18}
\begin{paste}{ugIntroYouPageFull18}{ugIntroYouPageEmpty18}
\pastebutton{ugIntroYouPageFull18}{\hidepaste}
\tab{5}\spadcommand{cosinv(y) == cos(1/y)\bound{cosinv }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroYouPageEmpty18}
\begin{paste}{ugIntroYouPageEmpty18}{ugIntroYouPagePatch18}
\pastebutton{ugIntroYouPageEmpty18}{\showpaste}
\tab{5}\spadcommand{cosinv(y) == cos(1/y)\bound{cosinv }}
\end{paste}\end{patch}

\begin{patch}{ugIntroYouPagePatch19}
\begin{paste}{ugIntroYouPageFull19}{ugIntroYouPageEmpty19}
\pastebutton{ugIntroYouPageFull19}{\hidepaste}
\tab{5}\spadcommand{t(cosinv, 5.2058)\free{t }\free{cosinv }}
\indentrel{3}\begin{verbatim}
   (19)  1.7392237241 800516493
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroYouPageEmpty19}
\begin{paste}{ugIntroYouPageEmpty19}{ugIntroYouPagePatch19}
\pastebutton{ugIntroYouPageEmpty19}{\showpaste}
\tab{5}\spadcommand{t(cosinv, 5.2058)\free{t }\free{cosinv }}
\end{paste}\end{patch}

\begin{patch}{ugIntroYouPagePatch20}
\begin{paste}{ugIntroYouPageFull20}{ugIntroYouPageEmpty20}
\pastebutton{ugIntroYouPageFull20}{\hidepaste}
\tab{5}\spadcommand{groupSqrt := rule(sqrt(a) * sqrt(b) == sqrt(a*b))\bound{g }}
\indentrel{3}\begin{verbatim}
             ÚÄ¿ ÚÄ¿        ÚÄÄÄ¿
   (20)  %BD\³a \³b  == %BD\³a b
  Type: RewriteRule(Integer,Integer,Expression Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroYouPageEmpty20}
\begin{paste}{ugIntroYouPageEmpty20}{ugIntroYouPagePatch20}
\pastebutton{ugIntroYouPageEmpty20}{\showpaste}
\tab{5}\spadcommand{groupSqrt := rule(sqrt(a) * sqrt(b) == sqrt(a*b))\bound{g }}
\end{paste}\end{patch}

\begin{patch}{ugIntroYouPagePatch21}
\begin{paste}{ugIntroYouPageFull21}{ugIntroYouPageEmpty21}
\pastebutton{ugIntroYouPageFull21}{\hidepaste}
\tab{5}\spadcommand{a := (sqrt(x) + sqrt(y) + sqrt(z))**4\bound{sxy }}
\indentrel{3}\begin{verbatim}
   (21)
                      ÚÄ¿                   ÚÄ¿  ÚÄ¿
     ((4z + 4y + 12x)\³y  + (4z + 12y + 4x)\³x )\³z
   + 
                     ÚÄ¿ ÚÄ¿    2                 2
     (12z + 4y + 4x)\³x \³y  + z  + (6y + 6x)z + y  + 6x y
   + 
      2
     x
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroYouPageEmpty21}
\begin{paste}{ugIntroYouPageEmpty21}{ugIntroYouPagePatch21}
\pastebutton{ugIntroYouPageEmpty21}{\showpaste}
\tab{5}\spadcommand{a := (sqrt(x) + sqrt(y) + sqrt(z))**4\bound{sxy }}
\end{paste}\end{patch}

\begin{patch}{ugIntroYouPagePatch22}
\begin{paste}{ugIntroYouPageFull22}{ugIntroYouPageEmpty22}
\pastebutton{ugIntroYouPageFull22}{\hidepaste}
\tab{5}\spadcommand{groupSqrt a\free{sxy }\free{g }}
\indentrel{3}\begin{verbatim}
   (22)
                     ÚÄÄÄ¿                   ÚÄÄÄ¿
     (4z + 4y + 12x)\³y z  + (4z + 12y + 4x)\³x z
   + 
                     ÚÄÄÄ¿    2                 2
     (12z + 4y + 4x)\³x y  + z  + (6y + 6x)z + y  + 6x y
   + 
      2
     x
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroYouPageEmpty22}
\begin{paste}{ugIntroYouPageEmpty22}{ugIntroYouPagePatch22}
\pastebutton{ugIntroYouPageEmpty22}{\showpaste}
\tab{5}\spadcommand{groupSqrt a\free{sxy }\free{g }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntroVariablesPage}{ug01.ht}{Polynomials}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroVariablesPage}{1.9. Polynomials}
\beginscroll
%

Polynomials are the commonly used algebraic types in symbolic
computation.
Interactive users of Axiom generally only see one type
of polynomial: \spadtype{Polynomial(R)}.
This type represents polynomials in any number of unspecified
variables over a particular coefficient domain \axiom{R}.
This type represents its coefficients
\spadglossSee{sparsely}{sparse}: only terms with non-zero
coefficients are represented.

In building applications, many other kinds of polynomial
representations are useful.
Polynomials may have one variable or multiple variables, the
variables can be named or unnamed, the coefficients can be stored
sparsely or densely.
So-called ``distributed multivariate polynomials'' store
polynomials as coefficients paired with vectors of exponents.
This type is particularly efficient for use in algorithms for
solving systems of non-linear polynomial equations.

\xtc{
The polynomial constructor most familiar to the interactive user
is \spadtype{Polynomial}.
}{
\spadpaste{(x**2 - x*y**3 +3*y)**2}
}
\xtc{
If you wish to restrict the variables used,
\spadtype{UnivariatePolynomial}
provides polynomials in one variable.
}{
\spadpaste{p: UP(x,INT) := (3*x-1)**2 * (2*x + 8)}
}
\xtc{
The constructor
\spadtype{MultivariatePolynomial} provides polynomials in one or more
specified variables.
}{
\spadpaste{m: MPOLY([x,y],INT) := (x**2-x*y**3+3*y)**2 \bound{m}}
}
\xtc{
You can change the way the polynomial appears by modifying the variable
ordering in the explicit list.
}{
\spadpaste{m :: MPOLY([y,x],INT) \free{m}}
}
\xtc{
The constructor
\spadtype{DistributedMultivariatePoly} provides
polynomials in one or more specified variables with the monomials
ordered lexicographically.
}{
\spadpaste{m :: DMP([y,x],INT) \free{m}}
}
\xtc{
The constructor
\spadtype{HomogeneousDistributedMultivariatePoly} is similar
except that the monomials are ordered by total order refined by
reverse lexicographic order.
}{
\spadpaste{m :: HDMP([y,x],INT) \free{m}}
}

More generally, the domain constructor
\spadtype{GeneralDistributedMultivariatePoly} allows the
user to provide an arbitrary predicate to define his own term ordering.
These last three constructors are typically used in
\texht{Gr\"{o}bner}{Groebner} basis
applications and when a flat (that is, non-recursive) display is
wanted and the term ordering is critical for controlling the computation.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntroVariablesPagePatch1}
\begin{paste}{ugIntroVariablesPageFull1}{ugIntroVariablesPageEmpty1}
\pastebutton{ugIntroVariablesPageFull1}{\hidepaste}
\tab{5}\spadcommand{(x**2 - x*y**3 +3*y)**2}
\indentrel{3}\begin{verbatim}
         2 6       4     3 3     2     2     4
   (1)  x y  - 6x y  - 2x y  + 9y  + 6x y + x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroVariablesPageEmpty1}
\begin{paste}{ugIntroVariablesPageEmpty1}{ugIntroVariablesPagePatch1}
\pastebutton{ugIntroVariablesPageEmpty1}{\showpaste}
\tab{5}\spadcommand{(x**2 - x*y**3 +3*y)**2}
\end{paste}\end{patch}

\begin{patch}{ugIntroVariablesPagePatch2}
\begin{paste}{ugIntroVariablesPageFull2}{ugIntroVariablesPageEmpty2}
\pastebutton{ugIntroVariablesPageFull2}{\hidepaste}
\tab{5}\spadcommand{p: UP(x,INT) := (3*x-1)**2 * (2*x + 8)}
\indentrel{3}\begin{verbatim}
           3      2
   (2)  18x  + 60x  - 46x + 8
                  Type: UnivariatePolynomial(x,Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroVariablesPageEmpty2}
\begin{paste}{ugIntroVariablesPageEmpty2}{ugIntroVariablesPagePatch2}
\pastebutton{ugIntroVariablesPageEmpty2}{\showpaste}
\tab{5}\spadcommand{p: UP(x,INT) := (3*x-1)**2 * (2*x + 8)}
\end{paste}\end{patch}

\begin{patch}{ugIntroVariablesPagePatch3}
\begin{paste}{ugIntroVariablesPageFull3}{ugIntroVariablesPageEmpty3}
\pastebutton{ugIntroVariablesPageFull3}{\hidepaste}
\tab{5}\spadcommand{m: MPOLY([x,y],INT) := (x**2-x*y**3+3*y)**2\bound{m }}
\indentrel{3}\begin{verbatim}
         4     3 3     6       2     4      2
   (3)  x  - 2y x  + (y  + 6y)x  - 6y x + 9y
            Type: MultivariatePolynomial([x,y],Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroVariablesPageEmpty3}
\begin{paste}{ugIntroVariablesPageEmpty3}{ugIntroVariablesPagePatch3}
\pastebutton{ugIntroVariablesPageEmpty3}{\showpaste}
\tab{5}\spadcommand{m: MPOLY([x,y],INT) := (x**2-x*y**3+3*y)**2\bound{m }}
\end{paste}\end{patch}

\begin{patch}{ugIntroVariablesPagePatch4}
\begin{paste}{ugIntroVariablesPageFull4}{ugIntroVariablesPageEmpty4}
\pastebutton{ugIntroVariablesPageFull4}{\hidepaste}
\tab{5}\spadcommand{m :: MPOLY([y,x],INT)\free{m }}
\indentrel{3}\begin{verbatim}
         2 6       4     3 3     2     2     4
   (4)  x y  - 6x y  - 2x y  + 9y  + 6x y + x
            Type: MultivariatePolynomial([y,x],Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroVariablesPageEmpty4}
\begin{paste}{ugIntroVariablesPageEmpty4}{ugIntroVariablesPagePatch4}
\pastebutton{ugIntroVariablesPageEmpty4}{\showpaste}
\tab{5}\spadcommand{m :: MPOLY([y,x],INT)\free{m }}
\end{paste}\end{patch}

\begin{patch}{ugIntroVariablesPagePatch5}
\begin{paste}{ugIntroVariablesPageFull5}{ugIntroVariablesPageEmpty5}
\pastebutton{ugIntroVariablesPageFull5}{\hidepaste}
\tab{5}\spadcommand{m :: DMP([y,x],INT)\free{m }}
\indentrel{3}\begin{verbatim}
         6 2     4      3 3     2       2    4
   (5)  y x  - 6y x - 2y x  + 9y  + 6y x  + x
 Type: DistributedMultivariatePolynomial([y,x],Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroVariablesPageEmpty5}
\begin{paste}{ugIntroVariablesPageEmpty5}{ugIntroVariablesPagePatch5}
\pastebutton{ugIntroVariablesPageEmpty5}{\showpaste}
\tab{5}\spadcommand{m :: DMP([y,x],INT)\free{m }}
\end{paste}\end{patch}

\begin{patch}{ugIntroVariablesPagePatch6}
\begin{paste}{ugIntroVariablesPageFull6}{ugIntroVariablesPageEmpty6}
\pastebutton{ugIntroVariablesPageFull6}{\hidepaste}
\tab{5}\spadcommand{m :: HDMP([y,x],INT)\free{m }}
\indentrel{3}\begin{verbatim}
         6 2     3 3     4     4       2     2
   (6)  y x  - 2y x  - 6y x + x  + 6y x  + 9y
Type: HomogeneousDistributedMultivariatePolynomial([y,x],Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroVariablesPageEmpty6}
\begin{paste}{ugIntroVariablesPageEmpty6}{ugIntroVariablesPagePatch6}
\pastebutton{ugIntroVariablesPageEmpty6}{\showpaste}
\tab{5}\spadcommand{m :: HDMP([y,x],INT)\free{m }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntroCalcLimitsPage}{ug01.ht}{Limits}
\pageto{notitle}{ugProblemLimitsPage}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroCalcLimitsPage}{1.10. Limits}
\beginscroll
%

Axiom's \axiomFun{limit} function is usually used to
evaluate limits of quotients where the numerator and denominator
both tend to zero or both tend to infinity.
To find the limit of an expression \axiom{f} as a real variable
\axiom{x} tends to a limit value \axiom{a}, enter \axiom{limit(f, x=a)}.
Use \axiomFun{complexLimit} if the variable is complex.
Additional information and examples of limits are in
\downlink{``Limits''}{ugProblemLimitsPage} 
in Section 8.6\ignore{ugProblemLimits}.

\xtc{
You can take limits of functions with parameters.
}{
\spadpaste{g := csc(a*x) / csch(b*x) \bound{g}}
}
\xtc{
As you can see, the limit is expressed in terms of the parameters.
}{
\spadpaste{limit(g,x=0) \free{g}}
}
%
\xtc{
A variable may also approach plus or minus infinity:
}{
\spadpaste{h := (1 + k/x)**x \bound{h}}
}
\xtc{
\texht{Use \axiom{\%plusInfinity} and \axiom{\%minusInfinity} to
denote $\infty$ and $-\infty$.}{}
}{
\spadpaste{limit(h,x=\%plusInfinity) \free{h}}
}
\xtc{
A function can be defined on both sides of a particular value, but may
tend to different limits as its variable approaches that value from
the left and from the right.
}{
\spadpaste{limit(sqrt(y**2)/y,y = 0)}
}
\xtc{
As \axiom{x} approaches \axiom{0} along the real axis, \axiom{exp(-1/x**2)}
tends to \axiom{0}.
}{
\spadpaste{limit(exp(-1/x**2),x = 0)}
}
\xtc{
However, if \axiom{x} is allowed to approach \axiom{0} along any path
in the complex plane, the limiting value of \axiom{exp(-1/x**2)}
depends on the path taken because the function has an essential
singularity at \axiom{x=0}.  This is reflected in the error message
returned by the function.
}{
\spadpaste{complexLimit(exp(-1/x**2),x = 0)}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntroCalcLimitsPagePatch1}
\begin{paste}{ugIntroCalcLimitsPageFull1}{ugIntroCalcLimitsPageEmpty1}
\pastebutton{ugIntroCalcLimitsPageFull1}{\hidepaste}
\tab{5}\spadcommand{g := csc(a*x) / csch(b*x)\bound{g }}
\indentrel{3}\begin{verbatim}
         csc(a x)
   (1)  ÄÄÄÄÄÄÄÄÄ
        csch(b x)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCalcLimitsPageEmpty1}
\begin{paste}{ugIntroCalcLimitsPageEmpty1}{ugIntroCalcLimitsPagePatch1}
\pastebutton{ugIntroCalcLimitsPageEmpty1}{\showpaste}
\tab{5}\spadcommand{g := csc(a*x) / csch(b*x)\bound{g }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCalcLimitsPagePatch2}
\begin{paste}{ugIntroCalcLimitsPageFull2}{ugIntroCalcLimitsPageEmpty2}
\pastebutton{ugIntroCalcLimitsPageFull2}{\hidepaste}
\tab{5}\spadcommand{limit(g,x=0)\free{g }}
\indentrel{3}\begin{verbatim}
        b
   (2)  Ä
        a
  Type: Union(OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCalcLimitsPageEmpty2}
\begin{paste}{ugIntroCalcLimitsPageEmpty2}{ugIntroCalcLimitsPagePatch2}
\pastebutton{ugIntroCalcLimitsPageEmpty2}{\showpaste}
\tab{5}\spadcommand{limit(g,x=0)\free{g }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCalcLimitsPagePatch3}
\begin{paste}{ugIntroCalcLimitsPageFull3}{ugIntroCalcLimitsPageEmpty3}
\pastebutton{ugIntroCalcLimitsPageFull3}{\hidepaste}
\tab{5}\spadcommand{h := (1 + k/x)**x\bound{h }}
\indentrel{3}\begin{verbatim}
         x + k x
   (3)  (ÄÄÄÄÄ)
           x
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCalcLimitsPageEmpty3}
\begin{paste}{ugIntroCalcLimitsPageEmpty3}{ugIntroCalcLimitsPagePatch3}
\pastebutton{ugIntroCalcLimitsPageEmpty3}{\showpaste}
\tab{5}\spadcommand{h := (1 + k/x)**x\bound{h }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCalcLimitsPagePatch4}
\begin{paste}{ugIntroCalcLimitsPageFull4}{ugIntroCalcLimitsPageEmpty4}
\pastebutton{ugIntroCalcLimitsPageFull4}{\hidepaste}
\tab{5}\spadcommand{limit(h,x=\%plusInfinity)\free{h }}
\indentrel{3}\begin{verbatim}
          k
   (4)  %e
  Type: Union(OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCalcLimitsPageEmpty4}
\begin{paste}{ugIntroCalcLimitsPageEmpty4}{ugIntroCalcLimitsPagePatch4}
\pastebutton{ugIntroCalcLimitsPageEmpty4}{\showpaste}
\tab{5}\spadcommand{limit(h,x=\%plusInfinity)\free{h }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCalcLimitsPagePatch5}
\begin{paste}{ugIntroCalcLimitsPageFull5}{ugIntroCalcLimitsPageEmpty5}
\pastebutton{ugIntroCalcLimitsPageFull5}{\hidepaste}
\tab{5}\spadcommand{limit(sqrt(y**2)/y,y = 0)}
\indentrel{3}\begin{verbatim}
   (5)  [leftHandLimit= - 1,rightHandLimit= 1]
Type: Union(Record(leftHandLimit: Union(OrderedCompletion Expression Integer,"failed"),rightHandLimit: Union(OrderedCompletion Expression Integer,"failed")),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCalcLimitsPageEmpty5}
\begin{paste}{ugIntroCalcLimitsPageEmpty5}{ugIntroCalcLimitsPagePatch5}
\pastebutton{ugIntroCalcLimitsPageEmpty5}{\showpaste}
\tab{5}\spadcommand{limit(sqrt(y**2)/y,y = 0)}
\end{paste}\end{patch}

\begin{patch}{ugIntroCalcLimitsPagePatch6}
\begin{paste}{ugIntroCalcLimitsPageFull6}{ugIntroCalcLimitsPageEmpty6}
\pastebutton{ugIntroCalcLimitsPageFull6}{\hidepaste}
\tab{5}\spadcommand{limit(exp(-1/x**2),x = 0)}
\indentrel{3}\begin{verbatim}
   (6)  0
  Type: Union(OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCalcLimitsPageEmpty6}
\begin{paste}{ugIntroCalcLimitsPageEmpty6}{ugIntroCalcLimitsPagePatch6}
\pastebutton{ugIntroCalcLimitsPageEmpty6}{\showpaste}
\tab{5}\spadcommand{limit(exp(-1/x**2),x = 0)}
\end{paste}\end{patch}

\begin{patch}{ugIntroCalcLimitsPagePatch7}
\begin{paste}{ugIntroCalcLimitsPageFull7}{ugIntroCalcLimitsPageEmpty7}
\pastebutton{ugIntroCalcLimitsPageFull7}{\hidepaste}
\tab{5}\spadcommand{complexLimit(exp(-1/x**2),x = 0)}
\indentrel{3}\begin{verbatim}
   (7)  "failed"
                              Type: Union("failed",...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCalcLimitsPageEmpty7}
\begin{paste}{ugIntroCalcLimitsPageEmpty7}{ugIntroCalcLimitsPagePatch7}
\pastebutton{ugIntroCalcLimitsPageEmpty7}{\showpaste}
\tab{5}\spadcommand{complexLimit(exp(-1/x**2),x = 0)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntroSeriesPage}{ug01.ht}{Series}
\pageto{notitle}{ugProblemSeriesPage}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroSeriesPage}{1.11. Series}
\beginscroll
%

Axiom also provides power series.
By default, Axiom tries to compute and display the first ten elements
of a series.
Use \spadsys{)set streams calculate} to change the default value
to something else.
For the purposes of this book, we have used this system command to display
fewer than ten terms.
For more information about working with series, see
\downlink{``Working with Power Series''}{ugProblemSeriesPage} 
in Section 8.9\ignore{ugProblemSeries}.

\xtc{
You can convert a functional expression to a power series by using the
operation \axiomFun{series}.
In this example,
\axiom{sin(a*x)} is expanded in powers of \axiom{(x - 0)},
that is, in powers of \axiom{x}.
}{
\spadpaste{series(sin(a*x),x = 0)}
}
\xtc{
This expression expands
\axiom{sin(a*x)} in powers of \axiom{(x - \%pi/4)}.
}{
\spadpaste{series(sin(a*x),x = \%pi/4)}
}
\xtc{
Axiom provides
{\it Puiseux series:}
series with rational number exponents.
The first argument to \axiomFun{series} is an in-place function that
computes the \eth{\axiom{n}} coefficient.
(Recall that
the \axiomSyntax{+->} is an infix operator meaning ``maps to.'')
}{
\spadpaste{
series(n +-> (-1)**((3*n - 4)/6)/factorial(n - 1/3),x = 0,4/3..,2)}
}
\xtc{
Once you have created a power series, you can perform arithmetic operations
on that series.
We compute the Taylor expansion of \axiom{1/(1-x)}.
}{
\spadpaste{f := series(1/(1-x),x = 0) \bound{f}}
}
\xtc{
Compute the square of the series.
}{
\spadpaste{f ** 2 \free{f}}
}
\xtc{
The usual elementary functions
(\axiomFun{log}, \axiomFun{exp}, trigonometric functions, and so on)
are defined for power series.
}{
\spadpaste{f := series(1/(1-x),x = 0) \bound{f1}}
}
\xtc{
}{
\spadpaste{g := log(f) \free{f1}\bound{g}}
}
\xtc{
}{
\spadpaste{exp(g) \free{g}}
}
\xtc{
Here is a way to obtain numerical approximations of
\axiom{e} from the Taylor series expansion of \axiom{exp(x)}.
First create the desired Taylor expansion.
}{
\spadpaste{f := taylor(exp(x)) \bound{f2}}
}
\xtc{
Evaluate the series at the value \axiom{1.0}.
As you see, you get a sequence of partial sums.
}{
\spadpaste{eval(f,1.0) \free{f2}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntroSeriesPagePatch1}
\begin{paste}{ugIntroSeriesPageFull1}{ugIntroSeriesPageEmpty1}
\pastebutton{ugIntroSeriesPageFull1}{\hidepaste}
\tab{5}\spadcommand{series(sin(a*x),x = 0)}
\indentrel{3}\begin{verbatim}
   (1)
            3        5        7          9
           a   3    a   5    a    7     a     9
     a x - ÄÄ x  + ÄÄÄ x  - ÄÄÄÄ x  + ÄÄÄÄÄÄ x
            6      120      5040      362880
   + 
           11
          a      11      12
     - ÄÄÄÄÄÄÄÄ x   + O(x  )
       39916800
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSeriesPageEmpty1}
\begin{paste}{ugIntroSeriesPageEmpty1}{ugIntroSeriesPagePatch1}
\pastebutton{ugIntroSeriesPageEmpty1}{\showpaste}
\tab{5}\spadcommand{series(sin(a*x),x = 0)}
\end{paste}\end{patch}

\begin{patch}{ugIntroSeriesPagePatch2}
\begin{paste}{ugIntroSeriesPageFull2}{ugIntroSeriesPageEmpty2}
\pastebutton{ugIntroSeriesPageFull2}{\hidepaste}
\tab{5}\spadcommand{series(sin(a*x),x = \%pi/4)}
\indentrel{3}\begin{verbatim}
   (2)
         a %pi          a %pi      %pi
     sin(ÄÄÄÄÄ) + a cos(ÄÄÄÄÄ)(x - ÄÄÄ)
           4              4         4
   + 
        2    a %pi                3    a %pi
       a sin(ÄÄÄÄÄ)              a cos(ÄÄÄÄÄ)
               4         %pi 2           4         %pi 3
     - ÄÄÄÄÄÄÄÄÄÄÄÄ (x - ÄÄÄ)  - ÄÄÄÄÄÄÄÄÄÄÄÄ (x - ÄÄÄ)
             2            4            6            4
   + 
      4    a %pi                5    a %pi
     a sin(ÄÄÄÄÄ)              a cos(ÄÄÄÄÄ)
             4         %pi 4           4         %pi 5
     ÄÄÄÄÄÄÄÄÄÄÄÄ (x - ÄÄÄ)  + ÄÄÄÄÄÄÄÄÄÄÄÄ (x - ÄÄÄ)
          24            4           120           4
   + 
        6    a %pi                7    a %pi
       a sin(ÄÄÄÄÄ)              a cos(ÄÄÄÄÄ)
               4         %pi 6           4         %pi 7
     - ÄÄÄÄÄÄÄÄÄÄÄÄ (x - ÄÄÄ)  - ÄÄÄÄÄÄÄÄÄÄÄÄ (x - ÄÄÄ)
            720           4          5040           4
   + 
      8    a %pi                9    a %pi
     a sin(ÄÄÄÄÄ)              a cos(ÄÄÄÄÄ)
             4         %pi 8           4         %pi 9
     ÄÄÄÄÄÄÄÄÄÄÄÄ (x - ÄÄÄ)  + ÄÄÄÄÄÄÄÄÄÄÄÄ (x - ÄÄÄ)
         40320          4         362880          4
   + 
        10    a %pi
       a  sin(ÄÄÄÄÄ)
                4         %pi 10          %pi 11
     - ÄÄÄÄÄÄÄÄÄÄÄÄÄ (x - ÄÄÄ)   + O((x - ÄÄÄ)  )
          3628800          4               4
Type: UnivariatePuiseuxSeries(Expression Integer,x,pi/4)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSeriesPageEmpty2}
\begin{paste}{ugIntroSeriesPageEmpty2}{ugIntroSeriesPagePatch2}
\pastebutton{ugIntroSeriesPageEmpty2}{\showpaste}
\tab{5}\spadcommand{series(sin(a*x),x = \%pi/4)}
\end{paste}\end{patch}

\begin{patch}{ugIntroSeriesPagePatch3}
\begin{paste}{ugIntroSeriesPageFull3}{ugIntroSeriesPageEmpty3}
\pastebutton{ugIntroSeriesPageFull3}{\hidepaste}
\tab{5}\spadcommand{series(n +-> (-1)**((3*n - 4)/6)/factorial(n - 1/3),x = 0,4/3..,2)}
\indentrel{3}\begin{verbatim}
         4      10
         Ä      ÄÄ
         3   1   3      5
   (3)  x  - Ä x   + O(x )
             6
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSeriesPageEmpty3}
\begin{paste}{ugIntroSeriesPageEmpty3}{ugIntroSeriesPagePatch3}
\pastebutton{ugIntroSeriesPageEmpty3}{\showpaste}
\tab{5}\spadcommand{series(n +-> (-1)**((3*n - 4)/6)/factorial(n - 1/3),x = 0,4/3..,2)}
\end{paste}\end{patch}

\begin{patch}{ugIntroSeriesPagePatch4}
\begin{paste}{ugIntroSeriesPageFull4}{ugIntroSeriesPageEmpty4}
\pastebutton{ugIntroSeriesPageFull4}{\hidepaste}
\tab{5}\spadcommand{f := series(1/(1-x),x = 0)\bound{f }}
\indentrel{3}\begin{verbatim}
   (4)
              2    3    4    5    6    7    8    9    10
     1 + x + x  + x  + x  + x  + x  + x  + x  + x  + x
   + 
        11
     O(x  )
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSeriesPageEmpty4}
\begin{paste}{ugIntroSeriesPageEmpty4}{ugIntroSeriesPagePatch4}
\pastebutton{ugIntroSeriesPageEmpty4}{\showpaste}
\tab{5}\spadcommand{f := series(1/(1-x),x = 0)\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ugIntroSeriesPagePatch5}
\begin{paste}{ugIntroSeriesPageFull5}{ugIntroSeriesPageEmpty5}
\pastebutton{ugIntroSeriesPageFull5}{\hidepaste}
\tab{5}\spadcommand{f ** 2\free{f }}
\indentrel{3}\begin{verbatim}
   (5)
                2     3     4     5     6     7     8
     1 + 2x + 3x  + 4x  + 5x  + 6x  + 7x  + 8x  + 9x
   + 
        9      10      11
     10x  + 11x   + O(x  )
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSeriesPageEmpty5}
\begin{paste}{ugIntroSeriesPageEmpty5}{ugIntroSeriesPagePatch5}
\pastebutton{ugIntroSeriesPageEmpty5}{\showpaste}
\tab{5}\spadcommand{f ** 2\free{f }}
\end{paste}\end{patch}

\begin{patch}{ugIntroSeriesPagePatch6}
\begin{paste}{ugIntroSeriesPageFull6}{ugIntroSeriesPageEmpty6}
\pastebutton{ugIntroSeriesPageFull6}{\hidepaste}
\tab{5}\spadcommand{f := series(1/(1-x),x = 0)\bound{f1 }}
\indentrel{3}\begin{verbatim}
   (6)
              2    3    4    5    6    7    8    9    10
     1 + x + x  + x  + x  + x  + x  + x  + x  + x  + x
   + 
        11
     O(x  )
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSeriesPageEmpty6}
\begin{paste}{ugIntroSeriesPageEmpty6}{ugIntroSeriesPagePatch6}
\pastebutton{ugIntroSeriesPageEmpty6}{\showpaste}
\tab{5}\spadcommand{f := series(1/(1-x),x = 0)\bound{f1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroSeriesPagePatch7}
\begin{paste}{ugIntroSeriesPageFull7}{ugIntroSeriesPageEmpty7}
\pastebutton{ugIntroSeriesPageFull7}{\hidepaste}
\tab{5}\spadcommand{g := log(f)\free{f1 }\bound{g }}
\indentrel{3}\begin{verbatim}
   (7)
         1  2   1  3   1  4   1  5   1  6   1  7   1  8
     x + Ä x  + Ä x  + Ä x  + Ä x  + Ä x  + Ä x  + Ä x
         2      3      4      5      6      7      8
   + 
     1  9    1  10    1  11      12
     Ä x  + ÄÄ x   + ÄÄ x   + O(x  )
     9      10       11
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSeriesPageEmpty7}
\begin{paste}{ugIntroSeriesPageEmpty7}{ugIntroSeriesPagePatch7}
\pastebutton{ugIntroSeriesPageEmpty7}{\showpaste}
\tab{5}\spadcommand{g := log(f)\free{f1 }\bound{g }}
\end{paste}\end{patch}

\begin{patch}{ugIntroSeriesPagePatch8}
\begin{paste}{ugIntroSeriesPageFull8}{ugIntroSeriesPageEmpty8}
\pastebutton{ugIntroSeriesPageFull8}{\hidepaste}
\tab{5}\spadcommand{exp(g)\free{g }}
\indentrel{3}\begin{verbatim}
   (8)
              2    3    4    5    6    7    8    9    10
     1 + x + x  + x  + x  + x  + x  + x  + x  + x  + x
   + 
        11
     O(x  )
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSeriesPageEmpty8}
\begin{paste}{ugIntroSeriesPageEmpty8}{ugIntroSeriesPagePatch8}
\pastebutton{ugIntroSeriesPageEmpty8}{\showpaste}
\tab{5}\spadcommand{exp(g)\free{g }}
\end{paste}\end{patch}

\begin{patch}{ugIntroSeriesPagePatch9}
\begin{paste}{ugIntroSeriesPageFull9}{ugIntroSeriesPageEmpty9}
\pastebutton{ugIntroSeriesPageFull9}{\hidepaste}
\tab{5}\spadcommand{f := taylor(exp(x))\bound{f2 }}
\indentrel{3}\begin{verbatim}
   (9)
             1  2   1  3    1  4    1   5    1   6
     1 + x + Ä x  + Ä x  + ÄÄ x  + ÄÄÄ x  + ÄÄÄ x
             2      6      24      120      720
   + 
     1   7     1    8      1    9      1     10      11
   ÄÄÄÄ x  + ÄÄÄÄÄ x  + ÄÄÄÄÄÄ x  + ÄÄÄÄÄÄÄ x   + O(x  )
   5040      40320      362880      3628800
   Type: UnivariateTaylorSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSeriesPageEmpty9}
\begin{paste}{ugIntroSeriesPageEmpty9}{ugIntroSeriesPagePatch9}
\pastebutton{ugIntroSeriesPageEmpty9}{\showpaste}
\tab{5}\spadcommand{f := taylor(exp(x))\bound{f2 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroSeriesPagePatch10}
\begin{paste}{ugIntroSeriesPageFull10}{ugIntroSeriesPageEmpty10}
\pastebutton{ugIntroSeriesPageFull10}{\hidepaste}
\tab{5}\spadcommand{eval(f,1.0)\free{f2 }}
\indentrel{3}\begin{verbatim}
   (10)
   [1.0, 2.0, 2.5, 2.6666666666 666666667,
    2.7083333333 333333333, 2.7166666666 666666667,
    2.7180555555 555555556, 2.7182539682 53968254,
    2.7182787698 412698413, 2.7182815255 731922399, ...]
                          Type: Stream Expression Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSeriesPageEmpty10}
\begin{paste}{ugIntroSeriesPageEmpty10}{ugIntroSeriesPagePatch10}
\pastebutton{ugIntroSeriesPageEmpty10}{\showpaste}
\tab{5}\spadcommand{eval(f,1.0)\free{f2 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntroCalcDerivPage}{ug01.ht}{Derivatives}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroCalcDerivPage}{1.12. Derivatives}
\beginscroll
%
Use the Axiom function \axiomFun{D} to differentiate an
expression.

\texht{\vskip 2pc}{}
\xtc{
To find the derivative of an expression \axiom{f} with respect to a
variable \axiom{x}, enter \axiom{D(f, x)}.
}{
\spadpaste{f := exp exp x \bound{f}}
}
\xtc{
}{
\spadpaste{D(f, x) \free{f}}
}
\xtc{
An optional third argument \axiom{n} in \axiomFun{D} asks
Axiom for the \eth{\axiom{n}} derivative of \axiom{f}.
This finds the fourth derivative of \axiom{f} with respect to \axiom{x}.
}{
\spadpaste{D(f, x, 4) \free{f}}
}
\xtc{
You can also compute partial derivatives by specifying the order of
differentiation.
}{
\spadpaste{g := sin(x**2 + y) \bound{g}}
}
\xtc{
}{
\spadpaste{D(g, y) \free{g}}
}
\xtc{
}{
\spadpaste{D(g, [y, y, x, x]) \free{g}}
}

Axiom can manipulate the derivatives (partial and iterated) of
expressions involving formal operators.
All the dependencies must be explicit.
\xtc{
This returns \axiom{0} since \axiom{F} (so far)
does not explicitly depend on \axiom{x}.
}{
\spadpaste{D(F,x)}
}
Suppose that we have \axiom{F} a function of \axiom{x},
\axiom{y}, and \axiom{z}, where \axiom{x} and \axiom{y} are themselves
functions of \axiom{z}.
\xtc{
Start by declaring that \axiom{F}, \axiom{x}, and \axiom{y}
are operators.
}{
\spadpaste{
F := operator 'F; x := operator 'x; y := operator 'y\bound{F x y}}
}
\xtc{
You can use \axiom{F}, \axiom{x}, and \axiom{y} in expressions.
}{
\spadpaste{
a := F(x z, y z, z**2) + x y(z+1) \bound{a}\free{F}\free{x}\free{y}}
}
\xtc{
Differentiate formally with respect to \axiom{z}.  The formal
derivatives appearing in \axiom{dadz} are not just formal symbols, but
do represent the derivatives of \axiom{x}, \axiom{y}, and \axiom{F}.
}{
\spadpaste{dadz := D(a, z)\bound{da}\free{a}}
}
\xtc{
You can evaluate the above for particular functional values of
\axiom{F}, \axiom{x}, and \axiom{y}.  If \axiom{x(z)} is
\axiom{exp(z)} and \axiom{y(z)} is \axiom{log(z+1)}, then this
evaluates \axiom{dadz}.
}{
\spadpaste{eval(eval(dadz, 'x, z +-> exp z), 'y, z +-> log(z+1))\free{da}}
}
\xtc{
You obtain the same result by first evaluating \axiom{a} and
then differentiating.
}{
\spadpaste{eval(eval(a, 'x, z +-> exp z), 'y, z +-> log(z+1)) \free{a}\bound{eva}}
}
\xtc{
}{
\spadpaste{D(\%, z)\free{eva}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntroCalcDerivPagePatch1}
\begin{paste}{ugIntroCalcDerivPageFull1}{ugIntroCalcDerivPageEmpty1}
\pastebutton{ugIntroCalcDerivPageFull1}{\hidepaste}
\tab{5}\spadcommand{f := exp exp x\bound{f }}
\indentrel{3}\begin{verbatim}
            x
          %e
   (1)  %e
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPageEmpty1}
\begin{paste}{ugIntroCalcDerivPageEmpty1}{ugIntroCalcDerivPagePatch1}
\pastebutton{ugIntroCalcDerivPageEmpty1}{\showpaste}
\tab{5}\spadcommand{f := exp exp x\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPagePatch2}
\begin{paste}{ugIntroCalcDerivPageFull2}{ugIntroCalcDerivPageEmpty2}
\pastebutton{ugIntroCalcDerivPageFull2}{\hidepaste}
\tab{5}\spadcommand{D(f, x)\free{f }}
\indentrel{3}\begin{verbatim}
               x
          x  %e
   (2)  %e %e
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPageEmpty2}
\begin{paste}{ugIntroCalcDerivPageEmpty2}{ugIntroCalcDerivPagePatch2}
\pastebutton{ugIntroCalcDerivPageEmpty2}{\showpaste}
\tab{5}\spadcommand{D(f, x)\free{f }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPagePatch3}
\begin{paste}{ugIntroCalcDerivPageFull3}{ugIntroCalcDerivPageEmpty3}
\pastebutton{ugIntroCalcDerivPageFull3}{\hidepaste}
\tab{5}\spadcommand{D(f, x, 4)\free{f }}
\indentrel{3}\begin{verbatim}
                                              x
            x 4       x 3       x 2     x   %e
   (3)  ((%e )  + 6(%e )  + 7(%e )  + %e )%e
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPageEmpty3}
\begin{paste}{ugIntroCalcDerivPageEmpty3}{ugIntroCalcDerivPagePatch3}
\pastebutton{ugIntroCalcDerivPageEmpty3}{\showpaste}
\tab{5}\spadcommand{D(f, x, 4)\free{f }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPagePatch4}
\begin{paste}{ugIntroCalcDerivPageFull4}{ugIntroCalcDerivPageEmpty4}
\pastebutton{ugIntroCalcDerivPageFull4}{\hidepaste}
\tab{5}\spadcommand{g := sin(x**2 + y)\bound{g }}
\indentrel{3}\begin{verbatim}
                 2
   (4)  sin(y + x )
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPageEmpty4}
\begin{paste}{ugIntroCalcDerivPageEmpty4}{ugIntroCalcDerivPagePatch4}
\pastebutton{ugIntroCalcDerivPageEmpty4}{\showpaste}
\tab{5}\spadcommand{g := sin(x**2 + y)\bound{g }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPagePatch5}
\begin{paste}{ugIntroCalcDerivPageFull5}{ugIntroCalcDerivPageEmpty5}
\pastebutton{ugIntroCalcDerivPageFull5}{\hidepaste}
\tab{5}\spadcommand{D(g, y)\free{g }}
\indentrel{3}\begin{verbatim}
                 2
   (5)  cos(y + x )
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPageEmpty5}
\begin{paste}{ugIntroCalcDerivPageEmpty5}{ugIntroCalcDerivPagePatch5}
\pastebutton{ugIntroCalcDerivPageEmpty5}{\showpaste}
\tab{5}\spadcommand{D(g, y)\free{g }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPagePatch6}
\begin{paste}{ugIntroCalcDerivPageFull6}{ugIntroCalcDerivPageEmpty6}
\pastebutton{ugIntroCalcDerivPageFull6}{\hidepaste}
\tab{5}\spadcommand{D(g, [y, y, x, x])\free{g }}
\indentrel{3}\begin{verbatim}
          2         2              2
   (6)  4x sin(y + x ) - 2cos(y + x )
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPageEmpty6}
\begin{paste}{ugIntroCalcDerivPageEmpty6}{ugIntroCalcDerivPagePatch6}
\pastebutton{ugIntroCalcDerivPageEmpty6}{\showpaste}
\tab{5}\spadcommand{D(g, [y, y, x, x])\free{g }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPagePatch7}
\begin{paste}{ugIntroCalcDerivPageFull7}{ugIntroCalcDerivPageEmpty7}
\pastebutton{ugIntroCalcDerivPageFull7}{\hidepaste}
\tab{5}\spadcommand{D(F,x)}
\indentrel{3}\begin{verbatim}
   (7)  0
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPageEmpty7}
\begin{paste}{ugIntroCalcDerivPageEmpty7}{ugIntroCalcDerivPagePatch7}
\pastebutton{ugIntroCalcDerivPageEmpty7}{\showpaste}
\tab{5}\spadcommand{D(F,x)}
\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPagePatch8}
\begin{paste}{ugIntroCalcDerivPageFull8}{ugIntroCalcDerivPageEmpty8}
\pastebutton{ugIntroCalcDerivPageFull8}{\hidepaste}
\tab{5}\spadcommand{F := operator 'F; x := operator 'x; y := operator 'y\bound{F x y }}
\indentrel{3}\begin{verbatim}
   (8)  y
                                    Type: BasicOperator
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPageEmpty8}
\begin{paste}{ugIntroCalcDerivPageEmpty8}{ugIntroCalcDerivPagePatch8}
\pastebutton{ugIntroCalcDerivPageEmpty8}{\showpaste}
\tab{5}\spadcommand{F := operator 'F; x := operator 'x; y := operator 'y\bound{F x y }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPagePatch9}
\begin{paste}{ugIntroCalcDerivPageFull9}{ugIntroCalcDerivPageEmpty9}
\pastebutton{ugIntroCalcDerivPageFull9}{\hidepaste}
\tab{5}\spadcommand{a := F(x z, y z, z**2) + x y(z+1)\bound{a }\free{F }\free{x }\free{y }}
\indentrel{3}\begin{verbatim}
                                   2
   (9)  x(y(z + 1)) + F(x(z),y(z),z )
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPageEmpty9}
\begin{paste}{ugIntroCalcDerivPageEmpty9}{ugIntroCalcDerivPagePatch9}
\pastebutton{ugIntroCalcDerivPageEmpty9}{\showpaste}
\tab{5}\spadcommand{a := F(x z, y z, z**2) + x y(z+1)\bound{a }\free{F }\free{x }\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPagePatch10}
\begin{paste}{ugIntroCalcDerivPageFull10}{ugIntroCalcDerivPageEmpty10}
\pastebutton{ugIntroCalcDerivPageFull10}{\hidepaste}
\tab{5}\spadcommand{dadz := D(a, z)\bound{da }\free{a }}
\indentrel{3}\begin{verbatim}
   (10)
                      2     ,                  2
     2zF  (x(z),y(z),z ) + y (z)F  (x(z),y(z),z )
        ,3                       ,2
   + 
      ,                  2     ,           ,
     x (z)F  (x(z),y(z),z ) + x (y(z + 1))y (z + 1)
           ,1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPageEmpty10}
\begin{paste}{ugIntroCalcDerivPageEmpty10}{ugIntroCalcDerivPagePatch10}
\pastebutton{ugIntroCalcDerivPageEmpty10}{\showpaste}
\tab{5}\spadcommand{dadz := D(a, z)\bound{da }\free{a }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPagePatch11}
\begin{paste}{ugIntroCalcDerivPageFull11}{ugIntroCalcDerivPageEmpty11}
\pastebutton{ugIntroCalcDerivPageFull11}{\hidepaste}
\tab{5}\spadcommand{eval(eval(dadz, 'x, z +-> exp z), 'y, z +-> log(z+1))\free{da }}
\indentrel{3}\begin{verbatim}
   (11)
          2            z             2
       (2z  + 2z)F  (%e ,log(z + 1),z )
                  ,3
     + 
             z             2
       F  (%e ,log(z + 1),z )
        ,2
     + 
                z      z             2
       (z + 1)%e F  (%e ,log(z + 1),z ) + z + 1
                  ,1
  /
     z + 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPageEmpty11}
\begin{paste}{ugIntroCalcDerivPageEmpty11}{ugIntroCalcDerivPagePatch11}
\pastebutton{ugIntroCalcDerivPageEmpty11}{\showpaste}
\tab{5}\spadcommand{eval(eval(dadz, 'x, z +-> exp z), 'y, z +-> log(z+1))\free{da }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPagePatch12}
\begin{paste}{ugIntroCalcDerivPageFull12}{ugIntroCalcDerivPageEmpty12}
\pastebutton{ugIntroCalcDerivPageFull12}{\hidepaste}
\tab{5}\spadcommand{eval(eval(a, 'x, z +-> exp z), 'y, z +-> log(z+1))\free{a }\bound{eva }}
\indentrel{3}\begin{verbatim}
             z             2
   (12)  F(%e ,log(z + 1),z ) + z + 2
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPageEmpty12}
\begin{paste}{ugIntroCalcDerivPageEmpty12}{ugIntroCalcDerivPagePatch12}
\pastebutton{ugIntroCalcDerivPageEmpty12}{\showpaste}
\tab{5}\spadcommand{eval(eval(a, 'x, z +-> exp z), 'y, z +-> log(z+1))\free{a }\bound{eva }}
\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPagePatch13}
\begin{paste}{ugIntroCalcDerivPageFull13}{ugIntroCalcDerivPageEmpty13}
\pastebutton{ugIntroCalcDerivPageFull13}{\hidepaste}
\tab{5}\spadcommand{D(\%, z)\free{eva }}
\indentrel{3}\begin{verbatim}
   (13)
          2            z             2
       (2z  + 2z)F  (%e ,log(z + 1),z )
                  ,3
     + 
             z             2
       F  (%e ,log(z + 1),z )
        ,2
     + 
                z      z             2
       (z + 1)%e F  (%e ,log(z + 1),z ) + z + 1
                  ,1
  /
     z + 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroCalcDerivPageEmpty13}
\begin{paste}{ugIntroCalcDerivPageEmpty13}{ugIntroCalcDerivPagePatch13}
\pastebutton{ugIntroCalcDerivPageEmpty13}{\showpaste}
\tab{5}\spadcommand{D(\%, z)\free{eva }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntroIntegratePage}{ug01.ht}{Integration}
\pageto{notitle}{ugProblemIntegrationPage}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroIntegratePage}{1.13. Integration}
\beginscroll
%

Axiom has extensive library facilities for integration.

The first example is the integration of a fraction with denominator
that factors into a quadratic and a quartic irreducible polynomial.
The usual partial fraction approach used by most other computer
algebra systems either fails or introduces expensive unneeded
algebraic numbers.

\xtc{
We use a factorization-free algorithm.
}{
\spadpaste{integrate((x**2+2*x+1)/((x+1)**6+1),x)}
}

When real parameters are present, the form of the integral can depend on
the signs of some expressions.

\xtc{
Rather than query the user or make sign assumptions, Axiom returns
all possible answers.
}{
\spadpaste{integrate(1/(x**2 + a),x)}
}

The \axiomFun{integrate} operation generally assumes that all
parameters are real.
The only exception is when the integrand has complex valued
quantities.

\xtc{
If the parameter is complex instead of real, then the notion of sign
is undefined and there is a unique answer.  You can request this
answer by ``prepending'' the word ``complex'' to the command name:
}{
\spadpaste{complexIntegrate(1/(x**2 + a),x)}
}

The following two examples illustrate the limitations of table-based
approaches.  The two integrands are very similar, but the answer to
one of them requires the addition of two new algebraic numbers.

\xtc{
This one is the easy one.
The next one looks very similar
but the answer is much more complicated.
}{
\spadpaste{integrate(x**3 / (a+b*x)**(1/3),x)}
}
\xtc{
Only an algorithmic approach
is guaranteed to find what new constants must be added in order to
find a solution.
}{
\spadpaste{integrate(1 / (x**3 * (a+b*x)**(1/3)),x)}
}

Some computer algebra systems use heuristics or table-driven
approaches to integration.  When these systems cannot determine the
answer to an integration problem, they reply ``I don't know.'' Axiom
uses an algorithm for integration.  that conclusively proves that an
integral cannot be expressed in terms of elementary functions.

\xtc{
When Axiom returns an integral sign, it has proved
that no answer exists as an elementary function.
}{
\spadpaste{integrate(log(1 + sqrt(a*x + b)) / x,x)}
}
Axiom can handle complicated mixed functions much beyond what you
can find in tables.
\xtc{
Whenever possible, Axiom tries to express the answer using the functions
present in the integrand.
}{
\spadpaste{integrate((sinh(1+sqrt(x+b))+2*sqrt(x+b)) / 
(sqrt(x+b) * (x + cosh(1+sqrt(x + b)))), x)}
}
\xtc{
A strong structure-checking algorithm in Axiom finds hidden algebraic
relationships between functions.
}{
\spadpaste{integrate(tan(atan(x)/3),x)}
}
\noindent
%%--> Bob---> please make these formulas in this section smaller.
The discovery of this algebraic relationship is necessary for correct
integration of this function.
Here are the details:
\indent{4}
\beginitems
\item[1. ] 
If \texht{$x=\tan t$}{\axiom{x=tan(t)}} and
\texht{$g=\tan (t/3)$}{\axiom{g=tan(t/3)}} then the following
algebraic relation is true:
\texht{$${g^3-3xg^2-3g+x=0}$$}
{\centerline{\axiom{g**3 - 3*x*g**2 - 3*g + x = 0}}}
\item[2. ] 
Integrate \axiom{g} using this algebraic relation; this produces:
\texht{$${%
{(24g^2 - 8)\log(3g^2 - 1) + (81x^2 + 24)g^2 + 72xg - 27x^2 - 16}
\over{54g^2 - 18}}$$}{\centerline{\axiom{(24g**2 - 8)log(3g**2 - 1) +
(81x**2 + 24)g**2 + 72xg - 27x**2 - 16/ (54g**2 - 18)}}}
\item[3. ] 
Rationalize the denominator, producing:
\texht{\narrowDisplay{{8\log(3g^2-1) - 3g^2 + 18xg + 16} \over
{18}}}{\centerline{\axiom{(8*log(3*g**2-1) - 3*g**2 + 18*x*g + 16)/18}}}
Replace \axiom{g} by the initial definition
\texht{$g = \tan(\arctan(x)/3)$}{\axiom{g = tan(arctan(x)/3)}}
to produce the final result.
\enditems
\indent{0}

\xtc{
This is an example of a mixed function where
the algebraic layer is over the transcendental one.
}{
\spadpaste{integrate((x + 1) / (x*(x + log x) ** (3/2)), x)}
}
\xtc{
While incomplete for non-elementary functions, Axiom can
handle some of them.
}{
\spadpaste{integrate(exp(-x**2) * erf(x) / 
(erf(x)**3 - erf(x)**2 - erf(x) + 1),x)}
}

More examples of Axiom's integration capabilities are discussed in
\downlink{``Integration''}{ugProblemIntegrationPage} 
in Section 8.8\ignore{ugProblemIntegration}.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntroIntegratePagePatch1}
\begin{paste}{ugIntroIntegratePageFull1}{ugIntroIntegratePageEmpty1}
\pastebutton{ugIntroIntegratePageFull1}{\hidepaste}
\tab{5}\spadcommand{integrate((x**2+2*x+1)/((x+1)**6+1),x)}
\indentrel{3}\begin{verbatim}
              3     2
        atan(x  + 3x  + 3x + 1)
   (1)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                   3
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroIntegratePageEmpty1}
\begin{paste}{ugIntroIntegratePageEmpty1}{ugIntroIntegratePagePatch1}
\pastebutton{ugIntroIntegratePageEmpty1}{\showpaste}
\tab{5}\spadcommand{integrate((x**2+2*x+1)/((x+1)**6+1),x)}
\end{paste}\end{patch}

\begin{patch}{ugIntroIntegratePagePatch2}
\begin{paste}{ugIntroIntegratePageFull2}{ugIntroIntegratePageEmpty2}
\pastebutton{ugIntroIntegratePageFull2}{\hidepaste}
\tab{5}\spadcommand{integrate(1/(x**2 + a),x)}
\indentrel{3}\begin{verbatim}
               2      ÚÄÄÄ¿
             (x  - a)\³- a  + 2a x         ÚÄ¿
         log(ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ)      x\³a
                      2             atan(ÄÄÄÄÄ)
                     x  + a                a
   (2)  [ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ,ÄÄÄÄÄÄÄÄÄÄÄ]
                     ÚÄÄÄ¿               ÚÄ¿
                   2\³- a               \³a
               Type: Union(List Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroIntegratePageEmpty2}
\begin{paste}{ugIntroIntegratePageEmpty2}{ugIntroIntegratePagePatch2}
\pastebutton{ugIntroIntegratePageEmpty2}{\showpaste}
\tab{5}\spadcommand{integrate(1/(x**2 + a),x)}
\end{paste}\end{patch}

\begin{patch}{ugIntroIntegratePagePatch3}
\begin{paste}{ugIntroIntegratePageFull3}{ugIntroIntegratePageEmpty3}
\pastebutton{ugIntroIntegratePageFull3}{\hidepaste}
\tab{5}\spadcommand{complexIntegrate(1/(x**2 + a),x)}
\indentrel{3}\begin{verbatim}
              ÚÄÄÄ¿              ÚÄÄÄ¿
            x\³- a  + a        x\³- a  - a
        log(ÄÄÄÄÄÄÄÄÄÄÄ) - log(ÄÄÄÄÄÄÄÄÄÄÄ)
                ÚÄÄÄ¿              ÚÄÄÄ¿
               \³- a              \³- a
   (3)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                        ÚÄÄÄ¿
                      2\³- a
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroIntegratePageEmpty3}
\begin{paste}{ugIntroIntegratePageEmpty3}{ugIntroIntegratePagePatch3}
\pastebutton{ugIntroIntegratePageEmpty3}{\showpaste}
\tab{5}\spadcommand{complexIntegrate(1/(x**2 + a),x)}
\end{paste}\end{patch}

\begin{patch}{ugIntroIntegratePagePatch4}
\begin{paste}{ugIntroIntegratePageFull4}{ugIntroIntegratePageEmpty4}
\pastebutton{ugIntroIntegratePageFull4}{\hidepaste}
\tab{5}\spadcommand{integrate(x**3 / (a+b*x)**(1/3),x)}
\indentrel{3}\begin{verbatim}
   (4)
        3 3         2 2       2          3 3ÚÄÄÄÄÄÄÄ¿2
   (120b x  - 135a b x  + 162a b x - 243a )\³b x + a
   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                              4
                          440b
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroIntegratePageEmpty4}
\begin{paste}{ugIntroIntegratePageEmpty4}{ugIntroIntegratePagePatch4}
\pastebutton{ugIntroIntegratePageEmpty4}{\showpaste}
\tab{5}\spadcommand{integrate(x**3 / (a+b*x)**(1/3),x)}
\end{paste}\end{patch}

\begin{patch}{ugIntroIntegratePagePatch5}
\begin{paste}{ugIntroIntegratePageFull5}{ugIntroIntegratePageEmpty5}
\pastebutton{ugIntroIntegratePageFull5}{\hidepaste}
\tab{5}\spadcommand{integrate(1 / (x**3 * (a+b*x)**(1/3)),x)}
\indentrel{3}\begin{verbatim}
   (5)
       -
              2 2 ÚÄ¿
            2b x \³3
         *
                3ÚÄ¿3ÚÄÄÄÄÄÄÄ¿2   3ÚÄ¿2 3ÚÄÄÄÄÄÄÄ¿
            log(\³a \³b x + a   + \³a   \³b x + a + a)
     + 
         2 2 ÚÄ¿    3ÚÄ¿2 3ÚÄÄÄÄÄÄÄ¿
       4b x \³3 log(\³a   \³b x + a - a)
     + 
                    ÚÄ¿3ÚÄ¿2 3ÚÄÄÄÄÄÄÄ¿    ÚÄ¿
          2 2     2\³3 \³a   \³b x + a + a\³3
       12b x atan(ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ)
                               3a
     + 
                    ÚÄ¿3ÚÄ¿3ÚÄÄÄÄÄÄÄ¿2
       (12b x - 9a)\³3 \³a \³b x + a
  /
        2 2 ÚÄ¿3ÚÄ¿
     18a x \³3 \³a
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroIntegratePageEmpty5}
\begin{paste}{ugIntroIntegratePageEmpty5}{ugIntroIntegratePagePatch5}
\pastebutton{ugIntroIntegratePageEmpty5}{\showpaste}
\tab{5}\spadcommand{integrate(1 / (x**3 * (a+b*x)**(1/3)),x)}
\end{paste}\end{patch}

\begin{patch}{ugIntroIntegratePagePatch6}
\begin{paste}{ugIntroIntegratePageFull6}{ugIntroIntegratePageEmpty6}
\pastebutton{ugIntroIntegratePageFull6}{\hidepaste}
\tab{5}\spadcommand{integrate(log(1 + sqrt(a*x + b)) / x,x)}
\indentrel{3}\begin{verbatim}
           x      ÚÄÄÄÄÄÄÄÄ¿
         Ú¿  log(\³b + %S a  + 1)
   (6)   ³   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ d%S
        ÀÙ            %S
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroIntegratePageEmpty6}
\begin{paste}{ugIntroIntegratePageEmpty6}{ugIntroIntegratePagePatch6}
\pastebutton{ugIntroIntegratePageEmpty6}{\showpaste}
\tab{5}\spadcommand{integrate(log(1 + sqrt(a*x + b)) / x,x)}
\end{paste}\end{patch}

\begin{patch}{ugIntroIntegratePagePatch7}
\begin{paste}{ugIntroIntegratePageFull7}{ugIntroIntegratePageEmpty7}
\pastebutton{ugIntroIntegratePageFull7}{\hidepaste}
\tab{5}\spadcommand{integrate((sinh(1+sqrt(x+b))+2*sqrt(x+b)) / (sqrt(x+b) * (x + cosh(1+sqrt(x + b)))), x)}
\indentrel{3}\begin{verbatim}
   (7)
                          ÚÄÄÄÄÄ¿
                 - 2cosh(\³x + b  + 1) - 2x
     2log(ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ)
                ÚÄÄÄÄÄ¿              ÚÄÄÄÄÄ¿
          sinh(\³x + b  + 1) - cosh(\³x + b  + 1)
   + 
         ÚÄÄÄÄÄ¿
     - 2\³x + b
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroIntegratePageEmpty7}
\begin{paste}{ugIntroIntegratePageEmpty7}{ugIntroIntegratePagePatch7}
\pastebutton{ugIntroIntegratePageEmpty7}{\showpaste}
\tab{5}\spadcommand{integrate((sinh(1+sqrt(x+b))+2*sqrt(x+b)) / (sqrt(x+b) * (x + cosh(1+sqrt(x + b)))), x)}
\end{paste}\end{patch}

\begin{patch}{ugIntroIntegratePagePatch8}
\begin{paste}{ugIntroIntegratePageFull8}{ugIntroIntegratePageEmpty8}
\pastebutton{ugIntroIntegratePageFull8}{\hidepaste}
\tab{5}\spadcommand{integrate(tan(atan(x)/3),x)}
\indentrel{3}\begin{verbatim}
   (8)
                 atan(x) 2             atan(x) 2
       8log(3tan(ÄÄÄÄÄÄÄ)  - 1) - 3tan(ÄÄÄÄÄÄÄ)
                    3                     3
     + 
               atan(x)
       18x tan(ÄÄÄÄÄÄÄ)
                  3
  /
     18
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroIntegratePageEmpty8}
\begin{paste}{ugIntroIntegratePageEmpty8}{ugIntroIntegratePagePatch8}
\pastebutton{ugIntroIntegratePageEmpty8}{\showpaste}
\tab{5}\spadcommand{integrate(tan(atan(x)/3),x)}
\end{paste}\end{patch}

\begin{patch}{ugIntroIntegratePagePatch9}
\begin{paste}{ugIntroIntegratePageFull9}{ugIntroIntegratePageEmpty9}
\pastebutton{ugIntroIntegratePageFull9}{\hidepaste}
\tab{5}\spadcommand{integrate((x + 1) / (x*(x + log x) ** (3/2)), x)}
\indentrel{3}\begin{verbatim}
            ÚÄÄÄÄÄÄÄÄÄÄ¿
          2\³log(x) + x
   (9)  - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
            log(x) + x
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroIntegratePageEmpty9}
\begin{paste}{ugIntroIntegratePageEmpty9}{ugIntroIntegratePagePatch9}
\pastebutton{ugIntroIntegratePageEmpty9}{\showpaste}
\tab{5}\spadcommand{integrate((x + 1) / (x*(x + log x) ** (3/2)), x)}
\end{paste}\end{patch}

\begin{patch}{ugIntroIntegratePagePatch10}
\begin{paste}{ugIntroIntegratePageFull10}{ugIntroIntegratePageEmpty10}
\pastebutton{ugIntroIntegratePageFull10}{\hidepaste}
\tab{5}\spadcommand{integrate(exp(-x**2) * erf(x) / (erf(x)**3 - erf(x)**2 - erf(x) + 1),x)}
\indentrel{3}\begin{verbatim}
                      ÚÄÄÄ¿    erf(x) - 1      ÚÄÄÄ¿
         (erf(x) - 1)\³%pi log(ÄÄÄÄÄÄÄÄÄÄ) - 2\³%pi
                               erf(x) + 1
   (10)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                         8erf(x) - 8
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroIntegratePageEmpty10}
\begin{paste}{ugIntroIntegratePageEmpty10}{ugIntroIntegratePagePatch10}
\pastebutton{ugIntroIntegratePageEmpty10}{\showpaste}
\tab{5}\spadcommand{integrate(exp(-x**2) * erf(x) / (erf(x)**3 - erf(x)**2 - erf(x) + 1),x)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntroDiffEqnsPage}{ug01.ht}{Differential Equations}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroDiffEqnsPage}{1.14. Differential Equations}
\beginscroll
%
The general approach used in integration also carries over to the
solution of linear differential equations.

\labelSpace{2pc}
\xtc{
Let's solve some differential equations.
Let \axiom{y} be the unknown function in terms of \axiom{x}.
}{
\spadpaste{y := operator 'y \bound{y}}
}
\xtc{
Here we solve a third order equation with polynomial coefficients.
}{
\spadpaste{deq := x**3 * D(y x, x, 3) + x**2 * D(y x, x, 2) - 2 * 
x * D(y x, x) + 2 * y x = 2 * x**4 \bound{e3}\free{y}}
}
\xtc{
}{
\spadpaste{solve(deq, y, x) \free{e3}\free{y}}
}
\xtc{
Here we find all the algebraic function solutions of the equation.
}{
\spadpaste{
deq := (x**2 + 1) * D(y x, x, 2) + 3 * x * D(y x, x) + y x = 0 
\bound{e5}\free{y}}
}
\xtc{
}{
\spadpaste{solve(deq, y, x) \free{e5}\free{y}}
}

Coefficients of differential equations can come from arbitrary
constant fields.
For example, coefficients can contain algebraic numbers.

\xtc{
This example has solutions
whose logarithmic derivative is an algebraic function of
degree two.
}{
\spadpaste{eq := 2*x**3 * D(y x,x,2) + 3*x**2 * D(y x,x) - 2 * y x
\bound{eq}\free{y}}
}
\xtc{
}{
\spadpaste{solve(eq,y,x).basis\free{eq}}
}

\xtc{
Here's another differential equation to solve.
}{
\spadpaste{deq := D(y x, x) = y(x) / (x + y(x) * log y x) 
\bound{deqi}\free{y}}
}
\xtc{
}{
\spadpaste{solve(deq, y, x) \free{deqi y}}
}

Rather than attempting to get a closed form solution of
a differential equation, you instead might want to find an
approximate solution in the form of a series.

\xtc{
Let's solve a system of nonlinear first order equations and get a
solution in power series.
Tell Axiom that \axiom{x} is also an operator.
}{
\spadpaste{x := operator 'x\bound{x}}
}
\xtc{
Here are the two equations forming our system.
}{
\spadpaste{eq1 := D(x(t), t) = 1 + x(t)**2\free{x}\free{y}\bound{eq1}}
}
\xtc{
}{
\spadpaste{eq2 := D(y(t), t) = x(t) * y(t)\free{x}\free{y}\bound{eq2}}
}
\xtc{
We can solve the system around \axiom{t = 0} with the initial conditions
\axiom{x(0) = 0} and \axiom{y(0) = 1}.
Notice that since we give the unknowns in the
order \axiom{[x, y]}, the answer is a list of two series in the order
\axiom{[series for x(t), series for y(t)]}.
}{
\spadpaste{seriesSolve([eq2, eq1], [x, y], t = 0, 
[y(0) = 1, x(0) = 0])\free{x}\free{y}\free{eq1}\free{eq2}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntroDiffEqnsPagePatch1}
\begin{paste}{ugIntroDiffEqnsPageFull1}{ugIntroDiffEqnsPageEmpty1}
\pastebutton{ugIntroDiffEqnsPageFull1}{\hidepaste}
\tab{5}\spadcommand{y := operator 'y\bound{y }}
\indentrel{3}\begin{verbatim}
   (1)  y
                                    Type: BasicOperator
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPageEmpty1}
\begin{paste}{ugIntroDiffEqnsPageEmpty1}{ugIntroDiffEqnsPagePatch1}
\pastebutton{ugIntroDiffEqnsPageEmpty1}{\showpaste}
\tab{5}\spadcommand{y := operator 'y\bound{y }}
\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPagePatch2}
\begin{paste}{ugIntroDiffEqnsPageFull2}{ugIntroDiffEqnsPageEmpty2}
\pastebutton{ugIntroDiffEqnsPageFull2}{\hidepaste}
\tab{5}\spadcommand{deq := x**3 * D(y x, x, 3) + x**2 * D(y x, x, 2) - 2 * x * D(y x, x) + 2 * y x = 2 * x**4\bound{e3 }\free{y }}
\indentrel{3}\begin{verbatim}
         3 ,,,       2 ,,         ,               4
   (2)  x y   (x) + x y  (x) - 2xy (x) + 2y(x)= 2x

                      Type: Equation Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPageEmpty2}
\begin{paste}{ugIntroDiffEqnsPageEmpty2}{ugIntroDiffEqnsPagePatch2}
\pastebutton{ugIntroDiffEqnsPageEmpty2}{\showpaste}
\tab{5}\spadcommand{deq := x**3 * D(y x, x, 3) + x**2 * D(y x, x, 2) - 2 * x * D(y x, x) + 2 * y x = 2 * x**4\bound{e3 }\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPagePatch3}
\begin{paste}{ugIntroDiffEqnsPageFull3}{ugIntroDiffEqnsPageEmpty3}
\pastebutton{ugIntroDiffEqnsPageFull3}{\hidepaste}
\tab{5}\spadcommand{solve(deq, y, x)\free{e3 }\free{y }}
\indentrel{3}\begin{verbatim}
   (3)
                 5      3      2
                x  - 10x  + 20x  + 4
   [particular= ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ,
                         15x
              3     2      3      3     2
            2x  - 3x  + 1 x  - 1 x  - 3x  - 1
    basis= [ÄÄÄÄÄÄÄÄÄÄÄÄÄ,ÄÄÄÄÄÄ,ÄÄÄÄÄÄÄÄÄÄÄÄ]]
                  x          x         x
Type: Union(Record(particular: Expression Integer,basis: List Expression Integer),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPageEmpty3}
\begin{paste}{ugIntroDiffEqnsPageEmpty3}{ugIntroDiffEqnsPagePatch3}
\pastebutton{ugIntroDiffEqnsPageEmpty3}{\showpaste}
\tab{5}\spadcommand{solve(deq, y, x)\free{e3 }\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPagePatch4}
\begin{paste}{ugIntroDiffEqnsPageFull4}{ugIntroDiffEqnsPageEmpty4}
\pastebutton{ugIntroDiffEqnsPageFull4}{\hidepaste}
\tab{5}\spadcommand{deq := (x**2 + 1) * D(y x, x, 2) + 3 * x * D(y x, x) + y x = 0\bound{e5 }\free{y }}
\indentrel{3}\begin{verbatim}
          2      ,,         ,
   (4)  (x  + 1)y  (x) + 3xy (x) + y(x)= 0

                      Type: Equation Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPageEmpty4}
\begin{paste}{ugIntroDiffEqnsPageEmpty4}{ugIntroDiffEqnsPagePatch4}
\pastebutton{ugIntroDiffEqnsPageEmpty4}{\showpaste}
\tab{5}\spadcommand{deq := (x**2 + 1) * D(y x, x, 2) + 3 * x * D(y x, x) + y x = 0\bound{e5 }\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPagePatch5}
\begin{paste}{ugIntroDiffEqnsPageFull5}{ugIntroDiffEqnsPageEmpty5}
\pastebutton{ugIntroDiffEqnsPageFull5}{\hidepaste}
\tab{5}\spadcommand{solve(deq, y, x)\free{e5 }\free{y }}
\indentrel{3}\begin{verbatim}
   (5)
                                         ÚÄÄÄÄÄÄ¿
                                         ³ 2
                              1     log(\³x  + 1  - x)
   [particular= 0,basis= [ÄÄÄÄÄÄÄÄÄ,ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ]]
                           ÚÄÄÄÄÄÄ¿       ÚÄÄÄÄÄÄ¿
                           ³ 2            ³ 2
                          \³x  + 1       \³x  + 1
Type: Union(Record(particular: Expression Integer,basis: List Expression Integer),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPageEmpty5}
\begin{paste}{ugIntroDiffEqnsPageEmpty5}{ugIntroDiffEqnsPagePatch5}
\pastebutton{ugIntroDiffEqnsPageEmpty5}{\showpaste}
\tab{5}\spadcommand{solve(deq, y, x)\free{e5 }\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPagePatch6}
\begin{paste}{ugIntroDiffEqnsPageFull6}{ugIntroDiffEqnsPageEmpty6}
\pastebutton{ugIntroDiffEqnsPageFull6}{\hidepaste}
\tab{5}\spadcommand{eq := 2*x**3 * D(y x,x,2) + 3*x**2 * D(y x,x) - 2 * y x\bound{eq }\free{y }}
\indentrel{3}\begin{verbatim}
          3 ,,        2 ,
   (6)  2x y  (x) + 3x y (x) - 2y(x)

                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPageEmpty6}
\begin{paste}{ugIntroDiffEqnsPageEmpty6}{ugIntroDiffEqnsPagePatch6}
\pastebutton{ugIntroDiffEqnsPageEmpty6}{\showpaste}
\tab{5}\spadcommand{eq := 2*x**3 * D(y x,x,2) + 3*x**2 * D(y x,x) - 2 * y x\bound{eq }\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPagePatch7}
\begin{paste}{ugIntroDiffEqnsPageFull7}{ugIntroDiffEqnsPageEmpty7}
\pastebutton{ugIntroDiffEqnsPageFull7}{\hidepaste}
\tab{5}\spadcommand{solve(eq,y,x).basis\free{eq }}
\indentrel{3}\begin{verbatim}
               2      2
           - ÄÄÄÄ   ÄÄÄÄ
              ÚÄ¿    ÚÄ¿
             \³x    \³x
   (7)  [%e      ,%e    ]
                          Type: List Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPageEmpty7}
\begin{paste}{ugIntroDiffEqnsPageEmpty7}{ugIntroDiffEqnsPagePatch7}
\pastebutton{ugIntroDiffEqnsPageEmpty7}{\showpaste}
\tab{5}\spadcommand{solve(eq,y,x).basis\free{eq }}
\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPagePatch8}
\begin{paste}{ugIntroDiffEqnsPageFull8}{ugIntroDiffEqnsPageEmpty8}
\pastebutton{ugIntroDiffEqnsPageFull8}{\hidepaste}
\tab{5}\spadcommand{deq := D(y x, x) = y(x) / (x + y(x) * log y x)\bound{deqi }\free{y }}
\indentrel{3}\begin{verbatim}
         ,            y(x)
   (8)  y (x)= ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
               y(x)log(y(x)) + x
                      Type: Equation Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPageEmpty8}
\begin{paste}{ugIntroDiffEqnsPageEmpty8}{ugIntroDiffEqnsPagePatch8}
\pastebutton{ugIntroDiffEqnsPageEmpty8}{\showpaste}
\tab{5}\spadcommand{deq := D(y x, x) = y(x) / (x + y(x) * log y x)\bound{deqi }\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPagePatch9}
\begin{paste}{ugIntroDiffEqnsPageFull9}{ugIntroDiffEqnsPageEmpty9}
\pastebutton{ugIntroDiffEqnsPageFull9}{\hidepaste}
\tab{5}\spadcommand{solve(deq, y, x)\free{deqi y }}
\indentrel{3}\begin{verbatim}
                     2
        y(x)log(y(x))  - 2x
   (9)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
               2y(x)
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPageEmpty9}
\begin{paste}{ugIntroDiffEqnsPageEmpty9}{ugIntroDiffEqnsPagePatch9}
\pastebutton{ugIntroDiffEqnsPageEmpty9}{\showpaste}
\tab{5}\spadcommand{solve(deq, y, x)\free{deqi y }}
\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPagePatch10}
\begin{paste}{ugIntroDiffEqnsPageFull10}{ugIntroDiffEqnsPageEmpty10}
\pastebutton{ugIntroDiffEqnsPageFull10}{\hidepaste}
\tab{5}\spadcommand{x := operator 'x\bound{x }}
\indentrel{3}\begin{verbatim}
   (10)  x
                                    Type: BasicOperator
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPageEmpty10}
\begin{paste}{ugIntroDiffEqnsPageEmpty10}{ugIntroDiffEqnsPagePatch10}
\pastebutton{ugIntroDiffEqnsPageEmpty10}{\showpaste}
\tab{5}\spadcommand{x := operator 'x\bound{x }}
\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPagePatch11}
\begin{paste}{ugIntroDiffEqnsPageFull11}{ugIntroDiffEqnsPageEmpty11}
\pastebutton{ugIntroDiffEqnsPageFull11}{\hidepaste}
\tab{5}\spadcommand{eq1 := D(x(t), t) = 1 + x(t)**2\free{x }\free{y }\bound{eq1 }}
\indentrel{3}\begin{verbatim}
          ,         2
   (11)  x (t)= x(t)  + 1

                      Type: Equation Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPageEmpty11}
\begin{paste}{ugIntroDiffEqnsPageEmpty11}{ugIntroDiffEqnsPagePatch11}
\pastebutton{ugIntroDiffEqnsPageEmpty11}{\showpaste}
\tab{5}\spadcommand{eq1 := D(x(t), t) = 1 + x(t)**2\free{x }\free{y }\bound{eq1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPagePatch12}
\begin{paste}{ugIntroDiffEqnsPageFull12}{ugIntroDiffEqnsPageEmpty12}
\pastebutton{ugIntroDiffEqnsPageFull12}{\hidepaste}
\tab{5}\spadcommand{eq2 := D(y(t), t) = x(t) * y(t)\free{x }\free{y }\bound{eq2 }}
\indentrel{3}\begin{verbatim}
          ,
   (12)  y (t)= x(t)y(t)

                      Type: Equation Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPageEmpty12}
\begin{paste}{ugIntroDiffEqnsPageEmpty12}{ugIntroDiffEqnsPagePatch12}
\pastebutton{ugIntroDiffEqnsPageEmpty12}{\showpaste}
\tab{5}\spadcommand{eq2 := D(y(t), t) = x(t) * y(t)\free{x }\free{y }\bound{eq2 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPagePatch13}
\begin{paste}{ugIntroDiffEqnsPageFull13}{ugIntroDiffEqnsPageEmpty13}
\pastebutton{ugIntroDiffEqnsPageFull13}{\hidepaste}
\tab{5}\spadcommand{seriesSolve([eq2, eq1], [x, y], t = 0, [y(0) = 1, x(0) = 0])\free{x }\free{y }\free{eq1 }\free{eq2 }}
\indentrel{3}\begin{verbatim}
   (13)
        1  3    2  5    17  7    62   9      11
   [t + Ä t  + ÄÄ t  + ÄÄÄ t  + ÄÄÄÄ t  + O(t  ),
        3      15      315      2835

           1  2    5  4    61  6    277  8    50521   10
       1 + Ä t  + ÄÄ t  + ÄÄÄ t  + ÄÄÄÄ t  + ÄÄÄÄÄÄÄ t
           2      24      720      8064      3628800
     + 
          11
       O(t  )
     ]
Type: List UnivariateTaylorSeries(Expression Integer,t,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroDiffEqnsPageEmpty13}
\begin{paste}{ugIntroDiffEqnsPageEmpty13}{ugIntroDiffEqnsPagePatch13}
\pastebutton{ugIntroDiffEqnsPageEmpty13}{\showpaste}
\tab{5}\spadcommand{seriesSolve([eq2, eq1], [x, y], t = 0, [y(0) = 1, x(0) = 0])\free{x }\free{y }\free{eq1 }\free{eq2 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntroSolutionPage}{ug01.ht}{Solution of Equations}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroSolutionPage}{1.15. Solution of Equations}
\beginscroll
%

Axiom also has state-of-the-art algorithms for the solution
of systems of polynomial equations.
When the number of equations and unknowns is the same, and you
have no symbolic coefficients, you can use \spadfun{solve} for
real roots and \spadfun{complexSolve} for complex roots.
In each case, you tell Axiom how accurate you want your
result to be.
All operations in the \spadfun{solve} family return answers in
the form of a list of solution sets, where each solution set is a
list of equations.

\xtc{
A system of two equations involving a symbolic
parameter \axiom{t}.
}{
\spadpaste{S(t) == [x**2-2*y**2 - t,x*y-y-5*x + 5]\bound{S1}}
}
\xtc{
Find the real roots of \spad{S(19)} with
rational arithmetic, correct to within \smath{1/10^{20}}.
}{
\spadpaste{solve(S(19),1/10**20)\free{S1}}
}
\xtc{
Find the complex roots of \spad{S(19)} with floating
point coefficients to \spad{20} digits accuracy in the mantissa.
}{
\spadpaste{complexSolve(S(19),10.e-20)\free{S1}}
}
\xtc{
If a system of equations has symbolic coefficients and you want
a solution in radicals, try \spadfun{radicalSolve}.
}{
\spadpaste{radicalSolve(S(a),[x,y])\free{S1}}
}
For systems of equations with symbolic coefficients, you can apply
\spadfun{solve}, listing the variables that you want Axiom to solve
for.  For polynomial equations, a solution cannot usually be expressed
solely in terms of the other variables.  Instead, the solution is
presented as a ``triangular'' system of equations, where each
polynomial has coefficients involving only the succeeding
variables. This is analogous to converting a linear system of
equations to ``triangular form''.
\xtc{
A system of three equations in five variables.
}{
\spadpaste{eqns := [x**2 - y + z,x**2*z + x**4 - b*y, y**2 *z - a - b*x]
\bound{e}}
}
\xtc{
Solve the system for unknowns \smath{[x,y,z]},
reducing the solution to triangular form.
}{
\spadpaste{solve(eqns,[x,y,z])\free{e}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntroSolutionPagePatch1}
\begin{paste}{ugIntroSolutionPageFull1}{ugIntroSolutionPageEmpty1}
\pastebutton{ugIntroSolutionPageFull1}{\hidepaste}
\tab{5}\spadcommand{S(t) == [x**2-2*y**2 - t,x*y-y-5*x + 5]\bound{S1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSolutionPageEmpty1}
\begin{paste}{ugIntroSolutionPageEmpty1}{ugIntroSolutionPagePatch1}
\pastebutton{ugIntroSolutionPageEmpty1}{\showpaste}
\tab{5}\spadcommand{S(t) == [x**2-2*y**2 - t,x*y-y-5*x + 5]\bound{S1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroSolutionPagePatch2}
\begin{paste}{ugIntroSolutionPageFull2}{ugIntroSolutionPageEmpty2}
\pastebutton{ugIntroSolutionPageFull2}{\hidepaste}
\tab{5}\spadcommand{solve(S(19),1/10**20)\free{S1 }}
\indentrel{3}\begin{verbatim}
   (2)
               2451682632253093442511
   [[y= 5,x= - ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ],
                295147905179352825856
             2451682632253093442511
    [y= 5,x= ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ]]
              295147905179352825856
   Type: List List Equation Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSolutionPageEmpty2}
\begin{paste}{ugIntroSolutionPageEmpty2}{ugIntroSolutionPagePatch2}
\pastebutton{ugIntroSolutionPageEmpty2}{\showpaste}
\tab{5}\spadcommand{solve(S(19),1/10**20)\free{S1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroSolutionPagePatch3}
\begin{paste}{ugIntroSolutionPageFull3}{ugIntroSolutionPageEmpty3}
\pastebutton{ugIntroSolutionPageFull3}{\hidepaste}
\tab{5}\spadcommand{complexSolve(S(19),10.e-20)\free{S1 }}
\indentrel{3}\begin{verbatim}
   (3)
   [
     [y= 5.0,
      x= 8.3066238629 1807485256 1669055295 290320373]
     ,

     [y= 5.0,
      x= - 8.3066238629 1807485256 1669055295 290320373]
     ,
    [y= - 3.0 %i,x= 1.0], [y= 3.0 %i,x= 1.0]]
      Type: List List Equation Polynomial Complex Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSolutionPageEmpty3}
\begin{paste}{ugIntroSolutionPageEmpty3}{ugIntroSolutionPagePatch3}
\pastebutton{ugIntroSolutionPageEmpty3}{\showpaste}
\tab{5}\spadcommand{complexSolve(S(19),10.e-20)\free{S1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroSolutionPagePatch4}
\begin{paste}{ugIntroSolutionPageFull4}{ugIntroSolutionPageEmpty4}
\pastebutton{ugIntroSolutionPageFull4}{\hidepaste}
\tab{5}\spadcommand{radicalSolve(S(a),[x,y])\free{S1 }}
\indentrel{3}\begin{verbatim}
   (4)
           ÚÄÄÄÄÄÄ¿             ÚÄÄÄÄÄÄ¿
   [[x= - \³a + 50 ,y= 5], [x= \³a + 50 ,y= 5],
              ÚÄÄÄÄÄÄÄ¿               ÚÄÄÄÄÄÄÄ¿
              ³- a + 1                ³- a + 1
    [x= 1,y=  ³ÄÄÄÄÄÄÄ ], [x= 1,y= -  ³ÄÄÄÄÄÄÄ ]]
             \³   2                  \³   2
            Type: List List Equation Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSolutionPageEmpty4}
\begin{paste}{ugIntroSolutionPageEmpty4}{ugIntroSolutionPagePatch4}
\pastebutton{ugIntroSolutionPageEmpty4}{\showpaste}
\tab{5}\spadcommand{radicalSolve(S(a),[x,y])\free{S1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroSolutionPagePatch5}
\begin{paste}{ugIntroSolutionPageFull5}{ugIntroSolutionPageEmpty5}
\pastebutton{ugIntroSolutionPageFull5}{\hidepaste}
\tab{5}\spadcommand{eqns := [x**2 - y + z,x**2*z + x**4 - b*y, y**2 *z - a - b*x]\bound{e }}
\indentrel{3}\begin{verbatim}
                  2  2           4  2
   (5)  [z - y + x ,x z - b y + x ,y z - b x - a]
                          Type: List Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSolutionPageEmpty5}
\begin{paste}{ugIntroSolutionPageEmpty5}{ugIntroSolutionPagePatch5}
\pastebutton{ugIntroSolutionPageEmpty5}{\showpaste}
\tab{5}\spadcommand{eqns := [x**2 - y + z,x**2*z + x**4 - b*y, y**2 *z - a - b*x]\bound{e }}
\end{paste}\end{patch}

\begin{patch}{ugIntroSolutionPagePatch6}
\begin{paste}{ugIntroSolutionPageFull6}{ugIntroSolutionPageEmpty6}
\pastebutton{ugIntroSolutionPageFull6}{\hidepaste}
\tab{5}\spadcommand{solve(eqns,[x,y,z])\free{e }}
\indentrel{3}\begin{verbatim}
   (6)
                       2
          a           a
   [[x= - Ä,y= 0,z= - ÄÄ],
          b            2
                      b

          3       2    2
         z  + 2b z  + b z - a
     [x= ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ, y= z + b,
                   b

          6       5     2 4      3       3     4         2
         z  + 4b z  + 6b z  + (4b  - 2a)z  + (b  - 4a b)z
       + 
               2     3    2
         - 2a b z - b  + a
         =
         0
       ]
     ]
   Type: List List Equation Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSolutionPageEmpty6}
\begin{paste}{ugIntroSolutionPageEmpty6}{ugIntroSolutionPagePatch6}
\pastebutton{ugIntroSolutionPageEmpty6}{\showpaste}
\tab{5}\spadcommand{solve(eqns,[x,y,z])\free{e }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntroSysCmmandsPage}{ug01.ht}{System Commands}
\pageto{notitle}{ugSysCmdPage}
\begin{chunk}{ug01.ht}
\begin{page}{ugIntroSysCmmandsPage}{1.16. System Commands}
\beginscroll
%

We conclude our tour of Axiom with a brief discussion of
\spadgloss{system commands}.  System commands are special statements
that start with a closing parenthesis (\axiomSyntax{)}). They are used
to control or display your Axiom environment, start the Hyperdoc
system, issue operating system commands and leave Axiom.  For example,
\spadsys{)system} is used to issue commands to the operating system
from Axiom.  Here is a brief description of some of these commands.
For more information on specific commands, see
\downlink{``Axiom System Commands''}{ugSysCmdPage} in Appendix B
\ignore{ugSysCmd}.

Perhaps the most important user command is the \spadsys{)clear all}
command that initializes your environment.  Every section and
subsection in this book has an invisible \spadsys{)clear all} that is
read prior to the examples given in the section.  \spadsys{)clear all}
gives you a fresh, empty environment with no user variables defined
and the step number reset to \axiom{1}.  The \spadsys{)clear} command
can also be used to selectively clear values and properties of system
variables.

Another useful system command is \spadsys{)read}.  A preferred way to
develop an application in Axiom is to put your interactive commands
into a file, say {\bf my.input} file.  To get Axiom to read this file,
you use the system command \spadsys{)read my.input}.  If you need to
make changes to your approach or definitions, go into your favorite
editor, change {\bf my.input}, then \spadsys{)read my.input} again.

Other system commands include: \spadsys{)history}, to display
previous input and/or output lines; \spadsys{)display}, to display
properties and values of workspace variables; and \spadsys{)what}.

\xtc{
Issue \spadsys{)what} to get a list of Axiom objects that
contain a given substring in their name.
}{
\spadpaste{)what operations integrate}
}

%\head{subsection}{Undo}{ugIntroUndo}

A useful system command is \spadcmd{)undo}.
Sometimes while computing interactively with Axiom, you make
a mistake and enter an incorrect definition or assignment.
Or perhaps you
need to try one of several alternative approaches, one after
another, to find the best way to approach an application.
For this, you will find the \spadgloss{undo} facility of
Axiom helpful.

System command \spadsys{)undo n} means ``undo back to step
\axiom{n}''; it restores the values of user variables to those that
existed immediately after input expression \axiom{n} was evaluated.
Similarly, \spadsys{)undo -n} undoes changes caused by the last
\axiom{n} input expressions.  Once you have done an \spadsys{)undo},
you can continue on from there, or make a change and {\bf redo} all
your input expressions from the point of the \spadsys{)undo} forward.
The \spadsys{)undo} is completely general: it changes the environment
like any user expression.  Thus you can \spadsys{)undo} any previous
undo.

Here is a sample dialogue between user and Axiom.
\xtc{
``Let me define
two mutually dependent functions \axiom{f} and \axiom{g} piece-wise.''
}{
\spadpaste{f(0) == 1; g(0) == 1\bound{u1}}
}
\xtc{
``Here is the general term for \axiom{f}.''
}{
\spadpaste{f(n) == e/2*f(n-1) - x*g(n-1)\bound{u2}\free{u1}}
}
\xtc{
``And here is the general term for \axiom{g}.''
}{
\spadpaste{g(n) == -x*f(n-1) + d/3*g(n-1)\bound{u3}\free{u2}}
}
\xtc{
``What is value of \axiom{f(3)}?''
}{
\spadpaste{f(3)\bound{u4}\free{u3}}
}
\noOutputXtc{
``Hmm, I think I want to define \axiom{f} differently.
Undo to the environment right after I defined \axiom{f}.''
}{
\spadpaste{)undo 2\bound{u5}\free{u4}}
}
\xtc{
``Here is how I think I want \axiom{f} to be defined instead.''
}{
\spadpaste{f(n) == d/3*f(n-1) - x*g(n-1)\bound{u6}\free{u5}}
}
\noOutputXtc{
Redo the computation from expression \axiom{3} forward.
}{
\spadpaste{)undo )redo\bound{u7}\free{u6}}
}
\noOutputXtc{
``I want my old definition of
\axiom{f} after all. Undo the undo and restore
the environment to that immediately after \axiom{(4)}.''
}{
\spadpaste{)undo 4\bound{u8}\free{u7}}
}
\xtc{
``Check that the value of \axiom{f(3)} is restored.''
}{
\spadpaste{f(3)\bound{u9}\free{u8}}
}

After you have gone off on several tangents, then backtracked to
previous points in your conversation using \spadsys{)undo}, you might
want to save all the ``correct'' input commands you issued,
disregarding those undone.  The system command \spadsys{)history
)write mynew.input} writes a clean straight-line program onto the file
{\bf mynew.input} on your disk.

This concludes your tour of Axiom.
To disembark, issue the system command \spadsys{)quit} to leave Axiom
and return to the operating system.
\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntroSysCmmandsPagePatch1}
\begin{paste}{ugIntroSysCmmandsPageFull1}{ugIntroSysCmmandsPageEmpty1}
\pastebutton{ugIntroSysCmmandsPageFull1}{\hidepaste}
\tab{5}\spadcommand{)what operations integrate}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSysCmmandsPageEmpty1}
\begin{paste}{ugIntroSysCmmandsPageEmpty1}{ugIntroSysCmmandsPagePatch1}
\pastebutton{ugIntroSysCmmandsPageEmpty1}{\showpaste}
\tab{5}\spadcommand{)what operations integrate}
\end{paste}\end{patch}

\begin{patch}{ugIntroSysCmmandsPagePatch2}
\begin{paste}{ugIntroSysCmmandsPageFull2}{ugIntroSysCmmandsPageEmpty2}
\pastebutton{ugIntroSysCmmandsPageFull2}{\hidepaste}
\tab{5}\spadcommand{f(0) == 1; g(0) == 1\bound{u1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSysCmmandsPageEmpty2}
\begin{paste}{ugIntroSysCmmandsPageEmpty2}{ugIntroSysCmmandsPagePatch2}
\pastebutton{ugIntroSysCmmandsPageEmpty2}{\showpaste}
\tab{5}\spadcommand{f(0) == 1; g(0) == 1\bound{u1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroSysCmmandsPagePatch3}
\begin{paste}{ugIntroSysCmmandsPageFull3}{ugIntroSysCmmandsPageEmpty3}
\pastebutton{ugIntroSysCmmandsPageFull3}{\hidepaste}
\tab{5}\spadcommand{f(n) == e/2*f(n-1) - x*g(n-1)\bound{u2 }\free{u1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSysCmmandsPageEmpty3}
\begin{paste}{ugIntroSysCmmandsPageEmpty3}{ugIntroSysCmmandsPagePatch3}
\pastebutton{ugIntroSysCmmandsPageEmpty3}{\showpaste}
\tab{5}\spadcommand{f(n) == e/2*f(n-1) - x*g(n-1)\bound{u2 }\free{u1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroSysCmmandsPagePatch4}
\begin{paste}{ugIntroSysCmmandsPageFull4}{ugIntroSysCmmandsPageEmpty4}
\pastebutton{ugIntroSysCmmandsPageFull4}{\hidepaste}
\tab{5}\spadcommand{g(n) == -x*f(n-1) + d/3*g(n-1)\bound{u3 }\free{u2 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSysCmmandsPageEmpty4}
\begin{paste}{ugIntroSysCmmandsPageEmpty4}{ugIntroSysCmmandsPagePatch4}
\pastebutton{ugIntroSysCmmandsPageEmpty4}{\showpaste}
\tab{5}\spadcommand{g(n) == -x*f(n-1) + d/3*g(n-1)\bound{u3 }\free{u2 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroSysCmmandsPagePatch5}
\begin{paste}{ugIntroSysCmmandsPageFull5}{ugIntroSysCmmandsPageEmpty5}
\pastebutton{ugIntroSysCmmandsPageFull5}{\hidepaste}
\tab{5}\spadcommand{f(3)\bound{u4 }\free{u3 }}
\indentrel{3}\begin{verbatim}
   (4)
      3        1    2      1  2   1       1  2     1  3
   - x  + (e + Ä d)x  + (- Ä e  - Ä d e - Ä d )x + Ä e
               3           4      6       9        8
                      Type: Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSysCmmandsPageEmpty5}
\begin{paste}{ugIntroSysCmmandsPageEmpty5}{ugIntroSysCmmandsPagePatch5}
\pastebutton{ugIntroSysCmmandsPageEmpty5}{\showpaste}
\tab{5}\spadcommand{f(3)\bound{u4 }\free{u3 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroSysCmmandsPagePatch6}
\begin{paste}{ugIntroSysCmmandsPageFull6}{ugIntroSysCmmandsPageEmpty6}
\pastebutton{ugIntroSysCmmandsPageFull6}{\hidepaste}
\tab{5}\spadcommand{)undo 2\bound{u5 }\free{u4 }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSysCmmandsPageEmpty6}
\begin{paste}{ugIntroSysCmmandsPageEmpty6}{ugIntroSysCmmandsPagePatch6}
\pastebutton{ugIntroSysCmmandsPageEmpty6}{\showpaste}
\tab{5}\spadcommand{)undo 2\bound{u5 }\free{u4 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroSysCmmandsPagePatch7}
\begin{paste}{ugIntroSysCmmandsPageFull7}{ugIntroSysCmmandsPageEmpty7}
\pastebutton{ugIntroSysCmmandsPageFull7}{\hidepaste}
\tab{5}\spadcommand{f(n) == d/3*f(n-1) - x*g(n-1)\bound{u6 }\free{u5 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSysCmmandsPageEmpty7}
\begin{paste}{ugIntroSysCmmandsPageEmpty7}{ugIntroSysCmmandsPagePatch7}
\pastebutton{ugIntroSysCmmandsPageEmpty7}{\showpaste}
\tab{5}\spadcommand{f(n) == d/3*f(n-1) - x*g(n-1)\bound{u6 }\free{u5 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroSysCmmandsPagePatch8}
\begin{paste}{ugIntroSysCmmandsPageFull8}{ugIntroSysCmmandsPageEmpty8}
\pastebutton{ugIntroSysCmmandsPageFull8}{\hidepaste}
\tab{5}\spadcommand{)undo )redo\bound{u7 }\free{u6 }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSysCmmandsPageEmpty8}
\begin{paste}{ugIntroSysCmmandsPageEmpty8}{ugIntroSysCmmandsPagePatch8}
\pastebutton{ugIntroSysCmmandsPageEmpty8}{\showpaste}
\tab{5}\spadcommand{)undo )redo\bound{u7 }\free{u6 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroSysCmmandsPagePatch9}
\begin{paste}{ugIntroSysCmmandsPageFull9}{ugIntroSysCmmandsPageEmpty9}
\pastebutton{ugIntroSysCmmandsPageFull9}{\hidepaste}
\tab{5}\spadcommand{)undo 4\bound{u8 }\free{u7 }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSysCmmandsPageEmpty9}
\begin{paste}{ugIntroSysCmmandsPageEmpty9}{ugIntroSysCmmandsPagePatch9}
\pastebutton{ugIntroSysCmmandsPageEmpty9}{\showpaste}
\tab{5}\spadcommand{)undo 4\bound{u8 }\free{u7 }}
\end{paste}\end{patch}

\begin{patch}{ugIntroSysCmmandsPagePatch10}
\begin{paste}{ugIntroSysCmmandsPageFull10}{ugIntroSysCmmandsPageEmpty10}
\pastebutton{ugIntroSysCmmandsPageFull10}{\hidepaste}
\tab{5}\spadcommand{f(3)\bound{u9 }\free{u8 }}
\indentrel{3}\begin{verbatim}
   (6)
      3        1    2      1  2   1       1  2     1  3
   - x  + (e + Ä d)x  + (- Ä e  - Ä d e - Ä d )x + Ä e
               3           4      6       9        8
                      Type: Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntroSysCmmandsPageEmpty10}
\begin{paste}{ugIntroSysCmmandsPageEmpty10}{ugIntroSysCmmandsPagePatch10}
\pastebutton{ugIntroSysCmmandsPageEmpty10}{\showpaste}
\tab{5}\spadcommand{f(3)\bound{u9 }\free{u8 }}
\end{paste}\end{patch}

\end{chunk}
\chapter{Users Guide Chapter 2 (ug02.ht)}
\pagetitle{ugTypesPage}{ug02.ht}{Using Types and Modes}
\pageto{notitle}{ugTypesBasicPage}
\pageto{notitle}{ugTypesWritingPage}
\pageto{notitle}{ugTypesDeclarePage}
\pageto{notitle}{ugTypesRecordsPage}
\pageto{notitle}{ugTypesUnionsPage}
\pageto{notitle}{ugTypesAnyNonePage}
\pageto{notitle}{ugTypesConvertPage}
\pageto{notitle}{ugTypesSubdomainsPage}
\pageto{notitle}{ugTypesPkgCallPage}
\pageto{notitle}{ugTypesResolvePage}
\pageto{notitle}{ugTypesExposePage}
\pageto{notitle}{ugAvailSnoopPage}
\begin{chunk}{ug02.ht}
\begin{page}{ugTypesPage}{2. Using Types and Modes}
\beginscroll

In this chapter we look at the key notion of \spadgloss{type} and its
generalization \spadgloss{mode}.  We show that every Axiom object has
a type that determines what you can do with the object.  In
particular, we explain how to use types to call specific functions
from particular parts of the library and how types and modes can be
used to create new objects from old.  We also look at
\pspadtype{Record} and \pspadtype{Union} types and the special type
\axiomType{Any}.  Finally, we give you an idea of how Axiom
manipulates types and modes internally to resolve ambiguities.

\beginmenu
    \menudownlink{{2.1. The Basic Idea}}{ugTypesBasicPage}
    \menudownlink{{2.2. Writing Types and Modes}}{ugTypesWritingPage}
    \menudownlink{{2.3. Declarations}}{ugTypesDeclarePage}
    \menudownlink{{2.4. Records}}{ugTypesRecordsPage}
    \menudownlink{{2.5. Unions}}{ugTypesUnionsPage}
    \menudownlink{{2.6. The ``Any'' Domain}}{ugTypesAnyNonePage}
    \menudownlink{{2.7. Conversion}}{ugTypesConvertPage}
    \menudownlink{{2.8. Subdomains Again}}{ugTypesSubdomainsPage}
    \menudownlink{{2.9. Package Calling and Target Types}}
{ugTypesPkgCallPage}
    \menudownlink{{2.10. Resolving Types}}{ugTypesResolvePage}
    \menudownlink{{2.11. Exposing Domains and Packages}}
{ugTypesExposePage}
    \menudownlink{{2.12. Commands for Snooping}}{ugAvailSnoopPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugTypesBasicPage}{ug02.ht}{The Basic Idea}
\pagepic{ps/v71ugtypesbasicpage.eps}{ugTypesBasicPage}{0.50}
\pagefrom{Conversion}{ugTypesConvertPage}
\pageto{Domain Constructors}{ugTypesBasicDomainConsPage}
\begin{chunk}{ug02.ht}
\begin{page}{ugTypesBasicPage}{2.1. The Basic Idea}
\beginscroll

The Axiom world deals with many kinds of objects.
There are mathematical objects such as numbers and polynomials,
data structure objects such as lists and arrays, and graphics
objects such as points and graphic images.
Functions are objects too.

Axiom organizes objects using the notion of \spadglossSee{domain of
computation}{domain}, or simply \spadgloss{domain}.  Each domain
denotes a class of objects.  The class of objects it denotes is
usually given by the name of the domain: \axiomType{Integer} for the
integers, \axiomType{Float} for floating-point numbers, and so on.
The convention is that the first letter of a domain name is
capitalized.  Similarly, the domain \axiomType{Polynomial(Integer)}
denotes ``polynomials with integer coefficients.''  Also,
\axiomType{Matrix(Float)} denotes ``matrices with floating-point
entries.''

Every basic Axiom object belongs to a unique domain.  The integer
\axiom{3} belongs to the domain \axiomType{Integer} and the polynomial
\axiom{x + 3} belongs to the domain \axiomType{Polynomial(Integer)}.
The domain of an object is also called its \spadgloss{type}.  Thus we
speak of ``the type \axiomType{Integer}'' and ``the type
\axiomType{Polynomial(Integer)}.''

\xtc{
After an Axiom computation, the type is displayed toward the
right-hand side of the page (or screen).
}{
\spadpaste{-3}
}
\xtc{
Here we create a rational number but it looks like the last result.
The type however tells you it is different.
You cannot identify the type of an object by how Axiom
displays the object.
}{
\spadpaste{-3/1}
}
\xtc{
When a computation produces a result of a simpler type, Axiom leaves
the type unsimplified.
Thus no information is lost.
}{
\spadpaste{x + 3 - x \bound{three}}
}
\xtc{
This seldom matters since Axiom retracts the answer to the
simpler type if it is necessary.
}{
\spadpaste{factorial(\%) \free{three}}
}
\xtc{
When you issue a positive number, the type \axiomType{PositiveInteger}
is printed.  Surely, \axiom{3} also has type \axiomType{Integer}!  The
curious reader may now have two questions.  First, is the type of an
object not unique?  Second, how is \axiomType{PositiveInteger} related
to \axiomType{Integer}?  Read on!
}{
\spadpaste{3}
}

Any domain can be refined to a \spadgloss{subdomain} by a membership
\spadgloss{predicate}.\footnote{A predicate is a function that, when
applied to an object of the domain, returns either \axiom{true} or
\axiom{false}.}  For example, the domain \axiomType{Integer} can be
refined to the subdomain \axiomType{PositiveInteger}, the set of
integers \axiom{x} such that \axiom{x > 0}, by giving the Axiom
predicate \axiom{x +-> x > 0}.  Similarly, Axiom can define subdomains
such as ``the subdomain of diagonal matrices,'' ``the subdomain of
lists of length two,'' ``the subdomain of monic irreducible
polynomials in \axiom{x},'' and so on.  Trivially, any domain is a
subdomain of itself.

While an object belongs to a unique domain, it can belong to any
number of subdomains.  Any subdomain of the domain of an object can be
used as the {\it type} of that object.  The type of \axiom{3} is
indeed both \axiomType{Integer} and \axiomType{PositiveInteger} as
well as any other subdomain of integer whose predicate is satisfied,
such as ``the prime integers,'' ``the odd positive integers between 3
and 17,'' and so on.

\beginmenu
    \menudownlink{{2.1.1. Domain Constructors}}{ugTypesBasicDomainConsPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\begin{patch}{ugTypesBasicPagePatch1}
\begin{paste}{ugTypesBasicPageFull1}{ugTypesBasicPageEmpty1}
\pastebutton{ugTypesBasicPageFull1}{\hidepaste}
\tab{5}\spadcommand{-3}
\indentrel{3}\begin{verbatim}
   (1)  - 3
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesBasicPageEmpty1}
\begin{paste}{ugTypesBasicPageEmpty1}{ugTypesBasicPagePatch1}
\pastebutton{ugTypesBasicPageEmpty1}{\showpaste}
\tab{5}\spadcommand{-3}
\end{paste}\end{patch}

\begin{patch}{ugTypesBasicPagePatch2}
\begin{paste}{ugTypesBasicPageFull2}{ugTypesBasicPageEmpty2}
\pastebutton{ugTypesBasicPageFull2}{\hidepaste}
\tab{5}\spadcommand{-3/1}
\indentrel{3}\begin{verbatim}
   (2)  - 3
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesBasicPageEmpty2}
\begin{paste}{ugTypesBasicPageEmpty2}{ugTypesBasicPagePatch2}
\pastebutton{ugTypesBasicPageEmpty2}{\showpaste}
\tab{5}\spadcommand{-3/1}
\end{paste}\end{patch}

\begin{patch}{ugTypesBasicPagePatch3}
\begin{paste}{ugTypesBasicPageFull3}{ugTypesBasicPageEmpty3}
\pastebutton{ugTypesBasicPageFull3}{\hidepaste}
\tab{5}\spadcommand{x + 3 - x\bound{three }}
\indentrel{3}\begin{verbatim}
   (3)  3
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesBasicPageEmpty3}
\begin{paste}{ugTypesBasicPageEmpty3}{ugTypesBasicPagePatch3}
\pastebutton{ugTypesBasicPageEmpty3}{\showpaste}
\tab{5}\spadcommand{x + 3 - x\bound{three }}
\end{paste}\end{patch}

\begin{patch}{ugTypesBasicPagePatch4}
\begin{paste}{ugTypesBasicPageFull4}{ugTypesBasicPageEmpty4}
\pastebutton{ugTypesBasicPageFull4}{\hidepaste}
\tab{5}\spadcommand{factorial(\%)\free{three }}
\indentrel{3}\begin{verbatim}
   (4)  6
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesBasicPageEmpty4}
\begin{paste}{ugTypesBasicPageEmpty4}{ugTypesBasicPagePatch4}
\pastebutton{ugTypesBasicPageEmpty4}{\showpaste}
\tab{5}\spadcommand{factorial(\%)\free{three }}
\end{paste}\end{patch}

\begin{patch}{ugTypesBasicPagePatch5}
\begin{paste}{ugTypesBasicPageFull5}{ugTypesBasicPageEmpty5}
\pastebutton{ugTypesBasicPageFull5}{\hidepaste}
\tab{5}\spadcommand{3}
\indentrel{3}\begin{verbatim}
   (5)  3
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesBasicPageEmpty5}
\begin{paste}{ugTypesBasicPageEmpty5}{ugTypesBasicPagePatch5}
\pastebutton{ugTypesBasicPageEmpty5}{\showpaste}
\tab{5}\spadcommand{3}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugTypesBasicDomainConsPage}{ug02.ht}{Domain Constructors}
\pagepic{ps/v71ugtypesbasicdomainconspage.eps}{ugTypesBasicDomainConsPage}{0.50}
\pagefrom{The Basic Idea}{ugTypesBasicPage}
\pageto{Categories}{ugCategoriesPage}
\pageto{Conversion}{ugTypesConvertPage}
\begin{chunk}{ug02.ht}
\begin{page}{ugTypesBasicDomainConsPage}{2.1.1. Domain Constructors}
\beginscroll

In Axiom, domains are objects.  You can create them, pass them to
functions, and, as we'll see later, test them for certain properties.

In Axiom, you ask for a value of a function by applying its name
to a set of arguments.

\xtc{
To ask for ``the factorial of 7'' you enter this expression to Axiom.
This applies the function \axiom{factorial} to the value \axiom{7} to
compute the result.
}{
\spadpaste{factorial(7)}
}
\xtc{
Enter the type \axiomType{Polynomial (Integer)} as an expression to
Axiom.  This looks much like a function call as well.  It is!  The
result is appropriately stated to be of type \axiomType{Domain}, which
according to our usual convention, denotes the class of all domains.
}{
\spadpaste{Polynomial(Integer)}
}

The most basic operation involving domains is that of building a new
domain from a given one.  To create the domain of ``polynomials over
the integers,'' Axiom applies the function \axiomType{Polynomial} to
the domain \axiomType{Integer}.  A function like
\axiomType{Polynomial} is called a \spadgloss{domain constructor} or,
more simply, a \spadgloss{constructor}.  A domain constructor is a
function that creates a domain.  An argument to a domain constructor
can be another domain or, in general, an arbitrary kind of object.
\axiomType{Polynomial} takes a single domain argument while
\axiomType{SquareMatrix} takes a positive integer as an argument to
give its dimension and a domain argument to give the type of its
components.

What kinds of domains can you use as the argument to
\axiomType{Polynomial} or \axiomType{SquareMatrix} or
\axiomType{List}?  Well, the first two are mathematical in nature.
You want to be able to perform algebraic operations like \axiomOp{+}
and \axiomOp{*} on polynomials and square matrices, and operations
such as \axiomFun{determinant} on square matrices.  So you want to
allow polynomials of integers {\it and} polynomials of square matrices
with complex number coefficients and, in general, anything that
``makes sense.'' At the same time, you don't want Axiom to be able to
build nonsense domains such as ``polynomials of strings!''

In contrast to algebraic structures, data structures can hold any kind
of object.  Operations on lists such as \axiomFunFrom{insert}{List},
\axiomFunFrom{delete}{List}, and \axiomFunFrom{concat}{List} just
manipulate the list itself without changing or operating on its
elements.  Thus you can build \axiomType{List} over almost any
datatype, including itself.
\xtc{
Create a complicated algebraic domain.
}{
\spadpaste{
List (List (Matrix (Polynomial (Complex (Fraction (Integer))))))}
}
\xtc{
Try to create a meaningless domain.
}{
\spadpaste{Polynomial(String)}
}
Evidently from our last example, Axiom has some mechanism
that tells what a constructor can use as an argument.
This brings us to the notion of \spadgloss{category}.
As domains are objects, they too have a domain.
The domain of a domain is a category.
A category is simply a type whose members are domains.

A common algebraic category is \axiomType{Ring}, the class of all
domains that are ``rings.''  A ring is an algebraic structure with
constants \axiom{0} and \axiom{1} and operations
\axiomOpFrom{+}{Ring}, \axiomOpFrom{-}{Ring}, and
\axiomOpFrom{*}{Ring}.  These operations are assumed ``closed'' with
respect to the domain, meaning that they take two objects of the
domain and produce a result object also in the domain.  The operations
are understood to satisfy certain ``axioms,'' certain mathematical
principles providing the algebraic foundation for rings.  For example,
the {\it additive inverse axiom} for rings states: \centerline{{Every
element \axiom{x} has an additive inverse \axiom{y} such}}
\centerline{{that \axiom{x + y = 0}.}}  The prototypical example of a
domain that is a ring is the integers.  Keep them in mind whenever we
mention \axiomType{Ring}.

Many algebraic domain constructors such as \axiomType{Complex},
\axiomType{Polynomial}, \axiomType{Fraction}, take rings as arguments
and return rings as values.  You can use the infix operator
``\axiom{has}'' \spadkey{has} to ask a domain if it belongs to a
particular category.

\xtc{
All numerical types are rings.  Domain constructor
\axiomType{Polynomial} builds ``the ring of polynomials over any other
ring.''
}{
\spadpaste{Polynomial(Integer) has Ring}
}
\xtc{
Constructor \axiomType{List} never produces a ring.
}{
\spadpaste{List(Integer) has Ring}
}
\xtc{
The constructor \axiomType{Matrix(R)} builds ``the domain of all
matrices over the ring \axiom{R}.'' This domain is never a ring since
the operations \axiomSyntax{+}, \axiomSyntax{-}, and \axiomSyntax{*}
on matrices of arbitrary shapes are undefined.
}{
\spadpaste{Matrix(Integer) has Ring}
}
\xtc{
Thus you can never build polynomials over matrices.
}{
\spadpaste{Polynomial(Matrix(Integer))}
}
\xtc{
Use \axiomType{SquareMatrix(n,R)} instead.
For any positive integer \axiom{n}, it builds ``the ring of \axiom{n} by
\axiom{n} matrices over \axiom{R}.''
}{
\spadpaste{Polynomial(SquareMatrix(7,Complex(Integer)))}
}

Another common category is \axiomType{Field}, the class of all fields.
A field is a ring with additional operations.  For example, a field
has commutative multiplication and a closed operation
\axiomOpFrom{/}{Field} for the division of two elements.
\axiomType{Integer} is not a field since, for example, \axiom{3/2}
does not have an integer result.  The prototypical example of a field
is the rational numbers, that is, the domain
\axiomType{Fraction(Integer)}.  In general, the constructor
\axiomType{Fraction} takes a ring as an argument and returns a
field.\footnote{Actually, the argument domain must have some
additional properties so as to belong to category
\axiomType{IntegralDomain}.}  Other domain constructors, such as
\axiomType{Complex}, build fields only if their argument domain is a
field.

\xtc{
The complex integers (often called the ``Gaussian integers'') do not 
form a field.
}{
\spadpaste{Complex(Integer) has Field}
}
\xtc{
But fractions of complex integers do.
}{
\spadpaste{Fraction(Complex(Integer)) has Field}
}
\xtc{
The algebraically equivalent domain of complex rational numbers is a
field since domain constructor \axiomType{Complex} produces a field
whenever its argument is a field.
}{
\spadpaste{Complex(Fraction(Integer)) has Field}
}

The most basic category is \axiomType{Type}.  It denotes the class of
all domains and subdomains.\footnote{\axiomType{Type} does not denote
the class of all types.  The type of all categories is
\axiomType{Category}.  The type of \axiomType{Type} itself is
undefined.}  Domain constructor \axiomType{List} is able to build
``lists of elements from domain \axiom{D}'' for arbitrary \axiom{D}
simply by requiring that \axiom{D} belong to category
\axiomType{Type}.

Now, you may ask, what exactly is a category?
Like domains, categories can be defined in the Axiom language.
A category is defined by three components:
%
\indent{4}
\beginitems
\item[1. ] a name (for example, \axiomType{Ring}),
used to refer to the class of domains that the category represents;
\item[2. ] a set of operations, used to refer to the operations that
the domains of this class support
(for example, \axiomOp{+}, \axiomOp{-}, and \axiomOp{*} for rings); and
\item[3. ] an optional list of other categories that this category extends.
\enditems
\indent{0}
%

This last component is a new idea.  And it is key to the design of
Axiom!  Because categories can extend one another, they form
hierarchies.  \texht{Detailed charts showing the category hierarchies
in Axiom are displayed in the endpages of this book.  There you see
that all categories are extensions of \axiomType{Type} and that
\axiomType{Field} is an extension of \axiomType{Ring}.}{}

The operations supported by the domains of a category are called the
\spadglossSee{exports}{export} of that category because these are the
operations made available for system-wide use.  The exports of a
domain of a given category are not only the ones explicitly mentioned
by the category.  Since a category extends other categories, the
operations of these other categories---and all categories these other
categories extend---are also exported by the domains.

For example, polynomial domains belong to
\axiomType{PolynomialCategory}.  This category explicitly mentions
some twenty-nine operations on polynomials, but it extends eleven
other categories (including \axiomType{Ring}).  As a result, the
current system has over one hundred operations on polynomials.

If a domain belongs to a category that extends, say, \axiomType{Ring},
it is convenient to say that the domain exports \axiomType{Ring}.  The
name of the category thus provides a convenient shorthand for the list
of operations exported by the category.  Rather than listing
operations such as \axiomOpFrom{+}{Ring} and \axiomOpFrom{*}{Ring} of
\axiomType{Ring} each time they are needed, the definition of a type
simply asserts that it exports category \axiomType{Ring}.

The category name, however, is more than a shorthand.
The name \axiomType{Ring}, in fact, implies that the operations exported by
rings are required to satisfy a set of ``axioms'' associated with the name
\axiomType{Ring}.\footnote{This subtle
but important feature distinguishes Axiom from
other abstract datatype designs.}

Why is it not correct to assume that some type is a ring if it exports
all of the operations of \axiomType{Ring}?  Here is why.  Some
languages such as {\bf APL} denote the \axiomType{Boolean} constants
\axiom{true} and \axiom{false} by the integers \axiom{1} and \axiom{0}
respectively, then use \axiomOp{+} and \axiomOp{*} to denote the
logical operators \axiomFun{or} and \axiomFun{and}.  But with these
definitions \axiomType{Boolean} is not a ring since the additive
inverse axiom is violated.\footnote{There is no inverse element
\axiom{a} such that \axiom{1 + a = 0}, or, in the usual terms:
\axiom{true or a = false}.}  This alternative definition of
\axiomType{Boolean} can be easily and correctly implemented in Axiom,
since \axiomType{Boolean} simply does not assert that it is of
category \axiomType{Ring}.  This prevents the system from building
meaningless domains such as \axiomType{Polynomial(Boolean)} and then
wrongfully applying algorithms that presume that the ring axioms hold.


Enough on categories. To learn more about them, see
\downlink{``Categories''}{ugCategoriesPage} 
in Chapter 12\ignore{ugCategories}.
We now return to our discussion of domains.

Domains \spadgloss{export} a set of operations to make them available
for system-wide use.  \axiomType{Integer}, for example, exports the
operations \axiomOpFrom{+}{Integer} and \axiomOpFrom{=}{Integer} given
by the \spadglossSee{signatures}{signature} \axiomOpFrom{+}{Integer}:
\spadsig{(Integer,Integer)}{Integer} and \axiomOpFrom{=}{Integer}:
\spadsig{(Integer,Integer)}{Boolean}, respectively.  Each of these
operations takes two \axiomType{Integer} arguments.  The
\axiomOpFrom{+}{Integer} operation also returns an \axiomType{Integer}
but \axiomOpFrom{=}{Integer} returns a \axiomType{Boolean}:
\axiom{true} or \axiom{false}.  The operations exported by a domain
usually manipulate objects of the domain---but not always.

The operations of a domain may actually take as arguments, and return
as values, objects from any domain.  For example, \axiomType{Fraction
(Integer)} exports the operations \axiomOpFrom{/}{Fraction}:
\spadsig{(Integer,Integer)}{Fraction(Integer)} and
\axiomFunFrom{characteristic}{Fraction}:
\spadsig{}{NonNegativeInteger}.

Suppose all operations of a domain take as arguments and return as
values, only objects from {\it other} domains.  This kind of domain is
what Axiom calls a \spadgloss{package}.

A package does not designate a class of objects at all.  Rather, a
package is just a collection of operations.  Actually the bulk of the
Axiom library of algorithms consists of packages.  The facilities for
factorization; integration; solution of linear, polynomial, and
differential equations; computation of limits; and so on, are all
defined in packages.  Domains needed by algorithms can be passed to a
package as arguments or used by name if they are not ``variable.''
Packages are useful for defining operations that convert objects of
one type to another, particularly when these types have different
parameterizations.  As an example, the package
\axiomType{PolynomialFunction2(R,S)} defines operations that convert
polynomials over a domain \axiom{R} to polynomials over \axiom{S}.  To
convert an object from \axiomType{Polynomial(Integer)} to
\axiomType{Polynomial(Float)}, Axiom builds the package
\axiomType{PolynomialFunctions2(Integer,Float)} in order to create the
required conversion function.  (This happens ``behind the scenes'' for
you: see \downlink{``Conversion''}{ugTypesConvertPage} in
Section 2.7\ignore{ugTypesConvert} for details on
how to convert objects.)

Axiom categories, domains and packages and all their contained
functions are written in the Axiom programming language and have
been compiled into machine code.
This is what comprises the Axiom \spadgloss{library}.
In the rest of this book we show you how to use these domains and
their functions and how to write your own functions.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugTypesBasicDomainConsPagePatch1}
\begin{paste}{ugTypesBasicDomainConsPageFull1}{ugTypesBasicDomainConsPageEmpty1}
\pastebutton{ugTypesBasicDomainConsPageFull1}{\hidepaste}
\tab{5}\spadcommand{factorial(7)}
\indentrel{3}\begin{verbatim}
   (1)  5040
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPageEmpty1}
\begin{paste}{ugTypesBasicDomainConsPageEmpty1}{ugTypesBasicDomainConsPagePatch1}
\pastebutton{ugTypesBasicDomainConsPageEmpty1}{\showpaste}
\tab{5}\spadcommand{factorial(7)}
\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPagePatch2}
\begin{paste}{ugTypesBasicDomainConsPageFull2}{ugTypesBasicDomainConsPageEmpty2}
\pastebutton{ugTypesBasicDomainConsPageFull2}{\hidepaste}
\tab{5}\spadcommand{Polynomial(Integer)}
\indentrel{3}\begin{verbatim}
   (2)  Polynomial Integer
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPageEmpty2}
\begin{paste}{ugTypesBasicDomainConsPageEmpty2}{ugTypesBasicDomainConsPagePatch2}
\pastebutton{ugTypesBasicDomainConsPageEmpty2}{\showpaste}
\tab{5}\spadcommand{Polynomial(Integer)}
\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPagePatch3}
\begin{paste}{ugTypesBasicDomainConsPageFull3}{ugTypesBasicDomainConsPageEmpty3}
\pastebutton{ugTypesBasicDomainConsPageFull3}{\hidepaste}
\tab{5}\spadcommand{List (List (Matrix (Polynomial (Complex (Fraction (Integer))))))}
\indentrel{3}\begin{verbatim}
   (3)
   List List Matrix Polynomial Complex Fraction Integer
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPageEmpty3}
\begin{paste}{ugTypesBasicDomainConsPageEmpty3}{ugTypesBasicDomainConsPagePatch3}
\pastebutton{ugTypesBasicDomainConsPageEmpty3}{\showpaste}
\tab{5}\spadcommand{List (List (Matrix (Polynomial (Complex (Fraction (Integer))))))}
\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPagePatch4}
\begin{paste}{ugTypesBasicDomainConsPageFull4}{ugTypesBasicDomainConsPageEmpty4}
\pastebutton{ugTypesBasicDomainConsPageFull4}{\hidepaste}
\tab{5}\spadcommand{Polynomial(String)}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPageEmpty4}
\begin{paste}{ugTypesBasicDomainConsPageEmpty4}{ugTypesBasicDomainConsPagePatch4}
\pastebutton{ugTypesBasicDomainConsPageEmpty4}{\showpaste}
\tab{5}\spadcommand{Polynomial(String)}
\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPagePatch5}
\begin{paste}{ugTypesBasicDomainConsPageFull5}{ugTypesBasicDomainConsPageEmpty5}
\pastebutton{ugTypesBasicDomainConsPageFull5}{\hidepaste}
\tab{5}\spadcommand{Polynomial(Integer) has Ring}
\indentrel{3}\begin{verbatim}
   (4)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPageEmpty5}
\begin{paste}{ugTypesBasicDomainConsPageEmpty5}{ugTypesBasicDomainConsPagePatch5}
\pastebutton{ugTypesBasicDomainConsPageEmpty5}{\showpaste}
\tab{5}\spadcommand{Polynomial(Integer) has Ring}
\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPagePatch6}
\begin{paste}{ugTypesBasicDomainConsPageFull6}{ugTypesBasicDomainConsPageEmpty6}
\pastebutton{ugTypesBasicDomainConsPageFull6}{\hidepaste}
\tab{5}\spadcommand{List(Integer) has Ring}
\indentrel{3}\begin{verbatim}
   (5)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPageEmpty6}
\begin{paste}{ugTypesBasicDomainConsPageEmpty6}{ugTypesBasicDomainConsPagePatch6}
\pastebutton{ugTypesBasicDomainConsPageEmpty6}{\showpaste}
\tab{5}\spadcommand{List(Integer) has Ring}
\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPagePatch7}
\begin{paste}{ugTypesBasicDomainConsPageFull7}{ugTypesBasicDomainConsPageEmpty7}
\pastebutton{ugTypesBasicDomainConsPageFull7}{\hidepaste}
\tab{5}\spadcommand{Matrix(Integer) has Ring}
\indentrel{3}\begin{verbatim}
   (6)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPageEmpty7}
\begin{paste}{ugTypesBasicDomainConsPageEmpty7}{ugTypesBasicDomainConsPagePatch7}
\pastebutton{ugTypesBasicDomainConsPageEmpty7}{\showpaste}
\tab{5}\spadcommand{Matrix(Integer) has Ring}
\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPagePatch8}
\begin{paste}{ugTypesBasicDomainConsPageFull8}{ugTypesBasicDomainConsPageEmpty8}
\pastebutton{ugTypesBasicDomainConsPageFull8}{\hidepaste}
\tab{5}\spadcommand{Polynomial(Matrix(Integer))}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPageEmpty8}
\begin{paste}{ugTypesBasicDomainConsPageEmpty8}{ugTypesBasicDomainConsPagePatch8}
\pastebutton{ugTypesBasicDomainConsPageEmpty8}{\showpaste}
\tab{5}\spadcommand{Polynomial(Matrix(Integer))}
\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPagePatch9}
\begin{paste}{ugTypesBasicDomainConsPageFull9}{ugTypesBasicDomainConsPageEmpty9}
\pastebutton{ugTypesBasicDomainConsPageFull9}{\hidepaste}
\tab{5}\spadcommand{Polynomial(SquareMatrix(7,Complex(Integer)))}
\indentrel{3}\begin{verbatim}
   (7)  Polynomial SquareMatrix(7,Complex Integer)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPageEmpty9}
\begin{paste}{ugTypesBasicDomainConsPageEmpty9}{ugTypesBasicDomainConsPagePatch9}
\pastebutton{ugTypesBasicDomainConsPageEmpty9}{\showpaste}
\tab{5}\spadcommand{Polynomial(SquareMatrix(7,Complex(Integer)))}
\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPagePatch10}
\begin{paste}{ugTypesBasicDomainConsPageFull10}{ugTypesBasicDomainConsPageEmpty10}
\pastebutton{ugTypesBasicDomainConsPageFull10}{\hidepaste}
\tab{5}\spadcommand{Complex(Integer) has Field}
\indentrel{3}\begin{verbatim}
   (8)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPageEmpty10}
\begin{paste}{ugTypesBasicDomainConsPageEmpty10}{ugTypesBasicDomainConsPagePatch10}
\pastebutton{ugTypesBasicDomainConsPageEmpty10}{\showpaste}
\tab{5}\spadcommand{Complex(Integer) has Field}
\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPagePatch11}
\begin{paste}{ugTypesBasicDomainConsPageFull11}{ugTypesBasicDomainConsPageEmpty11}
\pastebutton{ugTypesBasicDomainConsPageFull11}{\hidepaste}
\tab{5}\spadcommand{Fraction(Complex(Integer)) has Field}
\indentrel{3}\begin{verbatim}
   (9)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPageEmpty11}
\begin{paste}{ugTypesBasicDomainConsPageEmpty11}{ugTypesBasicDomainConsPagePatch11}
\pastebutton{ugTypesBasicDomainConsPageEmpty11}{\showpaste}
\tab{5}\spadcommand{Fraction(Complex(Integer)) has Field}
\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPagePatch12}
\begin{paste}{ugTypesBasicDomainConsPageFull12}{ugTypesBasicDomainConsPageEmpty12}
\pastebutton{ugTypesBasicDomainConsPageFull12}{\hidepaste}
\tab{5}\spadcommand{Complex(Fraction(Integer)) has Field}
\indentrel{3}\begin{verbatim}
   (10)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesBasicDomainConsPageEmpty12}
\begin{paste}{ugTypesBasicDomainConsPageEmpty12}{ugTypesBasicDomainConsPagePatch12}
\pastebutton{ugTypesBasicDomainConsPageEmpty12}{\showpaste}
\tab{5}\spadcommand{Complex(Fraction(Integer)) has Field}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugTypesWritingPage}{ug02.ht}{Writing Types and Modes}
\pageto{notitle}{ugTypesBasicPage}
\pageto{notitle}{ugTypesDeclarePage}
\pageto{notitle}{ugTypesConvertPage}
\pageto{notitle}{ugTypesPkgCallPage}
\pageto{notitle}{ugTypesWritingZeroPage}
\pageto{notitle}{ugTypesWritingOnePage}
\pageto{notitle}{ugTypesWritingMorePage}
\pageto{notitle}{ugTypesWritingModesPage}
\pageto{notitle}{ugTypesWritingAbbrPage}
\begin{chunk}{ug02.ht}
\begin{page}{ugTypesWritingPage}{2.2. Writing Types and Modes}
\beginscroll
%

We have already seen in \texht{the last
section}{\downlink{``The Basic Idea''}{ugTypesBasicPage} in
Section 2.1\ignore{ugTypesBasic}} several examples of
types.  Most of these examples had either no arguments (for example,
\axiomType{Integer}) or one argument (for example,
\axiomType{Polynomial (Integer)}).  In this section we give details
about writing arbitrary types.  We then define
\spadglossSee{modes}{mode} and discuss how to write them.  We conclude
the section with a discussion on constructor abbreviations.

\xtc{
When might you need to write a type or mode?
You need to do so when you declare variables.
}{
\spadpaste{a : PositiveInteger}
}
\xtc{
You need to do so when you declare functions
(\downlink{``Declarations''}{ugTypesDeclarePage} 
in Section 2.3\ignore{ugTypesDeclare}),
}{
\spadpaste{f : Integer -> String}
}
\xtc{
You need to do so when you convert an object from one type to another
(\downlink{``Conversion''}{ugTypesConvertPage} 
in Section 2.7\ignore{ugTypesConvert}).
}{
\spadpaste{factor(2 :: Complex(Integer))}
}
\xtc{
}{
\spadpaste{(2 = 3)\$Integer}
}
\xtc{
You need to do so when you give computation target type information
(\downlink{``Package Calling and Target Types''}{ugTypesPkgCallPage} 
in Section 2.9\ignore{ugTypesPkgCall}).
}{
\spadpaste{(2 = 3)@Boolean}
}

\beginmenu
    \menudownlink{{2.2.1. Types with No Arguments}}{ugTypesWritingZeroPage}
    \menudownlink{{2.2.2. Types with One Argument}}{ugTypesWritingOnePage}
    \menudownlink{{2.2.3. Types with More Than One Argument}}
{ugTypesWritingMorePage}
    \menudownlink{{2.2.4. Modes}}{ugTypesWritingModesPage}
    \menudownlink{{2.2.5. Abbreviations}}{ugTypesWritingAbbrPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\begin{patch}{ugTypesWritingPagePatch1}
\begin{paste}{ugTypesWritingPageFull1}{ugTypesWritingPageEmpty1}
\pastebutton{ugTypesWritingPageFull1}{\hidepaste}
\tab{5}\spadcommand{a : PositiveInteger}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesWritingPageEmpty1}
\begin{paste}{ugTypesWritingPageEmpty1}{ugTypesWritingPagePatch1}
\pastebutton{ugTypesWritingPageEmpty1}{\showpaste}
\tab{5}\spadcommand{a : PositiveInteger}
\end{paste}\end{patch}

\begin{patch}{ugTypesWritingPagePatch2}
\begin{paste}{ugTypesWritingPageFull2}{ugTypesWritingPageEmpty2}
\pastebutton{ugTypesWritingPageFull2}{\hidepaste}
\tab{5}\spadcommand{f : Integer -> String}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesWritingPageEmpty2}
\begin{paste}{ugTypesWritingPageEmpty2}{ugTypesWritingPagePatch2}
\pastebutton{ugTypesWritingPageEmpty2}{\showpaste}
\tab{5}\spadcommand{f : Integer -> String}
\end{paste}\end{patch}

\begin{patch}{ugTypesWritingPagePatch3}
\begin{paste}{ugTypesWritingPageFull3}{ugTypesWritingPageEmpty3}
\pastebutton{ugTypesWritingPageFull3}{\hidepaste}
\tab{5}\spadcommand{factor(2 :: Complex(Integer))}
\indentrel{3}\begin{verbatim}
                     2
   (3)  - %i (1 + %i)
                         Type: Factored Complex Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesWritingPageEmpty3}
\begin{paste}{ugTypesWritingPageEmpty3}{ugTypesWritingPagePatch3}
\pastebutton{ugTypesWritingPageEmpty3}{\showpaste}
\tab{5}\spadcommand{factor(2 :: Complex(Integer))}
\end{paste}\end{patch}

\begin{patch}{ugTypesWritingPagePatch4}
\begin{paste}{ugTypesWritingPageFull4}{ugTypesWritingPageEmpty4}
\pastebutton{ugTypesWritingPageFull4}{\hidepaste}
\tab{5}\spadcommand{(2 = 3)$Integer}
\indentrel{3}\begin{verbatim}
   (4)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesWritingPageEmpty4}
\begin{paste}{ugTypesWritingPageEmpty4}{ugTypesWritingPagePatch4}
\pastebutton{ugTypesWritingPageEmpty4}{\showpaste}
\tab{5}\spadcommand{(2 = 3)$Integer}
\end{paste}\end{patch}

\begin{patch}{ugTypesWritingPagePatch5}
\begin{paste}{ugTypesWritingPageFull5}{ugTypesWritingPageEmpty5}
\pastebutton{ugTypesWritingPageFull5}{\hidepaste}
\tab{5}\spadcommand{(2 = 3)@Boolean}
\indentrel{3}\begin{verbatim}
   (5)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesWritingPageEmpty5}
\begin{paste}{ugTypesWritingPageEmpty5}{ugTypesWritingPagePatch5}
\pastebutton{ugTypesWritingPageEmpty5}{\showpaste}
\tab{5}\spadcommand{(2 = 3)@Boolean}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugTypesWritingZeroPage}{ug02.ht}{Types with No Arguments}
\begin{chunk}{ug02.ht}
\begin{page}{ugTypesWritingZeroPage}{2.2.1. Types with No Arguments}
\beginscroll

A constructor with no arguments can be written either
with or without
trailing opening and closing parentheses (\axiomSyntax{()}).
\texht{
\centerline{{\begin{tabular}{ccc}}}
\centerline{{\axiomType{Boolean()} 
is the same as \axiomType{Boolean} & \quad &}}
\centerline{{\axiomType{Integer()} 
is the same as \axiomType{Integer} }}
\centerline{{\axiomType{String()} 
is the same as \axiomType{String} & \quad &}}
\centerline{{\axiomType{Void()} 
is the same as \axiomType{Void} }}
\centerline{{\end{tabular}}}
}{
\centerline{{\axiomType{Boolean()} 
is the same as \axiomType{Boolean} }}
\centerline{{\axiomType{Integer()} 
is the same as \axiomType{Integer} }}
\centerline{{\axiomType{String()} 
is the same as \axiomType{String} }}
\centerline{{\axiomType{Void()} 
is the same as \axiomType{Void} }}
and so on.
}
It is customary to omit the parentheses.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugTypesWritingOnePage}{ug02.ht}{Types with One Argument}
\pageto{notitle}{ugTypesPkgCallPage}
\begin{chunk}{ug02.ht}
\begin{page}{ugTypesWritingOnePage}{2.2.2. Types with One Argument}
\beginscroll

A constructor with one argument can frequently be written with no
parentheses.  Types nest from right to left so that \axiomType{Complex
Fraction Polynomial Integer} is the same as \axiomType{Complex
(Fraction (Polynomial (Integer)))}.  You need to use parentheses to
force the application of a constructor to the correct argument, but
you need not use any more than is necessary to remove ambiguities.

Here are some guidelines for using parentheses (they are possibly
slightly more restrictive than they need to be).
\xtc{
If the argument is an expression like \axiom{2 + 3}
then you must enclose the argument in parentheses.
}{
\spadpaste{e : PrimeField(2 + 3)}
}
%
\xtc{
If the type is to be used with package calling
then you must enclose the argument in parentheses.
}{
\spadpaste{content(2)\$Polynomial(Integer)}
}
\xtc{
Alternatively, you can write the type without parentheses
then enclose the whole type expression with parentheses.
}{
\spadpaste{content(2)\$(Polynomial Complex Fraction Integer)}
}
\xtc{
If you supply computation target type information
(\downlink{``Package Calling and Target Types''}{ugTypesPkgCallPage} 
in Section 2.9\ignore{ugTypesPkgCall})
then you should enclose the argument in parentheses.
}{
\spadpaste{(2/3)@Fraction(Polynomial(Integer))}
}
%
\xtc{
If the type itself has parentheses around it and we are
not in the case of the first example above,
then the parentheses can usually be omitted.
}{
\spadpaste{(2/3)@Fraction(Polynomial Integer)}
}
%
\xtc{
If the type is used in a declaration and the argument is a single-word
type, integer or symbol,
then the parentheses can usually be omitted.
}{
\spadpaste{(d,f,g) : Complex Polynomial Integer}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugTypesWritingOnePagePatch1}
\begin{paste}{ugTypesWritingOnePageFull1}{ugTypesWritingOnePageEmpty1}
\pastebutton{ugTypesWritingOnePageFull1}{\hidepaste}
\tab{5}\spadcommand{e : PrimeField(2 + 3)}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesWritingOnePageEmpty1}
\begin{paste}{ugTypesWritingOnePageEmpty1}{ugTypesWritingOnePagePatch1}
\pastebutton{ugTypesWritingOnePageEmpty1}{\showpaste}
\tab{5}\spadcommand{e : PrimeField(2 + 3)}
\end{paste}\end{patch}

\begin{patch}{ugTypesWritingOnePagePatch2}
\begin{paste}{ugTypesWritingOnePageFull2}{ugTypesWritingOnePageEmpty2}
\pastebutton{ugTypesWritingOnePageFull2}{\hidepaste}
\tab{5}\spadcommand{content(2)$Polynomial(Integer)}
\indentrel{3}\begin{verbatim}
   (2)  2
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesWritingOnePageEmpty2}
\begin{paste}{ugTypesWritingOnePageEmpty2}{ugTypesWritingOnePagePatch2}
\pastebutton{ugTypesWritingOnePageEmpty2}{\showpaste}
\tab{5}\spadcommand{content(2)$Polynomial(Integer)}
\end{paste}\end{patch}

\begin{patch}{ugTypesWritingOnePagePatch3}
\begin{paste}{ugTypesWritingOnePageFull3}{ugTypesWritingOnePageEmpty3}
\pastebutton{ugTypesWritingOnePageFull3}{\hidepaste}
\tab{5}\spadcommand{content(2)$(Polynomial Complex Fraction Integer)}
\indentrel{3}\begin{verbatim}
   (3)  2
                         Type: Complex Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesWritingOnePageEmpty3}
\begin{paste}{ugTypesWritingOnePageEmpty3}{ugTypesWritingOnePagePatch3}
\pastebutton{ugTypesWritingOnePageEmpty3}{\showpaste}
\tab{5}\spadcommand{content(2)$(Polynomial Complex Fraction Integer)}
\end{paste}\end{patch}

\begin{patch}{ugTypesWritingOnePagePatch4}
\begin{paste}{ugTypesWritingOnePageFull4}{ugTypesWritingOnePageEmpty4}
\pastebutton{ugTypesWritingOnePageFull4}{\hidepaste}
\tab{5}\spadcommand{(2/3)@Fraction(Polynomial(Integer))}
\indentrel{3}\begin{verbatim}
        2
   (4)  Ä
        3
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesWritingOnePageEmpty4}
\begin{paste}{ugTypesWritingOnePageEmpty4}{ugTypesWritingOnePagePatch4}
\pastebutton{ugTypesWritingOnePageEmpty4}{\showpaste}
\tab{5}\spadcommand{(2/3)@Fraction(Polynomial(Integer))}
\end{paste}\end{patch}

\begin{patch}{ugTypesWritingOnePagePatch5}
\begin{paste}{ugTypesWritingOnePageFull5}{ugTypesWritingOnePageEmpty5}
\pastebutton{ugTypesWritingOnePageFull5}{\hidepaste}
\tab{5}\spadcommand{(2/3)@Fraction(Polynomial Integer)}
\indentrel{3}\begin{verbatim}
        2
   (5)  Ä
        3
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesWritingOnePageEmpty5}
\begin{paste}{ugTypesWritingOnePageEmpty5}{ugTypesWritingOnePagePatch5}
\pastebutton{ugTypesWritingOnePageEmpty5}{\showpaste}
\tab{5}\spadcommand{(2/3)@Fraction(Polynomial Integer)}
\end{paste}\end{patch}

\begin{patch}{ugTypesWritingOnePagePatch6}
\begin{paste}{ugTypesWritingOnePageFull6}{ugTypesWritingOnePageEmpty6}
\pastebutton{ugTypesWritingOnePageFull6}{\hidepaste}
\tab{5}\spadcommand{(d,f,g) : Complex Polynomial Integer}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesWritingOnePageEmpty6}
\begin{paste}{ugTypesWritingOnePageEmpty6}{ugTypesWritingOnePagePatch6}
\pastebutton{ugTypesWritingOnePageEmpty6}{\showpaste}
\tab{5}\spadcommand{(d,f,g) : Complex Polynomial Integer}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugTypesWritingMorePage}{ug02.ht}
{Types with More Than One Argument}
\begin{chunk}{ug02.ht}
\begin{page}{ugTypesWritingMorePage}
{2.2.3. Types with More Than One Argument}
\beginscroll

If a constructor
has more than
one argument, you must use parentheses.
Some examples are
\centerline{{\axiomType{UnivariatePolynomial(x, Float)} }}
\centerline{{\axiomType{MultivariatePolynomial([z,w,r], Complex Float)} }}
\centerline{{\axiomType{SquareMatrix(3, Integer)} }}
\centerline{{\axiomType{FactoredFunctions2(Integer,Fraction Integer)}}}

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugTypesWritingModesPage}{ug02.ht}{Modes}
\pageto{notitle}{ugTypesDeclarePage}
\pageto{notitle}{ugTypesConvertPage}
\begin{chunk}{ug02.ht}
\begin{page}{ugTypesWritingModesPage}{2.2.4. Modes}
\beginscroll

A \spadgloss{mode} is a type that possibly is a
question mark (\axiomSyntax{?}) or contains one in an argument
position.
For example, the following are all modes.
\texht{
\centerline{{\begin{tabular}{ccc}}}
\centerline{{\axiomType{?} & \quad &}}
\centerline{{\axiomType{Polynomial ?} }}
\centerline{{\axiomType{Matrix Polynomial ?} & \quad &}}
\centerline{{\axiomType{SquareMatrix(3,?)} }}
\centerline{{\axiomType{Integer} & \quad &}}
\centerline{{\axiomType{OneDimensionalArray(Float)}}}
\centerline{{\end{tabular}}}
}{
\centerline{{\axiomType{?} }}
\centerline{{\axiomType{Polynomial ?} }}
\centerline{{\axiomType{Matrix Polynomial ?} }}
\centerline{{\axiomType{SquareMatrix(3,?)} }}
\centerline{{\axiomType{Integer} }}
\centerline{{\axiomType{OneDimensionalArray(Float)}}}
}

As is evident from these examples, a mode is a type with a part that
is not specified (indicated by a question mark).  Only one
\axiomSyntax{?} is allowed per mode and it must appear in the most
deeply nested argument that is a type. Thus
\nonLibAxiomType{?(Integer)}, \nonLibAxiomType{Matrix(?
(Polynomial))}, \nonLibAxiomType{SquareMatrix(?, Integer)} and
\nonLibAxiomType{SquareMatrix(?, ?)} are all invalid.  The question
mark must take the place of a domain, not data (for example, the
integer that is the dimension of a square matrix).  This rules out,
for example, the two \axiomType{SquareMatrix} expressions.

Modes can be used for declarations
(\downlink{``Declarations''}{ugTypesDeclarePage} 
in Section 2.3\ignore{ugTypesDeclare}) and conversions
(\downlink{``Conversion''}{ugTypesConvertPage} 
in Section 2.7\ignore{ugTypesConvert}).
However, you cannot use a mode for package calling or giving target
type information.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugTypesWritingAbbrPage}{ug02.ht}{Abbreviations}
\pageto{notitle}{ugSysCmdwhatPage}
\begin{chunk}{ug02.ht}
\begin{page}{ugTypesWritingAbbrPage}{2.2.5. Abbreviations}
\beginscroll

Every constructor has an abbreviation that you can freely substitute
for the constructor name.  In some cases, the abbreviation is nothing
more than the capitalized version of the constructor name.

\beginImportant
Aside from allowing types to be written more concisely,
abbreviations are used by Axiom to name various system
files for constructors (such as library filenames, test input
files and example files).
Here are some common abbreviations.
\texht{}{\table{
{\axiomType{COMPLEX}    abbreviates \axiomType{Complex}              }
{\axiomType{DFLOAT}     abbreviates \axiomType{DoubleFloat}          }
{\axiomType{EXPR}       abbreviates \axiomType{Expression}           }
{\axiomType{FLOAT}      abbreviates \axiomType{Float}                }
{\axiomType{FRAC}       abbreviates \axiomType{Fraction}             }
{\axiomType{INT}        abbreviates \axiomType{Integer}              }
{\axiomType{MATRIX}     abbreviates \axiomType{Matrix}               }
{\axiomType{NNI}        abbreviates \axiomType{NonNegativeInteger}   }
{\axiomType{PI}         abbreviates \axiomType{PositiveInteger}      }
{\axiomType{POLY}       abbreviates \axiomType{Polynomial}           }
{\axiomType{STRING}     abbreviates \axiomType{String}               }
{\axiomType{UP}         abbreviates \axiomType{UnivariatePolynomial} }
}}
\endImportant

You can combine both full constructor names and abbreviations
in a type expression.
Here are some types using abbreviations.
\centerline{{\axiomType{POLY INT} is the same as 
\axiomType{Polynomial(INT)} }}
\centerline{{\axiomType{POLY(Integer)} is the same 
as \axiomType{Polynomial(Integer)} }}
\centerline{{\axiomType{POLY(Integer)} is the same 
as \axiomType{Polynomial(INT)} }}
\centerline{{\axiomType{FRAC(COMPLEX(INT))} is the 
same as \axiomType{Fraction Complex Integer} }}
\centerline{{\axiomType{FRAC(COMPLEX(INT))} is the 
same as \axiomType{FRAC(Complex Integer)} }}

There are several ways of finding the names of constructors and their
abbreviations.  For a specific constructor, use \spadcmd{)abbreviation
query}.  You can also use the \spadcmd{)what} system command to see
the names and abbreviations of constructors.  For more information
about \spadcmd{)what}, see
\downlink{``)what''}{ugSysCmdwhatPage} in Section B.28
\ignore{ugSysCmdwhat}.
\xtc{
\spadcmd{)abbreviation query} can be
abbreviated (no pun intended) to \spadcmd{)abb q}.
}{
\spadpaste{)abb q Integer}
}
\xtc{
The \spadcmd{)abbreviation query} command lists
the constructor name if you give the abbreviation.
Issue \spadcmd{)abb q} if you want to see the names and abbreviations
of all Axiom constructors.
}{
\spadpaste{)abb q DMP}
}
\xtc{
Issue this to see all packages whose names contain the string ``ode''.
}{
\spadpaste{)what packages ode}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugTypesWritingAbbrPagePatch1}
\begin{paste}{ugTypesWritingAbbrPageFull1}{ugTypesWritingAbbrPageEmpty1}
\pastebutton{ugTypesWritingAbbrPageFull1}{\hidepaste}
\tab{5}\spadcommand{)abb q Integer}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesWritingAbbrPageEmpty1}
\begin{paste}{ugTypesWritingAbbrPageEmpty1}{ugTypesWritingAbbrPagePatch1}
\pastebutton{ugTypesWritingAbbrPageEmpty1}{\showpaste}
\tab{5}\spadcommand{)abb q Integer}
\end{paste}\end{patch}

\begin{patch}{ugTypesWritingAbbrPagePatch2}
\begin{paste}{ugTypesWritingAbbrPageFull2}{ugTypesWritingAbbrPageEmpty2}
\pastebutton{ugTypesWritingAbbrPageFull2}{\hidepaste}
\tab{5}\spadcommand{)abb q DMP}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesWritingAbbrPageEmpty2}
\begin{paste}{ugTypesWritingAbbrPageEmpty2}{ugTypesWritingAbbrPagePatch2}
\pastebutton{ugTypesWritingAbbrPageEmpty2}{\showpaste}
\tab{5}\spadcommand{)abb q DMP}
\end{paste}\end{patch}

\begin{patch}{ugTypesWritingAbbrPagePatch3}
\begin{paste}{ugTypesWritingAbbrPageFull3}{ugTypesWritingAbbrPageEmpty3}
\pastebutton{ugTypesWritingAbbrPageFull3}{\hidepaste}
\tab{5}\spadcommand{)what packages ode}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesWritingAbbrPageEmpty3}
\begin{paste}{ugTypesWritingAbbrPageEmpty3}{ugTypesWritingAbbrPagePatch3}
\pastebutton{ugTypesWritingAbbrPageEmpty3}{\showpaste}
\tab{5}\spadcommand{)what packages ode}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugTypesDeclarePage}{ug02.ht}{Declarations}
\pageto{notitle}{ugLangAssignPage}
\pageto{notitle}{ugUserDeclarePage}
\pageto{notitle}{ugTypesConvertPage}
\pageto{notitle}{ugIntroAssignPage}
\begin{chunk}{ug02.ht}
\begin{page}{ugTypesDeclarePage}{2.3. Declarations}
\beginscroll
%
A \spadgloss{declaration} is an expression used
to restrict the type of values that can be assigned to variables.
A colon (\axiomSyntax{:}) is always used after a variable or
list of variables to be declared.

\beginImportant
For a single variable, the syntax for declaration is \centerline{{{\it
variableName \axiom{:} typeOrMode}}} For multiple variables, the
syntax is \centerline{{{\tt (\subscriptIt{variableName}{1},
\subscriptIt{variableName}{2}, \ldots \subscriptIt{variableName}{N}):
{\it typeOrMode}}}}
\endImportant

You can always combine a declaration with an assignment.
When you do, it is equivalent to first giving a declaration statement,
then giving an assignment.
For more information on assignment, see
\downlink{``Symbols, Variables, Assignments, and Declarations''}
{ugIntroAssignPage} in Section 1.3.4\ignore{ugIntroAssign} and
\downlink{``Immediate and Delayed Assignments''}{ugLangAssignPage} 
in Section 5.1\ignore{ugLangAssign}.
To see how to declare your own functions, see
\downlink{``Declaring the Type of Functions''}{ugUserDeclarePage} 
in Section 6.4\ignore{ugUserDeclare}.

\xtc{
This declares one variable to have a type.
}{
\spadpaste{a : Integer \bound{a}}
}
\xtc{
This declares several variables to have a type.
}{
\spadpaste{(b,c) : Integer \bound{b c}}
}
\xtc{
\axiom{a, b} and \axiom{c} can only hold integer values.
}{
\spadpaste{a := 45 \free{a}}
}
\xtc{
If a value cannot be converted to a declared type,
an error message is displayed.
}{
\spadpaste{b := 4/5 \free{b}}
}
\xtc{
This declares a variable with a mode.
}{
\spadpaste{n : Complex ? \bound{n}}
}
\xtc{
This declares several variables with a mode.
}{
\spadpaste{(p,q,r) : Matrix Polynomial ? \bound{p q r}}
}
\xtc{
This complex object has integer real and imaginary parts.
}{
\spadpaste{n := -36 + 9 * \%i \free{n}}
}
\xtc{
This complex object has fractional symbolic real and imaginary parts.
}{
\spadpaste{n := complex(4/(x + y),y/x) \free{n}}
}
\xtc{
This matrix has entries that are polynomials with integer
coefficients.
}{
\spadpaste{p := [[1,2],[3,4],[5,6]] \free{p}}
}
\xtc{
This matrix has a single entry that is a polynomial with
rational number coefficients.
}{
\spadpaste{q := [[x - 2/3]] \free{q}}
}
\xtc{
This matrix has entries that are polynomials with complex integer
coefficients.
}{
\spadpaste{r := [[1-\%i*x,7*y+4*\%i]] \free{r}}
}
%
\xtc{
Note the difference between this and the next example.
This is a complex object with polynomial real and imaginary parts.
}{
\spadpaste{f : COMPLEX POLY ? := (x + y*\%i)**2}
}
\xtc{
This is a polynomial with complex integer coefficients.
The objects are convertible from one to the other.
See \downlink{``Conversion''}{ugTypesConvertPage} 
in Section 2.7\ignore{ugTypesConvert} for more 
information.
}{
\spadpaste{g : POLY COMPLEX ? := (x + y*\%i)**2}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugTypesDeclarePagePatch1}
\begin{paste}{ugTypesDeclarePageFull1}{ugTypesDeclarePageEmpty1}
\pastebutton{ugTypesDeclarePageFull1}{\hidepaste}
\tab{5}\spadcommand{a : Integer\bound{a }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePageEmpty1}
\begin{paste}{ugTypesDeclarePageEmpty1}{ugTypesDeclarePagePatch1}
\pastebutton{ugTypesDeclarePageEmpty1}{\showpaste}
\tab{5}\spadcommand{a : Integer\bound{a }}
\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePagePatch2}
\begin{paste}{ugTypesDeclarePageFull2}{ugTypesDeclarePageEmpty2}
\pastebutton{ugTypesDeclarePageFull2}{\hidepaste}
\tab{5}\spadcommand{(b,c) : Integer\bound{b c }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePageEmpty2}
\begin{paste}{ugTypesDeclarePageEmpty2}{ugTypesDeclarePagePatch2}
\pastebutton{ugTypesDeclarePageEmpty2}{\showpaste}
\tab{5}\spadcommand{(b,c) : Integer\bound{b c }}
\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePagePatch3}
\begin{paste}{ugTypesDeclarePageFull3}{ugTypesDeclarePageEmpty3}
\pastebutton{ugTypesDeclarePageFull3}{\hidepaste}
\tab{5}\spadcommand{a := 45\free{a }}
\indentrel{3}\begin{verbatim}
   (3)  45
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePageEmpty3}
\begin{paste}{ugTypesDeclarePageEmpty3}{ugTypesDeclarePagePatch3}
\pastebutton{ugTypesDeclarePageEmpty3}{\showpaste}
\tab{5}\spadcommand{a := 45\free{a }}
\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePagePatch4}
\begin{paste}{ugTypesDeclarePageFull4}{ugTypesDeclarePageEmpty4}
\pastebutton{ugTypesDeclarePageFull4}{\hidepaste}
\tab{5}\spadcommand{b := 4/5\free{b }}
\indentrel{3}\begin{verbatim}
   4
   Ä
   5
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePageEmpty4}
\begin{paste}{ugTypesDeclarePageEmpty4}{ugTypesDeclarePagePatch4}
\pastebutton{ugTypesDeclarePageEmpty4}{\showpaste}
\tab{5}\spadcommand{b := 4/5\free{b }}
\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePagePatch5}
\begin{paste}{ugTypesDeclarePageFull5}{ugTypesDeclarePageEmpty5}
\pastebutton{ugTypesDeclarePageFull5}{\hidepaste}
\tab{5}\spadcommand{n : Complex ?\bound{n }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePageEmpty5}
\begin{paste}{ugTypesDeclarePageEmpty5}{ugTypesDeclarePagePatch5}
\pastebutton{ugTypesDeclarePageEmpty5}{\showpaste}
\tab{5}\spadcommand{n : Complex ?\bound{n }}
\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePagePatch6}
\begin{paste}{ugTypesDeclarePageFull6}{ugTypesDeclarePageEmpty6}
\pastebutton{ugTypesDeclarePageFull6}{\hidepaste}
\tab{5}\spadcommand{(p,q,r) : Matrix Polynomial ?\bound{p q r }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePageEmpty6}
\begin{paste}{ugTypesDeclarePageEmpty6}{ugTypesDeclarePagePatch6}
\pastebutton{ugTypesDeclarePageEmpty6}{\showpaste}
\tab{5}\spadcommand{(p,q,r) : Matrix Polynomial ?\bound{p q r }}
\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePagePatch7}
\begin{paste}{ugTypesDeclarePageFull7}{ugTypesDeclarePageEmpty7}
\pastebutton{ugTypesDeclarePageFull7}{\hidepaste}
\tab{5}\spadcommand{n := -36 + 9 * \%i\free{n }}
\indentrel{3}\begin{verbatim}
   (6)  - 36 + 9%i
                                  Type: Complex Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePageEmpty7}
\begin{paste}{ugTypesDeclarePageEmpty7}{ugTypesDeclarePagePatch7}
\pastebutton{ugTypesDeclarePageEmpty7}{\showpaste}
\tab{5}\spadcommand{n := -36 + 9 * \%i\free{n }}
\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePagePatch8}
\begin{paste}{ugTypesDeclarePageFull8}{ugTypesDeclarePageEmpty8}
\pastebutton{ugTypesDeclarePageFull8}{\hidepaste}
\tab{5}\spadcommand{n := complex(4/(x + y),y/x)\free{n }}
\indentrel{3}\begin{verbatim}
          4     y
   (7)  ÄÄÄÄÄ + Ä %i
        y + x   x
              Type: Complex Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePageEmpty8}
\begin{paste}{ugTypesDeclarePageEmpty8}{ugTypesDeclarePagePatch8}
\pastebutton{ugTypesDeclarePageEmpty8}{\showpaste}
\tab{5}\spadcommand{n := complex(4/(x + y),y/x)\free{n }}
\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePagePatch9}
\begin{paste}{ugTypesDeclarePageFull9}{ugTypesDeclarePageEmpty9}
\pastebutton{ugTypesDeclarePageFull9}{\hidepaste}
\tab{5}\spadcommand{p := [[1,2],[3,4],[5,6]]\free{p }}
\indentrel{3}\begin{verbatim}
        Ú1  2¿
        ³    ³
   (8)  ³3  4³
        ³    ³
        À5  6Ù
                        Type: Matrix Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePageEmpty9}
\begin{paste}{ugTypesDeclarePageEmpty9}{ugTypesDeclarePagePatch9}
\pastebutton{ugTypesDeclarePageEmpty9}{\showpaste}
\tab{5}\spadcommand{p := [[1,2],[3,4],[5,6]]\free{p }}
\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePagePatch10}
\begin{paste}{ugTypesDeclarePageFull10}{ugTypesDeclarePageEmpty10}
\pastebutton{ugTypesDeclarePageFull10}{\hidepaste}
\tab{5}\spadcommand{q := [[x - 2/3]]\free{q }}
\indentrel{3}\begin{verbatim}
        Ú    2¿
   (9)  ³x - Ä³
        À    3Ù
               Type: Matrix Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePageEmpty10}
\begin{paste}{ugTypesDeclarePageEmpty10}{ugTypesDeclarePagePatch10}
\pastebutton{ugTypesDeclarePageEmpty10}{\showpaste}
\tab{5}\spadcommand{q := [[x - 2/3]]\free{q }}
\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePagePatch11}
\begin{paste}{ugTypesDeclarePageFull11}{ugTypesDeclarePageEmpty11}
\pastebutton{ugTypesDeclarePageFull11}{\hidepaste}
\tab{5}\spadcommand{r := [[1-\%i*x,7*y+4*\%i]]\free{r }}
\indentrel{3}\begin{verbatim}
   (10)  [- %i x + 1  7y + 4%i]
                Type: Matrix Polynomial Complex Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePageEmpty11}
\begin{paste}{ugTypesDeclarePageEmpty11}{ugTypesDeclarePagePatch11}
\pastebutton{ugTypesDeclarePageEmpty11}{\showpaste}
\tab{5}\spadcommand{r := [[1-\%i*x,7*y+4*\%i]]\free{r }}
\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePagePatch12}
\begin{paste}{ugTypesDeclarePageFull12}{ugTypesDeclarePageEmpty12}
\pastebutton{ugTypesDeclarePageFull12}{\hidepaste}
\tab{5}\spadcommand{f : COMPLEX POLY ? := (x + y*\%i)**2}
\indentrel{3}\begin{verbatim}
            2    2
   (11)  - y  + x  + 2x y %i
                       Type: Complex Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePageEmpty12}
\begin{paste}{ugTypesDeclarePageEmpty12}{ugTypesDeclarePagePatch12}
\pastebutton{ugTypesDeclarePageEmpty12}{\showpaste}
\tab{5}\spadcommand{f : COMPLEX POLY ? := (x + y*\%i)**2}
\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePagePatch13}
\begin{paste}{ugTypesDeclarePageFull13}{ugTypesDeclarePageEmpty13}
\pastebutton{ugTypesDeclarePageFull13}{\hidepaste}
\tab{5}\spadcommand{g : POLY COMPLEX ? := (x + y*\%i)**2}
\indentrel{3}\begin{verbatim}
            2              2
   (12)  - y  + 2%i x y + x
                       Type: Polynomial Complex Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesDeclarePageEmpty13}
\begin{paste}{ugTypesDeclarePageEmpty13}{ugTypesDeclarePagePatch13}
\pastebutton{ugTypesDeclarePageEmpty13}{\showpaste}
\tab{5}\spadcommand{g : POLY COMPLEX ? := (x + y*\%i)**2}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugTypesRecordsPage}{ug02.ht}{Records}
\begin{chunk}{ug02.ht}
\begin{page}{ugTypesRecordsPage}{2.4. Records}
\beginscroll
%
A \pspadtype{Record} is an object composed of one or more other objects,
each of which is referenced
with
a \spadgloss{selector}.
Components can all belong to the same type or each can have a different 
type.

\beginImportant
The syntax for writing a \pspadtype{Record} type is \centerline{{{\tt
Record(\subscriptIt{selector}{1}:\subscriptIt{type}{1},
\subscriptIt{selector}{2}:\subscriptIt{type}{2}, \ldots,
\subscriptIt{selector}{N}:\subscriptIt{type}{N})}}} You must be
careful if a selector has the same name as a variable in the
workspace.  If this occurs, precede the selector name by a single
quote.
\endImportant

Record components are implicitly ordered.  All the components of a
record can be set at once by assigning the record a bracketed
\spadgloss{tuple} of values of the proper length (for example,
\axiom{r : Record(a: Integer, b: String) := [1, "two"]}).  To access a
component of a record \axiom{r}, write the name \axiom{r}, followed by
a period, followed by a selector.

%
\xtc{
The object returned by this computation is a record with two components: a
\axiom{quotient} part and a \axiom{remainder} part.
}{
\spadpaste{u := divide(5,2) \bound{u}}
}
%
\xtc{
This is the quotient part.
}{
\spadpaste{u.quotient \free{u}}
}
\xtc{
This is the remainder part.
}{
\spadpaste{u.remainder \free{u}}
}
%
\xtc{
You can use selector expressions on the left-hand side of an assignment
to change destructively the components of a record.
}{
\spadpaste{u.quotient := 8978 \free{u}\bound{u1}}
}
\xtc{
The selected component \axiom{quotient} has the value \axiom{8978},
which is what is returned by the assignment.
Check that the value of \axiom{u} was modified.
}{
\spadpaste{u \free{u}\free{u1}}
}
\xtc{
Selectors are evaluated.
Thus you can use variables that evaluate to selectors instead of the
selectors themselves.
}{
\spadpaste{s := 'quotient \bound{s}}
}
\xtc{
Be careful!
A selector could have the same name as a variable in the workspace.
If this occurs, precede the selector name by a single quote, as in
\axiom{u.'quotient}.
}{
\spadpaste{divide(5,2).s \free{s}}
}
\xtc{
Here we declare that the value of \axiom{bd}
has two components: a string,
to be accessed via \axiom{name}, and an integer,
to be accessed via \axiom{birthdayMonth}.
}{
\spadpaste{bd : Record(name : String, birthdayMonth : Integer) 
\bound{bddec}}
}
\xtc{
You must initially set the value of the entire \pspadtype{Record}
at once.
}{
\spadpaste{bd := ["Judith", 3] \free{bddec}\bound{bd}}
}
\xtc{
Once set, you can change any of the individual components.
}{
\spadpaste{bd.name := "Katie" \free{bd}}
}
\xtc{
Records may be nested and the selector names can be shared at
different levels.
}{
\spadpaste{r : Record(a : Record(b: Integer, c: Integer), b: Integer) 
\bound{rdec}}
}
\xtc{
The record \axiom{r} has a \axiom{b} selector at two different levels.
Here is an initial value for \axiom{r}.
}{
\spadpaste{r := [[1,2],3] \bound{r}\free{rdec}}
}
\xtc{
This extracts the \axiom{b} component from the \axiom{a} component of 
\axiom{r}.
}{
\spadpaste{r.a.b \free{r}}
}
\xtc{
This extracts the \axiom{b} component from \axiom{r}.
}{
\spadpaste{r.b \free{r}}
}
%
\xtc{
You can also use spaces or parentheses to refer to \pspadtype{Record}
components.
This is the same as \axiom{r.a}.
}{
\spadpaste{r(a) \free{r}}
}
\xtc{
This is the same as \axiom{r.b}.
}{
\spadpaste{r b \free{r}}
}
\xtc{
This is the same as \axiom{r.b := 10}.
}{
\spadpaste{r(b) := 10 \free{r}\bound{r1}}
}
\xtc{
Look at \axiom{r} to make sure it was modified.
}{
\spadpaste{r \free{r1}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugTypesRecordsPagePatch1}
\begin{paste}{ugTypesRecordsPageFull1}{ugTypesRecordsPageEmpty1}
\pastebutton{ugTypesRecordsPageFull1}{\hidepaste}
\tab{5}\spadcommand{u := divide(5,2)\bound{u }}
\indentrel{3}\begin{verbatim}
   (1)  [quotient= 2,remainder= 1]
     Type: Record(quotient: Integer,remainder: Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPageEmpty1}
\begin{paste}{ugTypesRecordsPageEmpty1}{ugTypesRecordsPagePatch1}
\pastebutton{ugTypesRecordsPageEmpty1}{\showpaste}
\tab{5}\spadcommand{u := divide(5,2)\bound{u }}
\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPagePatch2}
\begin{paste}{ugTypesRecordsPageFull2}{ugTypesRecordsPageEmpty2}
\pastebutton{ugTypesRecordsPageFull2}{\hidepaste}
\tab{5}\spadcommand{u.quotient\free{u }}
\indentrel{3}\begin{verbatim}
   (2)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPageEmpty2}
\begin{paste}{ugTypesRecordsPageEmpty2}{ugTypesRecordsPagePatch2}
\pastebutton{ugTypesRecordsPageEmpty2}{\showpaste}
\tab{5}\spadcommand{u.quotient\free{u }}
\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPagePatch3}
\begin{paste}{ugTypesRecordsPageFull3}{ugTypesRecordsPageEmpty3}
\pastebutton{ugTypesRecordsPageFull3}{\hidepaste}
\tab{5}\spadcommand{u.remainder\free{u }}
\indentrel{3}\begin{verbatim}
   (3)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPageEmpty3}
\begin{paste}{ugTypesRecordsPageEmpty3}{ugTypesRecordsPagePatch3}
\pastebutton{ugTypesRecordsPageEmpty3}{\showpaste}
\tab{5}\spadcommand{u.remainder\free{u }}
\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPagePatch4}
\begin{paste}{ugTypesRecordsPageFull4}{ugTypesRecordsPageEmpty4}
\pastebutton{ugTypesRecordsPageFull4}{\hidepaste}
\tab{5}\spadcommand{u.quotient := 8978\free{u }\bound{u1 }}
\indentrel{3}\begin{verbatim}
   (4)  8978
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPageEmpty4}
\begin{paste}{ugTypesRecordsPageEmpty4}{ugTypesRecordsPagePatch4}
\pastebutton{ugTypesRecordsPageEmpty4}{\showpaste}
\tab{5}\spadcommand{u.quotient := 8978\free{u }\bound{u1 }}
\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPagePatch5}
\begin{paste}{ugTypesRecordsPageFull5}{ugTypesRecordsPageEmpty5}
\pastebutton{ugTypesRecordsPageFull5}{\hidepaste}
\tab{5}\spadcommand{u\free{u }\free{u1 }}
\indentrel{3}\begin{verbatim}
   (5)  [quotient= 8978,remainder= 1]
     Type: Record(quotient: Integer,remainder: Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPageEmpty5}
\begin{paste}{ugTypesRecordsPageEmpty5}{ugTypesRecordsPagePatch5}
\pastebutton{ugTypesRecordsPageEmpty5}{\showpaste}
\tab{5}\spadcommand{u\free{u }\free{u1 }}
\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPagePatch6}
\begin{paste}{ugTypesRecordsPageFull6}{ugTypesRecordsPageEmpty6}
\pastebutton{ugTypesRecordsPageFull6}{\hidepaste}
\tab{5}\spadcommand{s := 'quotient\bound{s }}
\indentrel{3}\begin{verbatim}
   (6)  quotient
                                Type: Variable quotient
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPageEmpty6}
\begin{paste}{ugTypesRecordsPageEmpty6}{ugTypesRecordsPagePatch6}
\pastebutton{ugTypesRecordsPageEmpty6}{\showpaste}
\tab{5}\spadcommand{s := 'quotient\bound{s }}
\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPagePatch7}
\begin{paste}{ugTypesRecordsPageFull7}{ugTypesRecordsPageEmpty7}
\pastebutton{ugTypesRecordsPageFull7}{\hidepaste}
\tab{5}\spadcommand{divide(5,2).s\free{s }}
\indentrel{3}\begin{verbatim}
   (7)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPageEmpty7}
\begin{paste}{ugTypesRecordsPageEmpty7}{ugTypesRecordsPagePatch7}
\pastebutton{ugTypesRecordsPageEmpty7}{\showpaste}
\tab{5}\spadcommand{divide(5,2).s\free{s }}
\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPagePatch8}
\begin{paste}{ugTypesRecordsPageFull8}{ugTypesRecordsPageEmpty8}
\pastebutton{ugTypesRecordsPageFull8}{\hidepaste}
\tab{5}\spadcommand{bd : Record(name : String, birthdayMonth : Integer)\bound{bddec }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPageEmpty8}
\begin{paste}{ugTypesRecordsPageEmpty8}{ugTypesRecordsPagePatch8}
\pastebutton{ugTypesRecordsPageEmpty8}{\showpaste}
\tab{5}\spadcommand{bd : Record(name : String, birthdayMonth : Integer)\bound{bddec }}
\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPagePatch9}
\begin{paste}{ugTypesRecordsPageFull9}{ugTypesRecordsPageEmpty9}
\pastebutton{ugTypesRecordsPageFull9}{\hidepaste}
\tab{5}\spadcommand{bd := ["Judith", 3]\free{bddec }\bound{bd }}
\indentrel{3}\begin{verbatim}
   (9)  [name= "Judith",birthdayMonth= 3]
      Type: Record(name: String,birthdayMonth: Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPageEmpty9}
\begin{paste}{ugTypesRecordsPageEmpty9}{ugTypesRecordsPagePatch9}
\pastebutton{ugTypesRecordsPageEmpty9}{\showpaste}
\tab{5}\spadcommand{bd := ["Judith", 3]\free{bddec }\bound{bd }}
\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPagePatch10}
\begin{paste}{ugTypesRecordsPageFull10}{ugTypesRecordsPageEmpty10}
\pastebutton{ugTypesRecordsPageFull10}{\hidepaste}
\tab{5}\spadcommand{bd.name := "Katie"\free{bd }}
\indentrel{3}\begin{verbatim}
   (10)  "Katie"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPageEmpty10}
\begin{paste}{ugTypesRecordsPageEmpty10}{ugTypesRecordsPagePatch10}
\pastebutton{ugTypesRecordsPageEmpty10}{\showpaste}
\tab{5}\spadcommand{bd.name := "Katie"\free{bd }}
\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPagePatch11}
\begin{paste}{ugTypesRecordsPageFull11}{ugTypesRecordsPageEmpty11}
\pastebutton{ugTypesRecordsPageFull11}{\hidepaste}
\tab{5}\spadcommand{r : Record(a : Record(b: Integer, c: Integer), b: Integer)\bound{rdec }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPageEmpty11}
\begin{paste}{ugTypesRecordsPageEmpty11}{ugTypesRecordsPagePatch11}
\pastebutton{ugTypesRecordsPageEmpty11}{\showpaste}
\tab{5}\spadcommand{r : Record(a : Record(b: Integer, c: Integer), b: Integer)\bound{rdec }}
\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPagePatch12}
\begin{paste}{ugTypesRecordsPageFull12}{ugTypesRecordsPageEmpty12}
\pastebutton{ugTypesRecordsPageFull12}{\hidepaste}
\tab{5}\spadcommand{r := [[1,2],3]\bound{r }\free{rdec }}
\indentrel{3}\begin{verbatim}
   (12)  [a= [b= 1,c= 2],b= 3]
Type: Record(a: Record(b: Integer,c: Integer),b: Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPageEmpty12}
\begin{paste}{ugTypesRecordsPageEmpty12}{ugTypesRecordsPagePatch12}
\pastebutton{ugTypesRecordsPageEmpty12}{\showpaste}
\tab{5}\spadcommand{r := [[1,2],3]\bound{r }\free{rdec }}
\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPagePatch13}
\begin{paste}{ugTypesRecordsPageFull13}{ugTypesRecordsPageEmpty13}
\pastebutton{ugTypesRecordsPageFull13}{\hidepaste}
\tab{5}\spadcommand{r.a.b\free{r }}
\indentrel{3}\begin{verbatim}
   (13)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPageEmpty13}
\begin{paste}{ugTypesRecordsPageEmpty13}{ugTypesRecordsPagePatch13}
\pastebutton{ugTypesRecordsPageEmpty13}{\showpaste}
\tab{5}\spadcommand{r.a.b\free{r }}
\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPagePatch14}
\begin{paste}{ugTypesRecordsPageFull14}{ugTypesRecordsPageEmpty14}
\pastebutton{ugTypesRecordsPageFull14}{\hidepaste}
\tab{5}\spadcommand{r.b\free{r }}
\indentrel{3}\begin{verbatim}
   (14)  3
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPageEmpty14}
\begin{paste}{ugTypesRecordsPageEmpty14}{ugTypesRecordsPagePatch14}
\pastebutton{ugTypesRecordsPageEmpty14}{\showpaste}
\tab{5}\spadcommand{r.b\free{r }}
\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPagePatch15}
\begin{paste}{ugTypesRecordsPageFull15}{ugTypesRecordsPageEmpty15}
\pastebutton{ugTypesRecordsPageFull15}{\hidepaste}
\tab{5}\spadcommand{r(a)\free{r }}
\indentrel{3}\begin{verbatim}
   (15)  [b= 1,c= 2]
                    Type: Record(b: Integer,c: Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPageEmpty15}
\begin{paste}{ugTypesRecordsPageEmpty15}{ugTypesRecordsPagePatch15}
\pastebutton{ugTypesRecordsPageEmpty15}{\showpaste}
\tab{5}\spadcommand{r(a)\free{r }}
\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPagePatch16}
\begin{paste}{ugTypesRecordsPageFull16}{ugTypesRecordsPageEmpty16}
\pastebutton{ugTypesRecordsPageFull16}{\hidepaste}
\tab{5}\spadcommand{r b\free{r }}
\indentrel{3}\begin{verbatim}
   (16)  3
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPageEmpty16}
\begin{paste}{ugTypesRecordsPageEmpty16}{ugTypesRecordsPagePatch16}
\pastebutton{ugTypesRecordsPageEmpty16}{\showpaste}
\tab{5}\spadcommand{r b\free{r }}
\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPagePatch17}
\begin{paste}{ugTypesRecordsPageFull17}{ugTypesRecordsPageEmpty17}
\pastebutton{ugTypesRecordsPageFull17}{\hidepaste}
\tab{5}\spadcommand{r(b) := 10\free{r }\bound{r1 }}
\indentrel{3}\begin{verbatim}
   (17)  10
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPageEmpty17}
\begin{paste}{ugTypesRecordsPageEmpty17}{ugTypesRecordsPagePatch17}
\pastebutton{ugTypesRecordsPageEmpty17}{\showpaste}
\tab{5}\spadcommand{r(b) := 10\free{r }\bound{r1 }}
\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPagePatch18}
\begin{paste}{ugTypesRecordsPageFull18}{ugTypesRecordsPageEmpty18}
\pastebutton{ugTypesRecordsPageFull18}{\hidepaste}
\tab{5}\spadcommand{r\free{r1 }}
\indentrel{3}\begin{verbatim}
   (18)  [a= [b= 1,c= 2],b= 10]
Type: Record(a: Record(b: Integer,c: Integer),b: Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesRecordsPageEmpty18}
\begin{paste}{ugTypesRecordsPageEmpty18}{ugTypesRecordsPagePatch18}
\pastebutton{ugTypesRecordsPageEmpty18}{\showpaste}
\tab{5}\spadcommand{r\free{r1 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugTypesUnionsPage}{ug02.ht}{Unions}
\pageto{notitle}{ugTypesUnionsWOSelPage}
\pageto{notitle}{ugTypesUnionsWSelPage}
\begin{chunk}{ug02.ht}
\begin{page}{ugTypesUnionsPage}{2.5. Unions}
\beginscroll
%
Type \pspadtype{Union} is used for objects that
can be of any of a specific finite set of types.
Two versions of unions are available,
one with selectors (like records) and one without.

\beginmenu
\menudownlink{{2.5.1. Unions Without Selectors}}{ugTypesUnionsWOSelPage}
\menudownlink{{2.5.2. Unions With Selectors}}{ugTypesUnionsWSelPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugTypesUnionsWOSelPage}{ug02.ht}{Unions Without Selectors}
\begin{chunk}{ug02.ht}
\begin{page}{ugTypesUnionsWOSelPage}{2.5.1. Unions Without Selectors}
\beginscroll

The declaration \axiom{x : Union(Integer, String, Float)}
states that \axiom{x} can have values that are integers,
strings or ``big'' floats.
If, for example, the \pspadtype{Union} object is an integer, the object is
said to belong to the \axiomType{Integer} {\it branch}
of the \pspadtype{Union}.\footnote{
Note that we are being a bit careless with the language here.
Technically, the type of \axiom{x} is always
\pspadtype{Union(Integer, String, Float)}.
If it belongs to the \axiomType{Integer} branch, \axiom{x}
may be converted to an object of type \axiomType{Integer}.}

\beginImportant
The syntax for writing a \pspadtype{Union} type without selectors is
\centerline{{{\tt Union(\subscriptIt{type}{1}, \subscriptIt{type}{2},
\ldots, \subscriptIt{type}{N})}}} The types in a union without
selectors must be distinct.
\endImportant

It is possible to create unions like
\pspadtype{Union(Integer, PositiveInteger)} but they are
difficult to work with because of the overlap in the branch
types.
See below for the rules Axiom uses for converting something
into a union object.

The \axiom{case} infix
\spadkey{case}
operator returns a \axiomType{Boolean}
and can be used to determine the branch in which an object lies.

\xtc{
This function displays a message stating in which
branch of the \pspadtype{Union} the object (defined as \axiom{x}
above) lies.
}{
\begin{spadsrc}[\bound{sayBranch}]
sayBranch(x : Union(Integer,String,Float)) : Void  ==
  output
    x case Integer => "Integer branch"
    x case String  => "String branch"
    "Float branch"
\end{spadsrc}
}
%
\xtc{
This tries \userfun{sayBranch} with an integer.
}{
\spadpaste{sayBranch 1 \free{sayBranch}}
}
\xtc{
This tries \userfun{sayBranch} with a string.
}{
\spadpaste{sayBranch "hello" \free{sayBranch}}
}
\xtc{
This tries \userfun{sayBranch} with a floating-point number.
}{
\spadpaste{sayBranch 2.718281828 \free{sayBranch}}
}
%

There are two things of interest about this particular
example to which we would like to draw your attention.
\indent{4}
\beginitems

\item[1. ] Axiom normally converts a result to the target value before
passing it to the function.  If we left the declaration information
out of this function definition then the \axiom{sayBranch} call would
have been attempted with an \axiomType{Integer} rather than a
\pspadtype{Union}, and an error would have resulted.

\item[2. ] The types in a \pspadtype{Union} are searched in the order given.
So if the type were given as

\noindent
{\small\axiom{sayBranch(x: Union(String,Integer,Float,Any)): Void}}

\noindent
then the result would have been ``String branch'' because there
is a conversion from \axiomType{Integer} to \axiomType{String}.
\enditems
\indent{0}

Sometimes \pspadtype{Union} types can have extremely
long names.
Axiom therefore abbreviates the names of unions by printing
the type of the branch first within the \pspadtype{Union} and then
eliding the remaining types with an ellipsis (\axiomSyntax{...}).

\xtc{
Here the \axiomType{Integer} branch is displayed first.
Use \axiomSyntax{::} to create a \pspadtype{Union} object from an object.
}{
\spadpaste{78 :: Union(Integer,String)}
}
\xtc{
Here the \axiomType{String} branch is displayed first.
}{
\spadpaste{s := "string" :: Union(Integer,String) \bound{s}}
}
\xtc{
Use \axiom{typeOf} to see the full and actual \pspadtype{Union} type.
\spadkey{typeOf}
}{
\spadpaste{typeOf s}
}
\xtc{
A common operation that returns a union is \axiomFunFrom{exquo}{Integer}
which returns the ``exact quotient'' if the quotient is exact,...
}{
\spadpaste{three := exquo(6,2) \bound{three}}
}
\xtc{
and \axiom{"failed"} if the quotient is not exact.
}{
\spadpaste{exquo(5,2)}
}
\xtc{
A union with a \axiom{"failed"} is frequently used to indicate the failure
or lack of applicability of an object.
As another example, assign an integer a variable \axiom{r} declared to be a
rational number.
}{
\spadpaste{r: FRAC INT := 3 \bound{r}\bound{rdec}}
}
\xtc{
The operation \axiomFunFrom{retractIfCan}{Fraction} tries to retract the
fraction to the underlying domain \axiomType{Integer}.
It produces a union object.
Here it succeeds.
}{
\spadpaste{retractIfCan(r) \free{r}}
}
\xtc{
Assign it a rational number.
}{
\spadpaste{r := 3/2 \bound{r1}\free{rdec}}
}
\xtc{
Here the retraction fails.
}{
\spadpaste{retractIfCan(r) \free{r1}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugTypesUnionsWOSelPagePatch1}
\begin{paste}{ugTypesUnionsWOSelPageFull1}{ugTypesUnionsWOSelPageEmpty1}
\pastebutton{ugTypesUnionsWOSelPageFull1}{\hidepaste}
\tab{5}\spadcommand{sayBranch(x : Union(Integer,String,Float)) : Void  ==
  output
    x case Integer => "Integer branch"
    x case String  => "String branch"
    "Float branch"
\bound{sayBranch }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPageEmpty1}
\begin{paste}{ugTypesUnionsWOSelPageEmpty1}{ugTypesUnionsWOSelPagePatch1}
\pastebutton{ugTypesUnionsWOSelPageEmpty1}{\showpaste}
\tab{5}\spadcommand{sayBranch(x : Union(Integer,String,Float)) : Void  ==
  output
    x case Integer => "Integer branch"
    x case String  => "String branch"
    "Float branch"
\bound{sayBranch }}
\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPagePatch2}
\begin{paste}{ugTypesUnionsWOSelPageFull2}{ugTypesUnionsWOSelPageEmpty2}
\pastebutton{ugTypesUnionsWOSelPageFull2}{\hidepaste}
\tab{5}\spadcommand{sayBranch 1\free{sayBranch }}
\indentrel{3}\begin{verbatim}
   Integer branch
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPageEmpty2}
\begin{paste}{ugTypesUnionsWOSelPageEmpty2}{ugTypesUnionsWOSelPagePatch2}
\pastebutton{ugTypesUnionsWOSelPageEmpty2}{\showpaste}
\tab{5}\spadcommand{sayBranch 1\free{sayBranch }}
\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPagePatch3}
\begin{paste}{ugTypesUnionsWOSelPageFull3}{ugTypesUnionsWOSelPageEmpty3}
\pastebutton{ugTypesUnionsWOSelPageFull3}{\hidepaste}
\tab{5}\spadcommand{sayBranch "hello"\free{sayBranch }}
\indentrel{3}\begin{verbatim}
   String branch
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPageEmpty3}
\begin{paste}{ugTypesUnionsWOSelPageEmpty3}{ugTypesUnionsWOSelPagePatch3}
\pastebutton{ugTypesUnionsWOSelPageEmpty3}{\showpaste}
\tab{5}\spadcommand{sayBranch "hello"\free{sayBranch }}
\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPagePatch4}
\begin{paste}{ugTypesUnionsWOSelPageFull4}{ugTypesUnionsWOSelPageEmpty4}
\pastebutton{ugTypesUnionsWOSelPageFull4}{\hidepaste}
\tab{5}\spadcommand{sayBranch 2.718281828\free{sayBranch }}
\indentrel{3}\begin{verbatim}
   Float branch
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPageEmpty4}
\begin{paste}{ugTypesUnionsWOSelPageEmpty4}{ugTypesUnionsWOSelPagePatch4}
\pastebutton{ugTypesUnionsWOSelPageEmpty4}{\showpaste}
\tab{5}\spadcommand{sayBranch 2.718281828\free{sayBranch }}
\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPagePatch5}
\begin{paste}{ugTypesUnionsWOSelPageFull5}{ugTypesUnionsWOSelPageEmpty5}
\pastebutton{ugTypesUnionsWOSelPageFull5}{\hidepaste}
\tab{5}\spadcommand{78 :: Union(Integer,String)}
\indentrel{3}\begin{verbatim}
   (5)  78
                               Type: Union(Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPageEmpty5}
\begin{paste}{ugTypesUnionsWOSelPageEmpty5}{ugTypesUnionsWOSelPagePatch5}
\pastebutton{ugTypesUnionsWOSelPageEmpty5}{\showpaste}
\tab{5}\spadcommand{78 :: Union(Integer,String)}
\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPagePatch6}
\begin{paste}{ugTypesUnionsWOSelPageFull6}{ugTypesUnionsWOSelPageEmpty6}
\pastebutton{ugTypesUnionsWOSelPageFull6}{\hidepaste}
\tab{5}\spadcommand{s := "string" :: Union(Integer,String)\bound{s }}
\indentrel{3}\begin{verbatim}
   (6)  "string"
                                Type: Union(String,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPageEmpty6}
\begin{paste}{ugTypesUnionsWOSelPageEmpty6}{ugTypesUnionsWOSelPagePatch6}
\pastebutton{ugTypesUnionsWOSelPageEmpty6}{\showpaste}
\tab{5}\spadcommand{s := "string" :: Union(Integer,String)\bound{s }}
\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPagePatch7}
\begin{paste}{ugTypesUnionsWOSelPageFull7}{ugTypesUnionsWOSelPageEmpty7}
\pastebutton{ugTypesUnionsWOSelPageFull7}{\hidepaste}
\tab{5}\spadcommand{typeOf s}
\indentrel{3}\begin{verbatim}
   (7)  Union(Integer,String)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPageEmpty7}
\begin{paste}{ugTypesUnionsWOSelPageEmpty7}{ugTypesUnionsWOSelPagePatch7}
\pastebutton{ugTypesUnionsWOSelPageEmpty7}{\showpaste}
\tab{5}\spadcommand{typeOf s}
\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPagePatch8}
\begin{paste}{ugTypesUnionsWOSelPageFull8}{ugTypesUnionsWOSelPageEmpty8}
\pastebutton{ugTypesUnionsWOSelPageFull8}{\hidepaste}
\tab{5}\spadcommand{three := exquo(6,2)\bound{three }}
\indentrel{3}\begin{verbatim}
   (8)  3
                               Type: Union(Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPageEmpty8}
\begin{paste}{ugTypesUnionsWOSelPageEmpty8}{ugTypesUnionsWOSelPagePatch8}
\pastebutton{ugTypesUnionsWOSelPageEmpty8}{\showpaste}
\tab{5}\spadcommand{three := exquo(6,2)\bound{three }}
\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPagePatch9}
\begin{paste}{ugTypesUnionsWOSelPageFull9}{ugTypesUnionsWOSelPageEmpty9}
\pastebutton{ugTypesUnionsWOSelPageFull9}{\hidepaste}
\tab{5}\spadcommand{exquo(5,2)}
\indentrel{3}\begin{verbatim}
   (9)  "failed"
                              Type: Union("failed",...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPageEmpty9}
\begin{paste}{ugTypesUnionsWOSelPageEmpty9}{ugTypesUnionsWOSelPagePatch9}
\pastebutton{ugTypesUnionsWOSelPageEmpty9}{\showpaste}
\tab{5}\spadcommand{exquo(5,2)}
\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPagePatch10}
\begin{paste}{ugTypesUnionsWOSelPageFull10}{ugTypesUnionsWOSelPageEmpty10}
\pastebutton{ugTypesUnionsWOSelPageFull10}{\hidepaste}
\tab{5}\spadcommand{r: FRAC INT := 3\bound{r }\bound{rdec }}
\indentrel{3}\begin{verbatim}
   (10)  3
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPageEmpty10}
\begin{paste}{ugTypesUnionsWOSelPageEmpty10}{ugTypesUnionsWOSelPagePatch10}
\pastebutton{ugTypesUnionsWOSelPageEmpty10}{\showpaste}
\tab{5}\spadcommand{r: FRAC INT := 3\bound{r }\bound{rdec }}
\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPagePatch11}
\begin{paste}{ugTypesUnionsWOSelPageFull11}{ugTypesUnionsWOSelPageEmpty11}
\pastebutton{ugTypesUnionsWOSelPageFull11}{\hidepaste}
\tab{5}\spadcommand{retractIfCan(r)\free{r }}
\indentrel{3}\begin{verbatim}
   (11)  3
                               Type: Union(Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPageEmpty11}
\begin{paste}{ugTypesUnionsWOSelPageEmpty11}{ugTypesUnionsWOSelPagePatch11}
\pastebutton{ugTypesUnionsWOSelPageEmpty11}{\showpaste}
\tab{5}\spadcommand{retractIfCan(r)\free{r }}
\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPagePatch12}
\begin{paste}{ugTypesUnionsWOSelPageFull12}{ugTypesUnionsWOSelPageEmpty12}
\pastebutton{ugTypesUnionsWOSelPageFull12}{\hidepaste}
\tab{5}\spadcommand{r := 3/2\bound{r1 }\free{rdec }}
\indentrel{3}\begin{verbatim}
         3
   (12)  Ä
         2
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPageEmpty12}
\begin{paste}{ugTypesUnionsWOSelPageEmpty12}{ugTypesUnionsWOSelPagePatch12}
\pastebutton{ugTypesUnionsWOSelPageEmpty12}{\showpaste}
\tab{5}\spadcommand{r := 3/2\bound{r1 }\free{rdec }}
\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPagePatch13}
\begin{paste}{ugTypesUnionsWOSelPageFull13}{ugTypesUnionsWOSelPageEmpty13}
\pastebutton{ugTypesUnionsWOSelPageFull13}{\hidepaste}
\tab{5}\spadcommand{retractIfCan(r)\free{r1 }}
\indentrel{3}\begin{verbatim}
   (13)  "failed"
                              Type: Union("failed",...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWOSelPageEmpty13}
\begin{paste}{ugTypesUnionsWOSelPageEmpty13}{ugTypesUnionsWOSelPagePatch13}
\pastebutton{ugTypesUnionsWOSelPageEmpty13}{\showpaste}
\tab{5}\spadcommand{retractIfCan(r)\free{r1 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugTypesUnionsWSelPage}{ug02.ht}{Unions With Selectors}
\pageto{notitle}{ugTypesRecordsPage}
\pageto{notitle}{ugTypesUnionsWOSelPage}
\begin{chunk}{ug02.ht}
\begin{page}{ugTypesUnionsWSelPage}{2.5.2. Unions With Selectors}
\beginscroll

Like records ( \downlink{``Records''}{ugTypesRecordsPage} in Section
2.4\ignore{ugTypesRecords}), you can write \pspadtype{Union} types
with selectors.

\beginImportant
The syntax for writing a \pspadtype{Union} type with selectors is
\centerline{{{\tt
Union(\subscriptIt{selector}{1}:\subscriptIt{type}{1},
\subscriptIt{selector}{2}:\subscriptIt{type}{2}, \ldots,
\subscriptIt{selector}{N}:\subscriptIt{type}{N})}}} You must be
careful if a selector has the same name as a variable in the
workspace.  If this occurs, precede the selector name by a single
quote.  It is an error to use a selector that does not correspond to
the branch of the \pspadtype{Union} in which the element actually
lies.
\endImportant

Be sure to understand the difference between records and unions with
selectors.  Records can have more than one component and the selectors
are used to refer to the components.  Unions always have one component
but the type of that one component can vary.  An object of type
\pspadtype{Record(a: Integer, b: Float, c: String)} contains an
integer {\it and} a float {\it and} a string.  An object of type
\pspadtype{Union(a: Integer, b: Float, c: String)} contains an integer
{\it or} a float {\it or} a string.

Here is a version of the \userfun{sayBranch} function (cf.
\downlink{``Unions Without Selectors''}{ugTypesUnionsWOSelPage} 
in Section 2.5.1\ignore{ugTypesUnionsWOSel}) 
that works with a union with selectors.
It displays a message stating in which branch of the \pspadtype{Union} the
object lies.
\begin{verbatim}
sayBranch(x:Union(i:Integer,s:String,f:Float)):Void==
  output
    x case i => "Integer branch"
    x case s  => "String branch"
    "Float branch"
\end{verbatim}
Note that \axiom{case} uses the selector name as its right-hand argument.
\spadkey{case}
If you accidentally use the branch type on the right-hand side of
\axiom{case}, \axiom{false} will be returned.

\xtc{
Declare variable \axiom{u} to have a union type with selectors.
}{
\spadpaste{u : Union(i : Integer, s : String) \bound{undec}}
}
\xtc{
Give an initial value to \axiom{u}.
}{
\spadpaste{u := "good morning" \bound{u}\free{undec}}
}
\xtc{
Use \axiom{case} to determine in which
branch of a \pspadtype{Union} an object lies.
}{
\spadpaste{u case i \free{u}}
}
\xtc{
}{
\spadpaste{u case s \free{u}}
}
\xtc{
To access the element in a particular branch, use the selector.
}{
\spadpaste{u.s \free{u}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugTypesUnionsWSelPagePatch1}
\begin{paste}{ugTypesUnionsWSelPageFull1}{ugTypesUnionsWSelPageEmpty1}
\pastebutton{ugTypesUnionsWSelPageFull1}{\hidepaste}
\tab{5}\spadcommand{u : Union(i : Integer, s : String)\bound{undec }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWSelPageEmpty1}
\begin{paste}{ugTypesUnionsWSelPageEmpty1}{ugTypesUnionsWSelPagePatch1}
\pastebutton{ugTypesUnionsWSelPageEmpty1}{\showpaste}
\tab{5}\spadcommand{u : Union(i : Integer, s : String)\bound{undec }}
\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWSelPagePatch2}
\begin{paste}{ugTypesUnionsWSelPageFull2}{ugTypesUnionsWSelPageEmpty2}
\pastebutton{ugTypesUnionsWSelPageFull2}{\hidepaste}
\tab{5}\spadcommand{u := "good morning"\bound{u }\free{undec }}
\indentrel{3}\begin{verbatim}
   (2)  "good morning"
                             Type: Union(s: String,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWSelPageEmpty2}
\begin{paste}{ugTypesUnionsWSelPageEmpty2}{ugTypesUnionsWSelPagePatch2}
\pastebutton{ugTypesUnionsWSelPageEmpty2}{\showpaste}
\tab{5}\spadcommand{u := "good morning"\bound{u }\free{undec }}
\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWSelPagePatch3}
\begin{paste}{ugTypesUnionsWSelPageFull3}{ugTypesUnionsWSelPageEmpty3}
\pastebutton{ugTypesUnionsWSelPageFull3}{\hidepaste}
\tab{5}\spadcommand{u case i\free{u }}
\indentrel{3}\begin{verbatim}
   (3)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWSelPageEmpty3}
\begin{paste}{ugTypesUnionsWSelPageEmpty3}{ugTypesUnionsWSelPagePatch3}
\pastebutton{ugTypesUnionsWSelPageEmpty3}{\showpaste}
\tab{5}\spadcommand{u case i\free{u }}
\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWSelPagePatch4}
\begin{paste}{ugTypesUnionsWSelPageFull4}{ugTypesUnionsWSelPageEmpty4}
\pastebutton{ugTypesUnionsWSelPageFull4}{\hidepaste}
\tab{5}\spadcommand{u case s\free{u }}
\indentrel{3}\begin{verbatim}
   (4)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWSelPageEmpty4}
\begin{paste}{ugTypesUnionsWSelPageEmpty4}{ugTypesUnionsWSelPagePatch4}
\pastebutton{ugTypesUnionsWSelPageEmpty4}{\showpaste}
\tab{5}\spadcommand{u case s\free{u }}
\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWSelPagePatch5}
\begin{paste}{ugTypesUnionsWSelPageFull5}{ugTypesUnionsWSelPageEmpty5}
\pastebutton{ugTypesUnionsWSelPageFull5}{\hidepaste}
\tab{5}\spadcommand{u.s\free{u }}
\indentrel{3}\begin{verbatim}
   (5)  "good morning"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesUnionsWSelPageEmpty5}
\begin{paste}{ugTypesUnionsWSelPageEmpty5}{ugTypesUnionsWSelPagePatch5}
\pastebutton{ugTypesUnionsWSelPageEmpty5}{\showpaste}
\tab{5}\spadcommand{u.s\free{u }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugTypesAnyNonePage}{ug02.ht}{The ``Any'' Domain}
\begin{chunk}{ug02.ht}
\begin{page}{ugTypesAnyNonePage}{2.6. The ``Any'' Domain}
\beginscroll

With the exception of objects of type \pspadtype{Record}, all Axiom
data structures are homogenous, that is, they hold objects all of the same
type.
If you need to get around this, you can use type \axiomType{Any}.
Using \axiomType{Any}, for example, you can create lists whose
elements are integers, rational numbers, strings, and even other lists.

\xtc{
Declare \axiom{u} to have type \axiomType{Any}.
}{
\spadpaste{u: Any\bound{uany}}
}
\xtc{
Assign a list of mixed type values to \axiom{u}
}{
\spadpaste{u := [1, 7.2, 3/2, x**2, "wally"]\free{uany}\bound{u}}
}
\xtc{
When we ask for the elements, Axiom displays these types.
}{
\spadpaste{u.1 \free{u}}
}
\xtc{
Actually, these objects belong to \axiomType{Any} but Axiom
automatically converts them to their natural types for you.
}{
\spadpaste{u.3 \free{u}}
}
\xtc{
Since type \axiomType{Any} can be anything,
it can only belong to type \axiomType{Type}.
Therefore it cannot be used in algebraic domains.
}{
\spadpaste{v : Matrix(Any)}
}

Perhaps you are wondering how Axiom internally represents
objects of type \axiomType{Any}.
An object of type \axiomType{Any} consists not only a data part
representing its normal value, but also a type part (a {\it badge}) giving
its type.
For example, the value \axiom{1} of type \axiomType{PositiveInteger} as an
object of type \axiomType{Any} internally looks like
\axiom{[1,\axiomType{PositiveInteger()}]}.

%When should you use \axiomType{Any} instead of a \pspadtype{Union} type?
%Can you plan ahead?
%For a \pspadtype{Union}, you must know in advance exactly which types you
%are
%\index{union!vs. Any@{vs. \protect\nonLibAxiomType{Any}}}
%going to allow.
%For \axiomType{Any}, anything that comes along can be accommodated.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugTypesAnyNonePagePatch1}
\begin{paste}{ugTypesAnyNonePageFull1}{ugTypesAnyNonePageEmpty1}
\pastebutton{ugTypesAnyNonePageFull1}{\hidepaste}
\tab{5}\spadcommand{u: Any\bound{uany }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesAnyNonePageEmpty1}
\begin{paste}{ugTypesAnyNonePageEmpty1}{ugTypesAnyNonePagePatch1}
\pastebutton{ugTypesAnyNonePageEmpty1}{\showpaste}
\tab{5}\spadcommand{u: Any\bound{uany }}
\end{paste}\end{patch}

\begin{patch}{ugTypesAnyNonePagePatch2}
\begin{paste}{ugTypesAnyNonePageFull2}{ugTypesAnyNonePageEmpty2}
\pastebutton{ugTypesAnyNonePageFull2}{\hidepaste}
\tab{5}\spadcommand{u := [1, 7.2, 3/2, x**2, "wally"]\free{uany }\bound{u }}
\indentrel{3}\begin{verbatim}
               3  2
   (2)  [1,7.2,Ä,x ,"wally"]
               2
                                         Type: List Any
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesAnyNonePageEmpty2}
\begin{paste}{ugTypesAnyNonePageEmpty2}{ugTypesAnyNonePagePatch2}
\pastebutton{ugTypesAnyNonePageEmpty2}{\showpaste}
\tab{5}\spadcommand{u := [1, 7.2, 3/2, x**2, "wally"]\free{uany }\bound{u }}
\end{paste}\end{patch}

\begin{patch}{ugTypesAnyNonePagePatch3}
\begin{paste}{ugTypesAnyNonePageFull3}{ugTypesAnyNonePageEmpty3}
\pastebutton{ugTypesAnyNonePageFull3}{\hidepaste}
\tab{5}\spadcommand{u.1\free{u }}
\indentrel{3}\begin{verbatim}
   (3)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesAnyNonePageEmpty3}
\begin{paste}{ugTypesAnyNonePageEmpty3}{ugTypesAnyNonePagePatch3}
\pastebutton{ugTypesAnyNonePageEmpty3}{\showpaste}
\tab{5}\spadcommand{u.1\free{u }}
\end{paste}\end{patch}

\begin{patch}{ugTypesAnyNonePagePatch4}
\begin{paste}{ugTypesAnyNonePageFull4}{ugTypesAnyNonePageEmpty4}
\pastebutton{ugTypesAnyNonePageFull4}{\hidepaste}
\tab{5}\spadcommand{u.3\free{u }}
\indentrel{3}\begin{verbatim}
        3
   (4)  Ä
        2
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesAnyNonePageEmpty4}
\begin{paste}{ugTypesAnyNonePageEmpty4}{ugTypesAnyNonePagePatch4}
\pastebutton{ugTypesAnyNonePageEmpty4}{\showpaste}
\tab{5}\spadcommand{u.3\free{u }}
\end{paste}\end{patch}

\begin{patch}{ugTypesAnyNonePagePatch5}
\begin{paste}{ugTypesAnyNonePageFull5}{ugTypesAnyNonePageEmpty5}
\pastebutton{ugTypesAnyNonePageFull5}{\hidepaste}
\tab{5}\spadcommand{v : Matrix(Any)}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesAnyNonePageEmpty5}
\begin{paste}{ugTypesAnyNonePageEmpty5}{ugTypesAnyNonePagePatch5}
\pastebutton{ugTypesAnyNonePageEmpty5}{\showpaste}
\tab{5}\spadcommand{v : Matrix(Any)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugTypesConvertPage}{ug02.ht}{Conversion}
\pagepic{ps/v71ugtypesconvertpage.eps}{ugTypesConvertPage}{0.50}
\pagefrom{Complex}{ComplexXmpPage}
\pageto{The Basic Idea}{ugTypesBasicPage}
\begin{chunk}{ug02.ht}
\begin{page}{ugTypesConvertPage}{2.7. Conversion}
\beginscroll
%
\beginImportant
\spadglossSee{Conversion}{conversion}
is the process of changing an object of one type
into an object of another type.
The syntax for conversion is:
\centerline{{{\it object} {\tt ::} {\it newType}}}
\endImportant

\xtc{
By default, \axiom{3} has the type \axiomType{PositiveInteger}.
}{
\spadpaste{3}
}
\xtc{
We can change this into an object of type \axiomType{Fraction Integer}
by using \axiomSyntax{::}.
}{
\spadpaste{3 :: Fraction Integer}
}

A \spadgloss{coercion} is a special kind of conversion that Axiom is
allowed to do automatically when you enter an expression.
Coercions are usually somewhat safer than more general conversions.
The Axiom library contains operations called
\axiomFun{coerce} and \axiomFun{convert}.
Only the \axiomFun{coerce} operations can be used by the
interpreter to change an object into an object of another type unless
you explicitly use a \axiomSyntax{::}.

By now you will be quite familiar with what types and modes look like.
It is useful to think of a type or mode as a pattern
for what you want the result to be.
\xtc{
Let's start with a square matrix of polynomials with complex rational 
number coefficients.
}{
\spadpaste{m : SquareMatrix(2,POLY COMPLEX FRAC INT) \bound{mdec}}
}
\xtc{
}{
\spadpaste{
m := matrix [[x-3/4*\%i,z*y**2+1/2],[3/7*\%i*y**4 - x,12-\%i*9/5]] 
\bound{m}\free{mdec}}
}
\xtc{
We first want to interchange the \axiomType{Complex} and
\axiomType{Fraction} layers.
We do the conversion by doing the interchange in the type expression.
}{
\spadpaste{m1 := m :: SquareMatrix(2,POLY FRAC COMPLEX INT) 
\free{m}\bound{m1}}
}
\xtc{
Interchange the \axiomType{Polynomial} and the
\axiomType{Fraction} levels.
}{
\spadpaste{m2 := m1 :: SquareMatrix(2,FRAC POLY COMPLEX INT) 
\free{m1}\bound{m2}}
}
\xtc{
Interchange the \axiomType{Polynomial} and the
\axiomType{Complex} levels.
}{
\spadpaste{m3 := m2 :: SquareMatrix(2,FRAC COMPLEX POLY INT) 
\free{m2}\bound{m3}}
}

All the entries have changed types, although in comparing the
last two results only the entry in the lower left corner looks different.
We did all the intermediate steps to show you what Axiom can do.

\xtc{
In fact, we could have combined all these into one conversion.
}{
\spadpaste{m :: SquareMatrix(2,FRAC COMPLEX POLY INT) \free{m}}
}

There are times when Axiom is not be able to do the conversion
in one step.
You may need to break up the transformation into several conversions
in order to get an object of the desired type.

We cannot move either \axiomType{Fraction} or \axiomType{Complex}
above (or to the left of, depending on how you look at it)
\axiomType{SquareMatrix} because each of these levels requires that its
argument type have commutative multiplication, whereas
\axiomType{SquareMatrix} does not.\footnote{\axiomType{Fraction} requires
that its argument belong to the category \axiomType{IntegralDomain} and
\axiomType{Complex} requires that its argument belong to
\axiomType{CommutativeRing}. See
\downlink{``The Basic Idea''}{ugTypesBasicPage} 
in Section 2.1\ignore{ugTypesBasic}
for a brief discussion of categories.}
The \axiomType{Integer} level did not move anywhere
because it does not allow any arguments.
We also did not move the \axiomType{SquareMatrix} part anywhere, but
we could have.
\xtc{
Recall that \axiom{m} looks like this.
}{
\spadpaste{m \free{m}}
}
\xtc{
If we want a polynomial with matrix coefficients rather than a matrix
with polynomial entries, we can just do the conversion.
}{
\spadpaste{m :: POLY SquareMatrix(2,COMPLEX FRAC INT) \free{m}}
}
\xtc{
We have not yet used modes for any conversions.
Modes are a great shorthand for indicating the type of the
object you want.
Instead of using the long type expression in the
last example, we could have simply said this.
}{
\spadpaste{m :: POLY ? \free{m}}
}
\xtc{
We can also indicate more structure if we want the entries
of the matrices to be fractions.
}{
\spadpaste{m :: POLY SquareMatrix(2,FRAC ?) \free{m}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugTypesConvertPagePatch1}
\begin{paste}{ugTypesConvertPageFull1}{ugTypesConvertPageEmpty1}
\pastebutton{ugTypesConvertPageFull1}{\hidepaste}
\tab{5}\spadcommand{3}
\indentrel{3}\begin{verbatim}
   (1)  3
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPageEmpty1}
\begin{paste}{ugTypesConvertPageEmpty1}{ugTypesConvertPagePatch1}
\pastebutton{ugTypesConvertPageEmpty1}{\showpaste}
\tab{5}\spadcommand{3}
\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPagePatch2}
\begin{paste}{ugTypesConvertPageFull2}{ugTypesConvertPageEmpty2}
\pastebutton{ugTypesConvertPageFull2}{\hidepaste}
\tab{5}\spadcommand{3 :: Fraction Integer}
\indentrel{3}\begin{verbatim}
   (2)  3
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPageEmpty2}
\begin{paste}{ugTypesConvertPageEmpty2}{ugTypesConvertPagePatch2}
\pastebutton{ugTypesConvertPageEmpty2}{\showpaste}
\tab{5}\spadcommand{3 :: Fraction Integer}
\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPagePatch3}
\begin{paste}{ugTypesConvertPageFull3}{ugTypesConvertPageEmpty3}
\pastebutton{ugTypesConvertPageFull3}{\hidepaste}
\tab{5}\spadcommand{m : SquareMatrix(2,POLY COMPLEX FRAC INT)\bound{mdec }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPageEmpty3}
\begin{paste}{ugTypesConvertPageEmpty3}{ugTypesConvertPagePatch3}
\pastebutton{ugTypesConvertPageEmpty3}{\showpaste}
\tab{5}\spadcommand{m : SquareMatrix(2,POLY COMPLEX FRAC INT)\bound{mdec }}
\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPagePatch4}
\begin{paste}{ugTypesConvertPageFull4}{ugTypesConvertPageEmpty4}
\pastebutton{ugTypesConvertPageFull4}{\hidepaste}
\tab{5}\spadcommand{m := matrix [[x-3/4*\%i,z*y**2+1/2],[3/7*\%i*y**4 - x,12-\%i*9/5]]\bound{m }\free{mdec }}
\indentrel{3}\begin{verbatim}
        Ú     3         2    1 ¿
        ³ x - Ä %i     y z + Ä ³
        ³     4              2 ³
   (4)  ³                      ³
        ³3     4           9   ³
        ³Ä %i y  - x  12 - Ä %i³
        À7                 5   Ù
Type: SquareMatrix(2,Polynomial Complex Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPageEmpty4}
\begin{paste}{ugTypesConvertPageEmpty4}{ugTypesConvertPagePatch4}
\pastebutton{ugTypesConvertPageEmpty4}{\showpaste}
\tab{5}\spadcommand{m := matrix [[x-3/4*\%i,z*y**2+1/2],[3/7*\%i*y**4 - x,12-\%i*9/5]]\bound{m }\free{mdec }}
\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPagePatch5}
\begin{paste}{ugTypesConvertPageFull5}{ugTypesConvertPageEmpty5}
\pastebutton{ugTypesConvertPageFull5}{\hidepaste}
\tab{5}\spadcommand{m1 := m :: SquareMatrix(2,POLY FRAC COMPLEX INT)\free{m }\bound{m1 }}
\indentrel{3}\begin{verbatim}
        Ú     3%i     2    1 ¿
        ³ x - ÄÄÄ    y z + Ä ³
        ³      4           2 ³
   (5)  ³                    ³
        ³3%i  4      60 - 9%i³
        ³ÄÄÄ y  - x  ÄÄÄÄÄÄÄÄ³
        À 7              5   Ù
Type: SquareMatrix(2,Polynomial Fraction Complex Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPageEmpty5}
\begin{paste}{ugTypesConvertPageEmpty5}{ugTypesConvertPagePatch5}
\pastebutton{ugTypesConvertPageEmpty5}{\showpaste}
\tab{5}\spadcommand{m1 := m :: SquareMatrix(2,POLY FRAC COMPLEX INT)\free{m }\bound{m1 }}
\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPagePatch6}
\begin{paste}{ugTypesConvertPageFull6}{ugTypesConvertPageEmpty6}
\pastebutton{ugTypesConvertPageFull6}{\hidepaste}
\tab{5}\spadcommand{m2 := m1 :: SquareMatrix(2,FRAC POLY COMPLEX INT)\free{m1 }\bound{m2 }}
\indentrel{3}\begin{verbatim}
        Ú               2     ¿
        ³ 4x - 3%i    2y z + 1³
        ³ ÄÄÄÄÄÄÄÄ    ÄÄÄÄÄÄÄÄ³
        ³     4           2   ³
   (6)  ³                     ³
        ³     4               ³
        ³3%i y  - 7x  60 - 9%i³
        ³ÄÄÄÄÄÄÄÄÄÄÄ  ÄÄÄÄÄÄÄÄ³
        À     7           5   Ù
Type: SquareMatrix(2,Fraction Polynomial Complex Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPageEmpty6}
\begin{paste}{ugTypesConvertPageEmpty6}{ugTypesConvertPagePatch6}
\pastebutton{ugTypesConvertPageEmpty6}{\showpaste}
\tab{5}\spadcommand{m2 := m1 :: SquareMatrix(2,FRAC POLY COMPLEX INT)\free{m1 }\bound{m2 }}
\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPagePatch7}
\begin{paste}{ugTypesConvertPageFull7}{ugTypesConvertPageEmpty7}
\pastebutton{ugTypesConvertPageFull7}{\hidepaste}
\tab{5}\spadcommand{m3 := m2 :: SquareMatrix(2,FRAC COMPLEX POLY INT)\free{m2 }\bound{m3 }}
\indentrel{3}\begin{verbatim}
        Ú                2     ¿
        ³  4x - 3%i    2y z + 1³
        ³  ÄÄÄÄÄÄÄÄ    ÄÄÄÄÄÄÄÄ³
        ³      4           2   ³
   (7)  ³                      ³
        ³         4            ³
        ³- 7x + 3y %i  60 - 9%i³
        ³ÄÄÄÄÄÄÄÄÄÄÄÄ  ÄÄÄÄÄÄÄÄ³
        À      7           5   Ù
Type: SquareMatrix(2,Fraction Complex Polynomial Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPageEmpty7}
\begin{paste}{ugTypesConvertPageEmpty7}{ugTypesConvertPagePatch7}
\pastebutton{ugTypesConvertPageEmpty7}{\showpaste}
\tab{5}\spadcommand{m3 := m2 :: SquareMatrix(2,FRAC COMPLEX POLY INT)\free{m2 }\bound{m3 }}
\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPagePatch8}
\begin{paste}{ugTypesConvertPageFull8}{ugTypesConvertPageEmpty8}
\pastebutton{ugTypesConvertPageFull8}{\hidepaste}
\tab{5}\spadcommand{m :: SquareMatrix(2,FRAC COMPLEX POLY INT)\free{m }}
\indentrel{3}\begin{verbatim}
        Ú                2     ¿
        ³  4x - 3%i    2y z + 1³
        ³  ÄÄÄÄÄÄÄÄ    ÄÄÄÄÄÄÄÄ³
        ³      4           2   ³
   (8)  ³                      ³
        ³         4            ³
        ³- 7x + 3y %i  60 - 9%i³
        ³ÄÄÄÄÄÄÄÄÄÄÄÄ  ÄÄÄÄÄÄÄÄ³
        À      7           5   Ù
Type: SquareMatrix(2,Fraction Complex Polynomial Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPageEmpty8}
\begin{paste}{ugTypesConvertPageEmpty8}{ugTypesConvertPagePatch8}
\pastebutton{ugTypesConvertPageEmpty8}{\showpaste}
\tab{5}\spadcommand{m :: SquareMatrix(2,FRAC COMPLEX POLY INT)\free{m }}
\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPagePatch9}
\begin{paste}{ugTypesConvertPageFull9}{ugTypesConvertPageEmpty9}
\pastebutton{ugTypesConvertPageFull9}{\hidepaste}
\tab{5}\spadcommand{m\free{m }}
\indentrel{3}\begin{verbatim}
        Ú     3         2    1 ¿
        ³ x - Ä %i     y z + Ä ³
        ³     4              2 ³
   (9)  ³                      ³
        ³3     4           9   ³
        ³Ä %i y  - x  12 - Ä %i³
        À7                 5   Ù
Type: SquareMatrix(2,Polynomial Complex Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPageEmpty9}
\begin{paste}{ugTypesConvertPageEmpty9}{ugTypesConvertPagePatch9}
\pastebutton{ugTypesConvertPageEmpty9}{\showpaste}
\tab{5}\spadcommand{m\free{m }}
\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPagePatch10}
\begin{paste}{ugTypesConvertPageFull10}{ugTypesConvertPageEmpty10}
\pastebutton{ugTypesConvertPageFull10}{\hidepaste}
\tab{5}\spadcommand{m :: POLY SquareMatrix(2,COMPLEX FRAC INT)\free{m }}
\indentrel{3}\begin{verbatim}
   (10)
                 Ú 0    0¿
     Ú0  1¿ 2    ³       ³ 4   Ú 1   0¿
     ³    ³y z + ³3      ³y  + ³      ³x
     À0  0Ù      ³Ä %i  0³     À- 1  0Ù
                 À7      Ù
   + 
     Ú  3         1    ¿
     ³- Ä %i      Ä    ³
     ³  4         2    ³
     ³                 ³
     ³             9   ³
     ³  0     12 - Ä %i³
     À             5   Ù
Type: Polynomial SquareMatrix(2,Complex Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPageEmpty10}
\begin{paste}{ugTypesConvertPageEmpty10}{ugTypesConvertPagePatch10}
\pastebutton{ugTypesConvertPageEmpty10}{\showpaste}
\tab{5}\spadcommand{m :: POLY SquareMatrix(2,COMPLEX FRAC INT)\free{m }}
\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPagePatch11}
\begin{paste}{ugTypesConvertPageFull11}{ugTypesConvertPageEmpty11}
\pastebutton{ugTypesConvertPageFull11}{\hidepaste}
\tab{5}\spadcommand{m :: POLY ?\free{m }}
\indentrel{3}\begin{verbatim}
   (11)
                 Ú 0    0¿
     Ú0  1¿ 2    ³       ³ 4   Ú 1   0¿
     ³    ³y z + ³3      ³y  + ³      ³x
     À0  0Ù      ³Ä %i  0³     À- 1  0Ù
                 À7      Ù
   + 
     Ú  3         1    ¿
     ³- Ä %i      Ä    ³
     ³  4         2    ³
     ³                 ³
     ³             9   ³
     ³  0     12 - Ä %i³
     À             5   Ù
Type: Polynomial SquareMatrix(2,Complex Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPageEmpty11}
\begin{paste}{ugTypesConvertPageEmpty11}{ugTypesConvertPagePatch11}
\pastebutton{ugTypesConvertPageEmpty11}{\showpaste}
\tab{5}\spadcommand{m :: POLY ?\free{m }}
\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPagePatch12}
\begin{paste}{ugTypesConvertPageFull12}{ugTypesConvertPageEmpty12}
\pastebutton{ugTypesConvertPageFull12}{\hidepaste}
\tab{5}\spadcommand{m :: POLY SquareMatrix(2,FRAC ?)\free{m }}
\indentrel{3}\begin{verbatim}
   (12)
                                        Ú  3%i     1    ¿
               Ú 0   0¿                 ³- ÄÄÄ     Ä    ³
   Ú0  1¿ 2    ³      ³ 4   Ú 1   0¿    ³   4      2    ³
   ³    ³y z + ³3%i   ³y  + ³      ³x + ³               ³
   À0  0Ù      ³ÄÄÄ  0³     À- 1  0Ù    ³       60 - 9%i³
               À 7    Ù                 ³  0    ÄÄÄÄÄÄÄÄ³
                                        À           5   Ù
Type: Polynomial SquareMatrix(2,Fraction Complex Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesConvertPageEmpty12}
\begin{paste}{ugTypesConvertPageEmpty12}{ugTypesConvertPagePatch12}
\pastebutton{ugTypesConvertPageEmpty12}{\showpaste}
\tab{5}\spadcommand{m :: POLY SquareMatrix(2,FRAC ?)\free{m }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugTypesSubdomainsPage}{ug02.ht}{Subdomains Again}
\begin{chunk}{ug02.ht}
\begin{page}{ugTypesSubdomainsPage}{2.8. Subdomains Again}
\beginscroll

A \spadgloss{subdomain} \axiom{S} of a domain \axiom{D} is a domain
consisting of
\indent{4}
\beginitems
\item[1. ] those elements of \axiom{D} that satisfy some
\spadgloss{predicate} (that is, a test that returns \axiom{true} or
\axiom{false}) and
\item[2. ] a subset of the operations of \axiom{D}.
\enditems
\indent{0}
Every domain is a subdomain of itself, trivially satisfying the
membership test: \axiom{true}.

Currently, there are only two system-defined subdomains in Axiom that
receive substantial use.  \axiomType{PositiveInteger} and
\axiomType{NonNegativeInteger} are subdomains of \axiomType{Integer}.
An element \axiom{x} of \axiomType{NonNegativeInteger} is an integer
that is greater than or equal to zero, that is, satisfies \axiom{x >=
0.}  An element \axiom{x} of \axiomType{PositiveInteger} is a
nonnegative integer that is, in fact, greater than zero, that is,
satisfies \axiom{x > 0.}  Not all operations from \axiomType{Integer}
are available for these subdomains.  For example, negation and
subtraction are not provided since the subdomains are not closed under
those operations.  When you use an integer in an expression, Axiom
assigns to it the type that is the most specific subdomain whose
predicate is satisfied.
\xtc{
This is a positive integer.
}{
\spadpaste{5}
}
\xtc{
This is a nonnegative integer.
}{
\spadpaste{0}
}
\xtc{
This is neither of the above.
}{
\spadpaste{-5}
}
\xtc{
Furthermore, unless you are assigning an integer to a declared variable
or using a conversion, any integer result has as type the most
specific subdomain.
}{
\spadpaste{(-2) - (-3)}
}
\xtc{
}{
\spadpaste{0 :: Integer}
}
\xtc{
}{
\spadpaste{x : NonNegativeInteger := 5}
}

When necessary, Axiom converts an integer object into one belonging to
a less specific subdomain.  For example, in \axiom{3-2}, the arguments
to \axiomOpFrom{-}{Integer} are both elements of
\axiomType{PositiveInteger}, but this type does not provide a
subtraction operation.  Neither does \axiomType{NonNegativeInteger},
so \axiom{3} and \axiom{2} are viewed as elements of
\axiomType{Integer}, where their difference can be calculated.  The
result is \axiom{1}, which Axiom then automatically assigns the type
\axiomType{PositiveInteger}.

\xtc{
Certain operations are very sensitive to the subdomains to which their
arguments belong.
This is an element of \axiomType{PositiveInteger}.
}{
\spadpaste{2 ** 2}
}
\xtc{
This is an element of \axiomType{Fraction Integer}.
}{
\spadpaste{2 ** (-2)}
}
\xtc{
It makes sense then that this
is a list of elements of \axiomType{PositiveInteger}.
}{
\spadpaste{[10**i for i in 2..5]}
}
What should the type of \axiom{[10**(i-1) for i in 2..5]} be?
On one hand, \axiom{i-1} is always an integer greater than zero
as \axiom{i} ranges from \axiom{2} to \axiom{5} and so \axiom{10**i}
is also always a positive integer.
On the other, \axiom{i-1} is a very simple function of \axiom{i}.
Axiom does not try to analyze every such function over the
index's range of values to determine whether it is always positive
or nowhere negative.
For an arbitrary Axiom function, this analysis is not possible.

\xtc{
So, to be consistent no such analysis is done and we get this.
}{
\spadpaste{[10**(i-1) for i in 2..5]}
}
\xtc{
To get a list of elements of \axiomType{PositiveInteger} instead, you
have two choices.
You can use a conversion.
}{
\spadpaste{[10**((i-1) :: PI) for i in 2..5]}
}
\xtc{
Or you can use \axiom{pretend}.
\spadkey{pretend}
}{
\spadpaste{[10**((i-1) pretend PI) for i in 2..5]}
}

The operation \axiom{pretend} is used to defeat the Axiom
type system.
The expression \axiom{object pretend D} means ``make a new object
(without copying) of type \axiom{D} from \axiom{object}.''
If \axiom{object} were an integer and you told Axiom
to pretend it was a list, you would probably see a message about a
fatal error being caught and memory possibly being damaged.
Lists do not have the same internal representation as integers!

You use \axiom{pretend} at your peril.

\xtc{
Use \axiom{pretend} with great care!
Axiom trusts you that the value is of the specified type.
}{
\spadpaste{(2/3) pretend Complex Integer}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugTypesSubdomainsPagePatch1}
\begin{paste}{ugTypesSubdomainsPageFull1}{ugTypesSubdomainsPageEmpty1}
\pastebutton{ugTypesSubdomainsPageFull1}{\hidepaste}
\tab{5}\spadcommand{5}
\indentrel{3}\begin{verbatim}
   (1)  5
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPageEmpty1}
\begin{paste}{ugTypesSubdomainsPageEmpty1}{ugTypesSubdomainsPagePatch1}
\pastebutton{ugTypesSubdomainsPageEmpty1}{\showpaste}
\tab{5}\spadcommand{5}
\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPagePatch2}
\begin{paste}{ugTypesSubdomainsPageFull2}{ugTypesSubdomainsPageEmpty2}
\pastebutton{ugTypesSubdomainsPageFull2}{\hidepaste}
\tab{5}\spadcommand{0}
\indentrel{3}\begin{verbatim}
   (2)  0
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPageEmpty2}
\begin{paste}{ugTypesSubdomainsPageEmpty2}{ugTypesSubdomainsPagePatch2}
\pastebutton{ugTypesSubdomainsPageEmpty2}{\showpaste}
\tab{5}\spadcommand{0}
\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPagePatch3}
\begin{paste}{ugTypesSubdomainsPageFull3}{ugTypesSubdomainsPageEmpty3}
\pastebutton{ugTypesSubdomainsPageFull3}{\hidepaste}
\tab{5}\spadcommand{-5}
\indentrel{3}\begin{verbatim}
   (3)  - 5
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPageEmpty3}
\begin{paste}{ugTypesSubdomainsPageEmpty3}{ugTypesSubdomainsPagePatch3}
\pastebutton{ugTypesSubdomainsPageEmpty3}{\showpaste}
\tab{5}\spadcommand{-5}
\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPagePatch4}
\begin{paste}{ugTypesSubdomainsPageFull4}{ugTypesSubdomainsPageEmpty4}
\pastebutton{ugTypesSubdomainsPageFull4}{\hidepaste}
\tab{5}\spadcommand{(-2) - (-3)}
\indentrel{3}\begin{verbatim}
   (4)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPageEmpty4}
\begin{paste}{ugTypesSubdomainsPageEmpty4}{ugTypesSubdomainsPagePatch4}
\pastebutton{ugTypesSubdomainsPageEmpty4}{\showpaste}
\tab{5}\spadcommand{(-2) - (-3)}
\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPagePatch5}
\begin{paste}{ugTypesSubdomainsPageFull5}{ugTypesSubdomainsPageEmpty5}
\pastebutton{ugTypesSubdomainsPageFull5}{\hidepaste}
\tab{5}\spadcommand{0 :: Integer}
\indentrel{3}\begin{verbatim}
   (5)  0
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPageEmpty5}
\begin{paste}{ugTypesSubdomainsPageEmpty5}{ugTypesSubdomainsPagePatch5}
\pastebutton{ugTypesSubdomainsPageEmpty5}{\showpaste}
\tab{5}\spadcommand{0 :: Integer}
\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPagePatch6}
\begin{paste}{ugTypesSubdomainsPageFull6}{ugTypesSubdomainsPageEmpty6}
\pastebutton{ugTypesSubdomainsPageFull6}{\hidepaste}
\tab{5}\spadcommand{x : NonNegativeInteger := 5}
\indentrel{3}\begin{verbatim}
   (6)  5
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPageEmpty6}
\begin{paste}{ugTypesSubdomainsPageEmpty6}{ugTypesSubdomainsPagePatch6}
\pastebutton{ugTypesSubdomainsPageEmpty6}{\showpaste}
\tab{5}\spadcommand{x : NonNegativeInteger := 5}
\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPagePatch7}
\begin{paste}{ugTypesSubdomainsPageFull7}{ugTypesSubdomainsPageEmpty7}
\pastebutton{ugTypesSubdomainsPageFull7}{\hidepaste}
\tab{5}\spadcommand{2 ** 2}
\indentrel{3}\begin{verbatim}
   (7)  4
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPageEmpty7}
\begin{paste}{ugTypesSubdomainsPageEmpty7}{ugTypesSubdomainsPagePatch7}
\pastebutton{ugTypesSubdomainsPageEmpty7}{\showpaste}
\tab{5}\spadcommand{2 ** 2}
\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPagePatch8}
\begin{paste}{ugTypesSubdomainsPageFull8}{ugTypesSubdomainsPageEmpty8}
\pastebutton{ugTypesSubdomainsPageFull8}{\hidepaste}
\tab{5}\spadcommand{2 ** (-2)}
\indentrel{3}\begin{verbatim}
        1
   (8)  Ä
        4
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPageEmpty8}
\begin{paste}{ugTypesSubdomainsPageEmpty8}{ugTypesSubdomainsPagePatch8}
\pastebutton{ugTypesSubdomainsPageEmpty8}{\showpaste}
\tab{5}\spadcommand{2 ** (-2)}
\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPagePatch9}
\begin{paste}{ugTypesSubdomainsPageFull9}{ugTypesSubdomainsPageEmpty9}
\pastebutton{ugTypesSubdomainsPageFull9}{\hidepaste}
\tab{5}\spadcommand{[10**i for i in 2..5]}
\indentrel{3}\begin{verbatim}
   (9)  [100,1000,10000,100000]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPageEmpty9}
\begin{paste}{ugTypesSubdomainsPageEmpty9}{ugTypesSubdomainsPagePatch9}
\pastebutton{ugTypesSubdomainsPageEmpty9}{\showpaste}
\tab{5}\spadcommand{[10**i for i in 2..5]}
\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPagePatch10}
\begin{paste}{ugTypesSubdomainsPageFull10}{ugTypesSubdomainsPageEmpty10}
\pastebutton{ugTypesSubdomainsPageFull10}{\hidepaste}
\tab{5}\spadcommand{[10**(i-1) for i in 2..5]}
\indentrel{3}\begin{verbatim}
   (10)  [10,100,1000,10000]
                            Type: List Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPageEmpty10}
\begin{paste}{ugTypesSubdomainsPageEmpty10}{ugTypesSubdomainsPagePatch10}
\pastebutton{ugTypesSubdomainsPageEmpty10}{\showpaste}
\tab{5}\spadcommand{[10**(i-1) for i in 2..5]}
\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPagePatch11}
\begin{paste}{ugTypesSubdomainsPageFull11}{ugTypesSubdomainsPageEmpty11}
\pastebutton{ugTypesSubdomainsPageFull11}{\hidepaste}
\tab{5}\spadcommand{[10**((i-1) :: PI) for i in 2..5]}
\indentrel{3}\begin{verbatim}
   (11)  [10,100,1000,10000]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPageEmpty11}
\begin{paste}{ugTypesSubdomainsPageEmpty11}{ugTypesSubdomainsPagePatch11}
\pastebutton{ugTypesSubdomainsPageEmpty11}{\showpaste}
\tab{5}\spadcommand{[10**((i-1) :: PI) for i in 2..5]}
\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPagePatch12}
\begin{paste}{ugTypesSubdomainsPageFull12}{ugTypesSubdomainsPageEmpty12}
\pastebutton{ugTypesSubdomainsPageFull12}{\hidepaste}
\tab{5}\spadcommand{[10**((i-1) pretend PI) for i in 2..5]}
\indentrel{3}\begin{verbatim}
   (12)  [10,100,1000,10000]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPageEmpty12}
\begin{paste}{ugTypesSubdomainsPageEmpty12}{ugTypesSubdomainsPagePatch12}
\pastebutton{ugTypesSubdomainsPageEmpty12}{\showpaste}
\tab{5}\spadcommand{[10**((i-1) pretend PI) for i in 2..5]}
\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPagePatch13}
\begin{paste}{ugTypesSubdomainsPageFull13}{ugTypesSubdomainsPageEmpty13}
\pastebutton{ugTypesSubdomainsPageFull13}{\hidepaste}
\tab{5}\spadcommand{(2/3) pretend Complex Integer}
\indentrel{3}\begin{verbatim}
   (13)  2 + 3%i
                                  Type: Complex Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesSubdomainsPageEmpty13}
\begin{paste}{ugTypesSubdomainsPageEmpty13}{ugTypesSubdomainsPagePatch13}
\pastebutton{ugTypesSubdomainsPageEmpty13}{\showpaste}
\tab{5}\spadcommand{(2/3) pretend Complex Integer}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugTypesPkgCallPage}{ug02.ht}{Package Calling and Target Types}
\pageto{notitle}{ugTypesDeclarePage}
\pageto{notitle}{ugUserUsePage}
\begin{chunk}{ug02.ht}
\begin{page}{ugTypesPkgCallPage}{2.9. Package Calling and Target Types}
\beginscroll

Axiom works hard to figure out what you mean by an
expression without your having to qualify it with type
information.
Nevertheless, there are times when you need to help it along by
providing hints (or even orders!) to get Axiom to do what
you want.

We saw in \downlink{``Declarations''}{ugTypesDeclarePage} 
in Section 2.3\ignore{ugTypesDeclare} that 
declarations using types
and modes control the type of the results produced.
For example, we can either produce a complex object with
polynomial real and imaginary parts or a polynomial with complex
integer coefficients, depending on the declaration.

\spadglossSee{Package calling}{package call} is how you tell
Axiom to use a particular function from a particular part of
the library.

\xtc{
Use the \axiomOpFrom{/}{Fraction} from \axiomType{Fraction Integer}
to create a fraction of two integers.
}{
\spadpaste{2/3}
}
\xtc{
If we wanted a floating point number, we can say ``use the
\axiomOpFrom{/}{Float} in \axiomType{Float}.''
}{
\spadpaste{(2/3)\$Float}
}
\xtc{
Perhaps we actually wanted a fraction of complex integers.
}{
\spadpaste{(2/3)\$Fraction(Complex Integer)}
}

In each case, Axiom used the indicated operations, sometimes
first needing to convert the two integers into objects of an
appropriate type.
In these examples, \axiomOpFrom{/}{Fraction} is written as an
infix operator.

\beginImportant
To use package calling with an infix operator, use the
following syntax:
\centerline{{{\tt ( \subscriptIt{arg}{1} {\it op} 
\subscriptIt{arg}{1} )\${\it type} }}}
\endImportant

We used, for example, \axiom{(2/3)\$Float}.  The expression \axiom{2 +
3 + 4} is equivalent to \axiom{(2+3) + 4.}  Therefore in the
expression \axiom{(2 + 3 + 4)\$Float} the second \axiomOp{+} comes
from the \axiomType{Float} domain.  Can you guess whether the first
\axiomOp{+} comes from \axiomType{Integer} or
\axiomType{Float}?\footnote{\axiomType{Float}, because the package
call causes Axiom to convert \axiom{(2 + 3)} and \axiom{4} to type
\axiomType{Float}.  Before the sum is converted, it is given a target
type (see below) of \axiomType{Float} by Axiom and then evaluated.
The target type causes the \axiomOp{+} from \axiomType{Float} to be
used.}

\beginImportant
For an operator written before its arguments, you must use
parentheses around the arguments (even if there is only one),
and follow the closing parenthesis by a \axiomSyntax{\$}
and then the type.
\centerline{{{\tt {\it fun} ( \subscriptIt{arg}{1}, 
\subscriptIt{arg}{1}, \ldots, \subscriptIt{arg}{N} )\${\it type}}}}
\endImportant

For example, to call the ``minimum'' function from \axiomType{DoubleFloat}
on two integers, you could write \axiom{min(4,89)\$DoubleFloat}.
Another use of package calling is to tell Axiom to use a library
function rather than a function you defined.
We discuss this in 
\downlink{``How Axiom Determines What Function to Use''}{ugUserUsePage} 
in Section 6.9\ignore{ugUserUse}.

Sometimes rather than specifying where an operation comes from, you just
want to say what type the result should be.
We say that you provide
a
\spadglossSee{target type}{target} for the expression.
Instead of using a \axiomSyntax{\$}, use a \axiomSyntax{@} to specify
the requested target type.
Otherwise, the syntax is the same.
Note that giving a target type is not the same as explicitly doing a
conversion.
The first says ``try to pick operations so that the result has
such-and-such a type.''
The second says ``compute the result and then convert to an object of
such-and-such a type.''

\xtc{
Sometimes it makes sense, as in this expression,
to say ``choose the operations in this expression so that
the final result is a \axiomType{Float}.''
}{
\spadpaste{(2/3)@Float}
}

Here we used \axiomSyntax{@} to say that the target type of the
left-hand side was \axiomType{Float}.
In this simple case, there was no real difference
between using \axiomSyntax{\$} and \axiomSyntax{@}.
You can see the difference if you try the following.
\xtc{
This says to try to choose \axiomOp{+} so that the result is
a string.
Axiom cannot do this.
}{
\spadpaste{(2 + 3)@String}
}
\xtc{
This says to get the \axiomOp{+} from \axiomType{String} and apply
it to the two integers.
Axiom also cannot do this because there is no \axiomOp{+}
exported by \axiomType{String}.
}{
\spadpaste{(2 + 3)\$String}
}
(By the way, the operation \axiomFunFrom{concat}{String} or juxtaposition
is used to concatenate two strings.)

When we have more than one operation in an expression, the
difference is even more evident.
The following two expressions show that Axiom uses the
target type to create different objects.
The \axiomOp{+}, \axiomOp{*} and \axiomOp{**} operations are all
chosen so that an object of the correct final type is created.

\xtc{
This says that the operations should be chosen so
that the result is a \axiomType{Complex} object.
}{
\spadpaste{((x + y * \%i)**2)@(Complex Polynomial Integer)}
}
\xtc{
This says that the operations should be chosen so
that the result is a \axiomType{Polynomial} object.
}{
\spadpaste{((x + y * \%i)**2)@(Polynomial Complex Integer)}
}
\xtc{
What do you think might happen if we left off all
target type and package call information in this last example?
}{
\spadpaste{(x + y * \%i)**2 \bound{prevC}}
}
\xtc{
We can convert it to \axiomType{Complex} as an afterthought.
But this is more work than just saying making what we want in the first
place.
}{
\spadpaste{\% :: Complex ? \free{prevC}}
}

Finally, another use of package calling is to qualify fully an
operation that is passed as an argument to a function.

\xtc{
Start with a small matrix of integers.
}{
\spadpaste{h := matrix [[8,6],[-4,9]] \bound{h}}
}
%
\xtc{
We want to produce a new matrix that has for entries the multiplicative
inverses of the entries of \axiom{h}.
One way to do this is by calling
\axiomFunFrom{map}{MatrixCategoryFunctions2} with the
\axiomFunFrom{inv}{Fraction} function from \axiomType{Fraction (Integer)}.
}{
\spadpaste{map(inv\$Fraction(Integer),h) \free{h}}
}
\xtc{
We could have been a bit less verbose and used abbreviations.
}{
\spadpaste{map(inv\$FRAC(INT),h) \free{h}\bound{h1}}
}
%
\xtc{
As it turns out, Axiom is smart enough to know what we mean
anyway.
We can just say this.
}{
\spadpaste{map(inv,h) \free{h}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugTypesPkgCallPagePatch1}
\begin{paste}{ugTypesPkgCallPageFull1}{ugTypesPkgCallPageEmpty1}
\pastebutton{ugTypesPkgCallPageFull1}{\hidepaste}
\tab{5}\spadcommand{2/3}
\indentrel{3}\begin{verbatim}
        2
   (1)  Ä
        3
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPageEmpty1}
\begin{paste}{ugTypesPkgCallPageEmpty1}{ugTypesPkgCallPagePatch1}
\pastebutton{ugTypesPkgCallPageEmpty1}{\showpaste}
\tab{5}\spadcommand{2/3}
\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPagePatch2}
\begin{paste}{ugTypesPkgCallPageFull2}{ugTypesPkgCallPageEmpty2}
\pastebutton{ugTypesPkgCallPageFull2}{\hidepaste}
\tab{5}\spadcommand{(2/3)$Float}
\indentrel{3}\begin{verbatim}
   (2)  0.6666666666 6666666667
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPageEmpty2}
\begin{paste}{ugTypesPkgCallPageEmpty2}{ugTypesPkgCallPagePatch2}
\pastebutton{ugTypesPkgCallPageEmpty2}{\showpaste}
\tab{5}\spadcommand{(2/3)$Float}
\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPagePatch3}
\begin{paste}{ugTypesPkgCallPageFull3}{ugTypesPkgCallPageEmpty3}
\pastebutton{ugTypesPkgCallPageFull3}{\hidepaste}
\tab{5}\spadcommand{(2/3)$Fraction(Complex Integer)}
\indentrel{3}\begin{verbatim}
        2
   (3)  Ä
        3
                         Type: Fraction Complex Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPageEmpty3}
\begin{paste}{ugTypesPkgCallPageEmpty3}{ugTypesPkgCallPagePatch3}
\pastebutton{ugTypesPkgCallPageEmpty3}{\showpaste}
\tab{5}\spadcommand{(2/3)$Fraction(Complex Integer)}
\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPagePatch4}
\begin{paste}{ugTypesPkgCallPageFull4}{ugTypesPkgCallPageEmpty4}
\pastebutton{ugTypesPkgCallPageFull4}{\hidepaste}
\tab{5}\spadcommand{(2/3)@Float}
\indentrel{3}\begin{verbatim}
   (4)  0.6666666666 6666666667
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPageEmpty4}
\begin{paste}{ugTypesPkgCallPageEmpty4}{ugTypesPkgCallPagePatch4}
\pastebutton{ugTypesPkgCallPageEmpty4}{\showpaste}
\tab{5}\spadcommand{(2/3)@Float}
\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPagePatch5}
\begin{paste}{ugTypesPkgCallPageFull5}{ugTypesPkgCallPageEmpty5}
\pastebutton{ugTypesPkgCallPageFull5}{\hidepaste}
\tab{5}\spadcommand{(2 + 3)@String}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPageEmpty5}
\begin{paste}{ugTypesPkgCallPageEmpty5}{ugTypesPkgCallPagePatch5}
\pastebutton{ugTypesPkgCallPageEmpty5}{\showpaste}
\tab{5}\spadcommand{(2 + 3)@String}
\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPagePatch6}
\begin{paste}{ugTypesPkgCallPageFull6}{ugTypesPkgCallPageEmpty6}
\pastebutton{ugTypesPkgCallPageFull6}{\hidepaste}
\tab{5}\spadcommand{(2 + 3)$String}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPageEmpty6}
\begin{paste}{ugTypesPkgCallPageEmpty6}{ugTypesPkgCallPagePatch6}
\pastebutton{ugTypesPkgCallPageEmpty6}{\showpaste}
\tab{5}\spadcommand{(2 + 3)$String}
\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPagePatch7}
\begin{paste}{ugTypesPkgCallPageFull7}{ugTypesPkgCallPageEmpty7}
\pastebutton{ugTypesPkgCallPageFull7}{\hidepaste}
\tab{5}\spadcommand{((x + y * \%i)**2)@(Complex Polynomial Integer)}
\indentrel{3}\begin{verbatim}
           2    2
   (5)  - y  + x  + 2x y %i
                       Type: Complex Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPageEmpty7}
\begin{paste}{ugTypesPkgCallPageEmpty7}{ugTypesPkgCallPagePatch7}
\pastebutton{ugTypesPkgCallPageEmpty7}{\showpaste}
\tab{5}\spadcommand{((x + y * \%i)**2)@(Complex Polynomial Integer)}
\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPagePatch8}
\begin{paste}{ugTypesPkgCallPageFull8}{ugTypesPkgCallPageEmpty8}
\pastebutton{ugTypesPkgCallPageFull8}{\hidepaste}
\tab{5}\spadcommand{((x + y * \%i)**2)@(Polynomial Complex Integer)}
\indentrel{3}\begin{verbatim}
           2              2
   (6)  - y  + 2%i x y + x
                       Type: Polynomial Complex Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPageEmpty8}
\begin{paste}{ugTypesPkgCallPageEmpty8}{ugTypesPkgCallPagePatch8}
\pastebutton{ugTypesPkgCallPageEmpty8}{\showpaste}
\tab{5}\spadcommand{((x + y * \%i)**2)@(Polynomial Complex Integer)}
\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPagePatch9}
\begin{paste}{ugTypesPkgCallPageFull9}{ugTypesPkgCallPageEmpty9}
\pastebutton{ugTypesPkgCallPageFull9}{\hidepaste}
\tab{5}\spadcommand{(x + y * \%i)**2\bound{prevC }}
\indentrel{3}\begin{verbatim}
           2              2
   (7)  - y  + 2%i x y + x
                       Type: Polynomial Complex Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPageEmpty9}
\begin{paste}{ugTypesPkgCallPageEmpty9}{ugTypesPkgCallPagePatch9}
\pastebutton{ugTypesPkgCallPageEmpty9}{\showpaste}
\tab{5}\spadcommand{(x + y * \%i)**2\bound{prevC }}
\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPagePatch10}
\begin{paste}{ugTypesPkgCallPageFull10}{ugTypesPkgCallPageEmpty10}
\pastebutton{ugTypesPkgCallPageFull10}{\hidepaste}
\tab{5}\spadcommand{\% :: Complex ?\free{prevC }}
\indentrel{3}\begin{verbatim}
           2    2
   (8)  - y  + x  + 2x y %i
                       Type: Complex Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPageEmpty10}
\begin{paste}{ugTypesPkgCallPageEmpty10}{ugTypesPkgCallPagePatch10}
\pastebutton{ugTypesPkgCallPageEmpty10}{\showpaste}
\tab{5}\spadcommand{\% :: Complex ?\free{prevC }}
\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPagePatch11}
\begin{paste}{ugTypesPkgCallPageFull11}{ugTypesPkgCallPageEmpty11}
\pastebutton{ugTypesPkgCallPageFull11}{\hidepaste}
\tab{5}\spadcommand{h := matrix [[8,6],[-4,9]]\bound{h }}
\indentrel{3}\begin{verbatim}
        Ú 8   6¿
   (9)  ³      ³
        À- 4  9Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPageEmpty11}
\begin{paste}{ugTypesPkgCallPageEmpty11}{ugTypesPkgCallPagePatch11}
\pastebutton{ugTypesPkgCallPageEmpty11}{\showpaste}
\tab{5}\spadcommand{h := matrix [[8,6],[-4,9]]\bound{h }}
\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPagePatch12}
\begin{paste}{ugTypesPkgCallPageFull12}{ugTypesPkgCallPageEmpty12}
\pastebutton{ugTypesPkgCallPageFull12}{\hidepaste}
\tab{5}\spadcommand{map(inv$Fraction(Integer),h)\free{h }}
\indentrel{3}\begin{verbatim}
         Ú 1   1¿
         ³ Ä   Ä³
         ³ 8   6³
   (10)  ³      ³
         ³  1  1³
         ³- Ä  Ä³
         À  4  9Ù
                          Type: Matrix Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPageEmpty12}
\begin{paste}{ugTypesPkgCallPageEmpty12}{ugTypesPkgCallPagePatch12}
\pastebutton{ugTypesPkgCallPageEmpty12}{\showpaste}
\tab{5}\spadcommand{map(inv$Fraction(Integer),h)\free{h }}
\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPagePatch13}
\begin{paste}{ugTypesPkgCallPageFull13}{ugTypesPkgCallPageEmpty13}
\pastebutton{ugTypesPkgCallPageFull13}{\hidepaste}
\tab{5}\spadcommand{map(inv$FRAC(INT),h)\free{h }\bound{h1 }}
\indentrel{3}\begin{verbatim}
         Ú 1   1¿
         ³ Ä   Ä³
         ³ 8   6³
   (11)  ³      ³
         ³  1  1³
         ³- Ä  Ä³
         À  4  9Ù
                          Type: Matrix Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPageEmpty13}
\begin{paste}{ugTypesPkgCallPageEmpty13}{ugTypesPkgCallPagePatch13}
\pastebutton{ugTypesPkgCallPageEmpty13}{\showpaste}
\tab{5}\spadcommand{map(inv$FRAC(INT),h)\free{h }\bound{h1 }}
\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPagePatch14}
\begin{paste}{ugTypesPkgCallPageFull14}{ugTypesPkgCallPageEmpty14}
\pastebutton{ugTypesPkgCallPageFull14}{\hidepaste}
\tab{5}\spadcommand{map(inv,h)\free{h }}
\indentrel{3}\begin{verbatim}
         Ú 1   1¿
         ³ Ä   Ä³
         ³ 8   6³
   (12)  ³      ³
         ³  1  1³
         ³- Ä  Ä³
         À  4  9Ù
                          Type: Matrix Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesPkgCallPageEmpty14}
\begin{paste}{ugTypesPkgCallPageEmpty14}{ugTypesPkgCallPagePatch14}
\pastebutton{ugTypesPkgCallPageEmpty14}{\showpaste}
\tab{5}\spadcommand{map(inv,h)\free{h }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugTypesResolvePage}{ug02.ht}{Resolving Types}
\begin{chunk}{ug02.ht}
\begin{page}{ugTypesResolvePage}{2.10. Resolving Types}
\beginscroll

In this section we briefly describe an internal process by which
Axiom determines a type to which two objects of possibly
different types can be converted.
We do this to give you further insight into how Axiom takes
your input, analyzes it, and produces a result.

What happens when you enter \axiom{x + 1} to Axiom?
Let's look at what you get from the two terms of this expression.

\xtc{
This is a symbolic object whose type indicates the name.
}{
\spadpaste{x}
}
\xtc{
This is a positive integer.
}{
\spadpaste{1}
}

There are no operations in \axiomType{PositiveInteger} that add
positive integers to objects of type \axiomType{Variable(x)} nor
are there any in \axiomType{Variable(x)}.
Before it can add the two parts, Axiom must come up with
a common type to which both \axiom{x} and \axiom{1} can be
converted.
We say that Axiom must {\it resolve} the two types
into a common type.
In this example, the common type is \axiomType{Polynomial(Integer)}.

\xtc{
Once this is determined, both parts are converted into polynomials,
and the addition operation from \axiomType{Polynomial(Integer)} is used
to get the answer.
}{
\spadpaste{x + 1}
}
\xtc{
Axiom can always resolve two types: if nothing resembling
the original types can be found, then \axiomType{Any} is be used.
This is fine and useful in some cases.
}{
\spadpaste{["string",3.14159]}
}
\xtc{
In other cases objects of type \axiomType{Any} can't be used
by the operations you specified.
}{
\spadpaste{"string" + 3.14159}
}
Although this example was contrived, your expressions may need
to be qualified slightly to help Axiom resolve the
types involved.
You may need to declare a few variables, do some package calling,
provide some target type information or do some explicit
conversions.

We suggest that you just enter the expression you want evaluated and
see what Axiom does.
We think you will be impressed with its ability to ``do what I
mean.''
If Axiom is still being obtuse, give it some hints.
As you work with Axiom, you will learn where it needs a
little help to analyze quickly and perform your computations.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugTypesResolvePagePatch1}
\begin{paste}{ugTypesResolvePageFull1}{ugTypesResolvePageEmpty1}
\pastebutton{ugTypesResolvePageFull1}{\hidepaste}
\tab{5}\spadcommand{x}
\indentrel{3}\begin{verbatim}
   (1)  x
                                       Type: Variable x
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesResolvePageEmpty1}
\begin{paste}{ugTypesResolvePageEmpty1}{ugTypesResolvePagePatch1}
\pastebutton{ugTypesResolvePageEmpty1}{\showpaste}
\tab{5}\spadcommand{x}
\end{paste}\end{patch}

\begin{patch}{ugTypesResolvePagePatch2}
\begin{paste}{ugTypesResolvePageFull2}{ugTypesResolvePageEmpty2}
\pastebutton{ugTypesResolvePageFull2}{\hidepaste}
\tab{5}\spadcommand{1}
\indentrel{3}\begin{verbatim}
   (2)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesResolvePageEmpty2}
\begin{paste}{ugTypesResolvePageEmpty2}{ugTypesResolvePagePatch2}
\pastebutton{ugTypesResolvePageEmpty2}{\showpaste}
\tab{5}\spadcommand{1}
\end{paste}\end{patch}

\begin{patch}{ugTypesResolvePagePatch3}
\begin{paste}{ugTypesResolvePageFull3}{ugTypesResolvePageEmpty3}
\pastebutton{ugTypesResolvePageFull3}{\hidepaste}
\tab{5}\spadcommand{x + 1}
\indentrel{3}\begin{verbatim}
   (3)  x + 1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesResolvePageEmpty3}
\begin{paste}{ugTypesResolvePageEmpty3}{ugTypesResolvePagePatch3}
\pastebutton{ugTypesResolvePageEmpty3}{\showpaste}
\tab{5}\spadcommand{x + 1}
\end{paste}\end{patch}

\begin{patch}{ugTypesResolvePagePatch4}
\begin{paste}{ugTypesResolvePageFull4}{ugTypesResolvePageEmpty4}
\pastebutton{ugTypesResolvePageFull4}{\hidepaste}
\tab{5}\spadcommand{["string",3.14159]}
\indentrel{3}\begin{verbatim}
   (4)  ["string",3.14159]
                                         Type: List Any
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesResolvePageEmpty4}
\begin{paste}{ugTypesResolvePageEmpty4}{ugTypesResolvePagePatch4}
\pastebutton{ugTypesResolvePageEmpty4}{\showpaste}
\tab{5}\spadcommand{["string",3.14159]}
\end{paste}\end{patch}

\begin{patch}{ugTypesResolvePagePatch5}
\begin{paste}{ugTypesResolvePageFull5}{ugTypesResolvePageEmpty5}
\pastebutton{ugTypesResolvePageFull5}{\hidepaste}
\tab{5}\spadcommand{"string" + 3.14159}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesResolvePageEmpty5}
\begin{paste}{ugTypesResolvePageEmpty5}{ugTypesResolvePagePatch5}
\pastebutton{ugTypesResolvePageEmpty5}{\showpaste}
\tab{5}\spadcommand{"string" + 3.14159}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugTypesExposePage}{ug02.ht}{Exposing Domains and Packages}
\pageto{notitle}{ugTypesPkgCallPage}
\pageto{notitle}{ugUserTrianglePage}
\pageto{notitle}{ugSysCmdframePage}
\begin{chunk}{ug02.ht}
\begin{page}{ugTypesExposePage}{2.11. Exposing Domains and Packages}
\beginscroll

In this section we discuss how Axiom makes some operations
available to you while hiding others that are meant to be used by
developers or only in rare cases.
If you are a new user of Axiom, it is likely that everything
you need is available by default and you may want
to skip over this section on first reading.

Every
domain and package in the Axiom library
is
either
\spadglossSee{exposed}{expose} (meaning that you can use its 
operations without doing
anything special) or it is {\it hidden} (meaning you have to either
package call
(see \downlink{``Package Calling and Target Types''}{ugTypesPkgCallPage} 
in Section 2.9\ignore{ugTypesPkgCall})
the operations it contains or explicitly expose it to use the
operations).
The initial exposure status for a constructor is set in the
file {\bf exposed.lsp} (see the {\it Installer's Note}
for Axiom
if you need to know the location of this file).
Constructors are collected together in
{\it exposure groups}.
Categories are all in the exposure group ``categories'' and the
bulk of the basic set of packages and domains that are exposed
are in the exposure group ``basic.''
Here is an abbreviated sample of the file (without the Lisp parentheses):
\begin{verbatim}
basic
        AlgebraicNumber                          AN
        AlgebraGivenByStructuralConstants        ALGSC
        Any                                      ANY
        AnyFunctions1                            ANY1
        BinaryExpansion                          BINARY
        Boolean                                  BOOLEAN
        CardinalNumber                           CARD
        CartesianTensor                          CARTEN
        Character                                CHAR
        CharacterClass                           CCLASS
        CliffordAlgebra                          CLIF
        Color                                    COLOR
        Complex                                  COMPLEX
        ContinuedFraction                        CONTFRAC
        DecimalExpansion                         DECIMAL
        ...
\end{verbatim}
\begin{verbatim}
categories
        AbelianGroup                             ABELGRP
        AbelianMonoid                            ABELMON
        AbelianMonoidRing                        AMR
        AbelianSemiGroup                         ABELSG
        Aggregate                                AGG
        Algebra                                  ALGEBRA
        AlgebraicallyClosedField                 ACF
        AlgebraicallyClosedFunctionSpace         ACFS
        ArcHyperbolicFunctionCategory            AHYP
        ...
\end{verbatim}
For each constructor in a group, the full name and the abbreviation
is given.
There are other groups in {\bf exposed.lsp} but initially only the
constructors in exposure groups ``basic'' ``categories'' ``naglink'' 
and ``anna'' are exposed.

As an interactive user of Axiom, you do not need to modify this file.
Instead, use \spadcmd{)set expose} to expose, hide or query the
exposure status of an individual constructor or exposure group.  The
reason for having exposure groups is to be able to expose or hide
multiple constructors with a single command.  For example, you might
group together into exposure group ``quantum'' a number of domains and
packages useful for quantum mechanical computations.  These probably
should not be available to every user, but you want an easy way to
make the whole collection visible to Axiom when it is looking for
operations to apply.

If you wanted to hide all the basic constructors available by default,
you would issue \spadcmd{)set expose drop group basic}.  If, however,
you discover that you have hidden all the basic constructors, you
should issue \spadcmd{)set expose add group basic} to restore your
default environment.

It is more likely that you would want to expose or hide individual
constructors.  In
\downlink{``A Famous Triangle''}{ugUserTrianglePage} in Section
6.19\ignore{ugUserTriangle} we use several operations
from \axiomType{OutputForm}, a domain usually hidden.  To avoid
package calling every operation from \axiomType{OutputForm}, we expose
the domain and let Axiom conclude that those operations should be
used.  Use \spadcmd{)set expose add constructor} and \spadcmd{)set
expose drop constructor} to expose and hide a constructor,
respectively.  You should use the constructor name, not the
abbreviation.  The \spadcmd{)set expose} command guides you through
these options.

If you expose a previously hidden constructor, Axiom exhibits new
behavior (that was your intention) though you might not expect the
results that you get.  \axiomType{OutputForm} is, in fact, one of the
worst offenders in this regard.  This domain is meant to be used by
other domains for creating a structure that Axiom knows how to
display.  It has functions like \axiomOpFrom{+}{OutputForm} that form
output representations rather than do mathematical calculations.
Because of the order in which Axiom looks at constructors when it is
deciding what operation to apply, \axiomType{OutputForm} might be used
instead of what you expect.  \xtc{ This is a polynomial.  }{
\spadpaste{x + x} } \xtc{ Expose \axiomType{OutputForm}.  }{
\spadpaste{)set expose add constructor OutputForm
\bound{setexposeadd}} } \xtc{ This is what we get when
\axiomType{OutputForm} is automatically available.  }{ \spadpaste{x +
x \free{setexposeadd}} } \xtc{ Hide \axiomType{OutputForm} so we don't
run into problems with any later examples!  }{ \spadpaste{)set expose
drop constructor OutputForm \bound{setexposedrop}} }

Finally, exposure is done on a frame-by-frame basis.  A
\spadgloss{frame} (see
\downlink{``)frame''}{ugSysCmdframePage} in Section B.11
\ignore{ugSysCmdframe}) is one of possibly several
logical Axiom workspaces within a physical one, each having its own
environment (for example, variables and function definitions).  If you
have several Axiom workspace windows on your screen, they are all
different frames, automatically created for you by Hyperdoc.  Frames
can be manually created, made active and destroyed by the
\spadcmd{)frame} system command.  They do not share exposure
information, so you need to use \spadcmd{)set expose} in each one to
add or drop constructors from view.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugTypesExposePagePatch1}
\begin{paste}{ugTypesExposePageFull1}{ugTypesExposePageEmpty1}
\pastebutton{ugTypesExposePageFull1}{\hidepaste}
\tab{5}\spadcommand{x + x}
\indentrel{3}\begin{verbatim}
   (1)  2x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesExposePageEmpty1}
\begin{paste}{ugTypesExposePageEmpty1}{ugTypesExposePagePatch1}
\pastebutton{ugTypesExposePageEmpty1}{\showpaste}
\tab{5}\spadcommand{x + x}
\end{paste}\end{patch}

\begin{patch}{ugTypesExposePagePatch2}
\begin{paste}{ugTypesExposePageFull2}{ugTypesExposePageEmpty2}
\pastebutton{ugTypesExposePageFull2}{\hidepaste}
\tab{5}\spadcommand{)set expose add constructor OutputForm\bound{setexposeadd }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesExposePageEmpty2}
\begin{paste}{ugTypesExposePageEmpty2}{ugTypesExposePagePatch2}
\pastebutton{ugTypesExposePageEmpty2}{\showpaste}
\tab{5}\spadcommand{)set expose add constructor OutputForm\bound{setexposeadd }}
\end{paste}\end{patch}

\begin{patch}{ugTypesExposePagePatch3}
\begin{paste}{ugTypesExposePageFull3}{ugTypesExposePageEmpty3}
\pastebutton{ugTypesExposePageFull3}{\hidepaste}
\tab{5}\spadcommand{x + x\free{setexposeadd }}
\indentrel{3}\begin{verbatim}
   (2)  x + x
                                       Type: OutputForm
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesExposePageEmpty3}
\begin{paste}{ugTypesExposePageEmpty3}{ugTypesExposePagePatch3}
\pastebutton{ugTypesExposePageEmpty3}{\showpaste}
\tab{5}\spadcommand{x + x\free{setexposeadd }}
\end{paste}\end{patch}

\begin{patch}{ugTypesExposePagePatch4}
\begin{paste}{ugTypesExposePageFull4}{ugTypesExposePageEmpty4}
\pastebutton{ugTypesExposePageFull4}{\hidepaste}
\tab{5}\spadcommand{)set expose drop constructor OutputForm\bound{setexposedrop }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugTypesExposePageEmpty4}
\begin{paste}{ugTypesExposePageEmpty4}{ugTypesExposePagePatch4}
\pastebutton{ugTypesExposePageEmpty4}{\showpaste}
\tab{5}\spadcommand{)set expose drop constructor OutputForm\bound{setexposedrop }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugAvailSnoopPage}{ug02.ht}{Commands for Snooping}
\pageto{notitle}{ugBrowsePage}
\pageto{notitle}{ComplexXmpPage}
\pageto{notitle}{ugUserDeclarePage}
\begin{chunk}{ug02.ht}
\begin{page}{ugAvailSnoopPage}{2.12. Commands for Snooping}
\beginscroll

To conclude this chapter, we introduce you to some system commands
that you can use for getting more information about domains,
packages, categories, and operations.
The most powerful Axiom facility for getting information about
constructors and operations is the \Browse{} component of Hyperdoc.
This is discussed in \downlink{``Browse''}{ugBrowsePage} 
in Chapter 14\ignore{ugBrowse}.

Use the \spadsys{)what} system command to see lists of system objects
whose name contain a particular substring (uppercase or lowercase is
not significant).

\xtc{
Issue this to see a list of all operations with
``{\tt complex}'' in their names.
}{
\spadpaste{)what operation complex}
}
\xtc{
If you want to see all domains with ``{\tt matrix}'' in their names, issue
this.
}{
\spadpaste{)what domain matrix}
}
\xtc{
Similarly, if you wish to see all packages whose names contain
``{\tt gauss}'', enter this.
}{
\spadpaste{)what package gauss}
}
\xtc{
This command shows all
the operations that \axiomType{Any} provides.
Wherever \axiomSyntax{\$} appears, it means ``\axiomType{Any}''.
}{
\spadpaste{)show Any}
}
\xtc{
This displays all operations with the name \axiomFun{complex}.
}{
\spadpaste{)display operation complex}
}
Let's analyze this output.
\xtc{
First we find out what some of the abbreviations mean.
}{
\spadpaste{)abbreviation query COMPCAT}
}
\xtc{
}{
\spadpaste{)abbreviation query COMRING}
}

So if \axiom{D1} is a commutative ring (such as the integers or
floats) and \axiom{D} belongs to \axiomType{ComplexCategory
D1}, then there is an operation called \axiomFun{complex} that
takes two elements of \axiom{D1} and creates an element of
\axiom{D}.
The primary example of a constructor implementing domains
belonging to \axiomType{ComplexCategory} is \axiomType{Complex}.
See \downlink{`Complex'}{ComplexXmpPage}\ignore{Complex} 
for more information on that and see
\downlink{``Declaring the Type of Functions''}{ugUserDeclarePage} in 
Section 6.4\ignore{ugUserDeclare} 
for more information on function types.
\endscroll
\autobuttons
\end{page}

\begin{patch}{ugAvailSnoopPagePatch1}
\begin{paste}{ugAvailSnoopPageFull1}{ugAvailSnoopPageEmpty1}
\pastebutton{ugAvailSnoopPageFull1}{\hidepaste}
\tab{5}\spadcommand{)what operation complex}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugAvailSnoopPageEmpty1}
\begin{paste}{ugAvailSnoopPageEmpty1}{ugAvailSnoopPagePatch1}
\pastebutton{ugAvailSnoopPageEmpty1}{\showpaste}
\tab{5}\spadcommand{)what operation complex}
\end{paste}\end{patch}

\begin{patch}{ugAvailSnoopPagePatch2}
\begin{paste}{ugAvailSnoopPageFull2}{ugAvailSnoopPageEmpty2}
\pastebutton{ugAvailSnoopPageFull2}{\hidepaste}
\tab{5}\spadcommand{)what domain matrix}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugAvailSnoopPageEmpty2}
\begin{paste}{ugAvailSnoopPageEmpty2}{ugAvailSnoopPagePatch2}
\pastebutton{ugAvailSnoopPageEmpty2}{\showpaste}
\tab{5}\spadcommand{)what domain matrix}
\end{paste}\end{patch}

\begin{patch}{ugAvailSnoopPagePatch3}
\begin{paste}{ugAvailSnoopPageFull3}{ugAvailSnoopPageEmpty3}
\pastebutton{ugAvailSnoopPageFull3}{\hidepaste}
\tab{5}\spadcommand{)what package gauss}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugAvailSnoopPageEmpty3}
\begin{paste}{ugAvailSnoopPageEmpty3}{ugAvailSnoopPagePatch3}
\pastebutton{ugAvailSnoopPageEmpty3}{\showpaste}
\tab{5}\spadcommand{)what package gauss}
\end{paste}\end{patch}

\begin{patch}{ugAvailSnoopPagePatch4}
\begin{paste}{ugAvailSnoopPageFull4}{ugAvailSnoopPageEmpty4}
\pastebutton{ugAvailSnoopPageFull4}{\hidepaste}
\tab{5}\spadcommand{)show Any}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugAvailSnoopPageEmpty4}
\begin{paste}{ugAvailSnoopPageEmpty4}{ugAvailSnoopPagePatch4}
\pastebutton{ugAvailSnoopPageEmpty4}{\showpaste}
\tab{5}\spadcommand{)show Any}
\end{paste}\end{patch}

\begin{patch}{ugAvailSnoopPagePatch5}
\begin{paste}{ugAvailSnoopPageFull5}{ugAvailSnoopPageEmpty5}
\pastebutton{ugAvailSnoopPageFull5}{\hidepaste}
\tab{5}\spadcommand{)display operation complex}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugAvailSnoopPageEmpty5}
\begin{paste}{ugAvailSnoopPageEmpty5}{ugAvailSnoopPagePatch5}
\pastebutton{ugAvailSnoopPageEmpty5}{\showpaste}
\tab{5}\spadcommand{)display operation complex}
\end{paste}\end{patch}

\begin{patch}{ugAvailSnoopPagePatch6}
\begin{paste}{ugAvailSnoopPageFull6}{ugAvailSnoopPageEmpty6}
\pastebutton{ugAvailSnoopPageFull6}{\hidepaste}
\tab{5}\spadcommand{)abbreviation query COMPCAT}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugAvailSnoopPageEmpty6}
\begin{paste}{ugAvailSnoopPageEmpty6}{ugAvailSnoopPagePatch6}
\pastebutton{ugAvailSnoopPageEmpty6}{\showpaste}
\tab{5}\spadcommand{)abbreviation query COMPCAT}
\end{paste}\end{patch}

\begin{patch}{ugAvailSnoopPagePatch7}
\begin{paste}{ugAvailSnoopPageFull7}{ugAvailSnoopPageEmpty7}
\pastebutton{ugAvailSnoopPageFull7}{\hidepaste}
\tab{5}\spadcommand{)abbreviation query COMRING}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugAvailSnoopPageEmpty7}
\begin{paste}{ugAvailSnoopPageEmpty7}{ugAvailSnoopPagePatch7}
\pastebutton{ugAvailSnoopPageEmpty7}{\showpaste}
\tab{5}\spadcommand{)abbreviation query COMRING}
\end{paste}\end{patch}

\end{chunk}
\chapter{Users Guide Chapter 3 (ug03.ht)}
\pagetitle{ugHyperPage}{ug03.ht}{Using Hyperdoc}
\pageto{notitle}{YouTriedIt}
\pageto{notitle}{ugHyperHeadingsPage}
\pageto{notitle}{ugHyperKeysPage}
\pageto{notitle}{ugHyperScrollPage}
\pageto{notitle}{ugHyperInputPage}
\pageto{notitle}{ugHyperButtonsPage}
\pageto{notitle}{ugHyperSearchPage}
\pageto{notitle}{ugHyperExamplePage}
\pageto{notitle}{ugHyperResourcesPage}
\begin{chunk}{ug03.ht}
\begin{page}{ugHyperPage}{3. Using Hyperdoc}
\beginscroll


Hyperdoc is the gateway to Axiom.
It's both an on-line tutorial and an on-line reference manual.
It also enables you to use Axiom simply by using the mouse and
filling in templates.
Hyperdoc is available to you if you are running Axiom under the
X Window System.

Pages usually have active areas, marked in
\texht{{\bf this font} (bold face).}{\downlink{this font.}{YouTriedIt}}
As you move the mouse pointer to an active area, the pointer changes from
a filled dot to an open circle.
The active areas are usually linked to other pages.
When you click on an active area, you move to the linked page.
\texht{}{Try clicking \downlink{here}{YouTriedIt} now.}

We suggest that you learn more about other features of
Hyperdoc by clicking on an active area in the menu below.

\beginmenu
    \menudownlink{{3.1. Headings}}{ugHyperHeadingsPage}
    \menudownlink{{3.2. Key Definitions}}{ugHyperKeysPage}
    \menudownlink{{3.3. Scroll Bars}}{ugHyperScrollPage}
    \menudownlink{{3.4. Input Areas}}{ugHyperInputPage}
    \menudownlink{{3.5. Radio Buttons and Toggles}}{ugHyperButtonsPage}
    \menudownlink{{3.6. Search Strings}}{ugHyperSearchPage}
    \menudownlink{{3.7. Example Pages}}{ugHyperExamplePage}
    \menudownlink{{3.8. X Window Resources for Hyperdoc}}
                  {ugHyperResourcesPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugHyperHeadingsPage}{ug03.ht}{Headings}
\begin{chunk}{ug03.ht}
\begin{page}{ugHyperHeadingsPage}{3.1. Headings}
\beginscroll
%
Most pages have a standard set of buttons at the top of the page.
This is what they mean:

\indent{0}
\beginitems
\item[\StdHelpButton{}] Click on this to get help.
The button only appears if there is specific help for the page you are
viewing.
You can get {\it general} help for Hyperdoc by clicking the help
button on the home page.

\item[\UpButton{}] Click here to go back one page.
By clicking on this button repeatedly, you can go back several pages and
then take off in a new direction.

\item[\ReturnButton{}] Go back to the home page, that is,
the page on which you started.
Use Hyperdoc to explore, to make forays into new topics.
Don't worry about how to get back.
Hyperdoc remembers where you came from.
Just click on this button to return.

\item[\StdExitButton{}] From the root window (the one that is
displayed when you start the system) this button leaves the Hyperdoc
program, and it must be restarted if you want to use it again.  From
any other Hyperdoc window, it just makes that one window go away.  You
{\it must} use this button to get rid of a window.  If you use the
window manager ``Close'' button, then all of Hyperdoc goes away.
\enditems
\indent{0}
%
The buttons are not displayed if they are not applicable to the page
you are viewing.
For example, there is no \ReturnButton{} button on the top-level menu.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugHyperKeysPage}{ug03.ht}{Key Definitions}
\pageto{notitle}{ugHyperScrollPage}
\pageto{notitle}{ugHyperInputPage}
\begin{chunk}{ug03.ht}
\begin{page}{ugHyperKeysPage}{3.2. Key Definitions}
\beginscroll

The following keyboard definitions are in effect throughout
Hyperdoc.
See \downlink{``Scroll Bars''}{ugHyperScrollPage} 
in Section 3.3\ignore{ugHyperScroll} and
\downlink{``Input Areas''}{ugHyperInputPage} 
in Section 3.4\ignore{ugHyperInput}
for some contextual key definitions.
%
\indent{0}
\beginitems
\item[F1] Display the main help page.
\item[F3] Same as \StdExitButton{}, makes the window go away if you are 
not at the top-level window or quits the Hyperdoc facility if you are 
at the top-level.
\item[F5] Rereads the Hyperdoc database, if necessary (for system 
developers).
\item[F9] Displays this information about key definitions.
\item[F12] Same as {\bf F3}.
\item[Up Arrow] Scroll up one line.
\item[Down Arrow] Scroll down one line.
\item[Page Up] Scroll up one page.
\item[Page Down] Scroll down one page.
\enditems
\indent{0}

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugHyperScrollPage}{ug03.ht}{Scroll Bars}
\pageto{notitle}{ugHyperInputPage}
\begin{chunk}{ug03.ht}
\begin{page}{ugHyperScrollPage}{3.3. Scroll Bars}
\beginscroll

Whenever there is too much text to fit on a page, a {\it scroll
bar} automatically appears along the right side.

With a scroll bar, your page becomes an aperture, that is, a
window into a larger amount of text than can be displayed at one
time.
The scroll bar lets you move up and down in the text to see
different parts.
It also shows where the aperture is relative to the whole text.
The aperture is indicated by a strip on the scroll bar.

Move the cursor with the mouse to the ``down-arrow'' at the bottom
of the scroll bar and click.
See that the aperture moves down one line.
Do it several times.
Each time you click, the aperture moves down one line.
Move the mouse to the ``up-arrow'' at the top of the scroll bar and
click.
The aperture moves up one line each time you click.

Next move the mouse to any position along the middle of the scroll bar
and click.  Hyperdoc attempts to move the top of the aperture to this
point in the text.

You cannot make the aperture go off the bottom edge.  When the
aperture is about half the size of text, the lowest you can move the
aperture is halfway down.

To move up or down one screen at a time, use the
\texht{\fbox{\bf PageUp}}{{\bf PageUp}} and 
\texht{\fbox{\bf PageDown}}{{\bf PageDown}} keys on your keyboard.
They move the visible part of the region up and down one page each 
time you press them.

If the Hyperdoc page does not contain an input area
(see \downlink{``Input Areas''}{ugHyperInputPage} 
in Section 3.4\ignore{ugHyperInput}), 
you can also use the
\texht{\fbox{\bf Home}}{{\bf Home}} and
\texht{\fbox{$\uparrow$}}{up} and
\texht{\fbox{$\downarrow$}}{down} arrow keys to navigate.
When you press the \texht{\fbox{\bf Home}}{{\bf Home}} key,
the screen is positioned at the very top of the page.
Use the \texht{\fbox{$\uparrow$}}{up} and
\texht{\fbox{$\downarrow$}}{down} arrow keys to move the screen up
and down one line at a time, respectively.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugHyperInputPage}{ug03.ht}{Input Areas}
\begin{chunk}{ug03.ht}
\begin{page}{ugHyperInputPage}{3.4. Input Areas}
\beginscroll
%
Input areas are boxes where you can put data.
Here is one:
\centerline{\inputstring{one}{40}{some text}}
\newline 
As you can see, the input area has some initial text {\it some text}
followed by an underscore cursor (the character {\it _}).

To enter characters, first
move your mouse cursor to somewhere within the Hyperdoc page.
Characters that you type are inserted in front of the underscore.
This means that when you type characters at your keyboard, they
go into this first input area.

The input area grows to accommodate as many characters as you type.
Use the \texht{\fbox{\bf Backspace}}{{\bf Backspace}}
key to erase characters to the left.
To modify what you type, use the right-arrow \texht{\fbox{$\rightarrow$}}{}
and left-arrow keys \texht{\fbox{$\leftarrow$}}{} and the
keys \texht{\fbox{\bf Insert}}{{\bf Insert}},
\texht{\fbox{\bf Delete}}{{\bf Delete}},
\texht{\fbox{\bf Home}}{{\bf Home}} and
\texht{\fbox{\bf End}}{{\bf End}}.
These keys are found immediately on the right of the standard IBM keyboard.

If you press the
\texht{\fbox{\bf Home}}{{\bf Home}}
key, the cursor moves to the beginning of the line and if you press the
\texht{\fbox{\bf End}}{{\bf End}}
key, the cursor moves to the end of the line.
Pressing
\texht{\fbox{\bf Ctrl}--\fbox{\bf End}}{{\bf Ctrl-End}}
deletes all the text from the cursor to the end of the line.

A page may have more than one input area.
Only one input area has an underscore cursor.
When you first see apage, the top-most input area contains the
cursor.
To type information into another input area,
use the \texht{\fbox{\bf Enter}}{{\bf Enter}} or
\texht{\fbox{\bf Tab}}{{\bf Tab}} key to move
from one input area to another.
To move in the reverse order, use
\texht{\fbox{\bf Shift}--\fbox{\bf Tab}}{{\bf Shift-Tab}}.

You can also move from one input area to another using your mouse.
Notice that each input area is active. Click on one of the areas.
As you can see, the underscore cursor moves to that window.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugHyperButtonsPage}{ug03.ht}{Radio Buttons and Toggles}
\begin{chunk}{ug03.ht}
\begin{page}{ugHyperButtonsPage}{3.5. Radio Buttons and Toggles}
\beginscroll
%
Some pages have {\it radio buttons} and {\it toggles}.
Radio buttons are a group of buttons like those on car radios: you can
select only one at a time.
\radioboxes{sample}{\htbmfile{pick}}{\htbmfile{unpick}}
Here are three radio buttons:
\centerline{
{\em\radiobox[1]{rone}{sample}\space{}\ First one}\space{3}
{\em\radiobox[0]{rtwo}{sample}\space{}\ Second one}\space{3}
{\em\radiobox[0]{rthree}{sample}\space{}\ Third one}
}
\newline
Once you have selected a button, it appears to be inverted and
contains a checkmark.
To change the selection, move the cursor with the mouse to a 
different radio button and click.
\texht{}{Try it now.}

A toggle is an independent button that displays some on/off
state.
When ``on'', the button appears to be inverted and
contains a checkmark.
When ``off'', the button is raised.
%
Unlike radio buttons, you can set a group of them any way you like.
Here are three:
\centerline{
{\em\inputbox[1]{one}{\htbmfile{pick}}{\htbmfile{unpick}}\space{}
\ First one}
\space{3}
{\em\inputbox[0]{two}{\htbmfile{pick}}{\htbmfile{unpick}}\space{}
\ Second one}
\space{3}
{\em\inputbox[1]{three}{\htbmfile{pick}}{\htbmfile{unpick}}\space{}
\ Third one}
}
\newline
To change toggle the selection, move the cursor with the mouse
to the button and click.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugHyperSearchPage}{ug03.ht}{Search Strings}
\pageto{notitle}{ugLogicalSearchesPage}
\begin{chunk}{ug03.ht}
\begin{page}{ugHyperSearchPage}{3.6. Search Strings}
\beginscroll
%
A {\it search string} is used for searching some database.
To learn about search strings, we suggest that
you bring up the Hyperdoc glossary.
To do this from the top-level page of Hyperdoc:
\indent{4}
\beginitems
\item[1. ] Click on \windowlink{Reference}{TopReferencePage},
bringing up the Axiom Reference page.
\item[2. ] Click on \windowlink{Glossary}{GlossaryPage}, 
bringing up the glossary.
\texht{}{(You can also just click on the word ``Glossary'' in the
last sentence.)}
\enditems
\indent{0}
Once you get the window containing the glossary, move it so that
it and this window are both visible.

The glossary has an input area at its bottom.
We review the various kinds of search strings
you can enter to search the glossary.

The simplest search string is a word, for example, {\tt operation}.
A word only matches an entry having exactly that spelling.
Enter the word {\tt operation} into the input area above then click on
{\bf Search}.
As you can see, {\tt operation} matches only one entry, namely with {\tt
operation} itself.

Normally matching is insensitive to whether the alphabetic characters
of your search string are in uppercase or lowercase.  Thus {\tt
operation} and {\tt OperAtion} both have the same effect.  %If you
prefer that matching be case-sensitive, issue the command
%\spadsys{set HHyperName mixedCase} command to the interpreter.

You will very often want to use the wildcard \spadSyntax{*} in your
search string so as to match multiple entries in the list.  The search
key \spadSyntax{*} matches every entry in the list.  You can also use
\spadSyntax{*} anywhere within a search string to match an arbitrary
substring.  Try {\tt cat*} for example: enter {\tt cat*} into the
input area and click on {\bf Search}.  This matches several entries.

You use any number of wildcards in a search string as long as they are
not adjacent.  Try search strings such as {\tt *dom*}.  As you see,
this search string matches {\tt domain}, {\tt domain constructor},
{\tt subdomain}, and so on.

\beginmenu
    \menudownlink{{3.6.1. Logical Searches}}{ugLogicalSearchesPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugLogicalSearchesPage}{ug03.ht}{Logical Searches}
\begin{chunk}{ug03.ht}
\begin{page}{ugLogicalSearchesPage}{3.6.1. Logical Searches}
\beginscroll

For more complicated searches, you can use
\spadSyntax{and}, \spadSyntax{or}, and \spadSyntax{not}
with basic search strings;
write logical expressions using these three operators just as
in the Axiom language.
For example, {\tt domain or package}  matches the two
entries {\tt domain} and {\tt package}.
Similarly, {\tt dom* and *con*} matches {\tt domain constructor}
and others.
Also {\tt not *a*} matches every entry that does not contain
the letter {\tt a} somewhere.

Use parentheses for grouping.
For example, {\tt dom* and (not *con*)}
matches {\tt domain} but not {\tt domain constructor}.

There is no limit to how complex your logical expression can be.
For example,
\centerline{{{\tt a* or b* or c* or d* or e* and (not *a*)}}}
is a valid expression.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugHyperExamplePage}{ug03.ht}{Example Pages}
\begin{chunk}{ug03.ht}
\begin{page}{ugHyperExamplePage}{3.7. Example Pages}
\beginscroll
%
Many pages have Axiom example commands.
%
Here are two:
\spadpaste{a:= x**2 + 1 \bound{a}} 
\spadpaste{(a - 2)**2 \free{a}} 
%
Each command has an active ``button'' along the left margin.
When you click on this button, the output for the command is
``pasted-in.''
Click again on the button and you see that the pasted-in output
disappears.

Maybe you would like to run an example?
To do so, just click on any part of its text!
When you do, the example line is copied into a new interactive
Axiom buffer for this Hyperdoc page.

Sometimes one example line cannot be run before you run an earlier one.
Don't worry---Hyperdoc automatically runs all the necessary
lines in the right order!
For instance, the second example line above refers to \spad{a} which is
assigned in the first example line.
What happens if you first click on the second example line?
Axiom first issues the first line (to assign \spad{a}), then the
second (to do the computation using \spad{a}).

The new interactive Axiom buffer disappears when you leave
Hyperdoc.
If you want to get rid of it beforehand,
use the {\bf Cancel} button of the X Window manager
or issue the Axiom system command \spadsys{)close.}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugHyperExamplePagePatch1}
\begin{paste}{ugHyperExamplePageFull1}{ugHyperExamplePageEmpty1}
\pastebutton{ugHyperExamplePageFull1}{\hidepaste}
\tab{5}\spadcommand{a:= x**2 + 1\bound{a }}
\indentrel{3}\begin{verbatim}
         2
   (1)  x  + 1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugHyperExamplePageEmpty1}
\begin{paste}{ugHyperExamplePageEmpty1}{ugHyperExamplePagePatch1}
\pastebutton{ugHyperExamplePageEmpty1}{\showpaste}
\tab{5}\spadcommand{a:= x**2 + 1\bound{a }}
\end{paste}\end{patch}

\begin{patch}{ugHyperExamplePagePatch2}
\begin{paste}{ugHyperExamplePageFull2}{ugHyperExamplePageEmpty2}
\pastebutton{ugHyperExamplePageFull2}{\hidepaste}
\tab{5}\spadcommand{(a - 2)**2\free{a }}
\indentrel{3}\begin{verbatim}
         4     2
   (2)  x  - 2x  + 1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugHyperExamplePageEmpty2}
\begin{paste}{ugHyperExamplePageEmpty2}{ugHyperExamplePagePatch2}
\pastebutton{ugHyperExamplePageEmpty2}{\showpaste}
\tab{5}\spadcommand{(a - 2)**2\free{a }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugHyperResourcesPage}{ug03.ht}{X Window Resources for Hyperdoc}
\begin{chunk}{ug03.ht}
\begin{page}{ugHyperResourcesPage}{3.8. X Window Resources for Hyperdoc}
\beginscroll
%
You can control the appearance of Hyperdoc while running under Version 11
of the X Window System by placing the following resources
in the file {\bf .Xdefaults} in your home directory.
In what follows, {\it font} is any valid X11 font name
(for example, {\tt Rom14}) and {\it color} is any valid X11 color
specification (for example, {\tt NavyBlue}).
For more information about fonts and colors, refer to the
X Window documentation for your system.
\indent{0}
\beginitems
\item[{\tt Axiom.hyperdoc.RmFont:} {\it font}] \ \newline
This is the standard text font.  \xdefault{Rom14}
\item[{\tt Axiom.hyperdoc.RmColor:} {\it color}] \ \newline
This is the standard text color.  \xdefault{black}
\item[{\tt Axiom.hyperdoc.ActiveFont:} {\it font}] \ \newline
This is the font used for Hyperdoc link buttons.  \xdefault{Bld14}
\item[{\tt Axiom.hyperdoc.ActiveColor:} {\it color}] \ \newline
This is the color used for Hyperdoc link buttons.  \xdefault{black}
\item[{\tt Axiom.hyperdoc.AxiomFont:} {\it font}] \ \newline
This is the font used for active Axiom commands.\footnote{
This was called {\tt Axiom.hyperdoc.SpadFont} in early versions
of Axiom.}
\xdefault{Bld14}
\item[{\tt Axiom.hyperdoc.AxiomColor:} {\it color}] \ \newline
This is the color used for active Axiom commands.\footnote{
This was called {\tt Axiom.hyperdoc.SpadColor} in early versions
of Axiom.}
\xdefault{black}
\item[{\tt Axiom.hyperdoc.BoldFont:} {\it font}] \ \newline
This is the font used for bold face.  \xdefault{Bld14}
\item[{\tt Axiom.hyperdoc.BoldColor:} {\it color}] \ \newline
This is the color used for bold face.  \xdefault{black}
\item[{\tt Axiom.hyperdoc.TtFont:} {\it font}] \ \newline
This is the font used for Axiom output in Hyperdoc.
This font must be fixed-width.  \xdefault{Rom14}
\item[{\tt Axiom.hyperdoc.TtColor:} {\it color}] \ \newline
This is the color used for Axiom output in Hyperdoc.
\xdefault{black}
\item[{\tt Axiom.hyperdoc.EmphasizeFont:} {\it font}] \ \newline
This is the font used for italics.  \xdefault{Itl14}
\item[{\tt Axiom.hyperdoc.EmphasizeColor:} {\it color}] \ \newline
This is the color used for italics.  \xdefault{black}
\item[{\tt Axiom.hyperdoc.InputBackground:} {\it color}] \ \newline
This is the color used as the background for input areas.
\xdefault{black}
\item[{\tt Axiom.hyperdoc.InputForeground:} {\it color}] \ \newline
This is the color used as the foreground for input areas.
\xdefault{white}
\item[{\tt Axiom.hyperdoc.BorderColor:} {\it color}] \ \newline
This is the color used for drawing border lines.
\xdefault{black}
\item[{\tt Axiom.hyperdoc.Background:} {\it color}] \ \newline
This is the color used for the background of all windows.
\xdefault{white}
\enditems
\indent{0}
\endscroll
\autobuttons
\end{page}
\end{chunk}
\chapter{Users Guide Chapter 4 (ug04.ht)}
\pagetitle{ugInOutPage}{ug04.ht}{Input Files and Output Styles}
\pageto{notitle}{ugInOutInPage}
\pageto{notitle}{ugInOutSpadprofPage}
\pageto{notitle}{ugInOutOutPage}
\pageto{notitle}{ugInOutAlgebraPage}
\pageto{notitle}{ugInOutTeXPage}
\pageto{notitle}{ugInOutScriptPage}
\pageto{notitle}{ugInOutFortranPage}
\begin{chunk}{ug04.ht}
\begin{page}{ugInOutPage}{4. Input Files and Output Styles}
\beginscroll

In this chapter we discuss how to collect Axiom statements
and commands into files and then read the contents into the
workspace.
We also show how to display the results of your computations in
several different styles including \texht{\TeX}{TeX}, FORTRAN and
monospace two-dimensional format.\footnote{\texht{\TeX}{TeX} is a
trademark of the American Mathematical Society.}

The printed version of this book uses the Axiom
\texht{\TeX}{TeX} output formatter.
When we demonstrate a particular output style, we will need to
turn \texht{\TeX}{TeX} formatting off and the output style on so
that the correct output is shown in the text.

\beginmenu
    \menudownlink{{4.1. Input Files}}{ugInOutInPage}
    \menudownlink{{4.2. The axiom.input File}}{ugInOutSpadprofPage}
    \menudownlink{{4.3. Common Features of Using Output Formats}}
{ugInOutOutPage}
    \menudownlink{{4.4. Monospace Two-Dimensional Mathematical Format}}
{ugInOutAlgebraPage}
    \menudownlink{{4.5. TeX Format}}{ugInOutTeXPage}
    \menudownlink{{4.6. IBM Script Formula Format}}{ugInOutScriptPage}
    \menudownlink{{4.7. FORTRAN Format}}{ugInOutFortranPage}
    \menudownlink{{4.8. HTML Format}}{ugInOutHTMLPage}
    \menudownlink{{4.9. MathML Format}}{ugInOutMathMLPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugInOutInPage}{ug04.ht}{Input Files}
\pageto{notitle}{ugLangBlocksPage}
\begin{chunk}{ug04.ht}
\begin{page}{ugInOutInPage}{4.1. Input Files}
\beginscroll
%
In this section we explain what an {\it input file} is and
why you would want to know about it.
We discuss where Axiom looks for input files and how you can
direct it to look elsewhere.
We also show how to read the contents of an input file into the
\spadgloss{workspace} and how to use the \spadgloss{history}
facility to generate an input file from the statements you have
entered directly into the workspace.

An {\it input} file contains Axiom expressions and system
commands.
Anything that you can enter directly to Axiom can be put
into an input file.
This is how you save input functions and expressions that you wish
to read into Axiom more than one time.

To read an input file into Axiom, use the \spadcmd{)read}
system command.
For example, you can read a file in a particular directory by issuing
\begin{verbatim}
)read /spad/src/input/matrix.input
\end{verbatim}
The ``{\bf .input}'' is optional; this also works:
\begin{verbatim}
)read /spad/src/input/matrix
\end{verbatim}
What happens if you just enter
\spadcmd{)read matrix.input} or even \spadcmd{)read matrix}?
Axiom looks in your current working directory for input files
that are not qualified by a directory name.
Typically, this directory is the directory from which you invoked
Axiom.
To change the current working directory, use the \spadcmd{)cd} system
command. The command \spadsys{)cd} by itself shows the current
working
directory.
To change it to
the \spadsys{src/input} subdirectory for user ``babar'',
issue
\begin{verbatim}
)cd /u/babar/src/input
\end{verbatim}
Axiom looks first in this directory for an input file.
If it is not found, it looks in the system's directories, assuming
you meant some input file that was provided with Axiom.

\beginImportant
If you have the Axiom history facility turned on (which it is
by default), you can save all the lines you have entered into the
workspace by entering
\begin{verbatim}
)history )write
\end{verbatim}

Axiom tells you what input file to edit to see your
statements.
The file is in your home directory or in the directory you
specified with \spadsys{)cd}.
\endImportant

In \downlink{``Blocks''}{ugLangBlocksPage} in Section 5.2
\ignore{ugLangBlocks}
we discuss using indentation in input files to group statements
into {\it blocks.}

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugInOutSpadprofPage}{ug04.ht}{The .axiom.input File}
\begin{chunk}{ug04.ht}
\begin{page}{ugInOutSpadprofPage}{4.2. The .axiom.input File}
\beginscroll

When Axiom starts up, it tries to read the input file
{\bf .axiom.input} from your home
directory.
It there is no {\bf axiom.input} in your home directory, it reads the copy
located in its own {\bf src/input} directory.
The file usually contains
system commands to personalize your Axiom environment.
In the remainder of this section we mention a few things
that users frequently place in their
{\bf axiom.input} files.

In order to have FORTRAN output always produced from your
computations, place the system command
\spadcmd{)set output fortran on}
in {\bf axiom.input}.
If you do not want to be prompted for confirmation when you issue
the \spadcmd{)quit} system command, place
\spadcmd{)set quit unprotected}
in {\bf axiom.input}.
If you then decide that you do want to be prompted, issue
\spadcmd{)set quit protected}.
This is the default setting
so that new users do not leave Axiom
inadvertently.\footnote{The
system command \spadsys{)pquit} always prompts you for
confirmation.}

To see the other system variables you can set, issue \spadsys{)set}
or use the Hyperdoc {\bf Settings} facility to view and change
Axiom system variables.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugInOutOutPage}{ug04.ht}{Common Features of Using Output Formats}
\begin{chunk}{ug04.ht}
\begin{page}{ugInOutOutPage}{4.3. Common Features of Using Output Formats}
\beginscroll

In this section we discuss how to start and stop the display
of the different output formats and how to send the output to the
screen or to a file.
To fix ideas, we use FORTRAN output format for most of the
examples.

You can use the \spadcmd{)set output}
system
command to
toggle or redirect the different kinds of output.
The name of the kind of output follows ``output'' in the command.
The names are

\indent{0}
\beginitems
\item[fortran]  for FORTRAN output.
\item[algebra]  for monospace two-dimensional mathematical output.
\item[tex]      for \texht{\TeX}{TeX} output.
\item[html]     for HTML output.
\item[mathml]   for MathML output.
\item[script]   for IBM Script Formula Format output.
\enditems
\indent{0}

For example, issue \spadsys{)set output fortran on} to turn on
FORTRAN format and
issue \spadsys{)set output fortran off} to turn it off.
By default, {\tt algebra} is {\tt on} and all others are {\tt off}.
When output is started, it is sent to the screen.
To send the output to a file, give the file name without
directory or extension.
Axiom appends a file extension depending on the kind of
output being produced.
\xtc{
Issue this to redirect FORTRAN output to, for example, the file
{\bf linalg.sfort}.
}{
\spadpaste{)set output fortran linalg}
}
\noOutputXtc{
You must {\it also} turn on the creation of FORTRAN output.
The above just says where it goes if it is created.
}{
\spadpaste{)set output fortran on}
}
In what directory is this output placed?
It goes into the directory from which you started Axiom,
or if you have used the \spadsys{)cd} system command, the one
that you specified with \spadsys{)cd}.
You should use \spadcmd{)cd} before you send the output to the file.

\noOutputXtc{
You can always direct output back to the screen by issuing this.
}{
\spadpaste{)set output fortran console}
}
\noOutputXtc{
Let's make sure FORTRAN formatting is off so that nothing we
do from now on produces FORTRAN output.
}{
\spadpaste{)set output fortran off}
}
\noOutputXtc{
We also delete the demonstrated output file we created.
}{
\spadpaste{)system rm linalg.sfort}
}

You can abbreviate the words ``\spad{on},'' ``\spad{off}'' and
``\spad{console}'' to the minimal number
of characters needed to distinguish them.
Because of this, you cannot send output to files called
{\bf on.sfort, off.sfort, of.sfort,
console.sfort, consol.sfort} and so on.

The width of the output on the page is set by
\spadcmd{)set output length}
for all formats except FORTRAN.
Use \spadcmd{)set fortran fortlength} to
change the FORTRAN line length from its default value of \spad{72}.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugInOutOutPagePatch1}
\begin{paste}{ugInOutOutPageFull1}{ugInOutOutPageEmpty1}
\pastebutton{ugInOutOutPageFull1}{\hidepaste}
\tab{5}\spadcommand{)set output fortran linalg}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutOutPageEmpty1}
\begin{paste}{ugInOutOutPageEmpty1}{ugInOutOutPagePatch1}
\pastebutton{ugInOutOutPageEmpty1}{\showpaste}
\tab{5}\spadcommand{)set output fortran linalg}
\end{paste}\end{patch}

\begin{patch}{ugInOutOutPagePatch2}
\begin{paste}{ugInOutOutPageFull2}{ugInOutOutPageEmpty2}
\pastebutton{ugInOutOutPageFull2}{\hidepaste}
\tab{5}\spadcommand{)set output fortran on}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutOutPageEmpty2}
\begin{paste}{ugInOutOutPageEmpty2}{ugInOutOutPagePatch2}
\pastebutton{ugInOutOutPageEmpty2}{\showpaste}
\tab{5}\spadcommand{)set output fortran on}
\end{paste}\end{patch}

\begin{patch}{ugInOutOutPagePatch3}
\begin{paste}{ugInOutOutPageFull3}{ugInOutOutPageEmpty3}
\pastebutton{ugInOutOutPageFull3}{\hidepaste}
\tab{5}\spadcommand{)set output fortran console}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutOutPageEmpty3}
\begin{paste}{ugInOutOutPageEmpty3}{ugInOutOutPagePatch3}
\pastebutton{ugInOutOutPageEmpty3}{\showpaste}
\tab{5}\spadcommand{)set output fortran console}
\end{paste}\end{patch}

\begin{patch}{ugInOutOutPagePatch4}
\begin{paste}{ugInOutOutPageFull4}{ugInOutOutPageEmpty4}
\pastebutton{ugInOutOutPageFull4}{\hidepaste}
\tab{5}\spadcommand{)set output fortran off}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutOutPageEmpty4}
\begin{paste}{ugInOutOutPageEmpty4}{ugInOutOutPagePatch4}
\pastebutton{ugInOutOutPageEmpty4}{\showpaste}
\tab{5}\spadcommand{)set output fortran off}
\end{paste}\end{patch}

\begin{patch}{ugInOutOutPagePatch5}
\begin{paste}{ugInOutOutPageFull5}{ugInOutOutPageEmpty5}
\pastebutton{ugInOutOutPageFull5}{\hidepaste}
\tab{5}\spadcommand{)system rm linalg.sfort}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutOutPageEmpty5}
\begin{paste}{ugInOutOutPageEmpty5}{ugInOutOutPagePatch5}
\pastebutton{ugInOutOutPageEmpty5}{\showpaste}
\tab{5}\spadcommand{)system rm linalg.sfort}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugInOutAlgebraPage}{ug04.ht}
{Monospace 2D Mathematical Format}
\begin{chunk}{ug04.ht}
\begin{page}{ugInOutAlgebraPage}
{4.4. Monospace 2D Mathematical Format}
\beginscroll

This is the default output format for Axiom.
It is usually on when you start the system.

\texht{\vskip 4pc}{}
\noOutputXtc{
If it is not, issue this.
}{
\spadpaste{)set output algebra on \bound{algon}}
}
\noOutputXtc{
Since the printed version of this book
(as opposed to the Hyperdoc version)
shows output produced by the
\texht{\TeX}{TeX}{} output formatter,
let us temporarily turn off
\texht{\TeX}{TeX}{} output.
}{
\spadpaste{)set output tex off \bound{texoff}}
}
\xtc{
Here is an example of what it looks like.
}{
\spadpaste{matrix [[i*x**i + j*\%i*y**j for i in 1..2] for j in 3..4] 
\free{algon texoff}}
}
\noOutputXtc{
Issue this to turn off this kind of formatting.
}{
\spadpaste{)set output algebra off}
}
\noOutputXtc{
Turn \texht{\TeX}{TeX}{} output on again.
}{
\spadpaste{)set output tex on}
}

The characters used for the matrix brackets above are rather ugly.
You get this character set when you issue
\spadcmd{)set output characters plain}.
This character set should be used when you are running on a machine
that does not support the IBM extended ASCII character set.
If you are running on an IBM workstation, for example, issue
\spadcmd{)set output characters default}
to get better looking output.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugInOutAlgebraPagePatch1}
\begin{paste}{ugInOutAlgebraPageFull1}{ugInOutAlgebraPageEmpty1}
\pastebutton{ugInOutAlgebraPageFull1}{\hidepaste}
\tab{5}\spadcommand{)set output algebra on\bound{algon }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutAlgebraPageEmpty1}
\begin{paste}{ugInOutAlgebraPageEmpty1}{ugInOutAlgebraPagePatch1}
\pastebutton{ugInOutAlgebraPageEmpty1}{\showpaste}
\tab{5}\spadcommand{)set output algebra on\bound{algon }}
\end{paste}\end{patch}

\begin{patch}{ugInOutAlgebraPagePatch2}
\begin{paste}{ugInOutAlgebraPageFull2}{ugInOutAlgebraPageEmpty2}
\pastebutton{ugInOutAlgebraPageFull2}{\hidepaste}
\tab{5}\spadcommand{)set output tex off\bound{texoff }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutAlgebraPageEmpty2}
\begin{paste}{ugInOutAlgebraPageEmpty2}{ugInOutAlgebraPagePatch2}
\pastebutton{ugInOutAlgebraPageEmpty2}{\showpaste}
\tab{5}\spadcommand{)set output tex off\bound{texoff }}
\end{paste}\end{patch}

\begin{patch}{ugInOutAlgebraPagePatch3}
\begin{paste}{ugInOutAlgebraPageFull3}{ugInOutAlgebraPageEmpty3}
\pastebutton{ugInOutAlgebraPageFull3}{\hidepaste}
\tab{5}\spadcommand{matrix [[i*x**i + j*\%i*y**j for i in 1..2] for j in 3..4]\free{algon texoff }}
\indentrel{3}\begin{verbatim}
        Ú     3           3     2¿
        ³3%i y  + x  3%i y  + 2x ³
   (1)  ³                        ³
        ³     4           4     2³
        À4%i y  + x  4%i y  + 2x Ù
                Type: Matrix Polynomial Complex Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutAlgebraPageEmpty3}
\begin{paste}{ugInOutAlgebraPageEmpty3}{ugInOutAlgebraPagePatch3}
\pastebutton{ugInOutAlgebraPageEmpty3}{\showpaste}
\tab{5}\spadcommand{matrix [[i*x**i + j*\%i*y**j for i in 1..2] for j in 3..4]\free{algon texoff }}
\end{paste}\end{patch}

\begin{patch}{ugInOutAlgebraPagePatch4}
\begin{paste}{ugInOutAlgebraPageFull4}{ugInOutAlgebraPageEmpty4}
\pastebutton{ugInOutAlgebraPageFull4}{\hidepaste}
\tab{5}\spadcommand{)set output algebra off}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutAlgebraPageEmpty4}
\begin{paste}{ugInOutAlgebraPageEmpty4}{ugInOutAlgebraPagePatch4}
\pastebutton{ugInOutAlgebraPageEmpty4}{\showpaste}
\tab{5}\spadcommand{)set output algebra off}
\end{paste}\end{patch}

\begin{patch}{ugInOutAlgebraPagePatch5}
\begin{paste}{ugInOutAlgebraPageFull5}{ugInOutAlgebraPageEmpty5}
\pastebutton{ugInOutAlgebraPageFull5}{\hidepaste}
\tab{5}\spadcommand{)set output tex on}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutAlgebraPageEmpty5}
\begin{paste}{ugInOutAlgebraPageEmpty5}{ugInOutAlgebraPagePatch5}
\pastebutton{ugInOutAlgebraPageEmpty5}{\showpaste}
\tab{5}\spadcommand{)set output tex on}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugInOutTeXPage}{ug04.ht}{TeX Format}
\begin{chunk}{ug04.ht}
\begin{page}{ugInOutTeXPage}{4.5. TeX Format}
\beginscroll

Axiom can produce \texht{\TeX}{TeX}{} output for your
expressions.
The output is produced using macros from the
\texht{\LaTeX}{LaTeX} document preparation system by
Leslie Lamport.\footnote{See Leslie Lamport, {\it LaTeX: A Document
Preparation System,} Reading, Massachusetts: Addison-Wesley
Publishing Company, Inc., 1986.}
The printed version of this book was produced using this formatter.

\noOutputXtc{
To turn on \texht{\TeX}{TeX}{} output formatting, issue this.
}{
\spadpaste{)set output tex on \bound{texon}}
}
Here is an example of its output.
\begin{verbatim}
matrix [[i*x**i + j*\%i*y**j for i in 1..2] for j in 3..4]

\[
\left[
\begin{array}{cc}
\displaystyle {{3 \  \%i \  {y \sp 3}}+x}&
\displaystyle {{3 \  \%i \  {y \sp 3}}+{2 \  {x \sp 2}}} \\
\displaystyle {{4 \  \%i \  {y \sp 4}}+x}&
\displaystyle {{4 \  \%i \  {y \sp 4}}+{2 \  {x \sp 2}}}
\end{array}
\right]
\leqno(3)
\]
%Axiom STEP NUMBER: 3
\end{verbatim}
To turn \texht{\TeX}{TeX}{} output formatting off, issue \spadsys{)set
output tex off}.
The \texht{\LaTeX}{LaTeX} macros in the output generated by Axiom
are all standard except for the following definitions:
\begin{verbatim}
\def\csch{\mathop{\rm csch}\nolimits}

\def\erf{\mathop{\rm erf}\nolimits}

\def\zag#1#2{
  {{\hfill \left. {#1} \right|}
   \over
   {\left| {#2} \right. \hfill}
  }
}
\end{verbatim}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugInOutTeXPagePatch1}
\begin{paste}{ugInOutTeXPageFull1}{ugInOutTeXPageEmpty1}
\pastebutton{ugInOutTeXPageFull1}{\hidepaste}
\tab{5}\spadcommand{)set output tex on\bound{texon }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutTeXPageEmpty1}
\begin{paste}{ugInOutTeXPageEmpty1}{ugInOutTeXPagePatch1}
\pastebutton{ugInOutTeXPageEmpty1}{\showpaste}
\tab{5}\spadcommand{)set output tex on\bound{texon }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugInOutScriptPage}{ug04.ht}{IBM Script Formula Format}
\begin{chunk}{ug04.ht}
\begin{page}{ugInOutScriptPage}{4.6. IBM Script Formula Format}
\beginscroll

Axiom can
produce IBM Script Formula Format output for your
expressions.

\texht{\vskip 2pc}{}
\noOutputXtc{
To turn IBM Script Formula Format on, issue this.
}{
\spadpaste{)set output script on}
}
Here is an example of its output.
\begin{verbatim}
matrix [[i*x**i + j*%i*y**j for i in 1..2] for j in 3..4]

.eq set blank @
:df.
<left lb < < < <3 @@ %i @@ <y sup 3>>+x> here < <3 @@ %i @@
<y sup 3>>+<2 @@ <x sup 2>>>> habove < < <4 @@ %i @@
<y sup 4>>+x> here < <4 @@ %i @@ <y sup 4>>+<2 @@
<x up 2>>>>> right rb>
:edf.
\end{verbatim}
\noOutputXtc{
To turn IBM Script Formula Format output formatting off, issue this.
}{
\spadpaste{)set output script off}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugInOutScriptPagePatch1}
\begin{paste}{ugInOutScriptPageFull1}{ugInOutScriptPageEmpty1}
\pastebutton{ugInOutScriptPageFull1}{\hidepaste}
\tab{5}\spadcommand{)set output script on}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutScriptPageEmpty1}
\begin{paste}{ugInOutScriptPageEmpty1}{ugInOutScriptPagePatch1}
\pastebutton{ugInOutScriptPageEmpty1}{\showpaste}
\tab{5}\spadcommand{)set output script on}
\end{paste}\end{patch}

\begin{patch}{ugInOutScriptPagePatch2}
\begin{paste}{ugInOutScriptPageFull2}{ugInOutScriptPageEmpty2}
\pastebutton{ugInOutScriptPageFull2}{\hidepaste}
\tab{5}\spadcommand{)set output script off}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutScriptPageEmpty2}
\begin{paste}{ugInOutScriptPageEmpty2}{ugInOutScriptPagePatch2}
\pastebutton{ugInOutScriptPageEmpty2}{\showpaste}
\tab{5}\spadcommand{)set output script off}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugInOutFortranPage}{ug04.ht}{FORTRAN Format}
\begin{chunk}{ug04.ht}
\begin{page}{ugInOutFortranPage}{4.7. FORTRAN Format}
\beginscroll

In addition to turning FORTRAN output on and off and stating where the
output should be placed, there are many options that control the
appearance of the generated code.  In this section we describe some of
the basic options.  Issue \spadcmd{)set fortran} to see a full list
with their current settings.

The output FORTRAN expression usually begins in column 7.  If the
expression needs more than one line, the ampersand character
\spadSyntax{\&} is used in column 6.  Since some versions of FORTRAN
have restrictions on the number of lines per statement, Axiom breaks
long expressions into segments with a maximum of 1320 characters (20
lines of 66 characters) per segment.  If you want to change this, say,
to 660 characters, issue the system command \spadcmd{)set fortran
explength 660}.  You can turn off the line breaking by issuing
\spadcmd{)set fortran segment off}.  Various code optimization levels
are available.  % \noOutputXtc{ FORTRAN output is produced after you
issue this.  }{ \spadpaste{)set output fortran on \bound{forton}} }
\noOutputXtc{ For the initial examples, we set the optimization level
to 0, which is the lowest level.  }{ \spadpaste{)set fortran optlevel
0 \bound{opt0}\free{forton}} } \noOutputXtc{ The output is usually in
columns 7 through 72, although fewer columns are used in the following
examples so that the output fits nicely on the page.  }{
\spadpaste{)set fortran fortlength 60} } \xtc{ By default, the output
goes to the screen and is displayed before the standard Axiom
two-dimensional output.  In this example, an assignment to the
variable \spad{R1} was generated because this is the result of step 1.
}{ \spadpaste{(x+y)**3 \free{opt0}} } 

\xtc{ Here is an example that illustrates the line breaking.  }
{ \spadpaste{(x+y+z)**3 \free{opt0}}
}

Note in the above examples that integers are generally converted to
floating point numbers, except in exponents.
This is the default behavior but can be turned off by issuing
\spadcmd{)set fortran ints2floats off}.
The rules governing when the conversion is done are:
\indent{4}
\beginitems
\item[1. ] If an integer is an exponent, convert it to a floating point
number if it is greater than 32767 in absolute value, otherwise leave it
as an integer.
\item[2. ] Convert all other integers in an expression to floating
point numbers.
\enditems
\indent{0}
These rules only govern integers in expressions.
Numbers generated by Axiom for \spad{DIMENSION} statements are also
integers.

To set the type of generated FORTRAN data,
use one of the following:
\begin{verbatim}
)set fortran defaulttype REAL
)set fortran defaulttype INTEGER
)set fortran defaulttype COMPLEX
)set fortran defaulttype LOGICAL
)set fortran defaulttype CHARACTER
\end{verbatim}

\xtc{
When temporaries are created, they are given a default type of
{\tt REAL.}
Also, the {\tt REAL} versions of functions are used by default.
}{
\spadpaste{sin(x) \free{opt1}}
}
\noOutputXtc{
At optimization level 1, Axiom removes common subexpressions.
}{
\spadpaste{)set fortran optlevel 1 \bound{opt1}\free{forton}}
}
\xtc{
}{
\spadpaste{(x+y+z)**3 \free{opt1}}
}
\noOutputXtc{
This changes the precision to {\tt DOUBLE}.
Substitute \spad{single} for \spad{double}
to return to single precision.
}{
\spadpaste{)set fortran precision double \free{opt1}\bound{double1}}
}
\xtc{
Complex constants display the precision.
}{
\spadpaste{2.3 + 5.6*\%i  \free{double1}}
}
\xtc{
The function names that Axiom generates depend on the chosen
precision.
}{
\spadpaste{sin \%e  \free{double1}}
}
\noOutputXtc{
Reset the precision to \spad{single} and look at these two
examples again.
}{
\spadpaste{)set fortran precision single \free{opt1}\bound{single1}}
}
\xtc{
}{
\spadpaste{2.3 + 5.6*\%i  \free{single1}}
}
\xtc{
}{
\spadpaste{sin \%e  \free{single1}}
}
\xtc{
Expressions that look like lists, streams, sets or matrices cause
array code to be generated.
}{
\spadpaste{[x+1,y+1,z+1] \free{opt1}}
}
\xtc{
A temporary variable is generated to be the name of the array.
This may have to be changed in your particular application.
}{
\spadpaste{set[2,3,4,3,5] \free{opt1}}
}
\xtc{
By default, the starting index for generated FORTRAN arrays is \spad{0}.
}{
\spadpaste{matrix [[2.3,9.7],[0.0,18.778]] \free{opt1}}
}
\noOutputXtc{
To change the starting index for generated FORTRAN arrays to be \spad{1},
issue this.
This value can only be \spad{0} or \spad{1}.
}{
\spadpaste{)set fortran startindex 1 \free{opt1}\bound{start1}}
}
\xtc{
Look at the code generated for the matrix again.
}{
\spadpaste{matrix [[2.3,9.7],[0.0,18.778]] \free{start1}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ugInOutFortranPagePatch1}
\begin{paste}{ugInOutFortranPageFull1}{ugInOutFortranPageEmpty1}
\pastebutton{ugInOutFortranPageFull1}{\hidepaste}
\tab{5}\spadcommand{)set output fortran on\bound{forton }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPageEmpty1}
\begin{paste}{ugInOutFortranPageEmpty1}{ugInOutFortranPagePatch1}
\pastebutton{ugInOutFortranPageEmpty1}{\showpaste}
\tab{5}\spadcommand{)set output fortran on\bound{forton }}
\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPagePatch2}
\begin{paste}{ugInOutFortranPageFull2}{ugInOutFortranPageEmpty2}
\pastebutton{ugInOutFortranPageFull2}{\hidepaste}
\tab{5}\spadcommand{)set fortran optlevel 0\bound{opt0 }\free{forton }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPageEmpty2}
\begin{paste}{ugInOutFortranPageEmpty2}{ugInOutFortranPagePatch2}
\pastebutton{ugInOutFortranPageEmpty2}{\showpaste}
\tab{5}\spadcommand{)set fortran optlevel 0\bound{opt0 }\free{forton }}
\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPagePatch3}
\begin{paste}{ugInOutFortranPageFull3}{ugInOutFortranPageEmpty3}
\pastebutton{ugInOutFortranPageFull3}{\hidepaste}
\tab{5}\spadcommand{)set fortran fortlength 60}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPageEmpty3}
\begin{paste}{ugInOutFortranPageEmpty3}{ugInOutFortranPagePatch3}
\pastebutton{ugInOutFortranPageEmpty3}{\showpaste}
\tab{5}\spadcommand{)set fortran fortlength 60}
\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPagePatch4}
\begin{paste}{ugInOutFortranPageFull4}{ugInOutFortranPageEmpty4}
\pastebutton{ugInOutFortranPageFull4}{\hidepaste}
\tab{5}\spadcommand{(x+y)**3\free{opt0 }}
\indentrel{3}\begin{verbatim}
         3       2     2     3
   (1)  y  + 3x y  + 3x y + x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPageEmpty4}
\begin{paste}{ugInOutFortranPageEmpty4}{ugInOutFortranPagePatch4}
\pastebutton{ugInOutFortranPageEmpty4}{\showpaste}
\tab{5}\spadcommand{(x+y)**3\free{opt0 }}
\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPagePatch5}
\begin{paste}{ugInOutFortranPageFull5}{ugInOutFortranPageEmpty5}
\pastebutton{ugInOutFortranPageFull5}{\hidepaste}
\tab{5}\spadcommand{(x+y+z)**3\free{opt0 }}
\indentrel{3}\begin{verbatim}
   (2)
      3             2      2            2      3       2
     z  + (3y + 3x)z  + (3y  + 6x y + 3x )z + y  + 3x y
   + 
       2     3
     3x y + x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPageEmpty5}
\begin{paste}{ugInOutFortranPageEmpty5}{ugInOutFortranPagePatch5}
\pastebutton{ugInOutFortranPageEmpty5}{\showpaste}
\tab{5}\spadcommand{(x+y+z)**3\free{opt0 }}
\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPagePatch6}
\begin{paste}{ugInOutFortranPageFull6}{ugInOutFortranPageEmpty6}
\pastebutton{ugInOutFortranPageFull6}{\hidepaste}
\tab{5}\spadcommand{sin(x)\free{opt1 }}
\indentrel{3}\begin{verbatim}
   (3)  sin(x)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPageEmpty6}
\begin{paste}{ugInOutFortranPageEmpty6}{ugInOutFortranPagePatch6}
\pastebutton{ugInOutFortranPageEmpty6}{\showpaste}
\tab{5}\spadcommand{sin(x)\free{opt1 }}
\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPagePatch7}
\begin{paste}{ugInOutFortranPageFull7}{ugInOutFortranPageEmpty7}
\pastebutton{ugInOutFortranPageFull7}{\hidepaste}
\tab{5}\spadcommand{)set fortran optlevel 1\bound{opt1 }\free{forton }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPageEmpty7}
\begin{paste}{ugInOutFortranPageEmpty7}{ugInOutFortranPagePatch7}
\pastebutton{ugInOutFortranPageEmpty7}{\showpaste}
\tab{5}\spadcommand{)set fortran optlevel 1\bound{opt1 }\free{forton }}
\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPagePatch8}
\begin{paste}{ugInOutFortranPageFull8}{ugInOutFortranPageEmpty8}
\pastebutton{ugInOutFortranPageFull8}{\hidepaste}
\tab{5}\spadcommand{(x+y+z)**3\free{opt1 }}
\indentrel{3}\begin{verbatim}
   (4)
      3             2      2            2      3       2
     z  + (3y + 3x)z  + (3y  + 6x y + 3x )z + y  + 3x y
   + 
       2     3
     3x y + x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPageEmpty8}
\begin{paste}{ugInOutFortranPageEmpty8}{ugInOutFortranPagePatch8}
\pastebutton{ugInOutFortranPageEmpty8}{\showpaste}
\tab{5}\spadcommand{(x+y+z)**3\free{opt1 }}
\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPagePatch9}
\begin{paste}{ugInOutFortranPageFull9}{ugInOutFortranPageEmpty9}
\pastebutton{ugInOutFortranPageFull9}{\hidepaste}
\tab{5}\spadcommand{)set fortran precision double\free{opt1 }\bound{double1 }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPageEmpty9}
\begin{paste}{ugInOutFortranPageEmpty9}{ugInOutFortranPagePatch9}
\pastebutton{ugInOutFortranPageEmpty9}{\showpaste}
\tab{5}\spadcommand{)set fortran precision double\free{opt1 }\bound{double1 }}
\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPagePatch10}
\begin{paste}{ugInOutFortranPageFull10}{ugInOutFortranPageEmpty10}
\pastebutton{ugInOutFortranPageFull10}{\hidepaste}
\tab{5}\spadcommand{2.3 + 5.6*\%i\free{double1 }}
\indentrel{3}\begin{verbatim}
   (5)  2.3 + 5.6 %i
                                    Type: Complex Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPageEmpty10}
\begin{paste}{ugInOutFortranPageEmpty10}{ugInOutFortranPagePatch10}
\pastebutton{ugInOutFortranPageEmpty10}{\showpaste}
\tab{5}\spadcommand{2.3 + 5.6*\%i\free{double1 }}
\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPagePatch11}
\begin{paste}{ugInOutFortranPageFull11}{ugInOutFortranPageEmpty11}
\pastebutton{ugInOutFortranPageFull11}{\hidepaste}
\tab{5}\spadcommand{sin \%e\free{double1 }}
\indentrel{3}\begin{verbatim}
   (6)  sin(%e)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPageEmpty11}
\begin{paste}{ugInOutFortranPageEmpty11}{ugInOutFortranPagePatch11}
\pastebutton{ugInOutFortranPageEmpty11}{\showpaste}
\tab{5}\spadcommand{sin \%e\free{double1 }}
\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPagePatch12}
\begin{paste}{ugInOutFortranPageFull12}{ugInOutFortranPageEmpty12}
\pastebutton{ugInOutFortranPageFull12}{\hidepaste}
\tab{5}\spadcommand{)set fortran precision single\free{opt1 }\bound{single1 }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPageEmpty12}
\begin{paste}{ugInOutFortranPageEmpty12}{ugInOutFortranPagePatch12}
\pastebutton{ugInOutFortranPageEmpty12}{\showpaste}
\tab{5}\spadcommand{)set fortran precision single\free{opt1 }\bound{single1 }}
\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPagePatch13}
\begin{paste}{ugInOutFortranPageFull13}{ugInOutFortranPageEmpty13}
\pastebutton{ugInOutFortranPageFull13}{\hidepaste}
\tab{5}\spadcommand{2.3 + 5.6*\%i\free{single1 }}
\indentrel{3}\begin{verbatim}
   (7)  2.3 + 5.6 %i
                                    Type: Complex Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPageEmpty13}
\begin{paste}{ugInOutFortranPageEmpty13}{ugInOutFortranPagePatch13}
\pastebutton{ugInOutFortranPageEmpty13}{\showpaste}
\tab{5}\spadcommand{2.3 + 5.6*\%i\free{single1 }}
\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPagePatch14}
\begin{paste}{ugInOutFortranPageFull14}{ugInOutFortranPageEmpty14}
\pastebutton{ugInOutFortranPageFull14}{\hidepaste}
\tab{5}\spadcommand{sin \%e\free{single1 }}
\indentrel{3}\begin{verbatim}
   (8)  sin(%e)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPageEmpty14}
\begin{paste}{ugInOutFortranPageEmpty14}{ugInOutFortranPagePatch14}
\pastebutton{ugInOutFortranPageEmpty14}{\showpaste}
\tab{5}\spadcommand{sin \%e\free{single1 }}
\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPagePatch15}
\begin{paste}{ugInOutFortranPageFull15}{ugInOutFortranPageEmpty15}
\pastebutton{ugInOutFortranPageFull15}{\hidepaste}
\tab{5}\spadcommand{[x+1,y+1,z+1]\free{opt1 }}
\indentrel{3}\begin{verbatim}
   (9)  [x + 1,y + 1,z + 1]
                          Type: List Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPageEmpty15}
\begin{paste}{ugInOutFortranPageEmpty15}{ugInOutFortranPagePatch15}
\pastebutton{ugInOutFortranPageEmpty15}{\showpaste}
\tab{5}\spadcommand{[x+1,y+1,z+1]\free{opt1 }}
\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPagePatch16}
\begin{paste}{ugInOutFortranPageFull16}{ugInOutFortranPageEmpty16}
\pastebutton{ugInOutFortranPageFull16}{\hidepaste}
\tab{5}\spadcommand{set[2,3,4,3,5]\free{opt1 }}
\indentrel{3}\begin{verbatim}
   (10)  {2,3,4,5}
                              Type: Set PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPageEmpty16}
\begin{paste}{ugInOutFortranPageEmpty16}{ugInOutFortranPagePatch16}
\pastebutton{ugInOutFortranPageEmpty16}{\showpaste}
\tab{5}\spadcommand{set[2,3,4,3,5]\free{opt1 }}
\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPagePatch17}
\begin{paste}{ugInOutFortranPageFull17}{ugInOutFortranPageEmpty17}
\pastebutton{ugInOutFortranPageFull17}{\hidepaste}
\tab{5}\spadcommand{matrix [[2.3,9.7],[0.0,18.778]]\free{opt1 }}
\indentrel{3}\begin{verbatim}
         Ú2.3   9.7  ¿
   (11)  ³           ³
         À0.0  18.778Ù
                                     Type: Matrix Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPageEmpty17}
\begin{paste}{ugInOutFortranPageEmpty17}{ugInOutFortranPagePatch17}
\pastebutton{ugInOutFortranPageEmpty17}{\showpaste}
\tab{5}\spadcommand{matrix [[2.3,9.7],[0.0,18.778]]\free{opt1 }}
\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPagePatch18}
\begin{paste}{ugInOutFortranPageFull18}{ugInOutFortranPageEmpty18}
\pastebutton{ugInOutFortranPageFull18}{\hidepaste}
\tab{5}\spadcommand{)set fortran startindex 1\free{opt1 }\bound{start1 }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPageEmpty18}
\begin{paste}{ugInOutFortranPageEmpty18}{ugInOutFortranPagePatch18}
\pastebutton{ugInOutFortranPageEmpty18}{\showpaste}
\tab{5}\spadcommand{)set fortran startindex 1\free{opt1 }\bound{start1 }}
\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPagePatch19}
\begin{paste}{ugInOutFortranPageFull19}{ugInOutFortranPageEmpty19}
\pastebutton{ugInOutFortranPageFull19}{\hidepaste}
\tab{5}\spadcommand{matrix [[2.3,9.7],[0.0,18.778]]\free{start1 }}
\indentrel{3}\begin{verbatim}
         Ú2.3   9.7  ¿
   (12)  ³           ³
         À0.0  18.778Ù
                                     Type: Matrix Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugInOutFortranPageEmpty19}
\begin{paste}{ugInOutFortranPageEmpty19}{ugInOutFortranPagePatch19}
\pastebutton{ugInOutFortranPageEmpty19}{\showpaste}
\tab{5}\spadcommand{matrix [[2.3,9.7],[0.0,18.778]]\free{start1 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugInOutHTMLPage}{ug04.ht}{HTML Format}
\begin{chunk}{ug04.ht}
\begin{page}{ugInOutHTMLPage}{4.8. HTML Format}
\beginscroll

Axiom can produce HTML output for your expressions.
The output is produced by the HTMLFormat domain.

To turn on HTML output formatting, issue this.

)set output html on

To turn HTML output formatting off, issue 

)set output html off

\endscroll
\autobuttons
\end{page}

\pagetitle{ugInOutMathMLPage}{ug04.ht}{MathML Format}
\begin{chunk}{ug04.ht}
\begin{page}{ugInOutMathMLPage}{4.9. MathML Format}
\beginscroll

Axiom can produce MathML output for your expressions.
The output is produced by the MathMLFormat domain.

To turn on MathML output formatting, issue this.

)set output mathml on

To turn MathML output formatting off, issue 

)set output mathml off

\endscroll
\autobuttons
\end{page}

\chapter{Users Guide Chapter 5 (ug05.ht)}
\pagetitle{ugLangPage}{ug05.ht}
{Introduction to the Axiom Interactive Language}
\pagepic{ps/v71uglangpage.eps}{uglangpage}{0.50}
\pagefrom{Reference}{TopReferencePage}
\pageto{Immediate and Delayed Assignments}
{ugLangAssignPage}
\pageto{Blocks}{ugLangBlocksPage}
\pageto{if-then-else}{ugLangIfPage}
\pageto{Loops}{ugLangLoopsPage}
\pageto{Creating Lists and Streams with Iterators}{ugLangItsPage}
\pageto{An Example: Streams of Primes}{ugLangStreamsPrimesPage}
\begin{chunk}{ug05.ht}
\begin{page}{ugLangPage}{5. Introduction to the Axiom Interactive Language}
\beginscroll

In this chapter we look at some of the basic components of the
Axiom language that you can use interactively.
We show how to create a \spadgloss{block} of expressions,
how to form loops and list iterations, how to modify the sequential
evaluation of a block and how to use {\tt if-then-else} to
evaluate parts of your program conditionally.
We suggest you first read the boxed material in each section and then
proceed to a more thorough reading of the chapter.

\beginmenu
    \menudownlink{{5.1. Immediate and Delayed Assignments}}
                  {ugLangAssignPage}
    \menudownlink{{5.2. Blocks}}{ugLangBlocksPage}
    \menudownlink{{5.3. if-then-else}}{ugLangIfPage}
    \menudownlink{{5.4. Loops}}{ugLangLoopsPage}
    \menudownlink{{5.5. Creating Lists and Streams with Iterators}}
{ugLangItsPage}
    \menudownlink{{5.6. An Example: Streams of Primes}}
{ugLangStreamsPrimesPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugLangAssignPage}{ug05.ht}{Immediate and Delayed Assignments}
\pageto{notitle}{ugUserDelayPage}
\begin{chunk}{ug05.ht}
\begin{page}{ugLangAssignPage}{5.1. Immediate and Delayed Assignments}
\beginscroll

A \spadgloss{variable} in Axiom refers to a value.
A variable has a name beginning with an uppercase or lowercase alphabetic
character, \axiomSyntax{\%}, or \axiomSyntax{!}.
Successive characters (if any) can be any of the above, digits, or
\axiomSyntax{?}.
Case is distinguished.
The following are all examples of valid, distinct variable names:
\begin{verbatim}
a             tooBig?    a1B2c3%!?
A             %j         numberOfPoints
beta6         %J         numberofpoints
\end{verbatim}

The \axiomSyntax{:=} operator is the immediate \spadgloss{assignment}
operator.
Use it to associate a value with a variable.

\beginImportant
The syntax for immediate assignment for a single variable is
\centerline{{{\it variable} \axiom{:=} {\it expression}}}
The value returned by an immediate assignment is the value of 
{\it expression}.
\endImportant

\xtc{
The right-hand side of the expression is evaluated,
yielding \axiom{1}.  This value is then assigned to \axiom{a}.
}{
\spadpaste{a := 1 \bound{a}}
}
\xtc{
The right-hand side of the expression is evaluated,
yielding \axiom{1}.  This value is then assigned to \axiom{b}.
Thus \axiom{a} and \axiom{b} both have the value \axiom{1} after 
the sequence of assignments.
}{
\spadpaste{b := a \free{a}\bound{b}}
}
\xtc{
What is the value of \axiom{b} if \axiom{a} is
assigned the value \axiom{2}?
}{
\spadpaste{a := 2 \bound{a2}}
}
\xtc{
As you see, the value of \axiom{b} is left unchanged.
}{
\spadpaste{b \free{b}}
}
This is what we mean when we say this kind of assignment is
{\it immediate};
\axiom{b} has no dependency on \axiom{a} after the initial assignment.
This is the usual notion of assignment found in programming
languages such as C,
PASCAL
and FORTRAN.

Axiom provides delayed assignment with \axiomSyntax{==}.
This implements a
delayed evaluation of the right-hand side and dependency
checking.

\beginImportant
The syntax for delayed assignment is
\centerline{{{\it variable} \axiom{==} {\it expression}}}
The value returned by a delayed assignment is \void{}.
\endImportant

\xtc{
Using \axiom{a} and \axiom{b} as above, these are the corresponding 
delayed assignments.
}{
\spadpaste{a == 1 \bound{ad}}
}
\xtc{
}{
\spadpaste{b == a \free{ad}\bound{bd}}
}
\xtc{
The right-hand side of each delayed assignment
is left unevaluated until the
variables on the left-hand sides are evaluated.
Therefore this evaluation and \ldots
}{
\spadpaste{a \free{ad}}
}
\xtc{
this evaluation seem the same as before.
}{
\spadpaste{b \free{bd}}
}
\xtc{
If we change \axiom{a} to \axiom{2}
}{
\spadpaste{a == 2 \bound{ad2}}
}
\xtc{
then
\axiom{a} evaluates to \axiom{2}, as expected, but
}{
\spadpaste{a \free{ad2}}
}
\xtc{
the value of \axiom{b} reflects the change to \axiom{a}.
}{
\spadpaste{b \free{bd ad2}}
}

It is possible to set several variables at the same time
by using
a \spadgloss{tuple} of variables and a tuple of expressions.\footnote{A
\spadgloss{tuple} is a collection of things separated by commas, often
surrounded by parentheses.}

\beginImportant
The syntax for multiple immediate assignments is
\centerline{{{\tt ( \subscriptIt{var}{1}, \subscriptIt{var}{2}, 
\ldots, \subscriptIt{var}{N} ) := ( \subscriptIt{expr}{1}, 
\subscriptIt{expr}{2}, \ldots, \subscriptIt{expr}{N} ) }}}
The value returned by an immediate assignment is the value of
\subscriptIt{expr}{N}.
\endImportant

\xtc{
This sets \axiom{x} to \axiom{1} and \axiom{y} to \axiom{2}.
}{
\spadpaste{(x,y) := (1,2) \bound{x}\bound{y}}
}
Multiple immediate assigments are parallel in the sense that the
expressions on the right are all evaluated before any assignments
on the left are made.
However, the order of evaluation of these expressions is undefined.
\xtc{
You can use multiple immediate assignment to swap the
values held by variables.
}{
\spadpaste{(x,y) := (y,x) \free{x y}\bound{swap}}
}
\xtc{
\axiom{x} has the previous value of \axiom{y}.
}{
\spadpaste{x \free{swap}}
}
\xtc{
\axiom{y} has the previous value of \axiom{x}.
}{
\spadpaste{y \free{swap}}
}

There is no syntactic form for multiple delayed assignments.
See the discussion in
\downlink{``Delayed Assignments vs. Functions with No Arguments''}
{ugUserDelayPage} 
in Section 6.8\ignore{ugUserDelay}
about how Axiom differentiates between delayed assignments and
user functions of no arguments.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugLangAssignPagePatch1}
\begin{paste}{ugLangAssignPageFull1}{ugLangAssignPageEmpty1}
\pastebutton{ugLangAssignPageFull1}{\hidepaste}
\tab{5}\spadcommand{a := 1\bound{a }}
\indentrel{3}\begin{verbatim}
   (1)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangAssignPageEmpty1}
\begin{paste}{ugLangAssignPageEmpty1}{ugLangAssignPagePatch1}
\pastebutton{ugLangAssignPageEmpty1}{\showpaste}
\tab{5}\spadcommand{a := 1\bound{a }}
\end{paste}\end{patch}

\begin{patch}{ugLangAssignPagePatch2}
\begin{paste}{ugLangAssignPageFull2}{ugLangAssignPageEmpty2}
\pastebutton{ugLangAssignPageFull2}{\hidepaste}
\tab{5}\spadcommand{b := a\free{a }\bound{b }}
\indentrel{3}\begin{verbatim}
   (2)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangAssignPageEmpty2}
\begin{paste}{ugLangAssignPageEmpty2}{ugLangAssignPagePatch2}
\pastebutton{ugLangAssignPageEmpty2}{\showpaste}
\tab{5}\spadcommand{b := a\free{a }\bound{b }}
\end{paste}\end{patch}

\begin{patch}{ugLangAssignPagePatch3}
\begin{paste}{ugLangAssignPageFull3}{ugLangAssignPageEmpty3}
\pastebutton{ugLangAssignPageFull3}{\hidepaste}
\tab{5}\spadcommand{a := 2\bound{a2 }}
\indentrel{3}\begin{verbatim}
   (3)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangAssignPageEmpty3}
\begin{paste}{ugLangAssignPageEmpty3}{ugLangAssignPagePatch3}
\pastebutton{ugLangAssignPageEmpty3}{\showpaste}
\tab{5}\spadcommand{a := 2\bound{a2 }}
\end{paste}\end{patch}

\begin{patch}{ugLangAssignPagePatch4}
\begin{paste}{ugLangAssignPageFull4}{ugLangAssignPageEmpty4}
\pastebutton{ugLangAssignPageFull4}{\hidepaste}
\tab{5}\spadcommand{b\free{b }}
\indentrel{3}\begin{verbatim}
   (4)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangAssignPageEmpty4}
\begin{paste}{ugLangAssignPageEmpty4}{ugLangAssignPagePatch4}
\pastebutton{ugLangAssignPageEmpty4}{\showpaste}
\tab{5}\spadcommand{b\free{b }}
\end{paste}\end{patch}

\begin{patch}{ugLangAssignPagePatch5}
\begin{paste}{ugLangAssignPageFull5}{ugLangAssignPageEmpty5}
\pastebutton{ugLangAssignPageFull5}{\hidepaste}
\tab{5}\spadcommand{a == 1\bound{ad }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangAssignPageEmpty5}
\begin{paste}{ugLangAssignPageEmpty5}{ugLangAssignPagePatch5}
\pastebutton{ugLangAssignPageEmpty5}{\showpaste}
\tab{5}\spadcommand{a == 1\bound{ad }}
\end{paste}\end{patch}

\begin{patch}{ugLangAssignPagePatch6}
\begin{paste}{ugLangAssignPageFull6}{ugLangAssignPageEmpty6}
\pastebutton{ugLangAssignPageFull6}{\hidepaste}
\tab{5}\spadcommand{b == a\free{ad }\bound{bd }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangAssignPageEmpty6}
\begin{paste}{ugLangAssignPageEmpty6}{ugLangAssignPagePatch6}
\pastebutton{ugLangAssignPageEmpty6}{\showpaste}
\tab{5}\spadcommand{b == a\free{ad }\bound{bd }}
\end{paste}\end{patch}

\begin{patch}{ugLangAssignPagePatch7}
\begin{paste}{ugLangAssignPageFull7}{ugLangAssignPageEmpty7}
\pastebutton{ugLangAssignPageFull7}{\hidepaste}
\tab{5}\spadcommand{a\free{ad }}
\indentrel{3}\begin{verbatim}
   (7)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangAssignPageEmpty7}
\begin{paste}{ugLangAssignPageEmpty7}{ugLangAssignPagePatch7}
\pastebutton{ugLangAssignPageEmpty7}{\showpaste}
\tab{5}\spadcommand{a\free{ad }}
\end{paste}\end{patch}

\begin{patch}{ugLangAssignPagePatch8}
\begin{paste}{ugLangAssignPageFull8}{ugLangAssignPageEmpty8}
\pastebutton{ugLangAssignPageFull8}{\hidepaste}
\tab{5}\spadcommand{b\free{bd }}
\indentrel{3}\begin{verbatim}
   (8)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangAssignPageEmpty8}
\begin{paste}{ugLangAssignPageEmpty8}{ugLangAssignPagePatch8}
\pastebutton{ugLangAssignPageEmpty8}{\showpaste}
\tab{5}\spadcommand{b\free{bd }}
\end{paste}\end{patch}

\begin{patch}{ugLangAssignPagePatch9}
\begin{paste}{ugLangAssignPageFull9}{ugLangAssignPageEmpty9}
\pastebutton{ugLangAssignPageFull9}{\hidepaste}
\tab{5}\spadcommand{a == 2\bound{ad2 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangAssignPageEmpty9}
\begin{paste}{ugLangAssignPageEmpty9}{ugLangAssignPagePatch9}
\pastebutton{ugLangAssignPageEmpty9}{\showpaste}
\tab{5}\spadcommand{a == 2\bound{ad2 }}
\end{paste}\end{patch}

\begin{patch}{ugLangAssignPagePatch10}
\begin{paste}{ugLangAssignPageFull10}{ugLangAssignPageEmpty10}
\pastebutton{ugLangAssignPageFull10}{\hidepaste}
\tab{5}\spadcommand{a\free{ad2 }}
\indentrel{3}\begin{verbatim}
   (10)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangAssignPageEmpty10}
\begin{paste}{ugLangAssignPageEmpty10}{ugLangAssignPagePatch10}
\pastebutton{ugLangAssignPageEmpty10}{\showpaste}
\tab{5}\spadcommand{a\free{ad2 }}
\end{paste}\end{patch}

\begin{patch}{ugLangAssignPagePatch11}
\begin{paste}{ugLangAssignPageFull11}{ugLangAssignPageEmpty11}
\pastebutton{ugLangAssignPageFull11}{\hidepaste}
\tab{5}\spadcommand{b\free{bd ad2 }}
\indentrel{3}\begin{verbatim}
   (11)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangAssignPageEmpty11}
\begin{paste}{ugLangAssignPageEmpty11}{ugLangAssignPagePatch11}
\pastebutton{ugLangAssignPageEmpty11}{\showpaste}
\tab{5}\spadcommand{b\free{bd ad2 }}
\end{paste}\end{patch}

\begin{patch}{ugLangAssignPagePatch12}
\begin{paste}{ugLangAssignPageFull12}{ugLangAssignPageEmpty12}
\pastebutton{ugLangAssignPageFull12}{\hidepaste}
\tab{5}\spadcommand{(x,y) := (1,2)\bound{x }\bound{y }}
\indentrel{3}\begin{verbatim}
   (12)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangAssignPageEmpty12}
\begin{paste}{ugLangAssignPageEmpty12}{ugLangAssignPagePatch12}
\pastebutton{ugLangAssignPageEmpty12}{\showpaste}
\tab{5}\spadcommand{(x,y) := (1,2)\bound{x }\bound{y }}
\end{paste}\end{patch}

\begin{patch}{ugLangAssignPagePatch13}
\begin{paste}{ugLangAssignPageFull13}{ugLangAssignPageEmpty13}
\pastebutton{ugLangAssignPageFull13}{\hidepaste}
\tab{5}\spadcommand{(x,y) := (y,x)\free{x y }\bound{swap }}
\indentrel{3}\begin{verbatim}
   (13)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangAssignPageEmpty13}
\begin{paste}{ugLangAssignPageEmpty13}{ugLangAssignPagePatch13}
\pastebutton{ugLangAssignPageEmpty13}{\showpaste}
\tab{5}\spadcommand{(x,y) := (y,x)\free{x y }\bound{swap }}
\end{paste}\end{patch}

\begin{patch}{ugLangAssignPagePatch14}
\begin{paste}{ugLangAssignPageFull14}{ugLangAssignPageEmpty14}
\pastebutton{ugLangAssignPageFull14}{\hidepaste}
\tab{5}\spadcommand{x\free{swap }}
\indentrel{3}\begin{verbatim}
   (14)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangAssignPageEmpty14}
\begin{paste}{ugLangAssignPageEmpty14}{ugLangAssignPagePatch14}
\pastebutton{ugLangAssignPageEmpty14}{\showpaste}
\tab{5}\spadcommand{x\free{swap }}
\end{paste}\end{patch}

\begin{patch}{ugLangAssignPagePatch15}
\begin{paste}{ugLangAssignPageFull15}{ugLangAssignPageEmpty15}
\pastebutton{ugLangAssignPageFull15}{\hidepaste}
\tab{5}\spadcommand{y\free{swap }}
\indentrel{3}\begin{verbatim}
   (15)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangAssignPageEmpty15}
\begin{paste}{ugLangAssignPageEmpty15}{ugLangAssignPagePatch15}
\pastebutton{ugLangAssignPageEmpty15}{\showpaste}
\tab{5}\spadcommand{y\free{swap }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugLangBlocksPage}{ug05.ht}{Blocks}
\pageto{notitle}{ugLangIfPage}
\begin{chunk}{ug05.ht}
\begin{page}{ugLangBlocksPage}{5.2. Blocks}
\beginscroll

%%
%% We should handle tabs in pile correctly but so far we do not.
%%

A \spadgloss{block} is a sequence of expressions evaluated
in the order that they appear, except as modified by control expressions
such as \axiom{break},
\spadkey{break}
\axiom{return},
\spadkey{return}
\axiom{iterate} and
\spadkey{iterate}
\axiom{if-then-else} constructions.
The value of a block is the value of the expression last evaluated
in the block.

To leave a block early, use \axiomSyntax{=>}.
For example, \axiom{i < 0 => x}.
The expression before the \axiomSyntax{=>} must evaluate to
\axiom{true} or \axiom{false}.
The expression following the \axiomSyntax{=>} is the return value
for the block.

A block can be constructed in two ways:
\indent{4}
\beginitems
\item[1. ] the expressions can be separated by semicolons
and the resulting expression surrounded by parentheses, and
\item[2. ] the expressions can be written on succeeding lines with 
each line indented the same number of spaces (which must be greater 
than zero).
A block entered in this form is
called a \spadgloss{pile}.
\enditems
\indent{0}
Only the first form is available if you are entering expressions
directly to Axiom.
Both forms are available in {\bf .input} files.

\beginImportant
The syntax for a simple block of expressions entered interactively is
\centerline{{{\tt ( \subscriptIt{expression}{1}; 
\subscriptIt{expression}{2}; \ldots; \subscriptIt{expression}{N} )}}}
The value returned by a block is the value of an
\axiomSyntax{=>} expression, or \subscriptIt{expression}{N}
if no \axiomSyntax{=>} is encountered.
\endImportant

In {\bf .input} files, blocks can also be written using
\spadglossSee{piles}{pile}.
The examples throughout this book are assumed to come from 
{\bf .input} files.

\xtc{
In this example, we assign a rational number to \axiom{a} using a block
consisting of three expressions.
This block is written as a pile.
Each expression in the pile has the same indentation, in this case two
spaces to the right of the first line.
}{
\begin{spadsrc}
a :=
  i := gcd(234,672)
  i := 3*i**5 - i + 1
  1 / i
\end{spadsrc}
}
\xtc{
Here is the same block written on one line.
This is how you are required to enter it at the input prompt.
}{
\spadpaste{a := (i := gcd(234,672); i := 3*i**5 - i + 1; 1 / i)}
}
\xtc{
Blocks can be used to put several expressions on one line.
The value returned is that of the last expression.
}{
\spadpaste{(a := 1; b := 2; c := 3; [a,b,c]) \bound{a b c}}
}

Axiom gives you two ways of writing a block and the
preferred way in an {\bf .input} file is to use a pile.
Roughly speaking, a pile is
a block whose constituent expressions are indented the same amount.
You begin a pile by starting a new line for the first expression,
indenting it to the right of the previous line.
You then enter the second expression on a new line, vertically aligning
it with the first line. And so on.
If you need to enter an inner pile, further indent its lines to the right
of the outer pile.
Axiom knows where a pile ends.
It ends when a subsequent line is indented to the left of the pile or
the end of the file.

\xtc{
Blocks can be used to perform several steps before an assignment
(immediate or delayed) is made.
}{
\begin{spadsrc}[\free{a b}]
d :=
   c := a**2 + b**2
   sqrt(c * 1.3)
\end{spadsrc}
}
\xtc{
Blocks can be used in the arguments to functions.
(Here \axiom{h} is assigned \axiom{2.1 + 3.5}.)
}{
\begin{spadsrc}[\bound{h}]
h := 2.1 +
   1.0
   3.5
\end{spadsrc}
}
\xtc{
Here the second argument to \axiomFun{eval} is \axiom{x = z}, where
the value of \axiom{z} is computed in the first line of the block
starting on the second line.
}{
\begin{spadsrc}
eval(x**2 - x*y**2,
     z := %pi/2.0 - exp(4.1)
     x = z
   )
\end{spadsrc}
}
\xtc{
Blocks can be used in the clauses of \axiom{if-then-else}
expressions (see \downlink{``if-then-else''}{ugLangIfPage} 
in Section 5.3\ignore{ugLangIf}).
}{
\spadpaste{if h > 3.1 then 1.0 else (z := cos(h); max(z,0.5)) \free{h}}
}
\xtc{
This is the pile version of the last block.
}{
\begin{spadsrc}[\free{h}]
if h > 3.1 then
    1.0
  else
    z := cos(h)
    max(z,0.5)
\end{spadsrc}
}
\xtc{
Blocks can be nested.
}{
\spadpaste{
a := (b := factorial(12); c := (d := eulerPhi(22); factorial(d));b+c)}
}
\xtc{
This is the pile version of the last block.
}{
\begin{spadsrc}
a :=
  b := factorial(12)
  c :=
    d := eulerPhi(22)
    factorial(d)
  b+c
\end{spadsrc}
}

\xtc{
Since \axiom{c + d} does equal \axiom{3628855}, \axiom{a} has the value
of \axiom{c} and the last line is never evaluated.
}{
\begin{spadsrc}
a :=
  c := factorial 10
  d := fibonacci 10
  c + d = 3628855 => c
  d
\end{spadsrc}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugLangBlocksPagePatch1}
\begin{paste}{ugLangBlocksPageFull1}{ugLangBlocksPageEmpty1}
\pastebutton{ugLangBlocksPageFull1}{\hidepaste}
\tab{5}\spadcommand{a :=
  i := gcd(234,672)
  i := 3*i**5 - i + 1
  1 / i
}
\indentrel{3}\begin{verbatim}
          1
   (1)  ÄÄÄÄÄ
        23323
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangBlocksPageEmpty1}
\begin{paste}{ugLangBlocksPageEmpty1}{ugLangBlocksPagePatch1}
\pastebutton{ugLangBlocksPageEmpty1}{\showpaste}
\tab{5}\spadcommand{a :=
  i := gcd(234,672)
  i := 3*i**5 - i + 1
  1 / i
}
\end{paste}\end{patch}

\begin{patch}{ugLangBlocksPagePatch2}
\begin{paste}{ugLangBlocksPageFull2}{ugLangBlocksPageEmpty2}
\pastebutton{ugLangBlocksPageFull2}{\hidepaste}
\tab{5}\spadcommand{a := (i := gcd(234,672); i := 3*i**5 - i + 1; 1 / i)}
\indentrel{3}\begin{verbatim}
          1
   (2)  ÄÄÄÄÄ
        23323
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangBlocksPageEmpty2}
\begin{paste}{ugLangBlocksPageEmpty2}{ugLangBlocksPagePatch2}
\pastebutton{ugLangBlocksPageEmpty2}{\showpaste}
\tab{5}\spadcommand{a := (i := gcd(234,672); i := 3*i**5 - i + 1; 1 / i)}
\end{paste}\end{patch}

\begin{patch}{ugLangBlocksPagePatch3}
\begin{paste}{ugLangBlocksPageFull3}{ugLangBlocksPageEmpty3}
\pastebutton{ugLangBlocksPageFull3}{\hidepaste}
\tab{5}\spadcommand{(a := 1; b := 2; c := 3; [a,b,c])\bound{a b c }}
\indentrel{3}\begin{verbatim}
   (3)  [1,2,3]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangBlocksPageEmpty3}
\begin{paste}{ugLangBlocksPageEmpty3}{ugLangBlocksPagePatch3}
\pastebutton{ugLangBlocksPageEmpty3}{\showpaste}
\tab{5}\spadcommand{(a := 1; b := 2; c := 3; [a,b,c])\bound{a b c }}
\end{paste}\end{patch}

\begin{patch}{ugLangBlocksPagePatch4}
\begin{paste}{ugLangBlocksPageFull4}{ugLangBlocksPageEmpty4}
\pastebutton{ugLangBlocksPageFull4}{\hidepaste}
\tab{5}\spadcommand{d :=
   c := a**2 + b**2
   sqrt(c * 1.3)
\free{a b }}
\indentrel{3}\begin{verbatim}
   (4)  2.5495097567 96392415
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangBlocksPageEmpty4}
\begin{paste}{ugLangBlocksPageEmpty4}{ugLangBlocksPagePatch4}
\pastebutton{ugLangBlocksPageEmpty4}{\showpaste}
\tab{5}\spadcommand{d :=
   c := a**2 + b**2
   sqrt(c * 1.3)
\free{a b }}
\end{paste}\end{patch}

\begin{patch}{ugLangBlocksPagePatch5}
\begin{paste}{ugLangBlocksPageFull5}{ugLangBlocksPageEmpty5}
\pastebutton{ugLangBlocksPageFull5}{\hidepaste}
\tab{5}\spadcommand{h := 2.1 +
   1.0
   3.5
\bound{h }}
\indentrel{3}\begin{verbatim}
   (5)  5.6
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangBlocksPageEmpty5}
\begin{paste}{ugLangBlocksPageEmpty5}{ugLangBlocksPagePatch5}
\pastebutton{ugLangBlocksPageEmpty5}{\showpaste}
\tab{5}\spadcommand{h := 2.1 +
   1.0
   3.5
\bound{h }}
\end{paste}\end{patch}

\begin{patch}{ugLangBlocksPagePatch6}
\begin{paste}{ugLangBlocksPageFull6}{ugLangBlocksPageEmpty6}
\pastebutton{ugLangBlocksPageFull6}{\hidepaste}
\tab{5}\spadcommand{eval(x**2 - x*y**2,
     z := \%pi/2.0 - exp(4.1)
     x = z
   )
}
\indentrel{3}\begin{verbatim}
   (6)
                           2
   58.7694912705 67072878 y  + 3453.8531042012 59382
                                 Type: Polynomial Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangBlocksPageEmpty6}
\begin{paste}{ugLangBlocksPageEmpty6}{ugLangBlocksPagePatch6}
\pastebutton{ugLangBlocksPageEmpty6}{\showpaste}
\tab{5}\spadcommand{eval(x**2 - x*y**2,
     z := \%pi/2.0 - exp(4.1)
     x = z
   )
}
\end{paste}\end{patch}

\begin{patch}{ugLangBlocksPagePatch7}
\begin{paste}{ugLangBlocksPageFull7}{ugLangBlocksPageEmpty7}
\pastebutton{ugLangBlocksPageFull7}{\hidepaste}
\tab{5}\spadcommand{if h > 3.1 then 1.0 else (z := cos(h); max(z,0.5))\free{h }}
\indentrel{3}\begin{verbatim}
   (7)  1.0
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangBlocksPageEmpty7}
\begin{paste}{ugLangBlocksPageEmpty7}{ugLangBlocksPagePatch7}
\pastebutton{ugLangBlocksPageEmpty7}{\showpaste}
\tab{5}\spadcommand{if h > 3.1 then 1.0 else (z := cos(h); max(z,0.5))\free{h }}
\end{paste}\end{patch}

\begin{patch}{ugLangBlocksPagePatch8}
\begin{paste}{ugLangBlocksPageFull8}{ugLangBlocksPageEmpty8}
\pastebutton{ugLangBlocksPageFull8}{\hidepaste}
\tab{5}\spadcommand{if h > 3.1 then
    1.0
  else
    z := cos(h)
    max(z,0.5)
\free{h }}
\indentrel{3}\begin{verbatim}
   (8)  1.0
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangBlocksPageEmpty8}
\begin{paste}{ugLangBlocksPageEmpty8}{ugLangBlocksPagePatch8}
\pastebutton{ugLangBlocksPageEmpty8}{\showpaste}
\tab{5}\spadcommand{if h > 3.1 then
    1.0
  else
    z := cos(h)
    max(z,0.5)
\free{h }}
\end{paste}\end{patch}

\begin{patch}{ugLangBlocksPagePatch9}
\begin{paste}{ugLangBlocksPageFull9}{ugLangBlocksPageEmpty9}
\pastebutton{ugLangBlocksPageFull9}{\hidepaste}
\tab{5}\spadcommand{a := (b := factorial(12); c := (d := eulerPhi(22); factorial(d));b+c)}
\indentrel{3}\begin{verbatim}
   (9)  482630400
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangBlocksPageEmpty9}
\begin{paste}{ugLangBlocksPageEmpty9}{ugLangBlocksPagePatch9}
\pastebutton{ugLangBlocksPageEmpty9}{\showpaste}
\tab{5}\spadcommand{a := (b := factorial(12); c := (d := eulerPhi(22); factorial(d));b+c)}
\end{paste}\end{patch}

\begin{patch}{ugLangBlocksPagePatch10}
\begin{paste}{ugLangBlocksPageFull10}{ugLangBlocksPageEmpty10}
\pastebutton{ugLangBlocksPageFull10}{\hidepaste}
\tab{5}\spadcommand{a :=
  b := factorial(12)
  c :=
    d := eulerPhi(22)
    factorial(d)
  b+c
}
\indentrel{3}\begin{verbatim}
   (10)  482630400
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangBlocksPageEmpty10}
\begin{paste}{ugLangBlocksPageEmpty10}{ugLangBlocksPagePatch10}
\pastebutton{ugLangBlocksPageEmpty10}{\showpaste}
\tab{5}\spadcommand{a :=
  b := factorial(12)
  c :=
    d := eulerPhi(22)
    factorial(d)
  b+c
}
\end{paste}\end{patch}

\begin{patch}{ugLangBlocksPagePatch11}
\begin{paste}{ugLangBlocksPageFull11}{ugLangBlocksPageEmpty11}
\pastebutton{ugLangBlocksPageFull11}{\hidepaste}
\tab{5}\spadcommand{a :=
  c := factorial 10
  d := fibonacci 10
  c + d = 3628855 => c
  d
}
\indentrel{3}\begin{verbatim}
   (11)  3628800
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangBlocksPageEmpty11}
\begin{paste}{ugLangBlocksPageEmpty11}{ugLangBlocksPagePatch11}
\pastebutton{ugLangBlocksPageEmpty11}{\showpaste}
\tab{5}\spadcommand{a :=
  c := factorial 10
  d := fibonacci 10
  c + d = 3628855 => c
  d
}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugLangIfPage}{ug05.ht}{if-then-else}
\pageto{notitle}{ugTypesResolvePage}
\pageto{notitle}{ugTypesPkgCallPage}
\begin{chunk}{ug05.ht}
\begin{page}{ugLangIfPage}{5.3. if-then-else}
\beginscroll

Like many other programming languages, Axiom uses the three
keywords \spadkey{if} \axiom{if, then} \spadkey{then} and \axiom{else}
\spadkey{else} to form
conditional expressions.
The \axiom{else} part of the conditional is optional.
The expression between the \axiom{if} and \axiom{then} keywords
is a
\spadgloss{predicate}: an expression that evaluates to or is 
convertible to either {\tt true} or {\tt false}, that is,
a \axiomType{Boolean}.

\beginImportant The syntax for conditional expressions is
\centerline{{{\tt if {\it predicate} then \subscriptIt{expression}{1}
else \subscriptIt{expression}{2}}}} where the \axiom{else}
\subscriptIt{\it expression}{2} part is optional.  The value returned
from a conditional expression is \subscriptIt{\it expression}{1} if
the predicate evaluates to \axiom{true} and \subscriptIt{\it
expression}{2} otherwise.  If no \axiom{else} clause is given, the
value is always \void{}.  \endImportant

An \axiom{if-then-else} expression always returns a value.
If the
\axiom{else} clause is missing then the entire expression returns
\void{}.
If both clauses are present, the type of the value returned by \axiom{if}
is obtained by resolving the types of the values of the two clauses.
See \downlink{``Resolving Types''}{ugTypesResolvePage} 
in Section 2.10\ignore{ugTypesResolve}
for more information.

The predicate must evaluate to, or be convertible to, an object of type
\axiomType{Boolean}: {\tt true} or {\tt false}.
By default, the equal sign \spadopFrom{=}{Equation} creates
an equation.
\xtc{
This is an equation.
In particular, it is an object of type 
\axiomType{Equation Polynomial Integer}.
}{
\spadpaste{x + 1 = y}
}
However, for predicates in \axiom{if} expressions, Axiom
places a default target type of \axiomType{Boolean} on the
predicate and equality testing is performed.
Thus you need not qualify the \axiomSyntax{=} in any way.
In other contexts you may need to tell Axiom that you want
to test for equality rather than create an equation.
In those cases, use \axiomSyntax{@} and a target type of
\axiomType{Boolean}.
See \downlink{``Package Calling and Target Types''}
{ugTypesPkgCallPage} in Section 2.9
\ignore{ugTypesPkgCall} for more information.

The compound symbol meaning ``not equal'' in Axiom is
``\texht{$\sim =$}{\axiom{~=}}''.
This can be used directly without a package call or a target 
specification. The expression
\axiom{a} \texht{$\sim =$}{\axiom{~=}} \axiom{b} is directly 
translated into \axiom{not (a = b)}.

Many other functions have return values of type \axiomType{Boolean}.
These include \axiom{<}, \axiom{<=}, \axiom{>},
\axiom{>=}, \texht{$\sim =$}{\axiom{~=}} and \axiom{member?}.
By convention, operations with names ending in \axiomSyntax{?}
return \axiomType{Boolean} values.

The usual rules for piles are suspended for conditional expressions.
In {\bf .input} files, the \axiom{then} and
\axiom{else} keywords can begin in the same column as the corresponding
\axiom{if} but may also appear to the right.
Each of the following styles of writing \axiom{if-then-else}
expressions is acceptable:
\begin{verbatim}
if i>0 then output("positive") else output("nonpositive")

if i > 0 then output("positive")
  else output("nonpositive")

if i > 0 then output("positive")
else output("nonpositive")

if i > 0
then output("positive")
else output("nonpositive")

if i > 0
  then output("positive")
  else output("nonpositive")
\end{verbatim}

A block can follow the \axiom{then} or \axiom{else} keywords.
In the following two assignments to \axiom{a}, 
the \axiom{then} and \axiom{else}
clauses each are followed by two-line piles.
The value returned in each is the value of the second line.

\begin{verbatim}
a :=
  if i > 0 then
    j := sin(i * pi())
    exp(j + 1/j)
  else
    j := cos(i * 0.5 * pi())
    log(abs(j)**5 + 1)

a :=
  if i > 0
    then
      j := sin(i * pi())
      exp(j + 1/j)
    else
      j := cos(i * 0.5 * pi())
      log(abs(j)**5 + 1)
\end{verbatim}
These are both equivalent to the following:
\begin{verbatim}
a :=
  if i > 0 then (j := sin(i * pi()); exp(j + 1/j))
  else (j := cos(i * 0.5 * pi()); log(abs(j)**5 + 1))
\end{verbatim}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugLangIfPagePatch1}
\begin{paste}{ugLangIfPageFull1}{ugLangIfPageEmpty1}
\pastebutton{ugLangIfPageFull1}{\hidepaste}
\tab{5}\spadcommand{x + 1 = y}
\indentrel{3}\begin{verbatim}
   (1)  x + 1= y
                      Type: Equation Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangIfPageEmpty1}
\begin{paste}{ugLangIfPageEmpty1}{ugLangIfPagePatch1}
\pastebutton{ugLangIfPageEmpty1}{\showpaste}
\tab{5}\spadcommand{x + 1 = y}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugLangLoopsPage}{ug05.ht}{Loops}
\pageto{notitle}{ugLangLoopsCompIntPage}
\pageto{notitle}{ugLangLoopsReturnPage}
\pageto{notitle}{ugLangLoopsBreakPage}
\pageto{notitle}{ugLangLoopsBreakVsPage}
\pageto{notitle}{ugLangLoopsBreakMorePage}
\pageto{notitle}{ugLangLoopsIteratePage}
\pageto{notitle}{ugLangLoopsWhilePage}
\pageto{notitle}{ugLangLoopsForInPage}
\pageto{notitle}{ugLangLoopsForInNMPage}
\pageto{notitle}{ugLangLoopsForInNMSPage}
\pageto{notitle}{ugLangLoopsForInNPage}
\pageto{notitle}{ugLangLoopsForInXLPage}
\pageto{notitle}{ugLangLoopsForInPredPage}
\pageto{notitle}{ugLangLoopsParPage}
\begin{chunk}{ug05.ht}
\begin{page}{ugLangLoopsPage}{5.4. Loops}
\beginscroll

A \spadgloss{loop} is an expression that contains another expression,
called the {\it loop body}, which is to be evaluated zero or more
times.
All loops contain the \axiom{repeat} keyword and return \void{}.
Loops can contain inner loops to any depth.

\beginImportant
The most basic loop is of the form
\centerline{{\axiom{repeat} {\it loopBody}}}
Unless {\it loopBody} contains a \axiom{break} or \axiom{return} 
expression, the loop repeats forever.
The value returned by the loop is \void{}.
\endImportant

\beginmenu
    \menudownlink{{5.4.1. Compiling vs. Interpreting Loops}}
{ugLangLoopsCompIntPage}
    \menudownlink{{5.4.2. return in Loops}}{ugLangLoopsReturnPage}
    \menudownlink{{5.4.3. break in Loops}}{ugLangLoopsBreakPage}
    \menudownlink{{5.4.4. break vs. {\tt =>} in Loop Bodies}}
{ugLangLoopsBreakVsPage}
    \menudownlink{{5.4.5. More Examples of break}}
{ugLangLoopsBreakMorePage}
    \menudownlink{{5.4.6. iterate in Loops}}{ugLangLoopsIteratePage}
    \menudownlink{{5.4.7. while Loops}}{ugLangLoopsWhilePage}
    \menudownlink{{5.4.8. for Loops}}{ugLangLoopsForInPage}
    \menudownlink{{5.4.9. for i in n..m repeat}}
{ugLangLoopsForInNMPage}
    \menudownlink{{5.4.10. for i in n..m by s repeat}}
{ugLangLoopsForInNMSPage}
    \menudownlink{{5.4.11. for i in n.. repeat}}{ugLangLoopsForInNPage}
    \menudownlink{{5.4.12. for x in l repeat}}{ugLangLoopsForInXLPage}
    \menudownlink{{5.4.13. ``Such that'' Predicates}}
{ugLangLoopsForInPredPage}
    \menudownlink{{5.4.14. Parallel Iteration}}{ugLangLoopsParPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugLangLoopsCompIntPage}{ug05.ht}
{Compiling vs. Interpreting Loops}
\pageto{notitle}{ugUserCompIntPage}
\begin{chunk}{ug05.ht}
\begin{page}{ugLangLoopsCompIntPage}
{5.4.1. Compiling vs. Interpreting Loops}
\beginscroll

Axiom tries to determine completely the type of every
object in a loop and then to translate the loop body to LISP or even to
machine code.
This translation is called \spadglossSee{compilation}{compiler}.

If Axiom decides that it cannot compile the loop, it issues a
message stating the problem and then the following message:
%
\centerline{
{{\bf We will attempt to step through and interpret the code.}}}
%
It is still possible that Axiom can evaluate the loop but in
\spadgloss{interpret-code mode}.
See \downlink{``Compiling vs. Interpreting''}{ugUserCompIntPage} 
in Section 6.10\ignore{ugUserCompInt} where 
this is discussed in terms
of compiling versus interpreting functions.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugLangLoopsReturnPage}{ug05.ht}{return in Loops}
\pageto{notitle}{ugUserBlocksPage}
\begin{chunk}{ug05.ht}
\begin{page}{ugLangLoopsReturnPage}{5.4.2. return in Loops}
\beginscroll

A \axiom{return} expression is used to exit a function with
a particular value.
In particular, if a \axiom{return} is in a loop within the
\spadkey{return}
function, the loop is terminated whenever the \axiom{return}
is evaluated.
%> This is a bug! The compiler should never accept allow
%> Void to be the return type of a function when it has to use
%> resolve to determine it.
\xtc{
Suppose we start with this.
}{
\begin{spadsrc}[\bound{f}]
f() ==
  i := 1
  repeat
    if factorial(i) > 1000 then return i
    i := i + 1
\end{spadsrc}
}
\xtc{
When \axiom{factorial(i)} is big enough, control passes from
inside the loop all the way outside the function, returning the
value of \axiom{i} (or so we think).
}{
\spadpaste{f() \free{f}}
}

What went wrong?
Isn't it obvious that this function should return an integer?
Well, Axiom makes no attempt to analyze the structure of a
loop to determine if it always returns a value because, in
general, this is impossible.
So Axiom has this simple rule: the type of the function is
determined by the type of its body, in this case a block.
The normal value of a block is the value of its last expression,
in this case, a loop.
And the value of every loop is \void{}!
So the return type of \userfun{f} is \axiomType{Void}.

There are two ways to fix this.
The best way is for you to tell Axiom what the return type
of \axiom{f} is.
You do this by giving \axiom{f} a declaration \axiom{f: () ->
Integer} prior to calling for its value.
This tells Axiom: ``trust me---an integer is returned.''
We'll explain more about this in the next chapter.
Another clumsy way is to add a dummy expression as follows.

\xtc{
Since we want an integer, let's stick in a dummy final expression that is
an integer and will never be evaluated.
}{
\begin{spadsrc}[\bound{f1}]
f() ==
  i := 1
  repeat
    if factorial(i) > 1000 then return i
    i := i + 1
  0
\end{spadsrc}
}
\xtc{
When we try \userfun{f} again we get what we wanted.
See
\downlink{``Functions Defined with Blocks''}{ugUserBlocksPage} 
in Section 6.15\ignore{ugUserBlocks}
for more information.
}{
\spadpaste{f() \free{f1}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugLangLoopsReturnPagePatch1}
\begin{paste}{ugLangLoopsReturnPageFull1}{ugLangLoopsReturnPageEmpty1}
\pastebutton{ugLangLoopsReturnPageFull1}{\hidepaste}
\tab{5}\spadcommand{f() ==
  i := 1
  repeat
    if factorial(i) > 1000 then return i
    i := i + 1
\bound{f }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsReturnPageEmpty1}
\begin{paste}{ugLangLoopsReturnPageEmpty1}{ugLangLoopsReturnPagePatch1}
\pastebutton{ugLangLoopsReturnPageEmpty1}{\showpaste}
\tab{5}\spadcommand{f() ==
  i := 1
  repeat
    if factorial(i) > 1000 then return i
    i := i + 1
\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsReturnPagePatch2}
\begin{paste}{ugLangLoopsReturnPageFull2}{ugLangLoopsReturnPageEmpty2}
\pastebutton{ugLangLoopsReturnPageFull2}{\hidepaste}
\tab{5}\spadcommand{f()\free{f }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsReturnPageEmpty2}
\begin{paste}{ugLangLoopsReturnPageEmpty2}{ugLangLoopsReturnPagePatch2}
\pastebutton{ugLangLoopsReturnPageEmpty2}{\showpaste}
\tab{5}\spadcommand{f()\free{f }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsReturnPagePatch3}
\begin{paste}{ugLangLoopsReturnPageFull3}{ugLangLoopsReturnPageEmpty3}
\pastebutton{ugLangLoopsReturnPageFull3}{\hidepaste}
\tab{5}\spadcommand{f() ==
  i := 1
  repeat
    if factorial(i) > 1000 then return i
    i := i + 1
  0
\bound{f1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsReturnPageEmpty3}
\begin{paste}{ugLangLoopsReturnPageEmpty3}{ugLangLoopsReturnPagePatch3}
\pastebutton{ugLangLoopsReturnPageEmpty3}{\showpaste}
\tab{5}\spadcommand{f() ==
  i := 1
  repeat
    if factorial(i) > 1000 then return i
    i := i + 1
  0
\bound{f1 }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsReturnPagePatch4}
\begin{paste}{ugLangLoopsReturnPageFull4}{ugLangLoopsReturnPageEmpty4}
\pastebutton{ugLangLoopsReturnPageFull4}{\hidepaste}
\tab{5}\spadcommand{f()\free{f1 }}
\indentrel{3}\begin{verbatim}
   (4)  7
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsReturnPageEmpty4}
\begin{paste}{ugLangLoopsReturnPageEmpty4}{ugLangLoopsReturnPagePatch4}
\pastebutton{ugLangLoopsReturnPageEmpty4}{\showpaste}
\tab{5}\spadcommand{f()\free{f1 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugLangLoopsBreakPage}{ug05.ht}{break in Loops}
\pageto{notitle}{ugLangLoopsReturnPage}
\begin{chunk}{ug05.ht}
\begin{page}{ugLangLoopsBreakPage}{5.4.3. break in Loops}
\beginscroll

The \axiom{break} keyword is often more useful
\spadkey{break}
in terminating
a loop.
%>  and more in keeping with the ideas of structured programming.
A \axiom{break} causes control to transfer to the expression
immediately following the loop.
As loops always return \void{},
you cannot return a value with \axiom{break}.
That is, \axiom{break} takes no argument.

\xtc{
This example is a modification of the last example in
\texht{the previous section}{
\downlink{``return in Loops''}{ugLangLoopsReturnPage} 
in Section 5.4.2\ignore{ugLangLoopsReturn}}.
Instead of using \axiom{return}, we'll use \axiom{break}.
}{
\begin{spadsrc}[\bound{f1}]
f() ==
  i := 1
  repeat
    if factorial(i) > 1000 then break
    i := i + 1
  i
\end{spadsrc}
}
\xtc{
The loop terminates when \axiom{factorial(i)} gets big enough,
the last line of the function evaluates to the corresponding ``good''
value of \axiom{i}, and the function terminates, returning that value.
}{
\spadpaste{f() \free{f1}}
}
\xtc{
You can only use \axiom{break} to terminate the evaluation of one loop.
Let's consider a loop within a loop, that is, a loop with a nested loop.
First, we initialize two counter variables.
}{
\spadpaste{(i,j) := (1, 1) \bound{i}\bound{j}}
}
\xtc{
Nested loops must have multiple \axiom{break}
expressions at the appropriate nesting level.
How would you rewrite this so \axiom{(i + j) > 10} is only evaluated once?
}{
\begin{spadsrc}[\free{i j}]
repeat
  repeat
    if (i + j) > 10 then break
    j := j + 1
  if (i + j) > 10 then break
  i := i + 1
\end{spadsrc}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugLangLoopsBreakPagePatch1}
\begin{paste}{ugLangLoopsBreakPageFull1}{ugLangLoopsBreakPageEmpty1}
\pastebutton{ugLangLoopsBreakPageFull1}{\hidepaste}
\tab{5}\spadcommand{f() ==
  i := 1
  repeat
    if factorial(i) > 1000 then break
    i := i + 1
  i
\bound{f1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakPageEmpty1}
\begin{paste}{ugLangLoopsBreakPageEmpty1}{ugLangLoopsBreakPagePatch1}
\pastebutton{ugLangLoopsBreakPageEmpty1}{\showpaste}
\tab{5}\spadcommand{f() ==
  i := 1
  repeat
    if factorial(i) > 1000 then break
    i := i + 1
  i
\bound{f1 }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakPagePatch2}
\begin{paste}{ugLangLoopsBreakPageFull2}{ugLangLoopsBreakPageEmpty2}
\pastebutton{ugLangLoopsBreakPageFull2}{\hidepaste}
\tab{5}\spadcommand{f()\free{f1 }}
\indentrel{3}\begin{verbatim}
   (2)  7
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakPageEmpty2}
\begin{paste}{ugLangLoopsBreakPageEmpty2}{ugLangLoopsBreakPagePatch2}
\pastebutton{ugLangLoopsBreakPageEmpty2}{\showpaste}
\tab{5}\spadcommand{f()\free{f1 }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakPagePatch3}
\begin{paste}{ugLangLoopsBreakPageFull3}{ugLangLoopsBreakPageEmpty3}
\pastebutton{ugLangLoopsBreakPageFull3}{\hidepaste}
\tab{5}\spadcommand{(i,j) := (1, 1)\bound{i }\bound{j }}
\indentrel{3}\begin{verbatim}
   (3)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakPageEmpty3}
\begin{paste}{ugLangLoopsBreakPageEmpty3}{ugLangLoopsBreakPagePatch3}
\pastebutton{ugLangLoopsBreakPageEmpty3}{\showpaste}
\tab{5}\spadcommand{(i,j) := (1, 1)\bound{i }\bound{j }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakPagePatch4}
\begin{paste}{ugLangLoopsBreakPageFull4}{ugLangLoopsBreakPageEmpty4}
\pastebutton{ugLangLoopsBreakPageFull4}{\hidepaste}
\tab{5}\spadcommand{repeat
  repeat
    if (i + j) > 10 then break
    j := j + 1
  if (i + j) > 10 then break
  i := i + 1
\free{i j }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakPageEmpty4}
\begin{paste}{ugLangLoopsBreakPageEmpty4}{ugLangLoopsBreakPagePatch4}
\pastebutton{ugLangLoopsBreakPageEmpty4}{\showpaste}
\tab{5}\spadcommand{repeat
  repeat
    if (i + j) > 10 then break
    j := j + 1
  if (i + j) > 10 then break
  i := i + 1
\free{i j }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugLangLoopsBreakVsPage}{ug05.ht}
{break vs. {\tt =>} in Loop Bodies}
\begin{chunk}{ug05.ht}
\begin{page}{ugLangLoopsBreakVsPage}
{5.4.4. break vs. {\tt =>} in Loop Bodies}
\beginscroll

Compare the following two loops:

\begin{verbatim}
i := 1                            i := 1
repeat                            repeat
  i := i + 1                        i := i + 1
  i > 3 => i                        if i > 3 then break
  output(i)                         output(i)
\end{verbatim}

In the example on the left, the values
\mathOrSpad{2} and \mathOrSpad{3} for \axiom{i} are displayed
but then the \axiomSyntax{=>} does not allow control to reach the call to
\axiomFunFrom{output}{OutputForm} again.
The loop will not terminate
until you run out of space or interrupt the execution.
The variable \axiom{i} will continue to be incremented because
the \axiomSyntax{=>} only means to leave the {\it block,} not the loop.

In the example on the right,
upon reaching \mathOrSpad{4}, the \axiom{break} will be
executed, and both the block and the loop will terminate.
This is one of the reasons why both \axiomSyntax{=>} and \axiom{break} are
provided.
Using a \axiom{while} clause (see below) with the \axiomSyntax{=>}
\spadkey{while}
lets you simulate the action of \axiom{break}.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugLangLoopsBreakMorePage}{ug05.ht}{More Examples of break}
\pageto{notitle}{ugLangLoopsForInPage}
\begin{chunk}{ug05.ht}
\begin{page}{ugLangLoopsBreakMorePage}{5.4.5. More Examples of break}
\beginscroll

Here we give four examples of \axiom{repeat} loops that
terminate when a value exceeds a given bound.

\texht{\vskip 1pc}{}
\xtc{
First, initialize \axiom{i} as the loop counter.
}{
\spadpaste{i := 0 \bound{i}}
}
\xtc{
Here is the first loop.
When the square of \axiom{i} exceeds \axiom{100}, the loop terminates.
}{
\begin{spadsrc}[\free{i}\bound{i1}]
repeat
  i := i + 1
  if i**2 > 100 then break
\end{spadsrc}
}
\xtc{
Upon completion, \axiom{i} should have the value \axiom{11}.
}{
\spadpaste{i \free{i1}}
}
%
%
\xtc{
Do the same thing except use \axiomSyntax{=>} instead
an \axiom{if-then} expression.
}{
\spadpaste{i := 0 \bound{i2}}
}
\xtc{
}{
\begin{spadsrc}[\free{i2}\bound{i3}]
repeat
  i := i + 1
  i**2 > 100 => break
\end{spadsrc}
}
\xtc{
}{
\spadpaste{i \free{i3}}
}
%
%
\xtc{
As a third example, we use a simple loop to compute \axiom{n!}.
}{
\spadpaste{(n, i, f) := (100, 1, 1) \bound{n}\bound{i4}\bound{f}}
}
\xtc{
Use \axiom{i} as the iteration variable and \axiom{f}
to compute the factorial.
}{
\begin{spadsrc}[\bound{f1}\bound{i5}\free{f i4 n}]
repeat
  if i > n then break
  f := f * i
  i := i + 1
\end{spadsrc}
}
\xtc{
Look at the value of \axiom{f}.
}{
\spadpaste{f \free{f1}}
}
%
%
\xtc{
Finally, we show an example of nested loops.
First define a four by four matrix.
}{
\spadpaste{m := 
matrix [[21,37,53,14], [8,-24,22,-16], [2,10,15,14], 
[26,33,55,-13]] \bound{m2}}
}
\xtc{
Next, set row counter \axiom{r} and column counter \axiom{c} to
\mathOrSpad{1}.
Note: if we were writing a function, these would all be local
variables rather than global workspace variables.
}{
\spadpaste{(r, c) := (1, 1) \bound{r}\bound{c}}
}
\xtc{
Also, let \axiom{lastrow} and
\axiom{lastcol} be the final row and column index.
}{
\spadpaste{(lastrow, lastcol) := (nrows(m), ncols(m)) 
\bound{lastrow}\bound{lastcol}\free{m2}}
}
%
\xtc{
Scan the rows looking for the first negative element.
We remark that you can reformulate this example in a better, more
concise form by using a \axiom{for} clause with \axiom{repeat}.
See
\downlink{``for Loops''}{ugLangLoopsForInPage} 
in Section 5.4.8\ignore{ugLangLoopsForIn}
for more information.
}{
\begin{spadsrc}[\free{m2 r c lastrow lastcol}]
repeat
  if r > lastrow then break
  c := 1
  repeat
    if c > lastcol then break
    if elt(m,r,c) < 0 then
      output [r, c, elt(m,r,c)]
      r := lastrow
      break     -- don't look any further
    c := c + 1
  r := r + 1
\end{spadsrc}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugLangLoopsBreakMorePagePatch1}
\begin{paste}{ugLangLoopsBreakMorePageFull1}{ugLangLoopsBreakMorePageEmpty1}
\pastebutton{ugLangLoopsBreakMorePageFull1}{\hidepaste}
\tab{5}\spadcommand{i := 0\bound{i }}
\indentrel{3}\begin{verbatim}
   (1)  0
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePageEmpty1}
\begin{paste}{ugLangLoopsBreakMorePageEmpty1}{ugLangLoopsBreakMorePagePatch1}
\pastebutton{ugLangLoopsBreakMorePageEmpty1}{\showpaste}
\tab{5}\spadcommand{i := 0\bound{i }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePagePatch2}
\begin{paste}{ugLangLoopsBreakMorePageFull2}{ugLangLoopsBreakMorePageEmpty2}
\pastebutton{ugLangLoopsBreakMorePageFull2}{\hidepaste}
\tab{5}\spadcommand{repeat
  i := i + 1
  if i**2 > 100 then break
\free{i }\bound{i1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePageEmpty2}
\begin{paste}{ugLangLoopsBreakMorePageEmpty2}{ugLangLoopsBreakMorePagePatch2}
\pastebutton{ugLangLoopsBreakMorePageEmpty2}{\showpaste}
\tab{5}\spadcommand{repeat
  i := i + 1
  if i**2 > 100 then break
\free{i }\bound{i1 }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePagePatch3}
\begin{paste}{ugLangLoopsBreakMorePageFull3}{ugLangLoopsBreakMorePageEmpty3}
\pastebutton{ugLangLoopsBreakMorePageFull3}{\hidepaste}
\tab{5}\spadcommand{i\free{i1 }}
\indentrel{3}\begin{verbatim}
   (3)  11
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePageEmpty3}
\begin{paste}{ugLangLoopsBreakMorePageEmpty3}{ugLangLoopsBreakMorePagePatch3}
\pastebutton{ugLangLoopsBreakMorePageEmpty3}{\showpaste}
\tab{5}\spadcommand{i\free{i1 }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePagePatch4}
\begin{paste}{ugLangLoopsBreakMorePageFull4}{ugLangLoopsBreakMorePageEmpty4}
\pastebutton{ugLangLoopsBreakMorePageFull4}{\hidepaste}
\tab{5}\spadcommand{i := 0\bound{i2 }}
\indentrel{3}\begin{verbatim}
   (4)  0
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePageEmpty4}
\begin{paste}{ugLangLoopsBreakMorePageEmpty4}{ugLangLoopsBreakMorePagePatch4}
\pastebutton{ugLangLoopsBreakMorePageEmpty4}{\showpaste}
\tab{5}\spadcommand{i := 0\bound{i2 }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePagePatch5}
\begin{paste}{ugLangLoopsBreakMorePageFull5}{ugLangLoopsBreakMorePageEmpty5}
\pastebutton{ugLangLoopsBreakMorePageFull5}{\hidepaste}
\tab{5}\spadcommand{repeat
  i := i + 1
  i**2 > 100 => break
\free{i2 }\bound{i3 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePageEmpty5}
\begin{paste}{ugLangLoopsBreakMorePageEmpty5}{ugLangLoopsBreakMorePagePatch5}
\pastebutton{ugLangLoopsBreakMorePageEmpty5}{\showpaste}
\tab{5}\spadcommand{repeat
  i := i + 1
  i**2 > 100 => break
\free{i2 }\bound{i3 }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePagePatch6}
\begin{paste}{ugLangLoopsBreakMorePageFull6}{ugLangLoopsBreakMorePageEmpty6}
\pastebutton{ugLangLoopsBreakMorePageFull6}{\hidepaste}
\tab{5}\spadcommand{i\free{i3 }}
\indentrel{3}\begin{verbatim}
   (6)  11
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePageEmpty6}
\begin{paste}{ugLangLoopsBreakMorePageEmpty6}{ugLangLoopsBreakMorePagePatch6}
\pastebutton{ugLangLoopsBreakMorePageEmpty6}{\showpaste}
\tab{5}\spadcommand{i\free{i3 }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePagePatch7}
\begin{paste}{ugLangLoopsBreakMorePageFull7}{ugLangLoopsBreakMorePageEmpty7}
\pastebutton{ugLangLoopsBreakMorePageFull7}{\hidepaste}
\tab{5}\spadcommand{(n, i, f) := (100, 1, 1)\bound{n }\bound{i4 }\bound{f }}
\indentrel{3}\begin{verbatim}
   (7)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePageEmpty7}
\begin{paste}{ugLangLoopsBreakMorePageEmpty7}{ugLangLoopsBreakMorePagePatch7}
\pastebutton{ugLangLoopsBreakMorePageEmpty7}{\showpaste}
\tab{5}\spadcommand{(n, i, f) := (100, 1, 1)\bound{n }\bound{i4 }\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePagePatch8}
\begin{paste}{ugLangLoopsBreakMorePageFull8}{ugLangLoopsBreakMorePageEmpty8}
\pastebutton{ugLangLoopsBreakMorePageFull8}{\hidepaste}
\tab{5}\spadcommand{repeat
  if i > n then break
  f := f * i
  i := i + 1
\bound{f1 }\bound{i5 }\free{f i4 n }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePageEmpty8}
\begin{paste}{ugLangLoopsBreakMorePageEmpty8}{ugLangLoopsBreakMorePagePatch8}
\pastebutton{ugLangLoopsBreakMorePageEmpty8}{\showpaste}
\tab{5}\spadcommand{repeat
  if i > n then break
  f := f * i
  i := i + 1
\bound{f1 }\bound{i5 }\free{f i4 n }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePagePatch9}
\begin{paste}{ugLangLoopsBreakMorePageFull9}{ugLangLoopsBreakMorePageEmpty9}
\pastebutton{ugLangLoopsBreakMorePageFull9}{\hidepaste}
\tab{5}\spadcommand{f\free{f1 }}
\indentrel{3}\begin{verbatim}
   (9)
  933262154439441526816992388562667004907159682643816214_
   68592963895217599993229915608941463976156518286253697_
   920827223758251185210916864000000000000000000000000
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePageEmpty9}
\begin{paste}{ugLangLoopsBreakMorePageEmpty9}{ugLangLoopsBreakMorePagePatch9}
\pastebutton{ugLangLoopsBreakMorePageEmpty9}{\showpaste}
\tab{5}\spadcommand{f\free{f1 }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePagePatch10}
\begin{paste}{ugLangLoopsBreakMorePageFull10}{ugLangLoopsBreakMorePageEmpty10}
\pastebutton{ugLangLoopsBreakMorePageFull10}{\hidepaste}
\tab{5}\spadcommand{m := matrix [[21,37,53,14], [8,-24,22,-16], [2,10,15,14], [26,33,55,-13]]\bound{m2 }}
\indentrel{3}\begin{verbatim}
         Ú21   37   53   14 ¿
         ³                  ³
         ³8   - 24  22  - 16³
   (10)  ³                  ³
         ³2    10   15   14 ³
         ³                  ³
         À26   33   55  - 13Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePageEmpty10}
\begin{paste}{ugLangLoopsBreakMorePageEmpty10}{ugLangLoopsBreakMorePagePatch10}
\pastebutton{ugLangLoopsBreakMorePageEmpty10}{\showpaste}
\tab{5}\spadcommand{m := matrix [[21,37,53,14], [8,-24,22,-16], [2,10,15,14], [26,33,55,-13]]\bound{m2 }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePagePatch11}
\begin{paste}{ugLangLoopsBreakMorePageFull11}{ugLangLoopsBreakMorePageEmpty11}
\pastebutton{ugLangLoopsBreakMorePageFull11}{\hidepaste}
\tab{5}\spadcommand{(r, c) := (1, 1)\bound{r }\bound{c }}
\indentrel{3}\begin{verbatim}
   (11)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePageEmpty11}
\begin{paste}{ugLangLoopsBreakMorePageEmpty11}{ugLangLoopsBreakMorePagePatch11}
\pastebutton{ugLangLoopsBreakMorePageEmpty11}{\showpaste}
\tab{5}\spadcommand{(r, c) := (1, 1)\bound{r }\bound{c }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePagePatch12}
\begin{paste}{ugLangLoopsBreakMorePageFull12}{ugLangLoopsBreakMorePageEmpty12}
\pastebutton{ugLangLoopsBreakMorePageFull12}{\hidepaste}
\tab{5}\spadcommand{(lastrow, lastcol) := (nrows(m), ncols(m))\bound{lastrow }\bound{lastcol }\free{m2 }}
\indentrel{3}\begin{verbatim}
   (12)  4
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePageEmpty12}
\begin{paste}{ugLangLoopsBreakMorePageEmpty12}{ugLangLoopsBreakMorePagePatch12}
\pastebutton{ugLangLoopsBreakMorePageEmpty12}{\showpaste}
\tab{5}\spadcommand{(lastrow, lastcol) := (nrows(m), ncols(m))\bound{lastrow }\bound{lastcol }\free{m2 }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePagePatch13}
\begin{paste}{ugLangLoopsBreakMorePageFull13}{ugLangLoopsBreakMorePageEmpty13}
\pastebutton{ugLangLoopsBreakMorePageFull13}{\hidepaste}
\tab{5}\spadcommand{repeat
  if r > lastrow then break
  c := 1
  repeat
    if c > lastcol then break
    if elt(m,r,c) < 0 then
      output [r, c, elt(m,r,c)]
      r := lastrow
      break     -- don't look any further
    c := c + 1
  r := r + 1
\free{m2 r c lastrow lastcol }}
\indentrel{3}\begin{verbatim}
   [2,2,- 24]
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsBreakMorePageEmpty13}
\begin{paste}{ugLangLoopsBreakMorePageEmpty13}{ugLangLoopsBreakMorePagePatch13}
\pastebutton{ugLangLoopsBreakMorePageEmpty13}{\showpaste}
\tab{5}\spadcommand{repeat
  if r > lastrow then break
  c := 1
  repeat
    if c > lastcol then break
    if elt(m,r,c) < 0 then
      output [r, c, elt(m,r,c)]
      r := lastrow
      break     -- don't look any further
    c := c + 1
  r := r + 1
\free{m2 r c lastrow lastcol }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugLangLoopsIteratePage}{ug05.ht}{iterate in Loops}
\begin{chunk}{ug05.ht}
\begin{page}{ugLangLoopsIteratePage}{5.4.6. iterate in Loops}
\beginscroll

Axiom provides an \axiom{iterate} expression that
\spadkey{iterate}
skips over the remainder of a loop body and starts the next loop iteration.
\xtc{
We first initialize a counter.
}{
\spadpaste{i := 0 \bound{i}}
}
\xtc{
Display the even integers from \axiom{2} to \axiom{5}.
}{
\begin{spadsrc}[\free{i}]
repeat
  i := i + 1
  if i > 5 then break
  if odd?(i) then iterate
  output(i)
\end{spadsrc}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugLangLoopsIteratePagePatch1}
\begin{paste}{ugLangLoopsIteratePageFull1}{ugLangLoopsIteratePageEmpty1}
\pastebutton{ugLangLoopsIteratePageFull1}{\hidepaste}
\tab{5}\spadcommand{i := 0\bound{i }}
\indentrel{3}\begin{verbatim}
   (1)  0
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsIteratePageEmpty1}
\begin{paste}{ugLangLoopsIteratePageEmpty1}{ugLangLoopsIteratePagePatch1}
\pastebutton{ugLangLoopsIteratePageEmpty1}{\showpaste}
\tab{5}\spadcommand{i := 0\bound{i }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsIteratePagePatch2}
\begin{paste}{ugLangLoopsIteratePageFull2}{ugLangLoopsIteratePageEmpty2}
\pastebutton{ugLangLoopsIteratePageFull2}{\hidepaste}
\tab{5}\spadcommand{repeat
  i := i + 1
  if i > 5 then break
  if odd?(i) then iterate
  output(i)
\free{i }}
\indentrel{3}\begin{verbatim}
   2
   4
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsIteratePageEmpty2}
\begin{paste}{ugLangLoopsIteratePageEmpty2}{ugLangLoopsIteratePagePatch2}
\pastebutton{ugLangLoopsIteratePageEmpty2}{\showpaste}
\tab{5}\spadcommand{repeat
  i := i + 1
  if i > 5 then break
  if odd?(i) then iterate
  output(i)
\free{i }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugLangLoopsWhilePage}{ug05.ht}{while Loops}
\begin{chunk}{ug05.ht}
\begin{page}{ugLangLoopsWhilePage}{5.4.7. while Loops}
\beginscroll

The \axiom{repeat} in a loop can be modified by adding one or
more \axiom{while} clauses.
\spadkey{while}
Each clause contains a \spadgloss{predicate}
immediately following the \axiom{while} keyword.
The predicate is tested {\it before}
the evaluation of the body of the loop.
The loop body is evaluated whenever the predicates in a \axiom{while}
clause are all \axiom{true}.

\beginImportant
The syntax for a simple loop using \axiom{while} is
\centerline{{\axiom{while} {\it predicate} \axiom{repeat} {\it loopBody}}}
The {\it predicate} is evaluated before {\it loopBody} is evaluated.
A \axiom{while} loop terminates immediately when {\it predicate}
evaluates to \axiom{false} or when a \axiom{break} or \axiom{return}
expression is evaluated in {\it loopBody}.
The value returned by the loop is \void{}.
\endImportant

\xtc{
Here is a simple example of using \axiom{while} in a loop.
We first initialize the counter.
}{
\spadpaste{i := 1 \bound{i}}
}
\xtc{
The steps involved in computing this example are
(1) set \axiom{i} to \axiom{1}, (2) test the condition \axiom{i < 1} and
determine that it is not true, and (3) do not evaluate the
loop body and therefore do not display \axiom{"hello"}.
}{
\begin{spadsrc}[\free{i}]
while i < 1 repeat
  output "hello"
  i := i + 1
\end{spadsrc}
}
\xtc{
If you have multiple predicates to be tested use the
logical \axiom{and} operation to separate them.
Axiom evaluates these predicates from left to right.
}{
\spadpaste{(x, y) := (1, 1) \bound{x}\bound{y}}
}
\xtc{
}{
\begin{spadsrc}[\free{x y}]
while x < 4 and y < 10 repeat
  output [x,y]
  x := x + 1
  y := y + 2
\end{spadsrc}
}
\xtc{
A \axiom{break} expression can be included in a loop body to terminate
a loop even if the predicate in any \axiom{while} clauses are not
\axiom{false}.
}{
\spadpaste{(x, y) := (1, 1) \bound{x1}\bound{y1}}
}
\xtc{
This loop has multiple \axiom{while} clauses and the loop terminates
before any one of their conditions evaluates to \axiom{false}.
}{
\begin{spadsrc}[\free{x1 y1}]
while x < 4 while y < 10 repeat
  if x + y > 7 then break
  output [x,y]
  x := x + 1
  y := y + 2
\end{spadsrc}
}
\xtc{
Here's a different version of the nested loops that looked
for the first negative element in a matrix.
}{
\spadpaste{m := matrix [[21,37,53,14], [8,-24,22,-16], [2,10,15,14], 
[26,33,55,-13]] \bound{m2}}
}
\xtc{
Initialized the row index to \axiom{1} and
get the number of rows and columns.
If we were writing a function, these would all be
local variables.
}{
\spadpaste{r := 1 \bound{r}}
}
\xtc{
}{
\spadpaste{(lastrow, lastcol) := (nrows(m), ncols(m)) 
\bound{lastrow}\bound{lastcol}\free{m2}}
}
%
\xtc{
Scan the rows looking for the first negative element.
}{
\begin{spadsrc}[\free{m2 r lastrow lastcol}]
while r <= lastrow repeat
  c := 1  -- index of first column
  while c <= lastcol repeat
    if elt(m,r,c) < 0 then
      output [r, c, elt(m,r,c)]
      r := lastrow
      break     -- don't look any further
    c := c + 1
  r := r + 1
\end{spadsrc}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugLangLoopsWhilePagePatch1}
\begin{paste}{ugLangLoopsWhilePageFull1}{ugLangLoopsWhilePageEmpty1}
\pastebutton{ugLangLoopsWhilePageFull1}{\hidepaste}
\tab{5}\spadcommand{i := 1\bound{i }}
\indentrel{3}\begin{verbatim}
   (1)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsWhilePageEmpty1}
\begin{paste}{ugLangLoopsWhilePageEmpty1}{ugLangLoopsWhilePagePatch1}
\pastebutton{ugLangLoopsWhilePageEmpty1}{\showpaste}
\tab{5}\spadcommand{i := 1\bound{i }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsWhilePagePatch2}
\begin{paste}{ugLangLoopsWhilePageFull2}{ugLangLoopsWhilePageEmpty2}
\pastebutton{ugLangLoopsWhilePageFull2}{\hidepaste}
\tab{5}\spadcommand{while i < 1 repeat
  output "hello"
  i := i + 1
\free{i }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsWhilePageEmpty2}
\begin{paste}{ugLangLoopsWhilePageEmpty2}{ugLangLoopsWhilePagePatch2}
\pastebutton{ugLangLoopsWhilePageEmpty2}{\showpaste}
\tab{5}\spadcommand{while i < 1 repeat
  output "hello"
  i := i + 1
\free{i }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsWhilePagePatch3}
\begin{paste}{ugLangLoopsWhilePageFull3}{ugLangLoopsWhilePageEmpty3}
\pastebutton{ugLangLoopsWhilePageFull3}{\hidepaste}
\tab{5}\spadcommand{(x, y) := (1, 1)\bound{x }\bound{y }}
\indentrel{3}\begin{verbatim}
   (3)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsWhilePageEmpty3}
\begin{paste}{ugLangLoopsWhilePageEmpty3}{ugLangLoopsWhilePagePatch3}
\pastebutton{ugLangLoopsWhilePageEmpty3}{\showpaste}
\tab{5}\spadcommand{(x, y) := (1, 1)\bound{x }\bound{y }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsWhilePagePatch4}
\begin{paste}{ugLangLoopsWhilePageFull4}{ugLangLoopsWhilePageEmpty4}
\pastebutton{ugLangLoopsWhilePageFull4}{\hidepaste}
\tab{5}\spadcommand{while x < 4 and y < 10 repeat
  output [x,y]
  x := x + 1
  y := y + 2
\free{x y }}
\indentrel{3}\begin{verbatim}
   [1,1]
   [2,3]
   [3,5]
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsWhilePageEmpty4}
\begin{paste}{ugLangLoopsWhilePageEmpty4}{ugLangLoopsWhilePagePatch4}
\pastebutton{ugLangLoopsWhilePageEmpty4}{\showpaste}
\tab{5}\spadcommand{while x < 4 and y < 10 repeat
  output [x,y]
  x := x + 1
  y := y + 2
\free{x y }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsWhilePagePatch5}
\begin{paste}{ugLangLoopsWhilePageFull5}{ugLangLoopsWhilePageEmpty5}
\pastebutton{ugLangLoopsWhilePageFull5}{\hidepaste}
\tab{5}\spadcommand{(x, y) := (1, 1)\bound{x1 }\bound{y1 }}
\indentrel{3}\begin{verbatim}
   (5)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsWhilePageEmpty5}
\begin{paste}{ugLangLoopsWhilePageEmpty5}{ugLangLoopsWhilePagePatch5}
\pastebutton{ugLangLoopsWhilePageEmpty5}{\showpaste}
\tab{5}\spadcommand{(x, y) := (1, 1)\bound{x1 }\bound{y1 }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsWhilePagePatch6}
\begin{paste}{ugLangLoopsWhilePageFull6}{ugLangLoopsWhilePageEmpty6}
\pastebutton{ugLangLoopsWhilePageFull6}{\hidepaste}
\tab{5}\spadcommand{while x < 4 while y < 10 repeat
  if x + y > 7 then break
  output [x,y]
  x := x + 1
  y := y + 2
\free{x1 y1 }}
\indentrel{3}\begin{verbatim}
   [1,1]
   [2,3]
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsWhilePageEmpty6}
\begin{paste}{ugLangLoopsWhilePageEmpty6}{ugLangLoopsWhilePagePatch6}
\pastebutton{ugLangLoopsWhilePageEmpty6}{\showpaste}
\tab{5}\spadcommand{while x < 4 while y < 10 repeat
  if x + y > 7 then break
  output [x,y]
  x := x + 1
  y := y + 2
\free{x1 y1 }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsWhilePagePatch7}
\begin{paste}{ugLangLoopsWhilePageFull7}{ugLangLoopsWhilePageEmpty7}
\pastebutton{ugLangLoopsWhilePageFull7}{\hidepaste}
\tab{5}\spadcommand{m := matrix [[21,37,53,14], [8,-24,22,-16], [2,10,15,14], [26,33,55,-13]]\bound{m2 }}
\indentrel{3}\begin{verbatim}
        Ú21   37   53   14 ¿
        ³                  ³
        ³8   - 24  22  - 16³
   (7)  ³                  ³
        ³2    10   15   14 ³
        ³                  ³
        À26   33   55  - 13Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsWhilePageEmpty7}
\begin{paste}{ugLangLoopsWhilePageEmpty7}{ugLangLoopsWhilePagePatch7}
\pastebutton{ugLangLoopsWhilePageEmpty7}{\showpaste}
\tab{5}\spadcommand{m := matrix [[21,37,53,14], [8,-24,22,-16], [2,10,15,14], [26,33,55,-13]]\bound{m2 }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsWhilePagePatch8}
\begin{paste}{ugLangLoopsWhilePageFull8}{ugLangLoopsWhilePageEmpty8}
\pastebutton{ugLangLoopsWhilePageFull8}{\hidepaste}
\tab{5}\spadcommand{r := 1\bound{r }}
\indentrel{3}\begin{verbatim}
   (8)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsWhilePageEmpty8}
\begin{paste}{ugLangLoopsWhilePageEmpty8}{ugLangLoopsWhilePagePatch8}
\pastebutton{ugLangLoopsWhilePageEmpty8}{\showpaste}
\tab{5}\spadcommand{r := 1\bound{r }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsWhilePagePatch9}
\begin{paste}{ugLangLoopsWhilePageFull9}{ugLangLoopsWhilePageEmpty9}
\pastebutton{ugLangLoopsWhilePageFull9}{\hidepaste}
\tab{5}\spadcommand{(lastrow, lastcol) := (nrows(m), ncols(m))\bound{lastrow }\bound{lastcol }\free{m2 }}
\indentrel{3}\begin{verbatim}
   (9)  4
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsWhilePageEmpty9}
\begin{paste}{ugLangLoopsWhilePageEmpty9}{ugLangLoopsWhilePagePatch9}
\pastebutton{ugLangLoopsWhilePageEmpty9}{\showpaste}
\tab{5}\spadcommand{(lastrow, lastcol) := (nrows(m), ncols(m))\bound{lastrow }\bound{lastcol }\free{m2 }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsWhilePagePatch10}
\begin{paste}{ugLangLoopsWhilePageFull10}{ugLangLoopsWhilePageEmpty10}
\pastebutton{ugLangLoopsWhilePageFull10}{\hidepaste}
\tab{5}\spadcommand{while r <= lastrow repeat
  c := 1  -- index of first column
  while c <= lastcol repeat
    if elt(m,r,c) < 0 then
      output [r, c, elt(m,r,c)]
      r := lastrow
      break     -- don't look any further
    c := c + 1
  r := r + 1
\free{m2 r lastrow lastcol }}
\indentrel{3}\begin{verbatim}
   [2,2,- 24]
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsWhilePageEmpty10}
\begin{paste}{ugLangLoopsWhilePageEmpty10}{ugLangLoopsWhilePagePatch10}
\pastebutton{ugLangLoopsWhilePageEmpty10}{\showpaste}
\tab{5}\spadcommand{while r <= lastrow repeat
  c := 1  -- index of first column
  while c <= lastcol repeat
    if elt(m,r,c) < 0 then
      output [r, c, elt(m,r,c)]
      r := lastrow
      break     -- don't look any further
    c := c + 1
  r := r + 1
\free{m2 r lastrow lastcol }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugLangLoopsForInPage}{ug05.ht}{for Loops}
\begin{chunk}{ug05.ht}
\begin{page}{ugLangLoopsForInPage}{5.4.8. for Loops}
\beginscroll

Axiom provides the \axiom{for}
\spadkey{for}
and \axiom{in}
\spadkey{in}
keywords in \axiom{repeat} loops,
allowing you to iterate across all
elements of a list, or to have a variable take on integral values
from a lower bound to an upper bound.
We shall refer to these modifying clauses of \axiom{repeat} loops as
\axiom{for} clauses.
These clauses can be present in addition to \axiom{while} clauses.
As with all other types of \axiom{repeat} loops, \axiom{break} can
\spadkey{break}
be used to prematurely terminate the evaluation of the loop.

\beginImportant
The syntax for a simple loop using \axiom{for} is
\centerline{{\axiom{for} {\it iterator} \axiom{repeat} {\it loopBody}}}
The {\it iterator} has several forms.
Each form has an end test which is evaluated
before {\it loopBody} is evaluated.
A \axiom{for} loop terminates immediately when the end test
succeeds (evaluates to \axiom{true}) or when a \axiom{break} or 
\axiom{return} expression is evaluated in {\it loopBody}.
The value returned by the loop is \void{}.
\endImportant

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugLangLoopsForInNMPage}{ug05.ht}{for i in n..m repeat}
\pageto{notitle}{SegmentXmpPage}
\begin{chunk}{ug05.ht}
\begin{page}{ugLangLoopsForInNMPage}{5.4.9. for i in n..m repeat}
\beginscroll

If \axiom{for}
\spadkey{for}
is followed by a variable name, the \axiom{in}
\spadkey{in}
keyword and then an integer segment of the form \axiom{n..m},
the end test for this loop is the predicate \axiom{i > m}.
The body of the loop is evaluated \axiom{m-n+1} times if this
number is greater than 0.
If this number is less than or equal to 0, the loop body is not evaluated
at all.

The variable \axiom{i} has the value
\axiom{n, n+1, ..., m} for successive iterations
of the loop body.
The loop variable is a \spadgloss{local variable}
within the loop body: its value is not available outside the loop body
and its value and type within the loop body completely mask any outer
definition of a variable with the same name.

%
\xtc{
This loop prints the values of
\texht{${10}^3$, ${11}^3$, and $12^3$}{\axiom{10**3, 11**3, and 12**3}}:
}{
\spadpaste{for i in 10..12 repeat output(i**3)}
}
%
\xtc{
Here is a sample list.
}{
\spadpaste{a := [1,2,3] \bound{a}}
}
\xtc{
Iterate across this list, 
using \axiomSyntax{.} to access the elements of a list and
the \axiomFun{\#} operation to count its elements.
}{
\spadpaste{for i in 1..\#a repeat output(a.i) \free{a}}
}
%
This type of iteration is applicable to anything that uses \axiomSyntax{.}.
You can also use it with functions that use indices to extract elements.
%
\xtc{
Define \axiom{m} to be a matrix.
}{
\spadpaste{m := matrix [[1,2],[4,3],[9,0]] \bound{m}}
}
\xtc{
Display the rows of \axiom{m}.
}{
\spadpaste{for i in 1..nrows(m) repeat output row(m,i) \free{m}}
}
%
You can use \axiom{iterate} with \axiom{for}-loops.
\spadkey{iterate}
\xtc{
Display the even integers in a segment.
}{
\begin{spadsrc}
for i in 1..5 repeat
  if odd?(i) then iterate
  output(i)
\end{spadsrc}
}

See \downlink{`Segment'}{SegmentXmpPage}\ignore{Segment} 
for more information about segments.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugLangLoopsForInNMPagePatch1}
\begin{paste}{ugLangLoopsForInNMPageFull1}{ugLangLoopsForInNMPageEmpty1}
\pastebutton{ugLangLoopsForInNMPageFull1}{\hidepaste}
\tab{5}\spadcommand{for i in 10..12 repeat output(i**3)}
\indentrel{3}\begin{verbatim}
   1000
   1331
   1728
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInNMPageEmpty1}
\begin{paste}{ugLangLoopsForInNMPageEmpty1}{ugLangLoopsForInNMPagePatch1}
\pastebutton{ugLangLoopsForInNMPageEmpty1}{\showpaste}
\tab{5}\spadcommand{for i in 10..12 repeat output(i**3)}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInNMPagePatch2}
\begin{paste}{ugLangLoopsForInNMPageFull2}{ugLangLoopsForInNMPageEmpty2}
\pastebutton{ugLangLoopsForInNMPageFull2}{\hidepaste}
\tab{5}\spadcommand{a := [1,2,3]\bound{a }}
\indentrel{3}\begin{verbatim}
   (2)  [1,2,3]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInNMPageEmpty2}
\begin{paste}{ugLangLoopsForInNMPageEmpty2}{ugLangLoopsForInNMPagePatch2}
\pastebutton{ugLangLoopsForInNMPageEmpty2}{\showpaste}
\tab{5}\spadcommand{a := [1,2,3]\bound{a }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInNMPagePatch3}
\begin{paste}{ugLangLoopsForInNMPageFull3}{ugLangLoopsForInNMPageEmpty3}
\pastebutton{ugLangLoopsForInNMPageFull3}{\hidepaste}
\tab{5}\spadcommand{for i in 1..\#a repeat output(a.i)\free{a }}
\indentrel{3}\begin{verbatim}
   1
   2
   3
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInNMPageEmpty3}
\begin{paste}{ugLangLoopsForInNMPageEmpty3}{ugLangLoopsForInNMPagePatch3}
\pastebutton{ugLangLoopsForInNMPageEmpty3}{\showpaste}
\tab{5}\spadcommand{for i in 1..\#a repeat output(a.i)\free{a }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInNMPagePatch4}
\begin{paste}{ugLangLoopsForInNMPageFull4}{ugLangLoopsForInNMPageEmpty4}
\pastebutton{ugLangLoopsForInNMPageFull4}{\hidepaste}
\tab{5}\spadcommand{m := matrix [[1,2],[4,3],[9,0]]\bound{m }}
\indentrel{3}\begin{verbatim}
        Ú1  2¿
        ³    ³
   (4)  ³4  3³
        ³    ³
        À9  0Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInNMPageEmpty4}
\begin{paste}{ugLangLoopsForInNMPageEmpty4}{ugLangLoopsForInNMPagePatch4}
\pastebutton{ugLangLoopsForInNMPageEmpty4}{\showpaste}
\tab{5}\spadcommand{m := matrix [[1,2],[4,3],[9,0]]\bound{m }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInNMPagePatch5}
\begin{paste}{ugLangLoopsForInNMPageFull5}{ugLangLoopsForInNMPageEmpty5}
\pastebutton{ugLangLoopsForInNMPageFull5}{\hidepaste}
\tab{5}\spadcommand{for i in 1..nrows(m) repeat output row(m,i)\free{m }}
\indentrel{3}\begin{verbatim}
   [1,2]
   [4,3]
   [9,0]
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInNMPageEmpty5}
\begin{paste}{ugLangLoopsForInNMPageEmpty5}{ugLangLoopsForInNMPagePatch5}
\pastebutton{ugLangLoopsForInNMPageEmpty5}{\showpaste}
\tab{5}\spadcommand{for i in 1..nrows(m) repeat output row(m,i)\free{m }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInNMPagePatch6}
\begin{paste}{ugLangLoopsForInNMPageFull6}{ugLangLoopsForInNMPageEmpty6}
\pastebutton{ugLangLoopsForInNMPageFull6}{\hidepaste}
\tab{5}\spadcommand{for i in 1..5 repeat
  if odd?(i) then iterate
  output(i)
}
\indentrel{3}\begin{verbatim}
   2
   4
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInNMPageEmpty6}
\begin{paste}{ugLangLoopsForInNMPageEmpty6}{ugLangLoopsForInNMPagePatch6}
\pastebutton{ugLangLoopsForInNMPageEmpty6}{\showpaste}
\tab{5}\spadcommand{for i in 1..5 repeat
  if odd?(i) then iterate
  output(i)
}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugLangLoopsForInNMSPage}{ug05.ht}{for i in n..m by s repeat}
\begin{chunk}{ug05.ht}
\begin{page}{ugLangLoopsForInNMSPage}{5.4.10. for i in n..m by s repeat}
\beginscroll

By default, the difference between values taken on by a variable in loops
such as \axiom{for i in n..m repeat ...} is \mathOrSpad{1}.
It is possible to supply another, possibly negative, step value by using
the \axiom{by}
\spadkey{by}
keyword along with \axiom{for} and \axiom{in}.
Like the upper and lower bounds, the step value following the
\axiom{by} keyword must be an integer.
Note that the loop
\axiom{for i in 1..2 by 0 repeat output(i)}
will not terminate by itself, as the step value does not change the index
from its initial value of \mathOrSpad{1}.

\xtc{
This expression displays the odd integers between two bounds.
}{
\spadpaste{for i in 1..5 by 2 repeat output(i)}
}
\xtc{
Use this to display the numbers in reverse order.
}{
\spadpaste{for i in 5..1 by -2 repeat output(i)}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugLangLoopsForInNMSPagePatch1}
\begin{paste}{ugLangLoopsForInNMSPageFull1}{ugLangLoopsForInNMSPageEmpty1}
\pastebutton{ugLangLoopsForInNMSPageFull1}{\hidepaste}
\tab{5}\spadcommand{for i in 1..5 by 2 repeat output(i)}
\indentrel{3}\begin{verbatim}
   1
   3
   5
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInNMSPageEmpty1}
\begin{paste}{ugLangLoopsForInNMSPageEmpty1}{ugLangLoopsForInNMSPagePatch1}
\pastebutton{ugLangLoopsForInNMSPageEmpty1}{\showpaste}
\tab{5}\spadcommand{for i in 1..5 by 2 repeat output(i)}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInNMSPagePatch2}
\begin{paste}{ugLangLoopsForInNMSPageFull2}{ugLangLoopsForInNMSPageEmpty2}
\pastebutton{ugLangLoopsForInNMSPageFull2}{\hidepaste}
\tab{5}\spadcommand{for i in 5..1 by -2 repeat output(i)}
\indentrel{3}\begin{verbatim}
   5
   3
   1
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInNMSPageEmpty2}
\begin{paste}{ugLangLoopsForInNMSPageEmpty2}{ugLangLoopsForInNMSPagePatch2}
\pastebutton{ugLangLoopsForInNMSPageEmpty2}{\showpaste}
\tab{5}\spadcommand{for i in 5..1 by -2 repeat output(i)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugLangLoopsForInNPage}{ug05.ht}{for i in n.. repeat}
\begin{chunk}{ug05.ht}
\begin{page}{ugLangLoopsForInNPage}{5.4.11. for i in n.. repeat}
\beginscroll

If the value after the \axiomSyntax{..}
is omitted, the loop has no end test.
A potentially infinite loop is thus created.
The variable is given the successive values \axiom{n, n+1, n+2, ...}
and the loop is terminated only if a \axiom{break} or \axiom{return}
expression is evaluated in the loop body.
However you may also add some other modifying clause on the
\axiom{repeat} (for example, a \axiom{while} clause) to stop the loop.

\xtc{
This loop displays the integers greater than or equal to \axiom{15}
and less than the first prime greater than \axiom{15}.
}{
\spadpaste{for i in 15.. while not prime?(i) repeat output(i)}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugLangLoopsForInNPagePatch1}
\begin{paste}{ugLangLoopsForInNPageFull1}{ugLangLoopsForInNPageEmpty1}
\pastebutton{ugLangLoopsForInNPageFull1}{\hidepaste}
\tab{5}\spadcommand{for i in 15.. while not prime?(i) repeat output(i)}
\indentrel{3}\begin{verbatim}
   15
   16
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInNPageEmpty1}
\begin{paste}{ugLangLoopsForInNPageEmpty1}{ugLangLoopsForInNPagePatch1}
\pastebutton{ugLangLoopsForInNPageEmpty1}{\showpaste}
\tab{5}\spadcommand{for i in 15.. while not prime?(i) repeat output(i)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugLangLoopsForInXLPage}{ug05.ht}{for x in l repeat}
\begin{chunk}{ug05.ht}
\begin{page}{ugLangLoopsForInXLPage}{5.4.12. for x in l repeat}
\beginscroll

Another variant of the \axiom{for} loop has the form:
\centerline{{{\it \axiom{for} x \axiom{in} list \axiom{repeat} loopBody}}}
This form is used when you want to iterate directly over the
elements of a list.
In this form of the \axiom{for} loop, the variable
\axiom{x} takes on the value of each successive element in \axiom{l}.
The end test is most simply stated in English: ``are there no more
\axiom{x} in \axiom{l}?''

\xtc{
If \axiom{l} is this list,
}{
\spadpaste{l := [0,-5,3] \bound{l}}
}
\xtc{
display all elements of \axiom{l}, one per line.
}{
\spadpaste{for x in l repeat output(x) \free{l}}
}

Since the list constructing expression \axiom{expand [n..m]} creates the
list \axiom{[n, n+1, ..., m]}\footnote{This list is empty if \axiom{n >
m}.}, you might be tempted to think that the loops
\begin{verbatim}
for i in n..m repeat output(i)
\end{verbatim}
and
\begin{verbatim}
for x in expand [n..m] repeat output(x)
\end{verbatim}
are equivalent.
The second form first creates the list
\axiom{expand [n..m]} (no matter how large it might be) and
then does the iteration.
The first form potentially runs in much less space, as the index variable
\axiom{i} is simply incremented once per loop and the list is not actually
created.
Using the first form is much more efficient.
%
\xtc{
Of course, sometimes you really want to iterate across a specific list.
This displays each of the factors of \axiom{2400000}.
}{
\spadpaste{for f in factors(factor(2400000)) repeat output(f)}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugLangLoopsForInXLPagePatch1}
\begin{paste}{ugLangLoopsForInXLPageFull1}{ugLangLoopsForInXLPageEmpty1}
\pastebutton{ugLangLoopsForInXLPageFull1}{\hidepaste}
\tab{5}\spadcommand{l := [0,-5,3]\bound{l }}
\indentrel{3}\begin{verbatim}
   (1)  [0,- 5,3]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInXLPageEmpty1}
\begin{paste}{ugLangLoopsForInXLPageEmpty1}{ugLangLoopsForInXLPagePatch1}
\pastebutton{ugLangLoopsForInXLPageEmpty1}{\showpaste}
\tab{5}\spadcommand{l := [0,-5,3]\bound{l }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInXLPagePatch2}
\begin{paste}{ugLangLoopsForInXLPageFull2}{ugLangLoopsForInXLPageEmpty2}
\pastebutton{ugLangLoopsForInXLPageFull2}{\hidepaste}
\tab{5}\spadcommand{for x in l repeat output(x)\free{l }}
\indentrel{3}\begin{verbatim}
   0
   - 5
   3
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInXLPageEmpty2}
\begin{paste}{ugLangLoopsForInXLPageEmpty2}{ugLangLoopsForInXLPagePatch2}
\pastebutton{ugLangLoopsForInXLPageEmpty2}{\showpaste}
\tab{5}\spadcommand{for x in l repeat output(x)\free{l }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInXLPagePatch3}
\begin{paste}{ugLangLoopsForInXLPageFull3}{ugLangLoopsForInXLPageEmpty3}
\pastebutton{ugLangLoopsForInXLPageFull3}{\hidepaste}
\tab{5}\spadcommand{for f in factors(factor(2400000)) repeat output(f)}
\indentrel{3}\begin{verbatim}
   [factor= 2,exponent= 8]
   [factor= 3,exponent= 1]
   [factor= 5,exponent= 5]
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInXLPageEmpty3}
\begin{paste}{ugLangLoopsForInXLPageEmpty3}{ugLangLoopsForInXLPagePatch3}
\pastebutton{ugLangLoopsForInXLPageEmpty3}{\showpaste}
\tab{5}\spadcommand{for f in factors(factor(2400000)) repeat output(f)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugLangLoopsForInPredPage}{ug05.ht}{``Such that'' Predicates}
\begin{chunk}{ug05.ht}
\begin{page}{ugLangLoopsForInPredPage}{5.4.13. ``Such that'' Predicates}
\beginscroll

A \axiom{for} loop can be followed by a \axiomSyntax{|} and then a
predicate.
The predicate qualifies the use of the values from the iterator following
the \axiom{for}.
Think of the vertical bar
\axiomSyntax{|} as the phrase ``such that.''
\xtc{
This loop expression
prints out the integers \axiom{n} in the given segment
such that \axiom{n} is odd.
}{
\spadpaste{for n in 0..4 | odd? n repeat output n}
}

\beginImportant
A \axiom{for} loop can also be written
\centerline{{\axiom{for} {\it iterator} \axiom{|} {\it predicate}  
\axiom{repeat} {\it loopBody}}}
which is equivalent to:
\centerline{{\axiom{for} {\it iterator} \axiom{repeat if}}}
\centerline{{{\it predicate} \axiom{then} {\it loopBody} \axiom{else} 
\axiom{iterate}}}
\endImportant

The predicate need not refer only to the variable in the \axiom{for} clause:
any variable in an outer scope can be part of the predicate.
\xtc{
In this example, the predicate on the inner \axiom{for} loop uses
\axiom{i} from the outer loop and the \axiom{j} from the \axiom{for}
clause that it directly modifies.
}{
\begin{spadsrc}
for i in 1..50 repeat
  for j in 1..50 | factorial(i+j) < 25 repeat
    output [i,j]
\end{spadsrc}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugLangLoopsForInPredPagePatch1}
\begin{paste}{ugLangLoopsForInPredPageFull1}{ugLangLoopsForInPredPageEmpty1}
\pastebutton{ugLangLoopsForInPredPageFull1}{\hidepaste}
\tab{5}\spadcommand{for n in 0..4 | odd? n repeat output n}
\indentrel{3}\begin{verbatim}
   1
   3
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInPredPageEmpty1}
\begin{paste}{ugLangLoopsForInPredPageEmpty1}{ugLangLoopsForInPredPagePatch1}
\pastebutton{ugLangLoopsForInPredPageEmpty1}{\showpaste}
\tab{5}\spadcommand{for n in 0..4 | odd? n repeat output n}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInPredPagePatch2}
\begin{paste}{ugLangLoopsForInPredPageFull2}{ugLangLoopsForInPredPageEmpty2}
\pastebutton{ugLangLoopsForInPredPageFull2}{\hidepaste}
\tab{5}\spadcommand{for i in 1..50 repeat
  for j in 1..50 | factorial(i+j) < 25 repeat
    output [i,j]
}
\indentrel{3}\begin{verbatim}
   [1,1]
   [1,2]
   [1,3]
   [2,1]
   [2,2]
   [3,1]
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsForInPredPageEmpty2}
\begin{paste}{ugLangLoopsForInPredPageEmpty2}{ugLangLoopsForInPredPagePatch2}
\pastebutton{ugLangLoopsForInPredPageEmpty2}{\showpaste}
\tab{5}\spadcommand{for i in 1..50 repeat
  for j in 1..50 | factorial(i+j) < 25 repeat
    output [i,j]
}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugLangLoopsParPage}{ug05.ht}{Parallel Iteration}
\pageto{notitle}{ugLangLoopsForInPredPage}
\begin{chunk}{ug05.ht}
\begin{page}{ugLangLoopsParPage}{5.4.14. Parallel Iteration}
\beginscroll

The last example of
\texht{the previous section}{
\downlink{``Such that Predicates''}{ugLangLoopsForInPredPage} 
in Section 5.4.13\ignore{ugLangLoopsForInPred}}
gives an example of
\spadgloss{nested iteration}: a loop is contained
in another loop.
Sometimes you want to iterate across two lists in parallel, or perhaps
you want to traverse a list while incrementing a variable.

\beginImportant
The general syntax of a repeat loop is
\centerline{{{\tt \subscriptIt{iterator}{1} \subscriptIt{iterator}{2} 
\ldots \subscriptIt{iterator}{N} repeat {\it loopBody}}}}
where each {\it iterator} is either a \axiom{for} or a \axiom{while} clause.
The loop terminates immediately when the end test of any {\it iterator}
succeeds or when a \axiom{break} or \axiom{return} expression is evaluated
in {\it loopBody}.
The value returned by the loop is \void{}.
\endImportant

\xtc{
Here we write a loop to iterate across
two lists, computing the sum of the pairwise product
of elements. Here is the first list.
}{
\spadpaste{l := [1,3,5,7] \bound{l}}
}
\xtc{
And the second.
}{
\spadpaste{m := [100,200] \bound{m}}
}
\xtc{
The initial value of the sum counter.
}{
\spadpaste{sum := 0 \bound{sum}}
}
\xtc{
The last two elements of \axiom{l} are not used in the calculation
because \axiom{m} has two fewer elements than \axiom{l}.
}{
\begin{spadsrc}[\bound{doit}\free{sum l m}]
for x in l for y in m repeat
    sum := sum + x*y
\end{spadsrc}
}
\xtc{
Display the ``dot product.''
}{
\spadpaste{sum \free{doit}}
}

\xtc{
Next, we write a loop to compute the sum of the products of the loop 
elements with
their positions in the loop.
}{
\spadpaste{l := [2,3,5,7,11,13,17,19,23,29,31,37] \bound{l1}}
}
\xtc{
The initial sum.
}{
\spadpaste{sum := 0 \bound{sum1}}
}
\xtc{
Here looping stops when the list \axiom{l} is exhausted, even though
the \axiom{for i in 0..} specifies no terminating condition.
}{
\spadpaste{
for i in 0.. for x in l repeat sum := i * x \bound{doit1}\free{sum1 l1}}
}
\xtc{
Display this weighted sum.
}{
\spadpaste{sum \free{doit1}}
}

When \axiomSyntax{|} is used to qualify any of the \axiom{for} clauses in a
parallel iteration, the variables in the predicates can be from an outer
scope or from a \axiom{for} clause in or to the left of a modified clause.

This is correct:
\begin{verbatim}
for i in 1..10 repeat
  for j in 200..300 | odd? (i+j) repeat
    output [i,j]
\end{verbatim}
This is not correct since the variable \axiom{j} has not been
defined outside the inner loop.
\begin{verbatim}
for i in 1..10 | odd? (i+j) repeat  -- wrong, j not defined
  for j in 200..300 repeat
    output [i,j]
\end{verbatim}

%>\head{subsection}{Mixing Loop Modifiers}{ugLangLoopsMix}

\xtc{
This example shows that it is possible to mix several of the
forms of \axiom{repeat} modifying clauses on a loop.
}{
\begin{spadsrc}
for i in 1..10
    for j in 151..160 | odd? j
      while i + j < 160 repeat
        output [i,j]
\end{spadsrc}
}
%
Here are useful rules for composing loop expressions:
\indent{4}
\beginitems
\item[1. ] \axiom{while} predicates can only refer to variables that
are global (or in an outer scope)
or that are defined in \axiom{for} clauses to the left of the
predicate.
\item[2. ] A ``such that'' predicate (something following \axiomSyntax{|})
must directly follow a \axiom{for} clause and can only refer to
variables that are global (or in an outer scope)
or defined in the modified \axiom{for} clause
or any \axiom{for} clause to the left.
\enditems
\indent{0}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugLangLoopsParPagePatch1}
\begin{paste}{ugLangLoopsParPageFull1}{ugLangLoopsParPageEmpty1}
\pastebutton{ugLangLoopsParPageFull1}{\hidepaste}
\tab{5}\spadcommand{l := [1,3,5,7]\bound{l }}
\indentrel{3}\begin{verbatim}
   (1)  [1,3,5,7]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsParPageEmpty1}
\begin{paste}{ugLangLoopsParPageEmpty1}{ugLangLoopsParPagePatch1}
\pastebutton{ugLangLoopsParPageEmpty1}{\showpaste}
\tab{5}\spadcommand{l := [1,3,5,7]\bound{l }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsParPagePatch2}
\begin{paste}{ugLangLoopsParPageFull2}{ugLangLoopsParPageEmpty2}
\pastebutton{ugLangLoopsParPageFull2}{\hidepaste}
\tab{5}\spadcommand{m := [100,200]\bound{m }}
\indentrel{3}\begin{verbatim}
   (2)  [100,200]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsParPageEmpty2}
\begin{paste}{ugLangLoopsParPageEmpty2}{ugLangLoopsParPagePatch2}
\pastebutton{ugLangLoopsParPageEmpty2}{\showpaste}
\tab{5}\spadcommand{m := [100,200]\bound{m }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsParPagePatch3}
\begin{paste}{ugLangLoopsParPageFull3}{ugLangLoopsParPageEmpty3}
\pastebutton{ugLangLoopsParPageFull3}{\hidepaste}
\tab{5}\spadcommand{sum := 0\bound{sum }}
\indentrel{3}\begin{verbatim}
   (3)  0
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsParPageEmpty3}
\begin{paste}{ugLangLoopsParPageEmpty3}{ugLangLoopsParPagePatch3}
\pastebutton{ugLangLoopsParPageEmpty3}{\showpaste}
\tab{5}\spadcommand{sum := 0\bound{sum }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsParPagePatch4}
\begin{paste}{ugLangLoopsParPageFull4}{ugLangLoopsParPageEmpty4}
\pastebutton{ugLangLoopsParPageFull4}{\hidepaste}
\tab{5}\spadcommand{for x in l for y in m repeat
    sum := sum + x*y
\bound{doit }\free{sum l m }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsParPageEmpty4}
\begin{paste}{ugLangLoopsParPageEmpty4}{ugLangLoopsParPagePatch4}
\pastebutton{ugLangLoopsParPageEmpty4}{\showpaste}
\tab{5}\spadcommand{for x in l for y in m repeat
    sum := sum + x*y
\bound{doit }\free{sum l m }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsParPagePatch5}
\begin{paste}{ugLangLoopsParPageFull5}{ugLangLoopsParPageEmpty5}
\pastebutton{ugLangLoopsParPageFull5}{\hidepaste}
\tab{5}\spadcommand{sum\free{doit }}
\indentrel{3}\begin{verbatim}
   (5)  700
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsParPageEmpty5}
\begin{paste}{ugLangLoopsParPageEmpty5}{ugLangLoopsParPagePatch5}
\pastebutton{ugLangLoopsParPageEmpty5}{\showpaste}
\tab{5}\spadcommand{sum\free{doit }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsParPagePatch6}
\begin{paste}{ugLangLoopsParPageFull6}{ugLangLoopsParPageEmpty6}
\pastebutton{ugLangLoopsParPageFull6}{\hidepaste}
\tab{5}\spadcommand{l := [2,3,5,7,11,13,17,19,23,29,31,37]\bound{l1 }}
\indentrel{3}\begin{verbatim}
   (6)  [2,3,5,7,11,13,17,19,23,29,31,37]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsParPageEmpty6}
\begin{paste}{ugLangLoopsParPageEmpty6}{ugLangLoopsParPagePatch6}
\pastebutton{ugLangLoopsParPageEmpty6}{\showpaste}
\tab{5}\spadcommand{l := [2,3,5,7,11,13,17,19,23,29,31,37]\bound{l1 }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsParPagePatch7}
\begin{paste}{ugLangLoopsParPageFull7}{ugLangLoopsParPageEmpty7}
\pastebutton{ugLangLoopsParPageFull7}{\hidepaste}
\tab{5}\spadcommand{sum := 0\bound{sum1 }}
\indentrel{3}\begin{verbatim}
   (7)  0
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsParPageEmpty7}
\begin{paste}{ugLangLoopsParPageEmpty7}{ugLangLoopsParPagePatch7}
\pastebutton{ugLangLoopsParPageEmpty7}{\showpaste}
\tab{5}\spadcommand{sum := 0\bound{sum1 }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsParPagePatch8}
\begin{paste}{ugLangLoopsParPageFull8}{ugLangLoopsParPageEmpty8}
\pastebutton{ugLangLoopsParPageFull8}{\hidepaste}
\tab{5}\spadcommand{for i in 0.. for x in l repeat sum := i * x\bound{doit1 }\free{sum1 l1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsParPageEmpty8}
\begin{paste}{ugLangLoopsParPageEmpty8}{ugLangLoopsParPagePatch8}
\pastebutton{ugLangLoopsParPageEmpty8}{\showpaste}
\tab{5}\spadcommand{for i in 0.. for x in l repeat sum := i * x\bound{doit1 }\free{sum1 l1 }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsParPagePatch9}
\begin{paste}{ugLangLoopsParPageFull9}{ugLangLoopsParPageEmpty9}
\pastebutton{ugLangLoopsParPageFull9}{\hidepaste}
\tab{5}\spadcommand{sum\free{doit1 }}
\indentrel{3}\begin{verbatim}
   (9)  407
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsParPageEmpty9}
\begin{paste}{ugLangLoopsParPageEmpty9}{ugLangLoopsParPagePatch9}
\pastebutton{ugLangLoopsParPageEmpty9}{\showpaste}
\tab{5}\spadcommand{sum\free{doit1 }}
\end{paste}\end{patch}

\begin{patch}{ugLangLoopsParPagePatch10}
\begin{paste}{ugLangLoopsParPageFull10}{ugLangLoopsParPageEmpty10}
\pastebutton{ugLangLoopsParPageFull10}{\hidepaste}
\tab{5}\spadcommand{for i in 1..10
    for j in 151..160 | odd? j
      while i + j < 160 repeat
        output [i,j]
}
\indentrel{3}\begin{verbatim}
   [1,151]
   [3,153]
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangLoopsParPageEmpty10}
\begin{paste}{ugLangLoopsParPageEmpty10}{ugLangLoopsParPagePatch10}
\pastebutton{ugLangLoopsParPageEmpty10}{\showpaste}
\tab{5}\spadcommand{for i in 1..10
    for j in 151..160 | odd? j
      while i + j < 160 repeat
        output [i,j]
}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugLangItsPage}{ug05.ht}{Creating Lists and Streams with Iterators}
\pageto{notitle}{ugLangLoopsPage}
\pageto{notitle}{ListXmpPage}
\pageto{notitle}{StreamXmpPage}
\begin{chunk}{ug05.ht}
\begin{page}{ugLangItsPage}{5.5. Creating Lists and Streams with Iterators}
\beginscroll

All of what we did for loops in 
\downlink{``Loops''}{ugLangLoopsPage} 
in Section 5.4\ignore{ugLangLoops}
can be transformed into expressions that create lists
and streams.
The \axiom{repeat,} \axiom{break} or \axiom{iterate} words are not used but
all the other ideas carry over.
Before we give you the general rule, here are some examples which
give you the idea.

\xtc{
This creates a simple list of the integers from \axiom{1} to \axiom{10}.
}{
\spadpaste{list := [i for i in 1..10] \bound{list}}
}
\xtc{
Create a stream of the integers greater than or equal to \axiom{1}.
}{
\spadpaste{stream := [i for i in 1..] \bound{stream}}
}
\xtc{
This is a list of the prime integers between \axiom{1} and \axiom{10},
inclusive.
}{
\spadpaste{[i for i in 1..10 | prime? i]}
}
\xtc{
This is a stream of the prime integers greater than or equal to \axiom{1}.
}{
\spadpaste{[i for i in 1..   | prime? i]}
}
\xtc{
This is a list of the integers between \axiom{1} and \axiom{10},
inclusive, whose squares are less than \axiom{700}.
}{
\spadpaste{[i for i in 1..10 while i*i < 700]}
}
\xtc{
This is a stream of the integers greater than or equal to \axiom{1}
whose squares are less than \axiom{700}.
}{
\spadpaste{[i for i in 1..   while i*i < 700]}
}

Got the idea?
Here is the general rule.

\beginImportant
The general syntax of a collection is
\centerline{{{\tt [ {\it collectExpression} \subscriptIt{iterator}{1}  
\subscriptIt{iterator}{2}  \ldots  \subscriptIt{iterator}{N} ]}}}
where each \subscriptIt{iterator}{i} is either a \axiom{for} or a
\axiom{while} clause.
The loop terminates immediately when the end test of any
\subscriptIt{iterator}{i} succeeds or when a \axiom{return} expression is
evaluated in {\it collectExpression}.
The value returned by the collection is either a list or a stream of
elements, one for each iteration of the {\it collectExpression}.
\endImportant

Be careful when you use \axiom{while}
to create a stream.
By default, Axiom tries to compute and display the first ten elements
of a stream.
If the \axiom{while} condition is not satisfied quickly, Axiom
can spend a long (possibly infinite) time trying to compute
the elements.
Use \spadcmd{)set streams calculate} to change the default
to something else.
This also affects the number of terms computed and displayed for power
series.
For the purposes of this book, we have used this system
command to display fewer than ten terms.
\xtc{
Use nested iterators to create lists of
lists which can then be given as an argument to \axiomFun{matrix}.
}{
\spadpaste{matrix [[x**i+j for i in 1..3] for j in 10..12]}
}
\xtc{
You can also create lists of streams, streams of lists and
streams of streams.
Here is a stream of streams.
}{
\spadpaste{[[i/j for i in j+1..] for j in 1..]}
}
\xtc{
You can use parallel iteration across lists and streams to create
new lists.
}{
\spadpaste{[i/j for i in 3.. by 10 for j in 2..]}
}
\xtc{
Iteration stops if the end of a list or stream is reached.
}{
\spadpaste{[i**j for i in 1..7 for j in 2.. ]}
}
%\xtc{
%or a while condition fails.
%}{
%\spadcommand{[i**j for i in 1..  for j in 2.. while i + j < 5 ]}
%}
\xtc{
As with loops, you can combine these modifiers to make very
complicated conditions.
}{
\spadpaste{[[[i,j] for i in 10..15 | prime? i] 
for j in 17..22 | j = squareFreePart j]}
}

See \downlink{`List'}{ListXmpPage}\ignore{List} and 
\downlink{`Stream'}{StreamXmpPage}\ignore{Stream} 
for more information on creating and
manipulating lists and streams, respectively.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugLangItsPagePatch1}
\begin{paste}{ugLangItsPageFull1}{ugLangItsPageEmpty1}
\pastebutton{ugLangItsPageFull1}{\hidepaste}
\tab{5}\spadcommand{list := [i for i in 1..10]\bound{list }}
\indentrel{3}\begin{verbatim}
   (1)  [1,2,3,4,5,6,7,8,9,10]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangItsPageEmpty1}
\begin{paste}{ugLangItsPageEmpty1}{ugLangItsPagePatch1}
\pastebutton{ugLangItsPageEmpty1}{\showpaste}
\tab{5}\spadcommand{list := [i for i in 1..10]\bound{list }}
\end{paste}\end{patch}

\begin{patch}{ugLangItsPagePatch2}
\begin{paste}{ugLangItsPageFull2}{ugLangItsPageEmpty2}
\pastebutton{ugLangItsPageFull2}{\hidepaste}
\tab{5}\spadcommand{stream := [i for i in 1..]\bound{stream }}
\indentrel{3}\begin{verbatim}
   (2)  [1,2,3,4,5,6,7,8,9,10,...]
                           Type: Stream PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangItsPageEmpty2}
\begin{paste}{ugLangItsPageEmpty2}{ugLangItsPagePatch2}
\pastebutton{ugLangItsPageEmpty2}{\showpaste}
\tab{5}\spadcommand{stream := [i for i in 1..]\bound{stream }}
\end{paste}\end{patch}

\begin{patch}{ugLangItsPagePatch3}
\begin{paste}{ugLangItsPageFull3}{ugLangItsPageEmpty3}
\pastebutton{ugLangItsPageFull3}{\hidepaste}
\tab{5}\spadcommand{[i for i in 1..10 | prime? i]}
\indentrel{3}\begin{verbatim}
   (3)  [2,3,5,7]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangItsPageEmpty3}
\begin{paste}{ugLangItsPageEmpty3}{ugLangItsPagePatch3}
\pastebutton{ugLangItsPageEmpty3}{\showpaste}
\tab{5}\spadcommand{[i for i in 1..10 | prime? i]}
\end{paste}\end{patch}

\begin{patch}{ugLangItsPagePatch4}
\begin{paste}{ugLangItsPageFull4}{ugLangItsPageEmpty4}
\pastebutton{ugLangItsPageFull4}{\hidepaste}
\tab{5}\spadcommand{[i for i in 1.. | prime? i]}
\indentrel{3}\begin{verbatim}
   (4)  [2,3,5,7,11,13,17,19,23,29,...]
                           Type: Stream PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangItsPageEmpty4}
\begin{paste}{ugLangItsPageEmpty4}{ugLangItsPagePatch4}
\pastebutton{ugLangItsPageEmpty4}{\showpaste}
\tab{5}\spadcommand{[i for i in 1.. | prime? i]}
\end{paste}\end{patch}

\begin{patch}{ugLangItsPagePatch5}
\begin{paste}{ugLangItsPageFull5}{ugLangItsPageEmpty5}
\pastebutton{ugLangItsPageFull5}{\hidepaste}
\tab{5}\spadcommand{[i for i in 1..10 while i*i < 700]}
\indentrel{3}\begin{verbatim}
   (5)  [1,2,3,4,5,6,7,8,9,10]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangItsPageEmpty5}
\begin{paste}{ugLangItsPageEmpty5}{ugLangItsPagePatch5}
\pastebutton{ugLangItsPageEmpty5}{\showpaste}
\tab{5}\spadcommand{[i for i in 1..10 while i*i < 700]}
\end{paste}\end{patch}

\begin{patch}{ugLangItsPagePatch6}
\begin{paste}{ugLangItsPageFull6}{ugLangItsPageEmpty6}
\pastebutton{ugLangItsPageFull6}{\hidepaste}
\tab{5}\spadcommand{[i for i in 1.. while i*i < 700]}
\indentrel{3}\begin{verbatim}
   (6)  [1,2,3,4,5,6,7,8,9,10,...]
                           Type: Stream PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangItsPageEmpty6}
\begin{paste}{ugLangItsPageEmpty6}{ugLangItsPagePatch6}
\pastebutton{ugLangItsPageEmpty6}{\showpaste}
\tab{5}\spadcommand{[i for i in 1.. while i*i < 700]}
\end{paste}\end{patch}

\begin{patch}{ugLangItsPagePatch7}
\begin{paste}{ugLangItsPageFull7}{ugLangItsPageEmpty7}
\pastebutton{ugLangItsPageFull7}{\hidepaste}
\tab{5}\spadcommand{matrix [[x**i+j for i in 1..3] for j in 10..12]}
\indentrel{3}\begin{verbatim}
        Ú         2        3     ¿
        ³x + 10  x  + 10  x  + 10³
        ³                        ³
   (7)  ³         2        3     ³
        ³x + 11  x  + 11  x  + 11³
        ³                        ³
        ³         2        3     ³
        Àx + 12  x  + 12  x  + 12Ù
                        Type: Matrix Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangItsPageEmpty7}
\begin{paste}{ugLangItsPageEmpty7}{ugLangItsPagePatch7}
\pastebutton{ugLangItsPageEmpty7}{\showpaste}
\tab{5}\spadcommand{matrix [[x**i+j for i in 1..3] for j in 10..12]}
\end{paste}\end{patch}

\begin{patch}{ugLangItsPagePatch8}
\begin{paste}{ugLangItsPageFull8}{ugLangItsPageEmpty8}
\pastebutton{ugLangItsPageFull8}{\hidepaste}
\tab{5}\spadcommand{[[i/j for i in j+1..] for j in 1..]}
\indentrel{3}\begin{verbatim}
   (8)
   [[2,3,4,5,6,7,8,9,10,11,...],
     3   5   7   9   11
    [Ä,2,Ä,3,Ä,4,Ä,5,ÄÄ,6,...],
     2   2   2   2    2
     4 5   7 8   10 11   13
    [Ä,Ä,2,Ä,Ä,3,ÄÄ,ÄÄ,4,ÄÄ,...],
     3 3   3 3    3  3    3
     5 3 7   9 5 11   13 7
    [Ä,Ä,Ä,2,Ä,Ä,ÄÄ,3,ÄÄ,Ä,...],
     4 2 4   4 2  4    4 2
     6 7 8 9   11 12 13 14
    [Ä,Ä,Ä,Ä,2,ÄÄ,ÄÄ,ÄÄ,ÄÄ,3,...],
     5 5 5 5    5  5  5  5
     7 4 3 5 11   13 7 5 8
    [Ä,Ä,Ä,Ä,ÄÄ,2,ÄÄ,Ä,Ä,Ä,...],
     6 3 2 3  6    6 3 2 3
     8 9 10 11 12 13   15 16 17
    [Ä,Ä,ÄÄ,ÄÄ,ÄÄ,ÄÄ,2,ÄÄ,ÄÄ,ÄÄ,...],
     7 7  7  7  7  7    7  7  7
     9 5 11 3 13 7 15   17 9
    [Ä,Ä,ÄÄ,Ä,ÄÄ,Ä,ÄÄ,2,ÄÄ,Ä,...],
     8 4  8 2  8 4  8    8 4
     10 11 4 13 14 5 16 17   19
    [ÄÄ,ÄÄ,Ä,ÄÄ,ÄÄ,Ä,ÄÄ,ÄÄ,2,ÄÄ,...],
      9  9 3  9  9 3  9  9    9
     11 6 13 7 3 8 17 9 19
    [ÄÄ,Ä,ÄÄ,Ä,Ä,Ä,ÄÄ,Ä,ÄÄ,2,...], ...]
     10 5 10 5 2 5 10 5 10
                   Type: Stream Stream Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangItsPageEmpty8}
\begin{paste}{ugLangItsPageEmpty8}{ugLangItsPagePatch8}
\pastebutton{ugLangItsPageEmpty8}{\showpaste}
\tab{5}\spadcommand{[[i/j for i in j+1..] for j in 1..]}
\end{paste}\end{patch}

\begin{patch}{ugLangItsPagePatch9}
\begin{paste}{ugLangItsPageFull9}{ugLangItsPageEmpty9}
\pastebutton{ugLangItsPageFull9}{\hidepaste}
\tab{5}\spadcommand{[i/j for i in 3.. by 10 for j in 2..]}
\indentrel{3}\begin{verbatim}
         3 13 23 33 43 53 63 73 83 93
   (9)  [Ä,ÄÄ,ÄÄ,ÄÄ,ÄÄ,ÄÄ,ÄÄ,ÄÄ,ÄÄ,ÄÄ,...]
         2  3  4  5  6  7  8  9 10 11
                          Type: Stream Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangItsPageEmpty9}
\begin{paste}{ugLangItsPageEmpty9}{ugLangItsPagePatch9}
\pastebutton{ugLangItsPageEmpty9}{\showpaste}
\tab{5}\spadcommand{[i/j for i in 3.. by 10 for j in 2..]}
\end{paste}\end{patch}

\begin{patch}{ugLangItsPagePatch10}
\begin{paste}{ugLangItsPageFull10}{ugLangItsPageEmpty10}
\pastebutton{ugLangItsPageFull10}{\hidepaste}
\tab{5}\spadcommand{[i**j for i in 1..7 for j in 2.. ]}
\indentrel{3}\begin{verbatim}
   (10)  [1,8,81,1024,15625,279936,5764801]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangItsPageEmpty10}
\begin{paste}{ugLangItsPageEmpty10}{ugLangItsPagePatch10}
\pastebutton{ugLangItsPageEmpty10}{\showpaste}
\tab{5}\spadcommand{[i**j for i in 1..7 for j in 2.. ]}
\end{paste}\end{patch}

\begin{patch}{ugLangItsPagePatch11}
\begin{paste}{ugLangItsPageFull11}{ugLangItsPageEmpty11}
\pastebutton{ugLangItsPageFull11}{\hidepaste}
\tab{5}\spadcommand{[[[i,j] for i in 10..15 | prime? i] for j in 17..22 | j = squareFreePart j]}
\indentrel{3}\begin{verbatim}
   (11)
   [[[11,17],[13,17]], [[11,19],[13,19]],
    [[11,21],[13,21]], [[11,22],[13,22]]]
                   Type: List List List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangItsPageEmpty11}
\begin{paste}{ugLangItsPageEmpty11}{ugLangItsPagePatch11}
\pastebutton{ugLangItsPageEmpty11}{\showpaste}
\tab{5}\spadcommand{[[[i,j] for i in 10..15 | prime? i] for j in 17..22 | j = squareFreePart j]}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugLangStreamsPrimesPage}{ug05.ht}{An Example: Streams of Primes}
\begin{chunk}{ug05.ht}
\begin{page}{ugLangStreamsPrimesPage}{5.6. An Example: Streams of Primes}
\beginscroll

We conclude this chapter with an example of the creation and
manipulation of infinite streams of prime integers.  This might be
useful for experiments with numbers or other applications where you
are using sequences of primes over and over again.  As for all
streams, the stream of primes is only computed as far out as you need.
Once computed, however, all the primes up to that point are saved for
future reference.

Two useful operations provided by the Axiom library are
\axiomFunFrom{prime?}{IntegerPrimesPackage} and
\axiomFunFrom{nextPrime}{IntegerPrimesPackage}.
A straight-forward way to create a stream of
prime numbers is to start with the stream of positive integers 
\axiom{[2,..]} and filter out those that are prime.
\xtc{
Create a stream of primes.
}{
\spadpaste{primes : Stream Integer := [i for i in 2.. | prime? i]}
}
A more elegant way, however, is to use the \axiomFunFrom{generate}{Stream}
operation from \axiomType{Stream}.
Given an initial value \axiom{a} and a function \axiom{f},
\axiomFunFrom{generate}{Stream}
constructs the stream \axiom{[a, f(a), f(f(a)), ...]}.
This function gives you the quickest method of getting the stream of primes.
\xtc{
This is how you use
\axiomFunFrom{generate}{Stream} to
generate an infinite stream of primes.
}{
\spadpaste{primes := generate(nextPrime,2)}
}
\xtc{
Once the stream is generated, you might only be interested in
primes starting at a particular value.
}{
\spadpaste{smallPrimes := [p for p in primes | p > 1000] 
\bound{smallPrimes}}
}
\xtc{
Here are the first 11 primes greater than 1000.
}{
\spadpaste{[p for p in smallPrimes for i in 1..11] \free{smallPrimes}}
}
\xtc{
Here is a stream of primes between 1000 and 1200.
}{
\spadpaste{[p for p in smallPrimes while p < 1200] \free{smallPrimes}}
}
\xtc{
To get these expanded into a finite stream,
you call \axiomFunFrom{complete}{Stream} on the stream.
}{
\spadpaste{complete \%}
}
\xtc{
Twin primes are consecutive odd number pairs which are prime.
Here is the stream of twin primes.
}{
\spadpaste{twinPrimes := [[p,p+2] for p in primes | prime?(p + 2)]}
}
\xtc{
Since we already have the primes computed we can
avoid the call to \axiomFunFrom{prime?}{IntegerPrimesPackage}
by using a double iteration.
This time we'll just generate a stream of the first of the twin primes.
}{
\spadpaste{
firstOfTwins:= [p for p in primes for q in rest primes | q=p+2]}
}

Let's try to compute the infinite stream of triplet primes,
the set of primes \axiom{p} such that \axiom{[p,p+2,p+4]}
are primes. For example, \axiom{[3,5,7]} is a triple prime.
We could do this by a triple \axiom{for} iteration.
A more economical way is to use \userfun{firstOfTwins}.
This time however, put a semicolon at the end of the line.

\xtc{Create the stream of firstTriplets.
Put a semicolon at the end so that no
elements are computed.
}{
\spadpaste{firstTriplets := 
[p for p in firstOfTwins for q in rest firstOfTwins | q = p+2];}
}

What happened?  As you know, by default Axiom displays the first ten
elements of a stream when you first display it.  And, therefore, it
needs to compute them!  If you want {\it no} elements computed, just
terminate the expression by a semicolon (\axiomSyntax{;}).\footnote{
Why does this happen? The semi-colon prevents the display of the
result of evaluating the expression.  Since no stream elements are
needed for display (or anything else, so far), none are computed.
}

\xtc{
Compute the first triplet prime.
}{
\spadpaste{firstTriplets.1}
}

If you want to compute another, just ask for it.
But wait a second!
Given three consecutive odd integers, one of them must be divisible
by 3. Thus there is only one triplet prime.
But suppose that you did not know this and wanted to know what was the
tenth triplet prime.
\begin{verbatim}
firstTriples.10
\end{verbatim}
To compute the tenth triplet prime, Axiom first must compute the second,
the third, and so on.
But since there isn't even a second triplet prime, Axiom will
compute forever.
Nonetheless, this effort can produce a useful result.
After waiting a bit, hit
\texht{\fbox{\bf Ctrl}--\fbox{\bf c}}{{\bf Ctrl-c}}.
The system responds as follows.
\begin{verbatim}
   >> System error:
   Console interrupt.
   You are being returned to the top level of
   the interpreter.
\end{verbatim}
Let's say that you want to know how many primes have been computed.
Issue
\begin{verbatim}
numberOfComputedEntries primes
\end{verbatim}
and, for this discussion, let's say that the result is \axiom{2045.}
\xtc{
How big is the \eth{\axiom{2045}} prime?
}{
\spadpaste{primes.2045}
}

What you have learned is that there are no triplet primes between 5
and 17837.  Although this result is well known (some might even say
trivial), there are many experiments you could make where the result
is not known.  What you see here is a paradigm for testing of
hypotheses.  Here our hypothesis could have been: ``there is more than
one triplet prime.''  We have tested this hypothesis for 17837 cases.
With streams, you can let your machine run, interrupt it to see how
far it has progressed, then start it up and let it continue from where
it left off.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugLangStreamsPrimesPagePatch1}
\begin{paste}{ugLangStreamsPrimesPageFull1}{ugLangStreamsPrimesPageEmpty1}
\pastebutton{ugLangStreamsPrimesPageFull1}{\hidepaste}
\tab{5}\spadcommand{primes : Stream Integer := [i for i in 2.. | prime? i]}
\indentrel{3}\begin{verbatim}
   (1)  [2,3,5,7,11,13,17,19,23,29,...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangStreamsPrimesPageEmpty1}
\begin{paste}{ugLangStreamsPrimesPageEmpty1}{ugLangStreamsPrimesPagePatch1}
\pastebutton{ugLangStreamsPrimesPageEmpty1}{\showpaste}
\tab{5}\spadcommand{primes : Stream Integer := [i for i in 2.. | prime? i]}
\end{paste}\end{patch}

\begin{patch}{ugLangStreamsPrimesPagePatch2}
\begin{paste}{ugLangStreamsPrimesPageFull2}{ugLangStreamsPrimesPageEmpty2}
\pastebutton{ugLangStreamsPrimesPageFull2}{\hidepaste}
\tab{5}\spadcommand{primes := generate(nextPrime,2)}
\indentrel{3}\begin{verbatim}
   (2)  [2,3,5,7,11,13,17,19,23,29,...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangStreamsPrimesPageEmpty2}
\begin{paste}{ugLangStreamsPrimesPageEmpty2}{ugLangStreamsPrimesPagePatch2}
\pastebutton{ugLangStreamsPrimesPageEmpty2}{\showpaste}
\tab{5}\spadcommand{primes := generate(nextPrime,2)}
\end{paste}\end{patch}

\begin{patch}{ugLangStreamsPrimesPagePatch3}
\begin{paste}{ugLangStreamsPrimesPageFull3}{ugLangStreamsPrimesPageEmpty3}
\pastebutton{ugLangStreamsPrimesPageFull3}{\hidepaste}
\tab{5}\spadcommand{smallPrimes := [p for p in primes | p > 1000]\bound{smallPrimes }}
\indentrel{3}\begin{verbatim}
   (3)
   [1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangStreamsPrimesPageEmpty3}
\begin{paste}{ugLangStreamsPrimesPageEmpty3}{ugLangStreamsPrimesPagePatch3}
\pastebutton{ugLangStreamsPrimesPageEmpty3}{\showpaste}
\tab{5}\spadcommand{smallPrimes := [p for p in primes | p > 1000]\bound{smallPrimes }}
\end{paste}\end{patch}

\begin{patch}{ugLangStreamsPrimesPagePatch4}
\begin{paste}{ugLangStreamsPrimesPageFull4}{ugLangStreamsPrimesPageEmpty4}
\pastebutton{ugLangStreamsPrimesPageFull4}{\hidepaste}
\tab{5}\spadcommand{[p for p in smallPrimes for i in 1..11]\free{smallPrimes }}
\indentrel{3}\begin{verbatim}
   (4)
   [1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangStreamsPrimesPageEmpty4}
\begin{paste}{ugLangStreamsPrimesPageEmpty4}{ugLangStreamsPrimesPagePatch4}
\pastebutton{ugLangStreamsPrimesPageEmpty4}{\showpaste}
\tab{5}\spadcommand{[p for p in smallPrimes for i in 1..11]\free{smallPrimes }}
\end{paste}\end{patch}

\begin{patch}{ugLangStreamsPrimesPagePatch5}
\begin{paste}{ugLangStreamsPrimesPageFull5}{ugLangStreamsPrimesPageEmpty5}
\pastebutton{ugLangStreamsPrimesPageFull5}{\hidepaste}
\tab{5}\spadcommand{[p for p in smallPrimes while p < 1200]\free{smallPrimes }}
\indentrel{3}\begin{verbatim}
   (5)
   [1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangStreamsPrimesPageEmpty5}
\begin{paste}{ugLangStreamsPrimesPageEmpty5}{ugLangStreamsPrimesPagePatch5}
\pastebutton{ugLangStreamsPrimesPageEmpty5}{\showpaste}
\tab{5}\spadcommand{[p for p in smallPrimes while p < 1200]\free{smallPrimes }}
\end{paste}\end{patch}

\begin{patch}{ugLangStreamsPrimesPagePatch6}
\begin{paste}{ugLangStreamsPrimesPageFull6}{ugLangStreamsPrimesPageEmpty6}
\pastebutton{ugLangStreamsPrimesPageFull6}{\hidepaste}
\tab{5}\spadcommand{complete \%}
\indentrel{3}\begin{verbatim}
   (6)
   [1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangStreamsPrimesPageEmpty6}
\begin{paste}{ugLangStreamsPrimesPageEmpty6}{ugLangStreamsPrimesPagePatch6}
\pastebutton{ugLangStreamsPrimesPageEmpty6}{\showpaste}
\tab{5}\spadcommand{complete \%}
\end{paste}\end{patch}

\begin{patch}{ugLangStreamsPrimesPagePatch7}
\begin{paste}{ugLangStreamsPrimesPageFull7}{ugLangStreamsPrimesPageEmpty7}
\pastebutton{ugLangStreamsPrimesPageFull7}{\hidepaste}
\tab{5}\spadcommand{twinPrimes := [[p,p+2] for p in primes | prime?(p + 2)]}
\indentrel{3}\begin{verbatim}
   (7)
   [[3,5], [5,7], [11,13], [17,19], [29,31], [41,43],
    [59,61], [71,73], [101,103], [107,109], ...]
                              Type: Stream List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangStreamsPrimesPageEmpty7}
\begin{paste}{ugLangStreamsPrimesPageEmpty7}{ugLangStreamsPrimesPagePatch7}
\pastebutton{ugLangStreamsPrimesPageEmpty7}{\showpaste}
\tab{5}\spadcommand{twinPrimes := [[p,p+2] for p in primes | prime?(p + 2)]}
\end{paste}\end{patch}

\begin{patch}{ugLangStreamsPrimesPagePatch8}
\begin{paste}{ugLangStreamsPrimesPageFull8}{ugLangStreamsPrimesPageEmpty8}
\pastebutton{ugLangStreamsPrimesPageFull8}{\hidepaste}
\tab{5}\spadcommand{firstOfTwins:= [p for p in primes for q in rest primes | q=p+2]}
\indentrel{3}\begin{verbatim}
   (8)  [3,5,11,17,29,41,59,71,101,107,...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangStreamsPrimesPageEmpty8}
\begin{paste}{ugLangStreamsPrimesPageEmpty8}{ugLangStreamsPrimesPagePatch8}
\pastebutton{ugLangStreamsPrimesPageEmpty8}{\showpaste}
\tab{5}\spadcommand{firstOfTwins:= [p for p in primes for q in rest primes | q=p+2]}
\end{paste}\end{patch}

\begin{patch}{ugLangStreamsPrimesPagePatch9}
\begin{paste}{ugLangStreamsPrimesPageFull9}{ugLangStreamsPrimesPageEmpty9}
\pastebutton{ugLangStreamsPrimesPageFull9}{\hidepaste}
\tab{5}\spadcommand{firstTriplets := [p for p in firstOfTwins for q in rest firstOfTwins | q = p+2];}
\indentrel{3}\begin{verbatim}
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangStreamsPrimesPageEmpty9}
\begin{paste}{ugLangStreamsPrimesPageEmpty9}{ugLangStreamsPrimesPagePatch9}
\pastebutton{ugLangStreamsPrimesPageEmpty9}{\showpaste}
\tab{5}\spadcommand{firstTriplets := [p for p in firstOfTwins for q in rest firstOfTwins | q = p+2];}
\end{paste}\end{patch}

\begin{patch}{ugLangStreamsPrimesPagePatch10}
\begin{paste}{ugLangStreamsPrimesPageFull10}{ugLangStreamsPrimesPageEmpty10}
\pastebutton{ugLangStreamsPrimesPageFull10}{\hidepaste}
\tab{5}\spadcommand{firstTriplets.1}
\indentrel{3}\begin{verbatim}
   (10)  3
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangStreamsPrimesPageEmpty10}
\begin{paste}{ugLangStreamsPrimesPageEmpty10}{ugLangStreamsPrimesPagePatch10}
\pastebutton{ugLangStreamsPrimesPageEmpty10}{\showpaste}
\tab{5}\spadcommand{firstTriplets.1}
\end{paste}\end{patch}

\begin{patch}{ugLangStreamsPrimesPagePatch11}
\begin{paste}{ugLangStreamsPrimesPageFull11}{ugLangStreamsPrimesPageEmpty11}
\pastebutton{ugLangStreamsPrimesPageFull11}{\hidepaste}
\tab{5}\spadcommand{primes.2045}
\indentrel{3}\begin{verbatim}
   (11)  17837
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugLangStreamsPrimesPageEmpty11}
\begin{paste}{ugLangStreamsPrimesPageEmpty11}{ugLangStreamsPrimesPagePatch11}
\pastebutton{ugLangStreamsPrimesPageEmpty11}{\showpaste}
\tab{5}\spadcommand{primes.2045}
\end{paste}\end{patch}

\end{chunk}
\chapter{Users Guide Chapter 6 (ug06.ht)}
\pagetitle{ugUserPage}{ug06.ht}{User-Defined Functions, Macros and Rules}
\pageto{notitle}{ugUserFunMacPage}
\pageto{notitle}{ugUserMacrosPage}
\pageto{notitle}{ugUserIntroPage}
\pageto{notitle}{ugUserDeclarePage}
\pageto{notitle}{ugUserOnePage}
\pageto{notitle}{ugUserDecUndecPage}
\pageto{notitle}{ugUserDecOpersPage}
\pageto{notitle}{ugUserDelayPage}
\pageto{notitle}{ugUserUsePage}
\pageto{notitle}{ugUserCompIntPage}
\pageto{notitle}{ugUserPiecePage}
\pageto{notitle}{ugUserCachePage}
\pageto{notitle}{ugUserRecurPage}
\pageto{notitle}{ugUserMakePage}
\pageto{notitle}{ugUserBlocksPage}
\pageto{notitle}{ugUserFreeLocalPage}
\pageto{notitle}{ugUserAnonPage}
\pageto{notitle}{ugUserDatabasePage}
\pageto{notitle}{ugUserTrianglePage}
\pageto{notitle}{ugUserPalPage}
\pageto{notitle}{ugUserRulesPage}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserPage}{6. User-Defined Functions, Macros and Rules}
\beginscroll

In this chapter we show you how to write functions and macros,
and we explain how Axiom looks for and applies them.
We show some simple one-line examples of functions, together
with larger ones that are defined piece-by-piece or through the use of
piles.

\beginmenu
    \menudownlink{{6.1. Functions vs. Macros}}{ugUserFunMacPage}
    \menudownlink{{6.2. Macros}}{ugUserMacrosPage}
    \menudownlink{{6.3. Introduction to Functions}}{ugUserIntroPage}
    \menudownlink{{6.4. Declaring the Type of Functions}}
{ugUserDeclarePage}
    \menudownlink{{6.5. One-Line Functions}}{ugUserOnePage}
    \menudownlink{{6.6. Declared vs. Undeclared Functions}}
{ugUserDecUndecPage}
    \menudownlink{{6.7. Functions vs. Operations}}{ugUserDecOpersPage}
    \menudownlink{
{6.8. Delayed Assignments vs. Functions with No Arguments}}
{ugUserDelayPage}
    \menudownlink{{6.9. How Axiom Determines What Function to Use}}
{ugUserUsePage}
    \menudownlink{{6.10. Compiling vs. Interpreting}}
{ugUserCompIntPage}
    \menudownlink{{6.11. Piece-Wise Function Definitions}}
{ugUserPiecePage}
    \menudownlink{{6.12. Caching Previously Computed Results}}
{ugUserCachePage}
    \menudownlink{{6.13. Recurrence Relations}}{ugUserRecurPage}
    \menudownlink{{6.14. Making Functions from Objects}}
{ugUserMakePage}
    \menudownlink{{6.15. Functions Defined with Blocks}}
{ugUserBlocksPage}
    \menudownlink{{6.16. Free and Local Variables}}{ugUserFreeLocalPage}
    \menudownlink{{6.17. Anonymous Functions}}{ugUserAnonPage}
    \menudownlink{{6.18. Example: A Database}}{ugUserDatabasePage}
    \menudownlink{{6.19. Example: A Famous Triangle}}
{ugUserTrianglePage}
    \menudownlink{{6.20. Example: Testing for Palindromes}}
{ugUserPalPage}
    \menudownlink{{6.21. Rules and Pattern Matching}}{ugUserRulesPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugUserFunMacPage}{ug06.ht}{Functions vs. Macros}
\pageto{notitle}{ugUserAnonPage}
\pageto{notitle}{ExitXmpPage}
\pageto{notitle}{VoidXmpPage}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserFunMacPage}{6.1. Functions vs. Macros}
\beginscroll

A function is a program to perform some
computation.
Most functions have names so that it is easy to refer to them.
A simple example of a function is one named
\axiomFunFrom{abs}{Integer} which
computes the absolute value of an integer.
%
\xtc{
This is a use of the ``absolute value'' library function for integers.
}{
\spadpaste{abs(-8)}
}
\xtc{
This is an unnamed function that does the same thing, using the
``maps-to'' syntax \axiomSyntax{+->} that we discuss in
\downlink{``Anonymous Functions''}{ugUserAnonPage} 
in Section 6.17\ignore{ugUserAnon}.
}{
\spadpaste{(x +-> if x < 0 then -x else x)(-8)}
}
%
Functions can be used alone or serve as the building blocks for larger
programs.
Usually they return a value that you might want to use in the next stage
of a computation, but not always (for example, see
\downlink{`Exit'}{ExitXmpPage}\ignore{Exit} and 
\downlink{`Void'}{VoidXmpPage}\ignore{Void}).
They may also read data from your keyboard, move information from one
place to another, or format and display results on your screen.

In Axiom, as in mathematics, functions are usually
\spadglossSee{parameterized}{parameterized form}.  Each time you {\it
call} (some people say \spadgloss{apply} or
\spadglossSee{invoke}{invocation}) a function, you give values to the
parameters (variables).  Such a value is called an
\spadgloss{argument} of the function.  Axiom uses the arguments for
the computation.  In this way you get different results depending on
what you ``feed'' the function.

Functions can have local variables or refer to global variables in the
workspace.
Axiom can often \spadglossSee{compile}{compiler} functions so that
they execute very efficiently.
Functions can be passed as arguments to other functions.

Macros are textual substitutions.  They are used to clarify the
meaning of constants or expressions and to be templates for frequently
used expressions.  Macros can be parameterized but they are not
objects that can be passed as arguments to functions.  In effect,
macros are extensions to the Axiom expression parser.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserFunMacPagePatch1}
\begin{paste}{ugUserFunMacPageFull1}{ugUserFunMacPageEmpty1}
\pastebutton{ugUserFunMacPageFull1}{\hidepaste}
\tab{5}\spadcommand{abs(-8)}
\indentrel{3}\begin{verbatim}
   (1)  8
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFunMacPageEmpty1}
\begin{paste}{ugUserFunMacPageEmpty1}{ugUserFunMacPagePatch1}
\pastebutton{ugUserFunMacPageEmpty1}{\showpaste}
\tab{5}\spadcommand{abs(-8)}
\end{paste}\end{patch}

\begin{patch}{ugUserFunMacPagePatch2}
\begin{paste}{ugUserFunMacPageFull2}{ugUserFunMacPageEmpty2}
\pastebutton{ugUserFunMacPageFull2}{\hidepaste}
\tab{5}\spadcommand{(x +-> if x < 0 then -x else x)(-8)}
\indentrel{3}\begin{verbatim}
   (2)  8
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFunMacPageEmpty2}
\begin{paste}{ugUserFunMacPageEmpty2}{ugUserFunMacPagePatch2}
\pastebutton{ugUserFunMacPageEmpty2}{\showpaste}
\tab{5}\spadcommand{(x +-> if x < 0 then -x else x)(-8)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugUserMacrosPage}{ug06.ht}{Macros}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserMacrosPage}{6.2. Macros}
\beginscroll

A \spadgloss{macro} provides general textual substitution of
an Axiom expression for a name.
You can think of a macro as being a generalized abbreviation.
You can only have one macro in your workspace with
a given name, no matter how many arguments it has.

\beginImportant
The two general forms for macros are
\centerline{{{\tt macro} {\it name} {\tt ==} {\it body} }}
\centerline{{{\tt macro} {\it name(arg1,...)} {\tt ==} {\it body}}}
where the body of the macro can be any Axiom expression.
\endImportant

%
\xtc{
For example, suppose you decided that you
like to use \axiom{df} for \axiomFun{D}.
You define the macro \axiom{df} like this.
}{
\spadpaste{macro df == D \bound{df}}
}
\xtc{
Whenever you type \axiom{df}, the system expands it to
\axiomFun{D}.
}{
\spadpaste{df(x**2 + x + 1,x) \free{df}}
}
\xtc{
Macros can be parameterized and so can be used for many different
kinds of objects.
}{
\spadpaste{macro ff(x) == x**2 + 1 \bound{ff}}
}
\xtc{
Apply it to a number, a symbol, or an expression.
}{
\spadpaste{ff z \free{ff}}
}
\xtc{
Macros can also be nested, but you get an error message if you
run out of space because of an infinite nesting loop.
}{
\spadpaste{macro gg(x) == ff(2*x - 2/3) \bound{gg}\free{ff}}
}
\xtc{
This new macro is fine as it does not produce a loop.
}{
\spadpaste{gg(1/w) \free{gg}}
}
%
\xtc{
This, however, loops since \axiom{gg} is
defined in terms of \axiom{ff}.
}{
\spadpaste{macro ff(x) == gg(-x) \free{gg}}
}
\xtc{
The body of a macro can be a block.
}{
\spadpaste{macro next == (past := present; present := future; 
future := past + present) \bound{next}}
}
\xtc{
Before entering \axiom{next}, we need
values for \axiom{present} and \axiom{future}.
}{
\spadpaste{present : Integer := 0 \bound{present}}
}
\xtc{
}{
\spadpaste{future : Integer := 1 \bound{future}}
}
\xtc{
Repeatedly evaluating \axiom{next} produces the next Fibonacci number.
}{
\spadpaste{next \free{future}\free{present}}
}
\xtc{
And the next one.
}{
\spadpaste{next \free{future}\free{present}}
}
\xtc{
Here is the infinite stream of the rest of the Fibonacci numbers.
}{
\spadpaste{[next for i in 1..] \free{future}\free{present}}
}
\xtc{
Bundle all the above lines into a single macro.
}{
\begin{spadsrc}[\bound{fibstr}]
macro fibStream ==
  present : Integer := 1
  future : Integer := 1
  [next for i in 1..] where
    macro next ==
      past := present
      present := future
      future := past + present
\end{spadsrc}
}
\xtc{
Use \axiomFunFrom{concat}{Stream} to start with the first two
Fibonacci numbers.
}{
\spadpaste{concat([0,1],fibStream) \free{fibstr}}
}
\xtc{
An easier way to compute these numbers is to
use the library operation \axiomFun{fibonacci}.
}{
\spadpaste{[fibonacci i for i in 1..]}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserMacrosPagePatch1}
\begin{paste}{ugUserMacrosPageFull1}{ugUserMacrosPageEmpty1}
\pastebutton{ugUserMacrosPageFull1}{\hidepaste}
\tab{5}\spadcommand{macro df == D\bound{df }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPageEmpty1}
\begin{paste}{ugUserMacrosPageEmpty1}{ugUserMacrosPagePatch1}
\pastebutton{ugUserMacrosPageEmpty1}{\showpaste}
\tab{5}\spadcommand{macro df == D\bound{df }}
\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPagePatch2}
\begin{paste}{ugUserMacrosPageFull2}{ugUserMacrosPageEmpty2}
\pastebutton{ugUserMacrosPageFull2}{\hidepaste}
\tab{5}\spadcommand{df(x**2 + x + 1,x)\free{df }}
\indentrel{3}\begin{verbatim}
   (2)  2x + 1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPageEmpty2}
\begin{paste}{ugUserMacrosPageEmpty2}{ugUserMacrosPagePatch2}
\pastebutton{ugUserMacrosPageEmpty2}{\showpaste}
\tab{5}\spadcommand{df(x**2 + x + 1,x)\free{df }}
\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPagePatch3}
\begin{paste}{ugUserMacrosPageFull3}{ugUserMacrosPageEmpty3}
\pastebutton{ugUserMacrosPageFull3}{\hidepaste}
\tab{5}\spadcommand{macro ff(x) == x**2 + 1\bound{ff }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPageEmpty3}
\begin{paste}{ugUserMacrosPageEmpty3}{ugUserMacrosPagePatch3}
\pastebutton{ugUserMacrosPageEmpty3}{\showpaste}
\tab{5}\spadcommand{macro ff(x) == x**2 + 1\bound{ff }}
\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPagePatch4}
\begin{paste}{ugUserMacrosPageFull4}{ugUserMacrosPageEmpty4}
\pastebutton{ugUserMacrosPageFull4}{\hidepaste}
\tab{5}\spadcommand{ff z\free{ff }}
\indentrel{3}\begin{verbatim}
         2
   (4)  z  + 1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPageEmpty4}
\begin{paste}{ugUserMacrosPageEmpty4}{ugUserMacrosPagePatch4}
\pastebutton{ugUserMacrosPageEmpty4}{\showpaste}
\tab{5}\spadcommand{ff z\free{ff }}
\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPagePatch5}
\begin{paste}{ugUserMacrosPageFull5}{ugUserMacrosPageEmpty5}
\pastebutton{ugUserMacrosPageFull5}{\hidepaste}
\tab{5}\spadcommand{macro gg(x) == ff(2*x - 2/3)\bound{gg }\free{ff }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPageEmpty5}
\begin{paste}{ugUserMacrosPageEmpty5}{ugUserMacrosPagePatch5}
\pastebutton{ugUserMacrosPageEmpty5}{\showpaste}
\tab{5}\spadcommand{macro gg(x) == ff(2*x - 2/3)\bound{gg }\free{ff }}
\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPagePatch6}
\begin{paste}{ugUserMacrosPageFull6}{ugUserMacrosPageEmpty6}
\pastebutton{ugUserMacrosPageFull6}{\hidepaste}
\tab{5}\spadcommand{gg(1/w)\free{gg }}
\indentrel{3}\begin{verbatim}
           2
        13w  - 24w + 36
   (6)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                2
              9w
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPageEmpty6}
\begin{paste}{ugUserMacrosPageEmpty6}{ugUserMacrosPagePatch6}
\pastebutton{ugUserMacrosPageEmpty6}{\showpaste}
\tab{5}\spadcommand{gg(1/w)\free{gg }}
\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPagePatch7}
\begin{paste}{ugUserMacrosPageFull7}{ugUserMacrosPageEmpty7}
\pastebutton{ugUserMacrosPageFull7}{\hidepaste}
\tab{5}\spadcommand{macro ff(x) == gg(-x)\free{gg }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPageEmpty7}
\begin{paste}{ugUserMacrosPageEmpty7}{ugUserMacrosPagePatch7}
\pastebutton{ugUserMacrosPageEmpty7}{\showpaste}
\tab{5}\spadcommand{macro ff(x) == gg(-x)\free{gg }}
\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPagePatch8}
\begin{paste}{ugUserMacrosPageFull8}{ugUserMacrosPageEmpty8}
\pastebutton{ugUserMacrosPageFull8}{\hidepaste}
\tab{5}\spadcommand{macro next == (past := present; present := future; future := past + present)\bound{next }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPageEmpty8}
\begin{paste}{ugUserMacrosPageEmpty8}{ugUserMacrosPagePatch8}
\pastebutton{ugUserMacrosPageEmpty8}{\showpaste}
\tab{5}\spadcommand{macro next == (past := present; present := future; future := past + present)\bound{next }}
\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPagePatch9}
\begin{paste}{ugUserMacrosPageFull9}{ugUserMacrosPageEmpty9}
\pastebutton{ugUserMacrosPageFull9}{\hidepaste}
\tab{5}\spadcommand{present : Integer := 0\bound{present }}
\indentrel{3}\begin{verbatim}
   (9)  0
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPageEmpty9}
\begin{paste}{ugUserMacrosPageEmpty9}{ugUserMacrosPagePatch9}
\pastebutton{ugUserMacrosPageEmpty9}{\showpaste}
\tab{5}\spadcommand{present : Integer := 0\bound{present }}
\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPagePatch10}
\begin{paste}{ugUserMacrosPageFull10}{ugUserMacrosPageEmpty10}
\pastebutton{ugUserMacrosPageFull10}{\hidepaste}
\tab{5}\spadcommand{future : Integer := 1\bound{future }}
\indentrel{3}\begin{verbatim}
   (10)  1
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPageEmpty10}
\begin{paste}{ugUserMacrosPageEmpty10}{ugUserMacrosPagePatch10}
\pastebutton{ugUserMacrosPageEmpty10}{\showpaste}
\tab{5}\spadcommand{future : Integer := 1\bound{future }}
\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPagePatch11}
\begin{paste}{ugUserMacrosPageFull11}{ugUserMacrosPageEmpty11}
\pastebutton{ugUserMacrosPageFull11}{\hidepaste}
\tab{5}\spadcommand{next\free{future }\free{present }}
\indentrel{3}\begin{verbatim}
   (11)  1
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPageEmpty11}
\begin{paste}{ugUserMacrosPageEmpty11}{ugUserMacrosPagePatch11}
\pastebutton{ugUserMacrosPageEmpty11}{\showpaste}
\tab{5}\spadcommand{next\free{future }\free{present }}
\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPagePatch12}
\begin{paste}{ugUserMacrosPageFull12}{ugUserMacrosPageEmpty12}
\pastebutton{ugUserMacrosPageFull12}{\hidepaste}
\tab{5}\spadcommand{next\free{future }\free{present }}
\indentrel{3}\begin{verbatim}
   (12)  2
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPageEmpty12}
\begin{paste}{ugUserMacrosPageEmpty12}{ugUserMacrosPagePatch12}
\pastebutton{ugUserMacrosPageEmpty12}{\showpaste}
\tab{5}\spadcommand{next\free{future }\free{present }}
\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPagePatch13}
\begin{paste}{ugUserMacrosPageFull13}{ugUserMacrosPageEmpty13}
\pastebutton{ugUserMacrosPageFull13}{\hidepaste}
\tab{5}\spadcommand{[next for i in 1..]\free{future }\free{present }}
\indentrel{3}\begin{verbatim}
   (13)  [3,5,8,13,21,34,55,89,144,233,...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPageEmpty13}
\begin{paste}{ugUserMacrosPageEmpty13}{ugUserMacrosPagePatch13}
\pastebutton{ugUserMacrosPageEmpty13}{\showpaste}
\tab{5}\spadcommand{[next for i in 1..]\free{future }\free{present }}
\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPagePatch14}
\begin{paste}{ugUserMacrosPageFull14}{ugUserMacrosPageEmpty14}
\pastebutton{ugUserMacrosPageFull14}{\hidepaste}
\tab{5}\spadcommand{macro fibStream ==
  present : Integer := 1
  future : Integer := 1
  [next for i in 1..] where
    macro next ==
      past := present
      present := future
      future := past + present
\bound{fibstr }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPageEmpty14}
\begin{paste}{ugUserMacrosPageEmpty14}{ugUserMacrosPagePatch14}
\pastebutton{ugUserMacrosPageEmpty14}{\showpaste}
\tab{5}\spadcommand{macro fibStream ==
  present : Integer := 1
  future : Integer := 1
  [next for i in 1..] where
    macro next ==
      past := present
      present := future
      future := past + present
\bound{fibstr }}
\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPagePatch15}
\begin{paste}{ugUserMacrosPageFull15}{ugUserMacrosPageEmpty15}
\pastebutton{ugUserMacrosPageFull15}{\hidepaste}
\tab{5}\spadcommand{concat([0,1],fibStream)\free{fibstr }}
\indentrel{3}\begin{verbatim}
   (15)  [0,1,2,3,5,8,13,21,34,55,...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPageEmpty15}
\begin{paste}{ugUserMacrosPageEmpty15}{ugUserMacrosPagePatch15}
\pastebutton{ugUserMacrosPageEmpty15}{\showpaste}
\tab{5}\spadcommand{concat([0,1],fibStream)\free{fibstr }}
\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPagePatch16}
\begin{paste}{ugUserMacrosPageFull16}{ugUserMacrosPageEmpty16}
\pastebutton{ugUserMacrosPageFull16}{\hidepaste}
\tab{5}\spadcommand{[fibonacci i for i in 1..]}
\indentrel{3}\begin{verbatim}
   (16)  [1,1,2,3,5,8,13,21,34,55,...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMacrosPageEmpty16}
\begin{paste}{ugUserMacrosPageEmpty16}{ugUserMacrosPagePatch16}
\pastebutton{ugUserMacrosPageEmpty16}{\showpaste}
\tab{5}\spadcommand{[fibonacci i for i in 1..]}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugUserIntroPage}{ug06.ht}{Introduction to Functions}
\pageto{notitle}{ugTypesPkgCallPage}
\pageto{notitle}{ugUserAnonPage}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserIntroPage}{6.3. Introduction to Functions}
\beginscroll

Each name in your workspace can refer to a single object.
This may be any kind of object including a function.
You can use interactively any function from the library or any that you
define in the workspace.
In the library the same name can have very many functions, but you
can have only one function with a given name, although it can have any
number of arguments that you choose.

If you define a function in the workspace that has the same name and number
of arguments as one in the library, then your definition takes precedence.
In fact, to get the library function you must
\spadglossSee{package-call}{package call} it (see 
\downlink{``Package Calling and Target Types''}{ugTypesPkgCallPage} 
in Section 2.9\ignore{ugTypesPkgCall}).

To use a function in Axiom, you apply it to its arguments.
Most functions are applied by entering the name of the function followed by
its argument or arguments.
\xtc{
}{
\spadpaste{factor(12)}
}
%
\xtc{
Some functions like 
\axiomOp{+} have {\it infix} \spadgloss{operators} as names.
}{
\spadpaste{3 + 4}
}
\xtc{
The function \axiomOp{+} has two arguments.
When you give it more than two arguments,
Axiom groups the arguments to the left.
This expression is equivalent to \axiom{(1 + 2) + 7}.
}{
\spadpaste{1 + 2 + 7}
}

All operations, including infix operators, can be written in prefix form,
that is, with the operation name followed by the arguments
in parentheses.
For example, \axiom{2 + 3} can alternatively be written as \axiom{+(2,3)}.
But \axiom{+(2,3,4)} is an error since \axiomOp{+}
takes only two arguments.

Prefix operations are generally applied before the infix operation.
Thus \axiom{factorial 3 + 1} means \axiom{factorial(3) + 1} producing
\axiom{7}, and
\axiom{- 2 + 5} means \axiom{(-2) + 5} producing \axiom{3}.
An example of a prefix operator is prefix \axiomOp{-}.
For example, \axiom{- 2 + 5} converts to \axiom{(- 2) + 5} producing
the value \axiom{3}.
Any prefix function taking two arguments can be written in
an infix manner by putting an
ampersand (\axiomSyntax{\&}) before the name.
Thus \axiom{D(2*x,x)} can be written as
\axiom{2*x \&D x} returning \axiom{2}.

Every function in Axiom is identified by
a \spadgloss{name} and \spadgloss{type}.\footnote{An exception is
an ``anonymous function''
discussed in
\downlink{``Anonymous Functions''}{ugUserAnonPage} 
in Section 6.17\ignore{ugUserAnon}.}
The type of a function is always a mapping of the form
\spadsig{Source}{Target}
where \axiom{Source} and \axiom{Target} are types.
To enter a type from the keyboard, enter the arrow by using
a hyphen \axiomSyntax{-} followed by a greater-than sign
\axiomSyntax{>}, e.g. {\tt Integer -> Integer}.

Let's go back to \axiomOp{+}.
There are many \axiomOp{+} functions in the
Axiom library: one for integers, one for floats, another for
rational numbers, and so on.
These \axiomOp{+} functions have different types and thus are
different functions.
You've seen examples of this \spadgloss{overloading}
before---using the same name for different functions.
Overloading is the rule rather than the exception.
You can add two integers, two polynomials, two matrices or
two power series.
These are all done with the same function name
but with different functions.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserIntroPagePatch1}
\begin{paste}{ugUserIntroPageFull1}{ugUserIntroPageEmpty1}
\pastebutton{ugUserIntroPageFull1}{\hidepaste}
\tab{5}\spadcommand{factor(12)}
\indentrel{3}\begin{verbatim}
         2
   (1)  2 3
                                 Type: Factored Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserIntroPageEmpty1}
\begin{paste}{ugUserIntroPageEmpty1}{ugUserIntroPagePatch1}
\pastebutton{ugUserIntroPageEmpty1}{\showpaste}
\tab{5}\spadcommand{factor(12)}
\end{paste}\end{patch}

\begin{patch}{ugUserIntroPagePatch2}
\begin{paste}{ugUserIntroPageFull2}{ugUserIntroPageEmpty2}
\pastebutton{ugUserIntroPageFull2}{\hidepaste}
\tab{5}\spadcommand{3 + 4}
\indentrel{3}\begin{verbatim}
   (2)  7
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserIntroPageEmpty2}
\begin{paste}{ugUserIntroPageEmpty2}{ugUserIntroPagePatch2}
\pastebutton{ugUserIntroPageEmpty2}{\showpaste}
\tab{5}\spadcommand{3 + 4}
\end{paste}\end{patch}

\begin{patch}{ugUserIntroPagePatch3}
\begin{paste}{ugUserIntroPageFull3}{ugUserIntroPageEmpty3}
\pastebutton{ugUserIntroPageFull3}{\hidepaste}
\tab{5}\spadcommand{1 + 2 + 7}
\indentrel{3}\begin{verbatim}
   (3)  10
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserIntroPageEmpty3}
\begin{paste}{ugUserIntroPageEmpty3}{ugUserIntroPagePatch3}
\pastebutton{ugUserIntroPageEmpty3}{\showpaste}
\tab{5}\spadcommand{1 + 2 + 7}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugUserDeclarePage}{ug06.ht}{Declaring the Type of Functions}
\pageto{notitle}{ugTypesDeclarePage}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserDeclarePage}{6.4. Declaring the Type of Functions}
\beginscroll

In \downlink{``Declarations''}{ugTypesDeclarePage} 
in Section 2.3\ignore{ugTypesDeclare} we 
discussed how to declare a variable
to restrict the kind of values that can be assigned to it.
In this section we show how to declare a variable that refers to
function objects.

\beginImportant
A function is an object of type
\centerline{{\spadsig{Source}{Type}}}
where \axiom{Source} and \axiom{Target} can be any type.
A common type for \axiom{Source} is
\axiomType{Tuple}(\subscriptIt{T}{1}, \ldots, \subscriptIt{T}{n}),
usually written
(\subscriptIt{T}{1}, \ldots, \subscriptIt{T}{n}),
to indicate a function of \axiom{n} arguments.
\endImportant

\xtc{
If \axiom{g} takes an \axiomType{Integer}, a \axiomType{Float} and
another \axiomType{Integer}, and returns a
\axiomType{String}, the declaration is written this way.
}{
\spadpaste{g: (Integer,Float,Integer) -> String}
}
\xtc{
The types need not be written fully; using abbreviations, the above
declaration is:
}{
\spadpaste{g: (INT,FLOAT,INT) -> STRING}
}
\xtc{
It is possible for a function to take no arguments.
If \axiom{ h} takes no arguments
but returns a \axiomType{Polynomial} \axiomType{Integer}, any
of the following declarations is acceptable.
}{
\spadpaste{h: () -> POLY INT}
}
\xtc{
}{
\spadpaste{h: () -> Polynomial INT}
}
\xtc{
}{
\spadpaste{h: () -> POLY Integer}
}


\beginImportant
Functions can also be declared when they are being defined.
The syntax for combined declaration/definition is:
\centerline{{\frenchspacing{\tt {\it functionName}(
\subscriptIt{parm}{1}: \subscriptIt{parmType}{1}, \ldots, 
\subscriptIt{parm}{N}: \subscriptIt{parmType}{N}): 
{\it functionReturnType}}}}
\endImportant

The following definition fragments show how this can be done for
the functions \axiom{g} and \axiom{h} above.
\begin{verbatim}
g(arg1: INT, arg2: FLOAT, arg3: INT): STRING == ...

h(): POLY INT == ...
\end{verbatim}

A current restriction on function declarations is that they must
involve fully specified types (that is, cannot include modes involving
explicit or implicit \axiomSyntax{?}).
For more information on declaring things in general, see
\downlink{``Declarations''}{ugTypesDeclarePage} 
in Section 2.3\ignore{ugTypesDeclare}.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserDeclarePagePatch1}
\begin{paste}{ugUserDeclarePageFull1}{ugUserDeclarePageEmpty1}
\pastebutton{ugUserDeclarePageFull1}{\hidepaste}
\tab{5}\spadcommand{g: (Integer,Float,Integer) -> String}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDeclarePageEmpty1}
\begin{paste}{ugUserDeclarePageEmpty1}{ugUserDeclarePagePatch1}
\pastebutton{ugUserDeclarePageEmpty1}{\showpaste}
\tab{5}\spadcommand{g: (Integer,Float,Integer) -> String}
\end{paste}\end{patch}

\begin{patch}{ugUserDeclarePagePatch2}
\begin{paste}{ugUserDeclarePageFull2}{ugUserDeclarePageEmpty2}
\pastebutton{ugUserDeclarePageFull2}{\hidepaste}
\tab{5}\spadcommand{g: (INT,FLOAT,INT) -> STRING}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDeclarePageEmpty2}
\begin{paste}{ugUserDeclarePageEmpty2}{ugUserDeclarePagePatch2}
\pastebutton{ugUserDeclarePageEmpty2}{\showpaste}
\tab{5}\spadcommand{g: (INT,FLOAT,INT) -> STRING}
\end{paste}\end{patch}

\begin{patch}{ugUserDeclarePagePatch3}
\begin{paste}{ugUserDeclarePageFull3}{ugUserDeclarePageEmpty3}
\pastebutton{ugUserDeclarePageFull3}{\hidepaste}
\tab{5}\spadcommand{h: () -> POLY INT}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDeclarePageEmpty3}
\begin{paste}{ugUserDeclarePageEmpty3}{ugUserDeclarePagePatch3}
\pastebutton{ugUserDeclarePageEmpty3}{\showpaste}
\tab{5}\spadcommand{h: () -> POLY INT}
\end{paste}\end{patch}

\begin{patch}{ugUserDeclarePagePatch4}
\begin{paste}{ugUserDeclarePageFull4}{ugUserDeclarePageEmpty4}
\pastebutton{ugUserDeclarePageFull4}{\hidepaste}
\tab{5}\spadcommand{h: () -> Polynomial INT}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDeclarePageEmpty4}
\begin{paste}{ugUserDeclarePageEmpty4}{ugUserDeclarePagePatch4}
\pastebutton{ugUserDeclarePageEmpty4}{\showpaste}
\tab{5}\spadcommand{h: () -> Polynomial INT}
\end{paste}\end{patch}

\begin{patch}{ugUserDeclarePagePatch5}
\begin{paste}{ugUserDeclarePageFull5}{ugUserDeclarePageEmpty5}
\pastebutton{ugUserDeclarePageFull5}{\hidepaste}
\tab{5}\spadcommand{h: () -> POLY Integer}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDeclarePageEmpty5}
\begin{paste}{ugUserDeclarePageEmpty5}{ugUserDeclarePagePatch5}
\pastebutton{ugUserDeclarePageEmpty5}{\showpaste}
\tab{5}\spadcommand{h: () -> POLY Integer}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugUserOnePage}{ug06.ht}{One-Line Functions}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserOnePage}{6.5. One-Line Functions}
\beginscroll

As you use Axiom, you will find that you will write many short functions
to codify sequences of operations that you often perform.
In this section we write some simple one-line functions.

\xtc{
This is a simple recursive factorial function for positive integers.
}{
\spadpaste{fac n == if n < 3 then n else n * fac(n-1) \bound{fac}}
}
\xtc{
}{
\spadpaste{fac 10 \free{fac}}
}
%>> Thankfully, the $ is no longer needed in the next example.
\xtc{
This function computes \axiom{1 + 1/2 + 1/3 + ... + 1/n}.
}{
\spadpaste{s n == reduce(+,[1/i for i in 1..n]) \bound{s}}
}
\xtc{
}{
\spadpaste{s 50 \free{s}}
}
\xtc{
This function computes a Mersenne number, several of which are prime.
}{
\spadpaste{mersenne i == 2**i - 1 \bound{mersenne}}
}
\xtc{
If you type \axiom{mersenne}, Axiom shows you
the function definition.
}{
\spadpaste{mersenne \free{mersenne}}
}
\xtc{
Generate a stream of Mersenne numbers.
}{
\spadpaste{[mersenne i for i in 1..] \free{mersenne}}
}
\xtc{
Create a stream of those values of \axiom{i} such that
\axiom{mersenne(i)} is prime.
}{
\spadpaste{mersenneIndex := [n for n in 1.. | prime?(mersenne(n))] 
\bound{mersenneIndex}\free{mersenne}}
}
\xtc{
Finally, write a function that returns the \eth{\axiom{n}} Mersenne
prime.
}{
\spadpaste{mersennePrime n == mersenne mersenneIndex(n) 
\free{mersenne mersenneIndex}\bound{mersennePrime}}
}
\xtc{
}{
\spadpaste{mersennePrime 5 \free{mersennePrime}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserOnePagePatch1}
\begin{paste}{ugUserOnePageFull1}{ugUserOnePageEmpty1}
\pastebutton{ugUserOnePageFull1}{\hidepaste}
\tab{5}\spadcommand{fac n == if n < 3 then n else n * fac(n-1)\bound{fac }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserOnePageEmpty1}
\begin{paste}{ugUserOnePageEmpty1}{ugUserOnePagePatch1}
\pastebutton{ugUserOnePageEmpty1}{\showpaste}
\tab{5}\spadcommand{fac n == if n < 3 then n else n * fac(n-1)\bound{fac }}
\end{paste}\end{patch}

\begin{patch}{ugUserOnePagePatch2}
\begin{paste}{ugUserOnePageFull2}{ugUserOnePageEmpty2}
\pastebutton{ugUserOnePageFull2}{\hidepaste}
\tab{5}\spadcommand{fac 10\free{fac }}
\indentrel{3}\begin{verbatim}
   (2)  3628800
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserOnePageEmpty2}
\begin{paste}{ugUserOnePageEmpty2}{ugUserOnePagePatch2}
\pastebutton{ugUserOnePageEmpty2}{\showpaste}
\tab{5}\spadcommand{fac 10\free{fac }}
\end{paste}\end{patch}

\begin{patch}{ugUserOnePagePatch3}
\begin{paste}{ugUserOnePageFull3}{ugUserOnePageEmpty3}
\pastebutton{ugUserOnePageFull3}{\hidepaste}
\tab{5}\spadcommand{s n == reduce(+,[1/i for i in 1..n])\bound{s }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserOnePageEmpty3}
\begin{paste}{ugUserOnePageEmpty3}{ugUserOnePagePatch3}
\pastebutton{ugUserOnePageEmpty3}{\showpaste}
\tab{5}\spadcommand{s n == reduce(+,[1/i for i in 1..n])\bound{s }}
\end{paste}\end{patch}

\begin{patch}{ugUserOnePagePatch4}
\begin{paste}{ugUserOnePageFull4}{ugUserOnePageEmpty4}
\pastebutton{ugUserOnePageFull4}{\hidepaste}
\tab{5}\spadcommand{s 50\free{s }}
\indentrel{3}\begin{verbatim}
        13943237577224054960759
   (4)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
         3099044504245996706400
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserOnePageEmpty4}
\begin{paste}{ugUserOnePageEmpty4}{ugUserOnePagePatch4}
\pastebutton{ugUserOnePageEmpty4}{\showpaste}
\tab{5}\spadcommand{s 50\free{s }}
\end{paste}\end{patch}

\begin{patch}{ugUserOnePagePatch5}
\begin{paste}{ugUserOnePageFull5}{ugUserOnePageEmpty5}
\pastebutton{ugUserOnePageFull5}{\hidepaste}
\tab{5}\spadcommand{mersenne i == 2**i - 1\bound{mersenne }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserOnePageEmpty5}
\begin{paste}{ugUserOnePageEmpty5}{ugUserOnePagePatch5}
\pastebutton{ugUserOnePageEmpty5}{\showpaste}
\tab{5}\spadcommand{mersenne i == 2**i - 1\bound{mersenne }}
\end{paste}\end{patch}

\begin{patch}{ugUserOnePagePatch6}
\begin{paste}{ugUserOnePageFull6}{ugUserOnePageEmpty6}
\pastebutton{ugUserOnePageFull6}{\hidepaste}
\tab{5}\spadcommand{mersenne\free{mersenne }}
\indentrel{3}\begin{verbatim}
                       i
   (6)  mersenne i == 2  - 1
                          Type: FunctionCalled mersenne
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserOnePageEmpty6}
\begin{paste}{ugUserOnePageEmpty6}{ugUserOnePagePatch6}
\pastebutton{ugUserOnePageEmpty6}{\showpaste}
\tab{5}\spadcommand{mersenne\free{mersenne }}
\end{paste}\end{patch}

\begin{patch}{ugUserOnePagePatch7}
\begin{paste}{ugUserOnePageFull7}{ugUserOnePageEmpty7}
\pastebutton{ugUserOnePageFull7}{\hidepaste}
\tab{5}\spadcommand{[mersenne i for i in 1..]\free{mersenne }}
\indentrel{3}\begin{verbatim}
   (7)  [1,3,7,15,31,63,127,255,511,1023,...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserOnePageEmpty7}
\begin{paste}{ugUserOnePageEmpty7}{ugUserOnePagePatch7}
\pastebutton{ugUserOnePageEmpty7}{\showpaste}
\tab{5}\spadcommand{[mersenne i for i in 1..]\free{mersenne }}
\end{paste}\end{patch}

\begin{patch}{ugUserOnePagePatch8}
\begin{paste}{ugUserOnePageFull8}{ugUserOnePageEmpty8}
\pastebutton{ugUserOnePageFull8}{\hidepaste}
\tab{5}\spadcommand{mersenneIndex := [n for n in 1.. | prime?(mersenne(n))]\bound{mersenneIndex }\free{mersenne }}
\indentrel{3}\begin{verbatim}
   (8)  [2,3,5,7,13,17,19,31,61,89,...]
                           Type: Stream PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserOnePageEmpty8}
\begin{paste}{ugUserOnePageEmpty8}{ugUserOnePagePatch8}
\pastebutton{ugUserOnePageEmpty8}{\showpaste}
\tab{5}\spadcommand{mersenneIndex := [n for n in 1.. | prime?(mersenne(n))]\bound{mersenneIndex }\free{mersenne }}
\end{paste}\end{patch}

\begin{patch}{ugUserOnePagePatch9}
\begin{paste}{ugUserOnePageFull9}{ugUserOnePageEmpty9}
\pastebutton{ugUserOnePageFull9}{\hidepaste}
\tab{5}\spadcommand{mersennePrime n == mersenne mersenneIndex(n)\free{mersenne mersenneIndex }\bound{mersennePrime }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserOnePageEmpty9}
\begin{paste}{ugUserOnePageEmpty9}{ugUserOnePagePatch9}
\pastebutton{ugUserOnePageEmpty9}{\showpaste}
\tab{5}\spadcommand{mersennePrime n == mersenne mersenneIndex(n)\free{mersenne mersenneIndex }\bound{mersennePrime }}
\end{paste}\end{patch}

\begin{patch}{ugUserOnePagePatch10}
\begin{paste}{ugUserOnePageFull10}{ugUserOnePageEmpty10}
\pastebutton{ugUserOnePageFull10}{\hidepaste}
\tab{5}\spadcommand{mersennePrime 5\free{mersennePrime }}
\indentrel{3}\begin{verbatim}
   (10)  8191
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserOnePageEmpty10}
\begin{paste}{ugUserOnePageEmpty10}{ugUserOnePagePatch10}
\pastebutton{ugUserOnePageEmpty10}{\showpaste}
\tab{5}\spadcommand{mersennePrime 5\free{mersennePrime }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugUserDecUndecPage}{ug06.ht}{Declared vs. Undeclared Functions}
\pageto{notitle}{ugCategoriesPage}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserDecUndecPage}{6.6. Declared vs. Undeclared Functions}
\beginscroll

If you declare the type of a function, you can apply
it to any data that can be converted to the source type
of the function.

\labelSpace{2pc}
\xtc{
Define \userfun{f} with type \spadsig{Integer}{Integer}.
}{
\spadpaste{f(x: Integer): Integer == x + 1 \bound{f}}
}
\xtc{
The function
\userfun{f} can be applied to integers, \ldots
}{
\spadpaste{f 9 \free{f}}
}
\xtc{
and to values that convert to integers, \ldots
}{
\spadpaste{f(-2.0) \free{f}}
}
\xtc{
but not to values that cannot be converted to integers.
}{
\spadpaste{f(2/3) \free{f}}
}

To make the function over a wide range of types, do not
declare its type.
\xtc{
Give the same definition with no declaration.
}{
\spadpaste{g x == x + 1 \bound{g}}
}
\xtc{
If \axiom{x + 1} makes sense, you can apply \userfun{g} to \axiom{x}.
}{
\spadpaste{g 9 \free{g}}
}
\xtc{
A version of \userfun{g} with different argument types
get compiled for each new kind of argument used.
}{
\spadpaste{g(2/3)  \free{g}}
}
\xtc{
Here \axiom{x+1} for \axiom{x = "axiom"} makes no sense.
}{
\spadpaste{g("axiom")\free{g}}
}

As you will see in \downlink{``Categories''}{ugCategoriesPage} 
in Chapter 12\ignore{ugCategories},
Axiom has a formal idea of categories for what ``makes sense.''

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserDecUndecPagePatch1}
\begin{paste}{ugUserDecUndecPageFull1}{ugUserDecUndecPageEmpty1}
\pastebutton{ugUserDecUndecPageFull1}{\hidepaste}
\tab{5}\spadcommand{f(x: Integer): Integer == x + 1\bound{f }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDecUndecPageEmpty1}
\begin{paste}{ugUserDecUndecPageEmpty1}{ugUserDecUndecPagePatch1}
\pastebutton{ugUserDecUndecPageEmpty1}{\showpaste}
\tab{5}\spadcommand{f(x: Integer): Integer == x + 1\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ugUserDecUndecPagePatch2}
\begin{paste}{ugUserDecUndecPageFull2}{ugUserDecUndecPageEmpty2}
\pastebutton{ugUserDecUndecPageFull2}{\hidepaste}
\tab{5}\spadcommand{f 9\free{f }}
\indentrel{3}\begin{verbatim}
   (2)  10
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDecUndecPageEmpty2}
\begin{paste}{ugUserDecUndecPageEmpty2}{ugUserDecUndecPagePatch2}
\pastebutton{ugUserDecUndecPageEmpty2}{\showpaste}
\tab{5}\spadcommand{f 9\free{f }}
\end{paste}\end{patch}

\begin{patch}{ugUserDecUndecPagePatch3}
\begin{paste}{ugUserDecUndecPageFull3}{ugUserDecUndecPageEmpty3}
\pastebutton{ugUserDecUndecPageFull3}{\hidepaste}
\tab{5}\spadcommand{f(-2.0)\free{f }}
\indentrel{3}\begin{verbatim}
   (3)  - 1
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDecUndecPageEmpty3}
\begin{paste}{ugUserDecUndecPageEmpty3}{ugUserDecUndecPagePatch3}
\pastebutton{ugUserDecUndecPageEmpty3}{\showpaste}
\tab{5}\spadcommand{f(-2.0)\free{f }}
\end{paste}\end{patch}

\begin{patch}{ugUserDecUndecPagePatch4}
\begin{paste}{ugUserDecUndecPageFull4}{ugUserDecUndecPageEmpty4}
\pastebutton{ugUserDecUndecPageFull4}{\hidepaste}
\tab{5}\spadcommand{f(2/3)\free{f }}
\indentrel{3}\begin{verbatim}
   2
   Ä
   3
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDecUndecPageEmpty4}
\begin{paste}{ugUserDecUndecPageEmpty4}{ugUserDecUndecPagePatch4}
\pastebutton{ugUserDecUndecPageEmpty4}{\showpaste}
\tab{5}\spadcommand{f(2/3)\free{f }}
\end{paste}\end{patch}

\begin{patch}{ugUserDecUndecPagePatch5}
\begin{paste}{ugUserDecUndecPageFull5}{ugUserDecUndecPageEmpty5}
\pastebutton{ugUserDecUndecPageFull5}{\hidepaste}
\tab{5}\spadcommand{g x == x + 1\bound{g }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDecUndecPageEmpty5}
\begin{paste}{ugUserDecUndecPageEmpty5}{ugUserDecUndecPagePatch5}
\pastebutton{ugUserDecUndecPageEmpty5}{\showpaste}
\tab{5}\spadcommand{g x == x + 1\bound{g }}
\end{paste}\end{patch}

\begin{patch}{ugUserDecUndecPagePatch6}
\begin{paste}{ugUserDecUndecPageFull6}{ugUserDecUndecPageEmpty6}
\pastebutton{ugUserDecUndecPageFull6}{\hidepaste}
\tab{5}\spadcommand{g 9\free{g }}
\indentrel{3}\begin{verbatim}
   (5)  10
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDecUndecPageEmpty6}
\begin{paste}{ugUserDecUndecPageEmpty6}{ugUserDecUndecPagePatch6}
\pastebutton{ugUserDecUndecPageEmpty6}{\showpaste}
\tab{5}\spadcommand{g 9\free{g }}
\end{paste}\end{patch}

\begin{patch}{ugUserDecUndecPagePatch7}
\begin{paste}{ugUserDecUndecPageFull7}{ugUserDecUndecPageEmpty7}
\pastebutton{ugUserDecUndecPageFull7}{\hidepaste}
\tab{5}\spadcommand{g(2/3)\free{g }}
\indentrel{3}\begin{verbatim}
        5
   (6)  Ä
        3
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDecUndecPageEmpty7}
\begin{paste}{ugUserDecUndecPageEmpty7}{ugUserDecUndecPagePatch7}
\pastebutton{ugUserDecUndecPageEmpty7}{\showpaste}
\tab{5}\spadcommand{g(2/3)\free{g }}
\end{paste}\end{patch}

\begin{patch}{ugUserDecUndecPagePatch8}
\begin{paste}{ugUserDecUndecPageFull8}{ugUserDecUndecPageEmpty8}
\pastebutton{ugUserDecUndecPageFull8}{\hidepaste}
\tab{5}\spadcommand{g("axiom")\free{g }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDecUndecPageEmpty8}
\begin{paste}{ugUserDecUndecPageEmpty8}{ugUserDecUndecPagePatch8}
\pastebutton{ugUserDecUndecPageEmpty8}{\showpaste}
\tab{5}\spadcommand{g("axiom")\free{g }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugUserDecOpersPage}{ug06.ht}{Functions vs. Operations}
\pageto{notitle}{MappingPackageOneXmpPage}
\pageto{notitle}{ugPackagesAbstractPage}
\pageto{notitle}{ugPackagesPage}
\pageto{notitle}{ugCategoriesPage}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserDecOpersPage}{6.7. Functions vs. Operations}
\beginscroll

A function is an object that you can create, manipulate, pass to,
and return from functions (for some interesting examples of
library functions that manipulate functions, see
\downlink{`MappingPackage1'}{MappingPackageOneXmpPage}
\ignore{MappingPackage1}).
Yet, we often seem to use the term \spadgloss{operation} and
function interchangeably in Axiom.
What is the distinction?

First consider values and types associated with some variable
\axiom{n} in your workspace.  You can make the declaration \axiom{n :
Integer}, then assign \axiom{n} an integer value.  You then speak of
the integer \axiom{n}.  However, note that the integer is not the name
\axiom{n} itself, but the value that you assign to \axiom{n}.

Similarly, you can declare a variable \axiom{f} in your workspace to
have type \spadsig{Integer}{Integer}, then assign \axiom{f}, through a
definition or an assignment of an anonymous function.  You then speak
of the function \axiom{f}.  However, the function is not \axiom{f},
but the value that you assign to \axiom{f}.

A function is a value, in fact, some machine code for doing something.
Doing what?  Well, performing some \spadgloss{operation}.  Formally,
an operation consists of the constituent parts of \axiom{f} in your
workspace, excluding the value; thus an operation has a name and a
type.  An operation is what domains and packages export.  Thus
\axiomType{Ring} exports one operation \axiomOp{+}.  Every ring also
exports this operation.  Also, the author of every ring in the system
is obliged under contract (see
\downlink{``Abstract Datatypes''}{ugPackagesAbstractPage} in
Section 11.3\ignore{ugPackagesAbstract}) to
provide an implementation for this operation.

This chapter is all about functions---how you create them
interactively and how you apply them to meet your needs.  In
\downlink{``Packages''}{ugPackagesPage} in Chapter
11\ignore{ugPackages} you will learn how to create them
for the Axiom library.  Then in
\downlink{``Categories''}{ugCategoriesPage} in Chapter
12\ignore{ugCategories}, you will learn about
categories and exported operations.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugUserDelayPage}{ug06.ht}
{Delayed Assignments vs. Functions with No Arguments}
\pageto{notitle}{ugLangAssignPage}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserDelayPage}
{6.8. Delayed Assignments vs. Functions with No Arguments}
\beginscroll

In \downlink{``Immediate and Delayed Assignments''}
{ugLangAssignPage} in Section 
5.1\ignore{ugLangAssign} we discussed the difference 
between immediate and
delayed assignments.
In this section we show the difference between delayed
assignments and functions of no arguments.

\labelSpace{2pc}
\xtc{
A function of no arguments is sometimes called a {\it nullary function.}
}{
\spadpaste{sin24() == sin(24.0) \bound{sin24}}
}
\xtc{
You must use the parentheses (\axiomSyntax{()}) to evaluate it.
Like a delayed assignment, the right-hand-side of a function evaluation
is not evaluated until the left-hand-side is used.
}{
\spadpaste{sin24() \free{sin24}}
}
\xtc{
If you omit the parentheses, you just get the function definition.
%(Note how the explicit floating point number in the definition
%has been translated into a function call involving a mantissa,
%exponent and radix.)
}{
\spadpaste{sin24 \free{sin24}}
}
\xtc{
You do not use the parentheses \axiomSyntax{()} in a 
delayed assignment\ldots
}{
\spadpaste{cos24 == cos(24.0) \bound{cos24}}
}
\xtc{
nor in the evaluation.
}{
\spadpaste{cos24 \free{cos24}}
}
The only syntactic difference between delayed assignments
and nullary functions is that you use \axiomSyntax{()} 
in the latter case.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserDelayPagePatch1}
\begin{paste}{ugUserDelayPageFull1}{ugUserDelayPageEmpty1}
\pastebutton{ugUserDelayPageFull1}{\hidepaste}
\tab{5}\spadcommand{sin24() == sin(24.0)\bound{sin24 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDelayPageEmpty1}
\begin{paste}{ugUserDelayPageEmpty1}{ugUserDelayPagePatch1}
\pastebutton{ugUserDelayPageEmpty1}{\showpaste}
\tab{5}\spadcommand{sin24() == sin(24.0)\bound{sin24 }}
\end{paste}\end{patch}

\begin{patch}{ugUserDelayPagePatch2}
\begin{paste}{ugUserDelayPageFull2}{ugUserDelayPageEmpty2}
\pastebutton{ugUserDelayPageFull2}{\hidepaste}
\tab{5}\spadcommand{sin24()\free{sin24 }}
\indentrel{3}\begin{verbatim}
   (2)  - 0.9055783620 0662384514
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDelayPageEmpty2}
\begin{paste}{ugUserDelayPageEmpty2}{ugUserDelayPagePatch2}
\pastebutton{ugUserDelayPageEmpty2}{\showpaste}
\tab{5}\spadcommand{sin24()\free{sin24 }}
\end{paste}\end{patch}

\begin{patch}{ugUserDelayPagePatch3}
\begin{paste}{ugUserDelayPageFull3}{ugUserDelayPageEmpty3}
\pastebutton{ugUserDelayPageFull3}{\hidepaste}
\tab{5}\spadcommand{sin24\free{sin24 }}
\indentrel{3}\begin{verbatim}
   (3)  sin24 () == sin(24.0)
                             Type: FunctionCalled sin24
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDelayPageEmpty3}
\begin{paste}{ugUserDelayPageEmpty3}{ugUserDelayPagePatch3}
\pastebutton{ugUserDelayPageEmpty3}{\showpaste}
\tab{5}\spadcommand{sin24\free{sin24 }}
\end{paste}\end{patch}

\begin{patch}{ugUserDelayPagePatch4}
\begin{paste}{ugUserDelayPageFull4}{ugUserDelayPageEmpty4}
\pastebutton{ugUserDelayPageFull4}{\hidepaste}
\tab{5}\spadcommand{cos24 == cos(24.0)\bound{cos24 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDelayPageEmpty4}
\begin{paste}{ugUserDelayPageEmpty4}{ugUserDelayPagePatch4}
\pastebutton{ugUserDelayPageEmpty4}{\showpaste}
\tab{5}\spadcommand{cos24 == cos(24.0)\bound{cos24 }}
\end{paste}\end{patch}

\begin{patch}{ugUserDelayPagePatch5}
\begin{paste}{ugUserDelayPageFull5}{ugUserDelayPageEmpty5}
\pastebutton{ugUserDelayPageFull5}{\hidepaste}
\tab{5}\spadcommand{cos24\free{cos24 }}
\indentrel{3}\begin{verbatim}
   (5)  0.4241790073 3699697594
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDelayPageEmpty5}
\begin{paste}{ugUserDelayPageEmpty5}{ugUserDelayPagePatch5}
\pastebutton{ugUserDelayPageEmpty5}{\showpaste}
\tab{5}\spadcommand{cos24\free{cos24 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugUserUsePage}{ug06.ht}{How Axiom Determines What Function to Use}
\pageto{notitle}{ugTypesPkgCallPage}
\pageto{notitle}{ugTypesResolvePage}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserUsePage}
{6.9. How Axiom Determines What Function to Use}
\beginscroll

What happens if you define a function that has the same name as a
library function?  Well, if your function has the same name and number
of arguments (we sometimes say \spadgloss{arity}) as another function
in the library, then your function covers up the library function.  If
you want then to call the library function, you will have to
package-call it.  Axiom can use both the functions you write and those
that come from the library.  Let's do a simple example to illustrate
this.
\xtc{
Suppose you (wrongly!) define \userfun{sin} in this way.
}{
\spadpaste{sin x == 1.0 \bound{sin}}
}
\xtc{
The value \axiom{1.0} is returned for any argument.
}{
\spadpaste{sin 4.3 \free{sin}}
}
\xtc{
If you want the library operation, we have to package-call it
(see \downlink{``Package Calling and Target Types''}{ugTypesPkgCallPage} 
in Section 2.9\ignore{ugTypesPkgCall}
for more information).
}{
\spadpaste{sin(4.3)\$Float}
}
\xtc{
}{
\spadpaste{sin(34.6)\$Float}
}
\xtc{
Even worse, say we accidentally used the same name as a library
function in the function.
}{
\spadpaste{sin x == sin x \bound{sin1}}
}
\xtc{
Then Axiom definitely does not understand us.
}{
\spadpaste{sin 4.3 \free{sin1}}
}
\xtc{
Again, we could package-call the inside function.
}{
\spadpaste{sin x == sin(x)\$Float \bound{sin2}}
}
\xtc{
}{
\spadpaste{sin 4.3 \free{sin2}}
}
Of course, you are unlikely to make such obvious errors.
It is more probable that you would write a function and in the body use a
function that you think is a library function.
If you had also written a function by that same name, the library function
would be invisible.

How does Axiom determine what library function to call?
It very much depends on the particular example, but the simple case of
creating the polynomial
\axiom{x + 2/3} will give you an idea.
\indent{4}
\beginitems
\item[1. ] The \axiom{x} is analyzed and its default type is
\axiomType{Variable(x)}.
\item[2. ] The \axiom{2} is analyzed and its default type is
\axiomType{PositiveInteger}.
\item[3. ] The \axiom{3} is analyzed and its default type is
\axiomType{PositiveInteger}.
\item[4. ] Because the arguments to \axiomOp{/} are integers, Axiom
gives the expression \axiom{2/3} a default target type of
\axiomType{Fraction(Integer)}.
\item[5. ] Axiom looks in \axiomType{PositiveInteger} for \axiomOp{/}.
It is not found.
\item[6. ] Axiom looks in \axiomType{Fraction(Integer)} for \axiomOp{/}.
It is found for arguments of type \axiomType{Integer}.
\item[7. ] The \axiom{2} and \axiom{3} are converted to objects of type
\axiomType{Integer} (this is trivial) and \axiomOp{/} is applied,
creating an object of type \axiomType{Fraction(Integer)}.
\item[8. ] No \axiomOp{+} for arguments of types \axiomType{Variable(x)} 
and \axiomType{Fraction(Integer)} are found in either domain.
\item[9. ] Axiom resolves
(see \downlink{``Resolving Types''}{ugTypesResolvePage} 
in Section 2.10\ignore{ugTypesResolve})
the types and gets \axiomType{Polynomial (Fraction (Integer))}.
\item[10. ] The \axiom{x} and the \axiom{2/3} are converted to objects 
of this type and \axiomOp{+} is applied, yielding the answer, an object 
of type \axiomType{Polynomial (Fraction (Integer))}.
\enditems
\indent{0}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserUsePagePatch1}
\begin{paste}{ugUserUsePageFull1}{ugUserUsePageEmpty1}
\pastebutton{ugUserUsePageFull1}{\hidepaste}
\tab{5}\spadcommand{sin x == 1.0\bound{sin }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserUsePageEmpty1}
\begin{paste}{ugUserUsePageEmpty1}{ugUserUsePagePatch1}
\pastebutton{ugUserUsePageEmpty1}{\showpaste}
\tab{5}\spadcommand{sin x == 1.0\bound{sin }}
\end{paste}\end{patch}

\begin{patch}{ugUserUsePagePatch2}
\begin{paste}{ugUserUsePageFull2}{ugUserUsePageEmpty2}
\pastebutton{ugUserUsePageFull2}{\hidepaste}
\tab{5}\spadcommand{sin 4.3\free{sin }}
\indentrel{3}\begin{verbatim}
   (2)  1.0
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserUsePageEmpty2}
\begin{paste}{ugUserUsePageEmpty2}{ugUserUsePagePatch2}
\pastebutton{ugUserUsePageEmpty2}{\showpaste}
\tab{5}\spadcommand{sin 4.3\free{sin }}
\end{paste}\end{patch}

\begin{patch}{ugUserUsePagePatch3}
\begin{paste}{ugUserUsePageFull3}{ugUserUsePageEmpty3}
\pastebutton{ugUserUsePageFull3}{\hidepaste}
\tab{5}\spadcommand{sin(4.3)$Float}
\indentrel{3}\begin{verbatim}
   (3)  - 0.9161659367 4945498404
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserUsePageEmpty3}
\begin{paste}{ugUserUsePageEmpty3}{ugUserUsePagePatch3}
\pastebutton{ugUserUsePageEmpty3}{\showpaste}
\tab{5}\spadcommand{sin(4.3)$Float}
\end{paste}\end{patch}

\begin{patch}{ugUserUsePagePatch4}
\begin{paste}{ugUserUsePageFull4}{ugUserUsePageEmpty4}
\pastebutton{ugUserUsePageFull4}{\hidepaste}
\tab{5}\spadcommand{sin(34.6)$Float}
\indentrel{3}\begin{verbatim}
   (4)  - 0.0424680347 1695010154 3
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserUsePageEmpty4}
\begin{paste}{ugUserUsePageEmpty4}{ugUserUsePagePatch4}
\pastebutton{ugUserUsePageEmpty4}{\showpaste}
\tab{5}\spadcommand{sin(34.6)$Float}
\end{paste}\end{patch}

\begin{patch}{ugUserUsePagePatch5}
\begin{paste}{ugUserUsePageFull5}{ugUserUsePageEmpty5}
\pastebutton{ugUserUsePageFull5}{\hidepaste}
\tab{5}\spadcommand{sin x == sin x\bound{sin1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserUsePageEmpty5}
\begin{paste}{ugUserUsePageEmpty5}{ugUserUsePagePatch5}
\pastebutton{ugUserUsePageEmpty5}{\showpaste}
\tab{5}\spadcommand{sin x == sin x\bound{sin1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserUsePagePatch6}
\begin{paste}{ugUserUsePageFull6}{ugUserUsePageEmpty6}
\pastebutton{ugUserUsePageFull6}{\hidepaste}
\tab{5}\spadcommand{sin 4.3\free{sin1 }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserUsePageEmpty6}
\begin{paste}{ugUserUsePageEmpty6}{ugUserUsePagePatch6}
\pastebutton{ugUserUsePageEmpty6}{\showpaste}
\tab{5}\spadcommand{sin 4.3\free{sin1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserUsePagePatch7}
\begin{paste}{ugUserUsePageFull7}{ugUserUsePageEmpty7}
\pastebutton{ugUserUsePageFull7}{\hidepaste}
\tab{5}\spadcommand{sin x == sin(x)$Float\bound{sin2 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserUsePageEmpty7}
\begin{paste}{ugUserUsePageEmpty7}{ugUserUsePagePatch7}
\pastebutton{ugUserUsePageEmpty7}{\showpaste}
\tab{5}\spadcommand{sin x == sin(x)$Float\bound{sin2 }}
\end{paste}\end{patch}

\begin{patch}{ugUserUsePagePatch8}
\begin{paste}{ugUserUsePageFull8}{ugUserUsePageEmpty8}
\pastebutton{ugUserUsePageFull8}{\hidepaste}
\tab{5}\spadcommand{sin 4.3\free{sin2 }}
\indentrel{3}\begin{verbatim}
   (7)  - 0.9161659367 4945498404
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserUsePageEmpty8}
\begin{paste}{ugUserUsePageEmpty8}{ugUserUsePagePatch8}
\pastebutton{ugUserUsePageEmpty8}{\showpaste}
\tab{5}\spadcommand{sin 4.3\free{sin2 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugUserCompIntPage}{ug06.ht}{Compiling vs. Interpreting}
\pageto{notitle}{ugTypesSubdomainsPage}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserCompIntPage}{6.10. Compiling vs. Interpreting}
\beginscroll

When possible, Axiom completely determines the type of every object in
a function, then translates the function definition to \Lisp{} or to
machine code (see next section).  This translation, called
\spadglossSee{compilation}{compiler}, happens the first time you call
the function and results in a computational delay.  Subsequent
function calls with the same argument types use the compiled version
of the code without delay.

If Axiom cannot determine the type of everything, the function may
still be executed but in \spadglossSee{interpret-code
mode}{interpreter} : each statement in the function is analyzed and
executed as the control flow indicates.  This process is slower than
executing a compiled function, but it allows the execution of code
that may involve objects whose types change.

\beginImportant
If Axiom decides that it cannot compile the code, it
issues a message stating the problem and then the following
message:
%
\centerline{
{{\bf We will attempt to step through and interpret the code.}}}
%
This is not a time to panic.
Rather, it just means that what you gave to Axiom
is somehow ambiguous: either it is not specific enough to be analyzed
completely, or it is beyond Axiom's present interactive
compilation abilities.
\endImportant

\xtc{
This function runs in interpret-code mode, but it does not compile.
}{
\begin{spadsrc}[\bound{varPolys}]
varPolys(vars) ==
  for var in vars repeat
    output(1 :: UnivariatePolynomial(var,Integer))
\end{spadsrc}
}
\xtc{
For \axiom{vars} equal to \axiom{['x, 'y, 'z]}, this function displays
\axiom{1} three times.
}{
\spadpaste{varPolys ['x,'y,'z] \free{varPolys}}
}
\xtc{
The type of the argument to \axiomFun{output} changes in each iteration,
so Axiom cannot compile the function.
In this case, even the inner loop by itself would have a problem:
}{
\begin{spadsrc}
for var in ['x,'y,'z] repeat
  output(1 :: UnivariatePolynomial(var,Integer))
\end{spadsrc}
}

Sometimes you can help a function to compile by using an extra
conversion or by using \axiom{pretend}.  \spadkey{pretend} See
\downlink{``Subdomains Again''}{ugTypesSubdomainsPage} in
Section 2.8\ignore{ugTypesSubdomains} for
details.

When a function is compilable, you have the choice of whether it is
compiled to \Lisp{} and then interpreted by the \Lisp{} interpreter or
then further compiled from \Lisp{} to machine code.  The option is
controlled via \spadcmd{)set functions compile}.  Issue \spadcmd{)set
functions compile on} to compile all the way to machine code.  With
the default setting \spadcmd{)set functions compile off}, Axiom has
its \Lisp{} code interpreted because the overhead of further
compilation is larger than the run-time of most of the functions our
users have defined.  You may find that selectively turning this option
on and off will give you the best performance in your particular
application.  For example, if you are writing functions for graphics
applications where hundreds of points are being computed, it is almost
certainly true that you will get the best performance by issuing
\spadcmd{)set functions compile on}.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserCompIntPagePatch1}
\begin{paste}{ugUserCompIntPageFull1}{ugUserCompIntPageEmpty1}
\pastebutton{ugUserCompIntPageFull1}{\hidepaste}
\tab{5}\spadcommand{varPolys(vars) ==
  for var in vars repeat
    output(1 :: UnivariatePolynomial(var,Integer))
\bound{varPolys }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserCompIntPageEmpty1}
\begin{paste}{ugUserCompIntPageEmpty1}{ugUserCompIntPagePatch1}
\pastebutton{ugUserCompIntPageEmpty1}{\showpaste}
\tab{5}\spadcommand{varPolys(vars) ==
  for var in vars repeat
    output(1 :: UnivariatePolynomial(var,Integer))
\bound{varPolys }}
\end{paste}\end{patch}

\begin{patch}{ugUserCompIntPagePatch2}
\begin{paste}{ugUserCompIntPageFull2}{ugUserCompIntPageEmpty2}
\pastebutton{ugUserCompIntPageFull2}{\hidepaste}
\tab{5}\spadcommand{varPolys ['x,'y,'z]\free{varPolys }}
\indentrel{3}\begin{verbatim}
   1
   1
   1
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserCompIntPageEmpty2}
\begin{paste}{ugUserCompIntPageEmpty2}{ugUserCompIntPagePatch2}
\pastebutton{ugUserCompIntPageEmpty2}{\showpaste}
\tab{5}\spadcommand{varPolys ['x,'y,'z]\free{varPolys }}
\end{paste}\end{patch}

\begin{patch}{ugUserCompIntPagePatch3}
\begin{paste}{ugUserCompIntPageFull3}{ugUserCompIntPageEmpty3}
\pastebutton{ugUserCompIntPageFull3}{\hidepaste}
\tab{5}\spadcommand{for var in ['x,'y,'z] repeat
  output(1 :: UnivariatePolynomial(var,Integer))
}
\indentrel{3}\begin{verbatim}
   1
   1
   1
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserCompIntPageEmpty3}
\begin{paste}{ugUserCompIntPageEmpty3}{ugUserCompIntPagePatch3}
\pastebutton{ugUserCompIntPageEmpty3}{\showpaste}
\tab{5}\spadcommand{for var in ['x,'y,'z] repeat
  output(1 :: UnivariatePolynomial(var,Integer))
}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugUserPiecePage}{ug06.ht}{Piece-Wise Function Definitions}
\pageto{notitle}{ugUserPieceBasicPage}
\pageto{notitle}{ugUserPiecePickingPage}
\pageto{notitle}{ugUserPiecePredPage}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserPiecePage}{6.11. Piece-Wise Function Definitions}
\beginscroll

To move beyond functions defined in one line, we introduce in this
section functions that are defined piece-by-piece.  That is, we say
``use this definition when the argument is such-and-such and use this
other definition when the argument is that-and-that.''

\beginmenu
    \menudownlink{{6.11.1. A Basic Example}}{ugUserPieceBasicPage}
    \menudownlink{{6.11.2. Picking Up the Pieces}}
{ugUserPiecePickingPage}
    \menudownlink{{6.11.3. Predicates}}{ugUserPiecePredPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugUserPieceBasicPage}{ug06.ht}{A Basic Example}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserPieceBasicPage}{6.11.1. A Basic Example}
\beginscroll

There are many other ways to define a factorial function for nonnegative
integers.
You might
say
factorial of \axiom{0} is \axiom{1,} otherwise factorial of \axiom{n} is
\axiom{n} times factorial of \axiom{n-1}.
Here is one way to do this in Axiom.
%
\xtc{
Here is the value for \axiom{n = 0}.
}{
\spadpaste{fact(0) == 1 \bound{fact0}}
}
\xtc{
Here is the value for \axiom{n > 0}.
The vertical bar \axiomSyntax{|} means
``such that''.
}{
\spadpaste{fact(n | n > 0) == n * fact(n - 1) \free{fact0}\bound{factn}}
}
\xtc{
What is the value for \axiom{n = 3}?
}{
\spadpaste{fact(3) \free{factn}}
}
\xtc{
What is the value for \axiom{n = -3}?
}{
\spadpaste{fact(-3) \free{factn}}
}
\xtc{
Now for a second definition.
Here is the value for \axiom{n = 0}.
}{
\spadpaste{facto(0) == 1 \bound{facto0}}
}
\xtc{
Give an error message if \axiom{n < 0}.
}{
\spadpaste{facto(n | n < 0) == 
error "arguments to facto must be non-negative" 
\free{facto0}\bound{factop}}
}
\xtc{
Here is the value otherwise.
}{
\spadpaste{facto(n) == n * facto(n - 1) \free{factop}\bound{facton}}
}
\xtc{
What is the value for \axiom{n = 7}?
}{
\spadpaste{facto(7) \free{facton}}
}
\xtc{
What is the value for \axiom{n = -7}?
}{
\spadpaste{facto(-7) \free{facton}}
}
\xtc{
To see the current piece-wise definition of a function,
use \spadsys{)display value}.
}{
\spadpaste{)display value facto \free{facton}}
}

In general a {\it piece-wise definition} of a function consists of two
or more parts.  Each part gives a ``piece'' of the entire definition.
Axiom collects the pieces of a function as you enter them.  When you
ask for a value of the function, it then ``glues'' the pieces together
to form a function.

The two piece-wise definitions for the factorial function are examples
of recursive functions, that is, functions that are defined in terms
of themselves.  Here is an interesting doubly-recursive function.
This function returns the value \axiom{11} for all positive integer
arguments.
\xtc{
Here is the first of two pieces.
}{
\spadpaste{eleven(n | n < 1) == n + 11\bound{ff0}}
}
\xtc{
And the general case.
}{
\spadpaste{eleven(m) == eleven(eleven(m - 12))\bound{ff1}\free{ff0}}
}
\xtc{
Compute \axiom{elevens}, the infinite stream
of values of \axiom{eleven}.
}{
\spadpaste{elevens := [eleven(i) for i in 0..]\bound{ff2}\free{ff1}}
}
\xtc{
What is the value at \axiom{n = 200}?
}{
\spadpaste{elevens 200\free{ff2}}
}
\xtc{
What is the Axiom's definition of \axiom{eleven}?
}{
\spadpaste{)display value eleven\free{ff2}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserPieceBasicPagePatch1}
\begin{paste}{ugUserPieceBasicPageFull1}{ugUserPieceBasicPageEmpty1}
\pastebutton{ugUserPieceBasicPageFull1}{\hidepaste}
\tab{5}\spadcommand{fact(0) == 1\bound{fact0 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPageEmpty1}
\begin{paste}{ugUserPieceBasicPageEmpty1}{ugUserPieceBasicPagePatch1}
\pastebutton{ugUserPieceBasicPageEmpty1}{\showpaste}
\tab{5}\spadcommand{fact(0) == 1\bound{fact0 }}
\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPagePatch2}
\begin{paste}{ugUserPieceBasicPageFull2}{ugUserPieceBasicPageEmpty2}
\pastebutton{ugUserPieceBasicPageFull2}{\hidepaste}
\tab{5}\spadcommand{fact(n | n > 0) == n * fact(n - 1)\free{fact0 }\bound{factn }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPageEmpty2}
\begin{paste}{ugUserPieceBasicPageEmpty2}{ugUserPieceBasicPagePatch2}
\pastebutton{ugUserPieceBasicPageEmpty2}{\showpaste}
\tab{5}\spadcommand{fact(n | n > 0) == n * fact(n - 1)\free{fact0 }\bound{factn }}
\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPagePatch3}
\begin{paste}{ugUserPieceBasicPageFull3}{ugUserPieceBasicPageEmpty3}
\pastebutton{ugUserPieceBasicPageFull3}{\hidepaste}
\tab{5}\spadcommand{fact(3)\free{factn }}
\indentrel{3}\begin{verbatim}
   (3)  6
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPageEmpty3}
\begin{paste}{ugUserPieceBasicPageEmpty3}{ugUserPieceBasicPagePatch3}
\pastebutton{ugUserPieceBasicPageEmpty3}{\showpaste}
\tab{5}\spadcommand{fact(3)\free{factn }}
\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPagePatch4}
\begin{paste}{ugUserPieceBasicPageFull4}{ugUserPieceBasicPageEmpty4}
\pastebutton{ugUserPieceBasicPageFull4}{\hidepaste}
\tab{5}\spadcommand{fact(-3)\free{factn }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPageEmpty4}
\begin{paste}{ugUserPieceBasicPageEmpty4}{ugUserPieceBasicPagePatch4}
\pastebutton{ugUserPieceBasicPageEmpty4}{\showpaste}
\tab{5}\spadcommand{fact(-3)\free{factn }}
\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPagePatch5}
\begin{paste}{ugUserPieceBasicPageFull5}{ugUserPieceBasicPageEmpty5}
\pastebutton{ugUserPieceBasicPageFull5}{\hidepaste}
\tab{5}\spadcommand{facto(0) == 1\bound{facto0 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPageEmpty5}
\begin{paste}{ugUserPieceBasicPageEmpty5}{ugUserPieceBasicPagePatch5}
\pastebutton{ugUserPieceBasicPageEmpty5}{\showpaste}
\tab{5}\spadcommand{facto(0) == 1\bound{facto0 }}
\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPagePatch6}
\begin{paste}{ugUserPieceBasicPageFull6}{ugUserPieceBasicPageEmpty6}
\pastebutton{ugUserPieceBasicPageFull6}{\hidepaste}
\tab{5}\spadcommand{facto(n | n < 0) == error "arguments to facto must be non-negative"\free{facto0 }\bound{factop }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPageEmpty6}
\begin{paste}{ugUserPieceBasicPageEmpty6}{ugUserPieceBasicPagePatch6}
\pastebutton{ugUserPieceBasicPageEmpty6}{\showpaste}
\tab{5}\spadcommand{facto(n | n < 0) == error "arguments to facto must be non-negative"\free{facto0 }\bound{factop }}
\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPagePatch7}
\begin{paste}{ugUserPieceBasicPageFull7}{ugUserPieceBasicPageEmpty7}
\pastebutton{ugUserPieceBasicPageFull7}{\hidepaste}
\tab{5}\spadcommand{facto(n) == n * facto(n - 1)\free{factop }\bound{facton }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPageEmpty7}
\begin{paste}{ugUserPieceBasicPageEmpty7}{ugUserPieceBasicPagePatch7}
\pastebutton{ugUserPieceBasicPageEmpty7}{\showpaste}
\tab{5}\spadcommand{facto(n) == n * facto(n - 1)\free{factop }\bound{facton }}
\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPagePatch8}
\begin{paste}{ugUserPieceBasicPageFull8}{ugUserPieceBasicPageEmpty8}
\pastebutton{ugUserPieceBasicPageFull8}{\hidepaste}
\tab{5}\spadcommand{facto(3)\free{facton }}
\indentrel{3}\begin{verbatim}
   (7)  6
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPageEmpty8}
\begin{paste}{ugUserPieceBasicPageEmpty8}{ugUserPieceBasicPagePatch8}
\pastebutton{ugUserPieceBasicPageEmpty8}{\showpaste}
\tab{5}\spadcommand{facto(3)\free{facton }}
\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPagePatch9}
\begin{paste}{ugUserPieceBasicPageFull9}{ugUserPieceBasicPageEmpty9}
\pastebutton{ugUserPieceBasicPageFull9}{\hidepaste}
\tab{5}\spadcommand{facto(-7)\free{facton }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPageEmpty9}
\begin{paste}{ugUserPieceBasicPageEmpty9}{ugUserPieceBasicPagePatch9}
\pastebutton{ugUserPieceBasicPageEmpty9}{\showpaste}
\tab{5}\spadcommand{facto(-7)\free{facton }}
\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPagePatch10}
\begin{paste}{ugUserPieceBasicPageFull10}{ugUserPieceBasicPageEmpty10}
\pastebutton{ugUserPieceBasicPageFull10}{\hidepaste}
\tab{5}\spadcommand{)display value facto\free{facton }}
\indentrel{3}\begin{verbatim}
   Definition:
     facto 0 == 1
     facto (n | n < 0) ==
       error(arguments to facto must be non-negative)
     facto n == n facto(n - 1)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPageEmpty10}
\begin{paste}{ugUserPieceBasicPageEmpty10}{ugUserPieceBasicPagePatch10}
\pastebutton{ugUserPieceBasicPageEmpty10}{\showpaste}
\tab{5}\spadcommand{)display value facto\free{facton }}
\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPagePatch11}
\begin{paste}{ugUserPieceBasicPageFull11}{ugUserPieceBasicPageEmpty11}
\pastebutton{ugUserPieceBasicPageFull11}{\hidepaste}
\tab{5}\spadcommand{eleven(n | n < 1) == n + 11\bound{ff0 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPageEmpty11}
\begin{paste}{ugUserPieceBasicPageEmpty11}{ugUserPieceBasicPagePatch11}
\pastebutton{ugUserPieceBasicPageEmpty11}{\showpaste}
\tab{5}\spadcommand{eleven(n | n < 1) == n + 11\bound{ff0 }}
\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPagePatch12}
\begin{paste}{ugUserPieceBasicPageFull12}{ugUserPieceBasicPageEmpty12}
\pastebutton{ugUserPieceBasicPageFull12}{\hidepaste}
\tab{5}\spadcommand{eleven(m) == eleven(eleven(m - 12))\bound{ff1 }\free{ff0 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPageEmpty12}
\begin{paste}{ugUserPieceBasicPageEmpty12}{ugUserPieceBasicPagePatch12}
\pastebutton{ugUserPieceBasicPageEmpty12}{\showpaste}
\tab{5}\spadcommand{eleven(m) == eleven(eleven(m - 12))\bound{ff1 }\free{ff0 }}
\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPagePatch13}
\begin{paste}{ugUserPieceBasicPageFull13}{ugUserPieceBasicPageEmpty13}
\pastebutton{ugUserPieceBasicPageFull13}{\hidepaste}
\tab{5}\spadcommand{elevens := [eleven(i) for i in 0..]\bound{ff2 }\free{ff1 }}
\indentrel{3}\begin{verbatim}
   (10)  [11,11,11,11,11,11,11,11,11,11,...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPageEmpty13}
\begin{paste}{ugUserPieceBasicPageEmpty13}{ugUserPieceBasicPagePatch13}
\pastebutton{ugUserPieceBasicPageEmpty13}{\showpaste}
\tab{5}\spadcommand{elevens := [eleven(i) for i in 0..]\bound{ff2 }\free{ff1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPagePatch14}
\begin{paste}{ugUserPieceBasicPageFull14}{ugUserPieceBasicPageEmpty14}
\pastebutton{ugUserPieceBasicPageFull14}{\hidepaste}
\tab{5}\spadcommand{elevens 200\free{ff2 }}
\indentrel{3}\begin{verbatim}
   (11)  11
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPageEmpty14}
\begin{paste}{ugUserPieceBasicPageEmpty14}{ugUserPieceBasicPagePatch14}
\pastebutton{ugUserPieceBasicPageEmpty14}{\showpaste}
\tab{5}\spadcommand{elevens 200\free{ff2 }}
\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPagePatch15}
\begin{paste}{ugUserPieceBasicPageFull15}{ugUserPieceBasicPageEmpty15}
\pastebutton{ugUserPieceBasicPageFull15}{\hidepaste}
\tab{5}\spadcommand{)display value eleven\free{ff2 }}
\indentrel{3}\begin{verbatim}
   Definition:
     eleven (m | m < 1) == m + 11
     eleven m == eleven(eleven(m - 12))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPieceBasicPageEmpty15}
\begin{paste}{ugUserPieceBasicPageEmpty15}{ugUserPieceBasicPagePatch15}
\pastebutton{ugUserPieceBasicPageEmpty15}{\showpaste}
\tab{5}\spadcommand{)display value eleven\free{ff2 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugUserPiecePickingPage}{ug06.ht}{Picking Up the Pieces}
\pageto{notitle}{ugUserPieceBasicPage}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserPiecePickingPage}{6.11.2. Picking Up the Pieces}
\beginscroll

Here are the details about how Axiom creates a function from its
pieces.  Axiom converts the \eth{\axiom{i}} piece of a function
definition into a conditional expression of the form: \axiom{if}
\pred{i} \axiom{then} \expr{i}.  If any new piece has a \pred{i} that
is identical\footnote{after all variables are uniformly named} to an
earlier \pred{j}, the earlier piece is removed.  Otherwise, the new
piece is always added at the end.

\beginImportant
If there are \axiom{n} pieces to a function definition for \axiom{f},
the function defined \axiom{f} is: \newline
%
\texht{\hspace*{3pc}}{\tab{6}}
{\tt if} \pred{1} {\tt then} \expr{1} {\tt else}\newline
\texht{\hspace*{6pc}}{\tab{12}}. . . \newline
\texht{\hspace*{3pc}}{\tab{6}}
{\tt if} \pred{n} {\tt then} \expr{n} {\tt else}\newline
\texht{\hspace*{3pc}}{\tab{6}}
{\tt  error "You did not define f for argument <arg>."}
%
\endImportant

You can give definitions of any number of mutually recursive function
definitions, piece-wise or otherwise.  No computation is done until
you ask for a value.  When you do ask for a value, all the relevant
definitions are gathered, analyzed, and translated into separate
functions and compiled.

\xtc{
Let's recall the definition of \userfun{eleven} from
\texht{the previous section}{
\downlink{``A Basic Example''}{ugUserPieceBasicPage} 
in Section 6.11.1\ignore{ugUserPieceBasic}}.
}{
\spadpaste{eleven(n | n < 1) == n + 11\bound{ff0}}
}
\xtc{
}{
\spadpaste{eleven(m) == eleven(eleven(m - 12))\bound{ff1}\free{ff0}}
}

A similar doubly-recursive function below produces \axiom{-11} for all
negative positive integers.  If you haven't worked out why or how
\userfun{eleven} works, the structure of this definition gives a clue.
\xtc{
This definition we write as a block.
}{
\begin{spadsrc}[\bound{rf1}]
minusEleven(n) ==
  n >= 0 => n - 11
  minusEleven (5 + minusEleven(n + 7))
\end{spadsrc}
}
\xtc{
Define \axiom{s(n)} to be the
sum of plus and minus ``eleven'' functions divided by \axiom{n}.
Since \axiom{11 - 11 = 0}, we define \axiom{s(0)} to be \axiom{1}.
}{
\spadpaste{s(0) == 1\bound{rf2}}
}
\xtc{
And the general term.
}{
\spadpaste{s(n) == (eleven(n) + minusEleven(n))/n
\bound{rf3}\free{rf2 rf1 ff1}}
}
\xtc{
What are the first ten values of \axiom{s}?
}{
\spadpaste{[s(n) for n in 0..]\free{rf3}}
}
%% interpreter puts the rule at the end - should fix
Axiom can create infinite streams in the positive direction (for
example, for index values \axiom{0,1, \ldots}) or negative direction
(for example, for index values \axiom{0,-1,-2, \ldots}).  Here we
would like a stream of values of \axiom{s(n)} that is infinite in both
directions.  The function \axiom{t(n)} below returns the
\eth{\axiom{n}} term of the infinite stream \axiom{[s(0), s(1), s(-1),
s(2), s(-2), \ldots].}  Its definition has three pieces.
\xtc{
Define the initial term.
}{
\spadpaste{t(1) == s(0)\bound{t1}\free{rf4}}
}
\xtc{
The even numbered terms are the \axiom{s(i)} for positive \axiom{i}.
We use \axiomOp{quo} rather than \axiomOp{/}
since we want the result to be an integer.
}{
\spadpaste{t(n | even?(n)) == s(n quo 2)\free{t1}\bound{t2}}
}
\xtc{
Finally, the odd numbered terms are the
\axiom{s(i)} for negative \axiom{i}.
In piece-wise definitions, you can use different variables
to define different pieces. Axiom will not get confused.
}{
\spadpaste{t(p) == s(- p quo 2)\free{t2}\bound{t3}}
}
\xtc{
Look at the definition of \axiom{t}.
In the first piece, the variable \axiom{n}
was used; in the second piece, \axiom{p}.
Axiom always uses
your last variable to display your definitions
back to you.
}{
\spadpaste{)display value t\free{t2}}
}
\xtc{
Create a series of values of \axiom{s} applied to
alternating positive and negative arguments.
}{
\spadpaste{[t(i) for i in 1..]\free{t3}\bound{t4}}
}
\xtc{
Evidently \axiom{t(n) = 1} for all \axiom{i.}
Check it at \axiom{n= 100}.
}{
\spadpaste{t(100)\free{t4}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserPiecePickingPagePatch1}
\begin{paste}{ugUserPiecePickingPageFull1}{ugUserPiecePickingPageEmpty1}
\pastebutton{ugUserPiecePickingPageFull1}{\hidepaste}
\tab{5}\spadcommand{eleven(n | n < 1) == n + 11\bound{ff0 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPageEmpty1}
\begin{paste}{ugUserPiecePickingPageEmpty1}{ugUserPiecePickingPagePatch1}
\pastebutton{ugUserPiecePickingPageEmpty1}{\showpaste}
\tab{5}\spadcommand{eleven(n | n < 1) == n + 11\bound{ff0 }}
\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPagePatch2}
\begin{paste}{ugUserPiecePickingPageFull2}{ugUserPiecePickingPageEmpty2}
\pastebutton{ugUserPiecePickingPageFull2}{\hidepaste}
\tab{5}\spadcommand{eleven(m) == eleven(eleven(m - 12))\bound{ff1 }\free{ff0 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPageEmpty2}
\begin{paste}{ugUserPiecePickingPageEmpty2}{ugUserPiecePickingPagePatch2}
\pastebutton{ugUserPiecePickingPageEmpty2}{\showpaste}
\tab{5}\spadcommand{eleven(m) == eleven(eleven(m - 12))\bound{ff1 }\free{ff0 }}
\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPagePatch3}
\begin{paste}{ugUserPiecePickingPageFull3}{ugUserPiecePickingPageEmpty3}
\pastebutton{ugUserPiecePickingPageFull3}{\hidepaste}
\tab{5}\spadcommand{minusEleven(n) ==
  n >= 0 => n - 11
  minusEleven (5 + minusEleven(n + 7))
\bound{rf1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPageEmpty3}
\begin{paste}{ugUserPiecePickingPageEmpty3}{ugUserPiecePickingPagePatch3}
\pastebutton{ugUserPiecePickingPageEmpty3}{\showpaste}
\tab{5}\spadcommand{minusEleven(n) ==
  n >= 0 => n - 11
  minusEleven (5 + minusEleven(n + 7))
\bound{rf1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPagePatch4}
\begin{paste}{ugUserPiecePickingPageFull4}{ugUserPiecePickingPageEmpty4}
\pastebutton{ugUserPiecePickingPageFull4}{\hidepaste}
\tab{5}\spadcommand{s(0) == 1\bound{rf2 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPageEmpty4}
\begin{paste}{ugUserPiecePickingPageEmpty4}{ugUserPiecePickingPagePatch4}
\pastebutton{ugUserPiecePickingPageEmpty4}{\showpaste}
\tab{5}\spadcommand{s(0) == 1\bound{rf2 }}
\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPagePatch5}
\begin{paste}{ugUserPiecePickingPageFull5}{ugUserPiecePickingPageEmpty5}
\pastebutton{ugUserPiecePickingPageFull5}{\hidepaste}
\tab{5}\spadcommand{s(n) == (eleven(n) + minusEleven(n))/n\bound{rf3 }\free{rf2 rf1 ff1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPageEmpty5}
\begin{paste}{ugUserPiecePickingPageEmpty5}{ugUserPiecePickingPagePatch5}
\pastebutton{ugUserPiecePickingPageEmpty5}{\showpaste}
\tab{5}\spadcommand{s(n) == (eleven(n) + minusEleven(n))/n\bound{rf3 }\free{rf2 rf1 ff1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPagePatch6}
\begin{paste}{ugUserPiecePickingPageFull6}{ugUserPiecePickingPageEmpty6}
\pastebutton{ugUserPiecePickingPageFull6}{\hidepaste}
\tab{5}\spadcommand{[s(n) for n in 0..]\free{rf3 }}
\indentrel{3}\begin{verbatim}
   (6)  [1,1,1,1,1,1,1,1,1,1,...]
                          Type: Stream Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPageEmpty6}
\begin{paste}{ugUserPiecePickingPageEmpty6}{ugUserPiecePickingPagePatch6}
\pastebutton{ugUserPiecePickingPageEmpty6}{\showpaste}
\tab{5}\spadcommand{[s(n) for n in 0..]\free{rf3 }}
\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPagePatch7}
\begin{paste}{ugUserPiecePickingPageFull7}{ugUserPiecePickingPageEmpty7}
\pastebutton{ugUserPiecePickingPageFull7}{\hidepaste}
\tab{5}\spadcommand{t(1) == s(0)\bound{t1 }\free{rf4 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPageEmpty7}
\begin{paste}{ugUserPiecePickingPageEmpty7}{ugUserPiecePickingPagePatch7}
\pastebutton{ugUserPiecePickingPageEmpty7}{\showpaste}
\tab{5}\spadcommand{t(1) == s(0)\bound{t1 }\free{rf4 }}
\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPagePatch8}
\begin{paste}{ugUserPiecePickingPageFull8}{ugUserPiecePickingPageEmpty8}
\pastebutton{ugUserPiecePickingPageFull8}{\hidepaste}
\tab{5}\spadcommand{t(n | even?(n)) == s(n quo 2)\free{t1 }\bound{t2 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPageEmpty8}
\begin{paste}{ugUserPiecePickingPageEmpty8}{ugUserPiecePickingPagePatch8}
\pastebutton{ugUserPiecePickingPageEmpty8}{\showpaste}
\tab{5}\spadcommand{t(n | even?(n)) == s(n quo 2)\free{t1 }\bound{t2 }}
\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPagePatch9}
\begin{paste}{ugUserPiecePickingPageFull9}{ugUserPiecePickingPageEmpty9}
\pastebutton{ugUserPiecePickingPageFull9}{\hidepaste}
\tab{5}\spadcommand{t(p) == s(- p quo 2)\free{t2 }\bound{t3 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPageEmpty9}
\begin{paste}{ugUserPiecePickingPageEmpty9}{ugUserPiecePickingPagePatch9}
\pastebutton{ugUserPiecePickingPageEmpty9}{\showpaste}
\tab{5}\spadcommand{t(p) == s(- p quo 2)\free{t2 }\bound{t3 }}
\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPagePatch10}
\begin{paste}{ugUserPiecePickingPageFull10}{ugUserPiecePickingPageEmpty10}
\pastebutton{ugUserPiecePickingPageFull10}{\hidepaste}
\tab{5}\spadcommand{)display value t\free{t2 }}
\indentrel{3}\begin{verbatim}
   Definition:
     t 1 == s(0)
     t (p | even?(p)) == s(p quo 2)
     t p == s(- p quo 2)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPageEmpty10}
\begin{paste}{ugUserPiecePickingPageEmpty10}{ugUserPiecePickingPagePatch10}
\pastebutton{ugUserPiecePickingPageEmpty10}{\showpaste}
\tab{5}\spadcommand{)display value t\free{t2 }}
\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPagePatch11}
\begin{paste}{ugUserPiecePickingPageFull11}{ugUserPiecePickingPageEmpty11}
\pastebutton{ugUserPiecePickingPageFull11}{\hidepaste}
\tab{5}\spadcommand{[t(i) for i in 1..]\free{t3 }\bound{t4 }}
\indentrel{3}\begin{verbatim}
   (10)  [1,1,1,1,1,1,1,1,1,1,...]
                          Type: Stream Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPageEmpty11}
\begin{paste}{ugUserPiecePickingPageEmpty11}{ugUserPiecePickingPagePatch11}
\pastebutton{ugUserPiecePickingPageEmpty11}{\showpaste}
\tab{5}\spadcommand{[t(i) for i in 1..]\free{t3 }\bound{t4 }}
\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPagePatch12}
\begin{paste}{ugUserPiecePickingPageFull12}{ugUserPiecePickingPageEmpty12}
\pastebutton{ugUserPiecePickingPageFull12}{\hidepaste}
\tab{5}\spadcommand{t(100)\free{t4 }}
\indentrel{3}\begin{verbatim}
   (11)  1
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPiecePickingPageEmpty12}
\begin{paste}{ugUserPiecePickingPageEmpty12}{ugUserPiecePickingPagePatch12}
\pastebutton{ugUserPiecePickingPageEmpty12}{\showpaste}
\tab{5}\spadcommand{t(100)\free{t4 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugUserPiecePredPage}{ug06.ht}{Predicates}
\pageto{notitle}{ugUserPieceBasicPage}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserPiecePredPage}{6.11.3. Predicates}
\beginscroll

We have already seen some examples of
predicates
(\downlink{``A Basic Example''}{ugUserPieceBasicPage} 
in Section 6.11.1\ignore{ugUserPieceBasic}).
Predicates are \axiomType{Boolean}-valued expressions and Axiom uses them
for filtering collections
(see \downlink{``Creating Lists and Streams with Iterators''}
{ugLangItsPage} in Section 5.5\ignore{ugLangIts})
and for placing constraints on function arguments.
In this section we discuss their latter usage.

\xtc{
The simplest use of a predicate is one you don't see at all.
}{
\spadpaste{opposite 'right == 'left}
}
\xtc{
Here is a longer way to give the ``opposite definition.''
}{
\spadpaste{opposite (x | x = 'left) == 'right}
}
\xtc{
Try it out.
}{
\spadpaste{for x in ['right,'left,'inbetween] repeat output opposite x}
}

Explicit predicates tell Axiom that the given function definition
piece is to be applied if the predicate evaluates to {\tt true} for
the arguments to the function.  You can use such ``constant''
arguments for integers, strings, and quoted symbols.  The
\axiomType{Boolean} values \axiom{true} and \axiom{false} can also be
used if qualified with ``\spad{@}'' or ``\spad{\$}'' and
\axiomType{Boolean}.  The following are all valid function definition
fragments using constant arguments.
\begin{verbatim}
a(1) == ...
b("unramified") == ...
c('untested) == ...
d(true@Boolean) == ...
\end{verbatim}

If a function has more than one argument, each argument can have its
own predicate.  However, if a predicate involves two or more
arguments, it must be given {\it after} all the arguments mentioned in
the predicate have been given.  You are always safe to give a single
predicate at the end of the argument list.
\xtc{
A function involving predicates on two arguments.
}{
\spadpaste{inFirstHalfQuadrant(x | x > 0,y | y < x) == true}
}
\xtc{
This is incorrect as it gives a predicate on \axiom{y}
before the argument \axiom{y} is given.
}{
\spadpaste{inFirstHalfQuadrant(x | x > 0 and y < x,y) == true}
}
\xtc{
It is always correct to write the predicate at the end.
}{
\spadpaste{inFirstHalfQuadrant(x,y | x > 0 and y < x) == true \bound{ifq1a}}
}
\xtc{
Here is the rest of the definition.
}{
\spadpaste{inFirstHalfQuadrant(x,y) == false \bound{ifq1b}}
}
\xtc{
Try it out.
}{
\spadpaste{[inFirstHalfQuadrant(i,3) for i in 1..5]\bound{ifq1b}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserPiecePredPagePatch1}
\begin{paste}{ugUserPiecePredPageFull1}{ugUserPiecePredPageEmpty1}
\pastebutton{ugUserPiecePredPageFull1}{\hidepaste}
\tab{5}\spadcommand{opposite 'right == 'left}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPiecePredPageEmpty1}
\begin{paste}{ugUserPiecePredPageEmpty1}{ugUserPiecePredPagePatch1}
\pastebutton{ugUserPiecePredPageEmpty1}{\showpaste}
\tab{5}\spadcommand{opposite 'right == 'left}
\end{paste}\end{patch}

\begin{patch}{ugUserPiecePredPagePatch2}
\begin{paste}{ugUserPiecePredPageFull2}{ugUserPiecePredPageEmpty2}
\pastebutton{ugUserPiecePredPageFull2}{\hidepaste}
\tab{5}\spadcommand{opposite (x | x = 'left) == 'right}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPiecePredPageEmpty2}
\begin{paste}{ugUserPiecePredPageEmpty2}{ugUserPiecePredPagePatch2}
\pastebutton{ugUserPiecePredPageEmpty2}{\showpaste}
\tab{5}\spadcommand{opposite (x | x = 'left) == 'right}
\end{paste}\end{patch}

\begin{patch}{ugUserPiecePredPagePatch3}
\begin{paste}{ugUserPiecePredPageFull3}{ugUserPiecePredPageEmpty3}
\pastebutton{ugUserPiecePredPageFull3}{\hidepaste}
\tab{5}\spadcommand{for x in ['right,'left,'inbetween] repeat output opposite x}
\indentrel{3}\begin{verbatim}
   left
   right
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPiecePredPageEmpty3}
\begin{paste}{ugUserPiecePredPageEmpty3}{ugUserPiecePredPagePatch3}
\pastebutton{ugUserPiecePredPageEmpty3}{\showpaste}
\tab{5}\spadcommand{for x in ['right,'left,'inbetween] repeat output opposite x}
\end{paste}\end{patch}

\begin{patch}{ugUserPiecePredPagePatch4}
\begin{paste}{ugUserPiecePredPageFull4}{ugUserPiecePredPageEmpty4}
\pastebutton{ugUserPiecePredPageFull4}{\hidepaste}
\tab{5}\spadcommand{inFirstHalfQuadrant(x | x > 0,y | y < x) == true}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPiecePredPageEmpty4}
\begin{paste}{ugUserPiecePredPageEmpty4}{ugUserPiecePredPagePatch4}
\pastebutton{ugUserPiecePredPageEmpty4}{\showpaste}
\tab{5}\spadcommand{inFirstHalfQuadrant(x | x > 0,y | y < x) == true}
\end{paste}\end{patch}

\begin{patch}{ugUserPiecePredPagePatch5}
\begin{paste}{ugUserPiecePredPageFull5}{ugUserPiecePredPageEmpty5}
\pastebutton{ugUserPiecePredPageFull5}{\hidepaste}
\tab{5}\spadcommand{inFirstHalfQuadrant(x | x > 0 and y < x,y) == true}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPiecePredPageEmpty5}
\begin{paste}{ugUserPiecePredPageEmpty5}{ugUserPiecePredPagePatch5}
\pastebutton{ugUserPiecePredPageEmpty5}{\showpaste}
\tab{5}\spadcommand{inFirstHalfQuadrant(x | x > 0 and y < x,y) == true}
\end{paste}\end{patch}

\begin{patch}{ugUserPiecePredPagePatch6}
\begin{paste}{ugUserPiecePredPageFull6}{ugUserPiecePredPageEmpty6}
\pastebutton{ugUserPiecePredPageFull6}{\hidepaste}
\tab{5}\spadcommand{inFirstHalfQuadrant(x,y | x > 0 and y < x) == true\bound{ifq1a }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPiecePredPageEmpty6}
\begin{paste}{ugUserPiecePredPageEmpty6}{ugUserPiecePredPagePatch6}
\pastebutton{ugUserPiecePredPageEmpty6}{\showpaste}
\tab{5}\spadcommand{inFirstHalfQuadrant(x,y | x > 0 and y < x) == true\bound{ifq1a }}
\end{paste}\end{patch}

\begin{patch}{ugUserPiecePredPagePatch7}
\begin{paste}{ugUserPiecePredPageFull7}{ugUserPiecePredPageEmpty7}
\pastebutton{ugUserPiecePredPageFull7}{\hidepaste}
\tab{5}\spadcommand{inFirstHalfQuadrant(x,y) == false\bound{ifq1b }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPiecePredPageEmpty7}
\begin{paste}{ugUserPiecePredPageEmpty7}{ugUserPiecePredPagePatch7}
\pastebutton{ugUserPiecePredPageEmpty7}{\showpaste}
\tab{5}\spadcommand{inFirstHalfQuadrant(x,y) == false\bound{ifq1b }}
\end{paste}\end{patch}

\begin{patch}{ugUserPiecePredPagePatch8}
\begin{paste}{ugUserPiecePredPageFull8}{ugUserPiecePredPageEmpty8}
\pastebutton{ugUserPiecePredPageFull8}{\hidepaste}
\tab{5}\spadcommand{[inFirstHalfQuadrant(i,3) for i in 1..5]\bound{ifq1b }}
\indentrel{3}\begin{verbatim}
   (7)  [false,false,false,true,true]
                                     Type: List Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPiecePredPageEmpty8}
\begin{paste}{ugUserPiecePredPageEmpty8}{ugUserPiecePredPagePatch8}
\pastebutton{ugUserPiecePredPageEmpty8}{\showpaste}
\tab{5}\spadcommand{[inFirstHalfQuadrant(i,3) for i in 1..5]\bound{ifq1b }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugUserCachePage}{ug06.ht}{Caching Previously Computed Results}
\pageto{notitle}{ugUserFreeLocalPage}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserCachePage}{6.12. Caching Previously Computed Results}
\beginscroll

By default, Axiom does not save the values of any function.  You can
cause it to save values and not to recompute unnecessarily by using
\spadcmd{)set functions cache}.  This should be used before the
functions are defined or, at least, before they are executed.  The
word following ``cache'' should be \axiom{0} to turn off caching, a
positive integer \axiom{n} to save the last \axiom{n} computed values
or ``all'' to save all computed values.  If you then give a list of
names of functions, the caching only affects those functions.  Use no
list of names or ``all'' when you want to define the default behavior
for functions not specifically mentioned in other \spadcmd{)set
functions cache} statements.  If you give no list of names, all
functions will have the caching behavior.  If you explicitly turn on
caching for one or more names, you must explicitly turn off caching
for those names when you want to stop saving their values.

\xtc{
This causes the functions \userfun{f} and \userfun{g} to have
the last three computed values saved.
}{
\spadpaste{)set functions cache 3 f g \bound{cache}}
}
\xtc{
This is a sample definition for \userfun{f}.
}{
\spadpaste{f x == factorial(2**x) \bound{fdef}\free{cache}}
}
\xtc{
A message is displayed stating what \userfun{f} will cache.
}{
\spadpaste{f(4) \free{}\free{cache}}
}
\xtc{
This causes all other functions to have all computed values saved by
default.
}{
\spadpaste{)set functions cache all}
}
\xtc{
This causes all functions that have not been specifically cached in
some way to have no computed values saved.
}{
\spadpaste{)set functions cache 0}
}
\xtc{
We also make \userfun{f} and \userfun{g} uncached.
}{
\spadpaste{)set functions cache 0 f g}
}

\beginImportant
Be careful about caching functions that have \spadglossSee{side
effects}{side effect}.  Such a function might destructively modify the
elements of an array or issue a \axiomFun{draw} command, for example.
A function that you expect to execute every time it is called should
not be cached.  Also, it is highly unlikely that a function with no
arguments should be cached.
\endImportant

You should also be careful about caching functions that depend on
free variables.
See \downlink{``Free and Local Variables''}{ugUserFreeLocalPage} in 
Section 6.16\ignore{ugUserFreeLocal}
for an example.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserCachePagePatch1}
\begin{paste}{ugUserCachePageFull1}{ugUserCachePageEmpty1}
\pastebutton{ugUserCachePageFull1}{\hidepaste}
\tab{5}\spadcommand{)set functions cache 3 f g\bound{cache }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserCachePageEmpty1}
\begin{paste}{ugUserCachePageEmpty1}{ugUserCachePagePatch1}
\pastebutton{ugUserCachePageEmpty1}{\showpaste}
\tab{5}\spadcommand{)set functions cache 3 f g\bound{cache }}
\end{paste}\end{patch}

\begin{patch}{ugUserCachePagePatch2}
\begin{paste}{ugUserCachePageFull2}{ugUserCachePageEmpty2}
\pastebutton{ugUserCachePageFull2}{\hidepaste}
\tab{5}\spadcommand{f x == factorial(2**x)\bound{fdef }\free{cache }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserCachePageEmpty2}
\begin{paste}{ugUserCachePageEmpty2}{ugUserCachePagePatch2}
\pastebutton{ugUserCachePageEmpty2}{\showpaste}
\tab{5}\spadcommand{f x == factorial(2**x)\bound{fdef }\free{cache }}
\end{paste}\end{patch}

\begin{patch}{ugUserCachePagePatch3}
\begin{paste}{ugUserCachePageFull3}{ugUserCachePageEmpty3}
\pastebutton{ugUserCachePageFull3}{\hidepaste}
\tab{5}\spadcommand{f(4)\free{}\free{cache }}
\indentrel{3}\begin{verbatim}
   (2)  20922789888000
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserCachePageEmpty3}
\begin{paste}{ugUserCachePageEmpty3}{ugUserCachePagePatch3}
\pastebutton{ugUserCachePageEmpty3}{\showpaste}
\tab{5}\spadcommand{f(4)\free{}\free{cache }}
\end{paste}\end{patch}

\begin{patch}{ugUserCachePagePatch4}
\begin{paste}{ugUserCachePageFull4}{ugUserCachePageEmpty4}
\pastebutton{ugUserCachePageFull4}{\hidepaste}
\tab{5}\spadcommand{)set functions cache all}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserCachePageEmpty4}
\begin{paste}{ugUserCachePageEmpty4}{ugUserCachePagePatch4}
\pastebutton{ugUserCachePageEmpty4}{\showpaste}
\tab{5}\spadcommand{)set functions cache all}
\end{paste}\end{patch}

\begin{patch}{ugUserCachePagePatch5}
\begin{paste}{ugUserCachePageFull5}{ugUserCachePageEmpty5}
\pastebutton{ugUserCachePageFull5}{\hidepaste}
\tab{5}\spadcommand{)set functions cache 0}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserCachePageEmpty5}
\begin{paste}{ugUserCachePageEmpty5}{ugUserCachePagePatch5}
\pastebutton{ugUserCachePageEmpty5}{\showpaste}
\tab{5}\spadcommand{)set functions cache 0}
\end{paste}\end{patch}

\begin{patch}{ugUserCachePagePatch6}
\begin{paste}{ugUserCachePageFull6}{ugUserCachePageEmpty6}
\pastebutton{ugUserCachePageFull6}{\hidepaste}
\tab{5}\spadcommand{)set functions cache 0 f g}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserCachePageEmpty6}
\begin{paste}{ugUserCachePageEmpty6}{ugUserCachePagePatch6}
\pastebutton{ugUserCachePageEmpty6}{\showpaste}
\tab{5}\spadcommand{)set functions cache 0 f g}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugUserRecurPage}{ug06.ht}{Recurrence Relations}
\pageto{notitle}{ugUserFreeLocalPage}
\pageto{notitle}{ugUserCachePage}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserRecurPage}{6.13. Recurrence Relations}
\beginscroll

One of the most useful classes of function are those defined via a
``recurrence relation.''
A {\it recurrence relation} makes each successive
value depend on some or all of the previous values.
A simple example is the ordinary ``factorial'' function:
\begin{verbatim}
fact(0) == 1
fact(n | n > 0) == n * fact(n-1)
\end{verbatim}

The value of \axiom{fact(10)} depends on the value of \axiom{fact(9)},
\axiom{fact(9)} on \axiom{fact(8)}, and so on.  Because it depends on
only one previous value, it is usually called a {\it first order
recurrence relation.}  You can easily imagine a function based on two,
three or more previous values.  The Fibonacci numbers are probably the
most famous function defined by a second order recurrence relation.
\xtc{
The library function \axiomFun{fibonacci} computes Fibonacci numbers.
It is obviously optimized for speed.
}{
\spadpaste{[fibonacci(i) for i in 0..]}
}
\xtc{
Define the
Fibonacci numbers ourselves using a piece-wise definition.
}{
\spadpaste{fib(1) == 1 \bound{fib0}}
}
\xtc{
}{
\spadpaste{fib(2) == 1 \bound{fib1}\free{fib0}}
}
\xtc{
}{
\spadpaste{fib(n) == fib(n-1) + fib(n-2) \bound{fibn}\free{fib1}}
}

As defined, this recurrence relation is obviously doubly-recursive.
To compute \axiom{fib(10)}, we need to compute \axiom{fib(9)} and
\axiom{fib(8)}.  And to \axiom{fib(9)}, we need to compute
\axiom{fib(8)} and \axiom{fib(7)}.  And so on.  It seems that to
compute \axiom{fib(10)} we need to compute \axiom{fib(9)} once,
\axiom{fib(8)} twice, \axiom{fib(7)} three times.  Look familiar?  The
number of function calls needed to compute {\it any} second order
recurrence relation in the obvious way is exactly \axiom{fib(n)}.
These numbers grow!  For example, if Axiom actually did this, then
\axiom{fib(500)} requires more than
\texht{$10^{104}$}{\axiom{10**104}} function calls.  And, given all
this, our definition of \userfun{fib} obviously could not be used to
calculate the five-hundredth Fibonacci number.
\xtc{
Let's try it anyway.
}{
\spadpaste{fib(500) \free{fibn}}
}

Since this takes a short time to compute, it obviously didn't do as
many as \texht{$10^{104}$}{\axiom{10**104}} operations!  By default,
Axiom transforms any recurrence relation it recognizes into an
iteration.  Iterations are efficient.  To compute the value of the
\eth{\axiom{n}} term of a recurrence relation using an iteration
requires only \axiom{n} function calls.\footnote{If you compare the
speed of our \userfun{fib} function to the library function, our
version is still slower.  This is because the library
\axiomFunFrom{fibonacci}{IntegerNumberTheoryFunctions} uses a
``powering algorithm'' with a computing time proportional to
\texht{$\log^3(n)$}{\axiom{log(n)**3}} to compute
\axiom{fibonacci(n).}}

To turn off this special recurrence relation compilation, issue
\begin{verbatim}
)set functions recurrence off
\end{verbatim}
To turn it back on, substitute ``{\tt on}'' for ``{\tt off}''.

The transformations that Axiom uses for \userfun{fib} caches the
last two values.\footnote{For a more general \eth{\axiom{k}} order recurrence
relation, Axiom caches the last \axiom{k} values.}
If, after computing a value for \userfun{fib}, you ask
for some larger value, Axiom picks up the cached values
and continues computing from there.
See \downlink{``Free and Local Variables''}{ugUserFreeLocalPage} 
in Section 6.16\ignore{ugUserFreeLocal}
for an example of a function definition that has this same behavior.
Also see \downlink{``Caching Previously Computed Results''}
{ugUserCachePage} in Section 6.12\ignore{ugUserCache}
for a more general discussion of how you can cache function values.

Recurrence relations can be used for defining recurrence relations
involving polynomials, rational functions, or anything you like.
Here we compute the infinite stream of Legendre polynomials.
\xtc{
The Legendre polynomial of degree \axiom{0.}
}{
\spadpaste{p(0) == 1\bound{p0}}
}
\xtc{
The Legendre polynomial of degree \axiom{1.}
}{
\spadpaste{p(1) == x\bound{p1}}
}

\xtc{
The Legendre polynomial of degree \axiom{n}.
}{
\spadpaste{p(n) == ((2*n-1)*x*p(n-1) - (n-1)*p(n-2))/n\bound{pn}\free{p1}}
}
\xtc{
Compute the Legendre polynomial of degree \axiom{6.}
}{
\spadpaste{p(6)\free{pn}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserRecurPagePatch1}
\begin{paste}{ugUserRecurPageFull1}{ugUserRecurPageEmpty1}
\pastebutton{ugUserRecurPageFull1}{\hidepaste}
\tab{5}\spadcommand{[fibonacci(i) for i in 0..]}
\indentrel{3}\begin{verbatim}
   (1)  [0,1,1,2,3,5,8,13,21,34,...]
                                   Type: Stream Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRecurPageEmpty1}
\begin{paste}{ugUserRecurPageEmpty1}{ugUserRecurPagePatch1}
\pastebutton{ugUserRecurPageEmpty1}{\showpaste}
\tab{5}\spadcommand{[fibonacci(i) for i in 0..]}
\end{paste}\end{patch}

\begin{patch}{ugUserRecurPagePatch2}
\begin{paste}{ugUserRecurPageFull2}{ugUserRecurPageEmpty2}
\pastebutton{ugUserRecurPageFull2}{\hidepaste}
\tab{5}\spadcommand{fib(1) == 1\bound{fib0 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRecurPageEmpty2}
\begin{paste}{ugUserRecurPageEmpty2}{ugUserRecurPagePatch2}
\pastebutton{ugUserRecurPageEmpty2}{\showpaste}
\tab{5}\spadcommand{fib(1) == 1\bound{fib0 }}
\end{paste}\end{patch}

\begin{patch}{ugUserRecurPagePatch3}
\begin{paste}{ugUserRecurPageFull3}{ugUserRecurPageEmpty3}
\pastebutton{ugUserRecurPageFull3}{\hidepaste}
\tab{5}\spadcommand{fib(2) == 1\bound{fib1 }\free{fib0 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRecurPageEmpty3}
\begin{paste}{ugUserRecurPageEmpty3}{ugUserRecurPagePatch3}
\pastebutton{ugUserRecurPageEmpty3}{\showpaste}
\tab{5}\spadcommand{fib(2) == 1\bound{fib1 }\free{fib0 }}
\end{paste}\end{patch}

\begin{patch}{ugUserRecurPagePatch4}
\begin{paste}{ugUserRecurPageFull4}{ugUserRecurPageEmpty4}
\pastebutton{ugUserRecurPageFull4}{\hidepaste}
\tab{5}\spadcommand{fib(n) == fib(n-1) + fib(n-2)\bound{fibn }\free{fib1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRecurPageEmpty4}
\begin{paste}{ugUserRecurPageEmpty4}{ugUserRecurPagePatch4}
\pastebutton{ugUserRecurPageEmpty4}{\showpaste}
\tab{5}\spadcommand{fib(n) == fib(n-1) + fib(n-2)\bound{fibn }\free{fib1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserRecurPagePatch5}
\begin{paste}{ugUserRecurPageFull5}{ugUserRecurPageEmpty5}
\pastebutton{ugUserRecurPageFull5}{\hidepaste}
\tab{5}\spadcommand{fib(500)\free{fibn }}
\indentrel{3}\begin{verbatim}
   (5)
  139423224561697880139724382870407283950070256587697307_
   264108962948325571622863290691557658876222521294125
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRecurPageEmpty5}
\begin{paste}{ugUserRecurPageEmpty5}{ugUserRecurPagePatch5}
\pastebutton{ugUserRecurPageEmpty5}{\showpaste}
\tab{5}\spadcommand{fib(500)\free{fibn }}
\end{paste}\end{patch}

\begin{patch}{ugUserRecurPagePatch6}
\begin{paste}{ugUserRecurPageFull6}{ugUserRecurPageEmpty6}
\pastebutton{ugUserRecurPageFull6}{\hidepaste}
\tab{5}\spadcommand{p(0) == 1\bound{p0 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRecurPageEmpty6}
\begin{paste}{ugUserRecurPageEmpty6}{ugUserRecurPagePatch6}
\pastebutton{ugUserRecurPageEmpty6}{\showpaste}
\tab{5}\spadcommand{p(0) == 1\bound{p0 }}
\end{paste}\end{patch}

\begin{patch}{ugUserRecurPagePatch7}
\begin{paste}{ugUserRecurPageFull7}{ugUserRecurPageEmpty7}
\pastebutton{ugUserRecurPageFull7}{\hidepaste}
\tab{5}\spadcommand{p(1) == x\bound{p1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRecurPageEmpty7}
\begin{paste}{ugUserRecurPageEmpty7}{ugUserRecurPagePatch7}
\pastebutton{ugUserRecurPageEmpty7}{\showpaste}
\tab{5}\spadcommand{p(1) == x\bound{p1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserRecurPagePatch8}
\begin{paste}{ugUserRecurPageFull8}{ugUserRecurPageEmpty8}
\pastebutton{ugUserRecurPageFull8}{\hidepaste}
\tab{5}\spadcommand{p(n) == ((2*n-1)*x*p(n-1) - (n-1)*p(n-2))/n\bound{pn }\free{p1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRecurPageEmpty8}
\begin{paste}{ugUserRecurPageEmpty8}{ugUserRecurPagePatch8}
\pastebutton{ugUserRecurPageEmpty8}{\showpaste}
\tab{5}\spadcommand{p(n) == ((2*n-1)*x*p(n-1) - (n-1)*p(n-2))/n\bound{pn }\free{p1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserRecurPagePatch9}
\begin{paste}{ugUserRecurPageFull9}{ugUserRecurPageEmpty9}
\pastebutton{ugUserRecurPageFull9}{\hidepaste}
\tab{5}\spadcommand{p(6)\free{pn }}
\indentrel{3}\begin{verbatim}
        231  6   315  4   105  2    5
   (9)  ÄÄÄ x  - ÄÄÄ x  + ÄÄÄ x  - ÄÄ
         16       16       16      16
                      Type: Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRecurPageEmpty9}
\begin{paste}{ugUserRecurPageEmpty9}{ugUserRecurPagePatch9}
\pastebutton{ugUserRecurPageEmpty9}{\showpaste}
\tab{5}\spadcommand{p(6)\free{pn }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugUserMakePage}{ug06.ht}{Making Functions from Objects}
\pageto{notitle}{MakeFunctionXmpPage}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserMakePage}{6.14. Making Functions from Objects}
\beginscroll

There are many times when you compute a complicated expression
and then wish to use that expression as the body of a function.
Axiom provides an operation called \axiomFun{function} to do
this.
It creates a function object and places it into the workspace.
There are several versions, depending on how many arguments the function
has.
The first argument to \axiomFun{function} is always the expression to be
converted into the function body, and the second is always the name to be
used for the function.
For more information, see \downlink{`MakeFunction'}{MakeFunctionXmpPage}
\ignore{MakeFunction}.

\xtc{
Start with a simple example of a polynomial in three variables.
}{
\spadpaste{p := -x + y**2 - z**3 \bound{p}}
}
\xtc{
To make this into a function of no arguments that
simply returns the polynomial, use the two argument form of
\axiomFun{function}.
}{
\spadpaste{function(p,'f0) \free{p}\bound{f0}}
}
\xtc{
To avoid possible conflicts (see below), it is a good idea to
quote always this second argument.
}{
\spadpaste{f0 \free{f0}}
}
\xtc{
This is what you get when you evaluate the function.
}{
\spadpaste{f0() \free{f0}}
}
\xtc{
To make a function in \axiom{x}, use a version of
\axiomFun{function} that takes three arguments.
The last argument is the name of the variable to use as the parameter.
Typically, this variable occurs in the expression and, like the function
name, you should quote it to avoid possible confusion.
}{
\spadpaste{function(p,'f1,'x) \free{p}\bound{f1}}
}
\xtc{
This is what the new function looks like.
}{
\spadpaste{f1 \free{f1}}
}
\xtc{
This is the value of \userfun{f1} at \axiom{x = 3}.
Notice that the return type of the function is
\axiomType{Polynomial (Integer)}, the same as \axiom{p}.
}{
\spadpaste{f1(3) \free{f1}}
}
\xtc{
To use \axiom{x} and \axiom{y} as parameters, use the
four argument form of \axiomFun{function}.
}{
\spadpaste{function(p,'f2,'x,'y) \free{p}\bound{f2}}
}
\xtc{
}{
\spadpaste{f2 \free{f2}}
}
\xtc{
Evaluate \axiom{f2} at \axiom{x = 3} and \axiom{y = 0}.
The return type of \userfun{f2} is still
\axiomType{Polynomial(Integer)} because the variable \axiom{z}
is still present and not one of the parameters.
}{
\spadpaste{f2(3,0) \free{f2}}
}
\xtc{
Finally, use all three variables as parameters.
There is no five argument form of \axiomFun{function}, so use the one with
three arguments, the third argument being a list of the parameters.
}{
\spadpaste{function(p,'f3,['x,'y,'z]) \free{p}\bound{f3}}
}
\xtc{
Evaluate this using the same values for \axiom{x} and \axiom{y}
as above, but let \axiom{z} be \axiom{-6}.
The result type of \userfun{f3} is \axiomType{Integer}.
}{
\spadpaste{f3 \free{f3}}
}
\xtc{
}{
\spadpaste{f3(3,0,-6) \free{f3}}
}

The four functions we have defined via \axiom{p} have been undeclared.
To declare a function whose body is to be generated by
\axiomFun{function}, 
issue the declaration {\it before} the function is created.
\xtc{
}{
\spadpaste{g: (Integer, Integer) -> Float \bound{g}}
}
\xtc{
}{
\spadpaste{D(sin(x-y)/cos(x+y),x) \bound{prev}}
}
\xtc{
}{
\spadpaste{function(\%,'g,'x,'y) \free{g}\free{prev}}
}
\xtc{
}{
\spadpaste{g \free{g}}
}
It is an error to use \axiom{g} without the quote in the penultimate
expression since \axiom{g} had been declared but did not have a value.
Similarly, since it is common to overuse variable names like
\axiom{x}, \axiom{y}, and so on, you avoid problems if you always
quote the variable names for \axiomFun{function}.  In general, if
\axiom{x} has a value and you use \axiom{x} without a quote in a call
to \axiomFun{function}, then Axiom does not know what you are trying
to do.

What kind of object is allowable as the first argument to
\axiomFun{function}?  Let's use the \Browse{} facility of Hyperdoc to
find out.  At the main \Browse{} menu, enter the string {\tt function}
and then click on {\bf Operations.}  The exposed operations called
\axiomFun{function} all take an object whose type belongs to category
\axiomType{ConvertibleTo InputForm}.  What domains are those?  Go back
to the main \Browse{} menu, erase {\tt function}, enter {\tt
ConvertibleTo} in the input area, and click on {\bf categories} on the
{\bf Constructors} line.  At the bottom of the page, enter {\tt
InputForm} in the input area following {\bf S =}.  Click on {\bf Cross
Reference} and then on {\bf Domains}.  The list you see contains over
forty domains that belong to the category \axiomType{ConvertibleTo
InputForm}.  Thus you can use \axiomFun{function} for
\axiomType{Integer}, \axiomType{Float}, \axiomType{Symbol},
\axiomType{Complex}, \axiomType{Expression}, and so on.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserMakePagePatch1}
\begin{paste}{ugUserMakePageFull1}{ugUserMakePageEmpty1}
\pastebutton{ugUserMakePageFull1}{\hidepaste}
\tab{5}\spadcommand{p := -x + y**2 - z**3\bound{p }}
\indentrel{3}\begin{verbatim}
           3    2
   (1)  - z  + y  - x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMakePageEmpty1}
\begin{paste}{ugUserMakePageEmpty1}{ugUserMakePagePatch1}
\pastebutton{ugUserMakePageEmpty1}{\showpaste}
\tab{5}\spadcommand{p := -x + y**2 - z**3\bound{p }}
\end{paste}\end{patch}

\begin{patch}{ugUserMakePagePatch2}
\begin{paste}{ugUserMakePageFull2}{ugUserMakePageEmpty2}
\pastebutton{ugUserMakePageFull2}{\hidepaste}
\tab{5}\spadcommand{function(p,'f0)\free{p }\bound{f0 }}
\indentrel{3}\begin{verbatim}
   (2)  f0
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMakePageEmpty2}
\begin{paste}{ugUserMakePageEmpty2}{ugUserMakePagePatch2}
\pastebutton{ugUserMakePageEmpty2}{\showpaste}
\tab{5}\spadcommand{function(p,'f0)\free{p }\bound{f0 }}
\end{paste}\end{patch}

\begin{patch}{ugUserMakePagePatch3}
\begin{paste}{ugUserMakePageFull3}{ugUserMakePageEmpty3}
\pastebutton{ugUserMakePageFull3}{\hidepaste}
\tab{5}\spadcommand{f0\free{f0 }}
\indentrel{3}\begin{verbatim}
                    3    2
   (3)  f0 () == - z  + y  - x
                                Type: FunctionCalled f0
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMakePageEmpty3}
\begin{paste}{ugUserMakePageEmpty3}{ugUserMakePagePatch3}
\pastebutton{ugUserMakePageEmpty3}{\showpaste}
\tab{5}\spadcommand{f0\free{f0 }}
\end{paste}\end{patch}

\begin{patch}{ugUserMakePagePatch4}
\begin{paste}{ugUserMakePageFull4}{ugUserMakePageEmpty4}
\pastebutton{ugUserMakePageFull4}{\hidepaste}
\tab{5}\spadcommand{f0()\free{f0 }}
\indentrel{3}\begin{verbatim}
           3    2
   (4)  - z  + y  - x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMakePageEmpty4}
\begin{paste}{ugUserMakePageEmpty4}{ugUserMakePagePatch4}
\pastebutton{ugUserMakePageEmpty4}{\showpaste}
\tab{5}\spadcommand{f0()\free{f0 }}
\end{paste}\end{patch}

\begin{patch}{ugUserMakePagePatch5}
\begin{paste}{ugUserMakePageFull5}{ugUserMakePageEmpty5}
\pastebutton{ugUserMakePageFull5}{\hidepaste}
\tab{5}\spadcommand{function(p,'f1,'x)\free{p }\bound{f1 }}
\indentrel{3}\begin{verbatim}
   (5)  f1
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMakePageEmpty5}
\begin{paste}{ugUserMakePageEmpty5}{ugUserMakePagePatch5}
\pastebutton{ugUserMakePageEmpty5}{\showpaste}
\tab{5}\spadcommand{function(p,'f1,'x)\free{p }\bound{f1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserMakePagePatch6}
\begin{paste}{ugUserMakePageFull6}{ugUserMakePageEmpty6}
\pastebutton{ugUserMakePageFull6}{\hidepaste}
\tab{5}\spadcommand{f1\free{f1 }}
\indentrel{3}\begin{verbatim}
                   3    2
   (6)  f1 x == - z  + y  - x
                                Type: FunctionCalled f1
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMakePageEmpty6}
\begin{paste}{ugUserMakePageEmpty6}{ugUserMakePagePatch6}
\pastebutton{ugUserMakePageEmpty6}{\showpaste}
\tab{5}\spadcommand{f1\free{f1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserMakePagePatch7}
\begin{paste}{ugUserMakePageFull7}{ugUserMakePageEmpty7}
\pastebutton{ugUserMakePageFull7}{\hidepaste}
\tab{5}\spadcommand{f1(3)\free{f1 }}
\indentrel{3}\begin{verbatim}
           3    2
   (7)  - z  + y  - 3
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMakePageEmpty7}
\begin{paste}{ugUserMakePageEmpty7}{ugUserMakePagePatch7}
\pastebutton{ugUserMakePageEmpty7}{\showpaste}
\tab{5}\spadcommand{f1(3)\free{f1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserMakePagePatch8}
\begin{paste}{ugUserMakePageFull8}{ugUserMakePageEmpty8}
\pastebutton{ugUserMakePageFull8}{\hidepaste}
\tab{5}\spadcommand{function(p,'f2,'x,'y)\free{p }\bound{f2 }}
\indentrel{3}\begin{verbatim}
   (8)  f2
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMakePageEmpty8}
\begin{paste}{ugUserMakePageEmpty8}{ugUserMakePagePatch8}
\pastebutton{ugUserMakePageEmpty8}{\showpaste}
\tab{5}\spadcommand{function(p,'f2,'x,'y)\free{p }\bound{f2 }}
\end{paste}\end{patch}

\begin{patch}{ugUserMakePagePatch9}
\begin{paste}{ugUserMakePageFull9}{ugUserMakePageEmpty9}
\pastebutton{ugUserMakePageFull9}{\hidepaste}
\tab{5}\spadcommand{f2\free{f2 }}
\indentrel{3}\begin{verbatim}
                       3    2
   (9)  f2 (x,y) == - z  + y  - x
                                Type: FunctionCalled f2
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMakePageEmpty9}
\begin{paste}{ugUserMakePageEmpty9}{ugUserMakePagePatch9}
\pastebutton{ugUserMakePageEmpty9}{\showpaste}
\tab{5}\spadcommand{f2\free{f2 }}
\end{paste}\end{patch}

\begin{patch}{ugUserMakePagePatch10}
\begin{paste}{ugUserMakePageFull10}{ugUserMakePageEmpty10}
\pastebutton{ugUserMakePageFull10}{\hidepaste}
\tab{5}\spadcommand{f2(3,0)\free{f2 }}
\indentrel{3}\begin{verbatim}
            3
   (10)  - z  - 3
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMakePageEmpty10}
\begin{paste}{ugUserMakePageEmpty10}{ugUserMakePagePatch10}
\pastebutton{ugUserMakePageEmpty10}{\showpaste}
\tab{5}\spadcommand{f2(3,0)\free{f2 }}
\end{paste}\end{patch}

\begin{patch}{ugUserMakePagePatch11}
\begin{paste}{ugUserMakePageFull11}{ugUserMakePageEmpty11}
\pastebutton{ugUserMakePageFull11}{\hidepaste}
\tab{5}\spadcommand{function(p,'f3,['x,'y,'z])\free{p }\bound{f3 }}
\indentrel{3}\begin{verbatim}
   (11)  f3
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMakePageEmpty11}
\begin{paste}{ugUserMakePageEmpty11}{ugUserMakePagePatch11}
\pastebutton{ugUserMakePageEmpty11}{\showpaste}
\tab{5}\spadcommand{function(p,'f3,['x,'y,'z])\free{p }\bound{f3 }}
\end{paste}\end{patch}

\begin{patch}{ugUserMakePagePatch12}
\begin{paste}{ugUserMakePageFull12}{ugUserMakePageEmpty12}
\pastebutton{ugUserMakePageFull12}{\hidepaste}
\tab{5}\spadcommand{f3\free{f3 }}
\indentrel{3}\begin{verbatim}
                          3    2
   (12)  f3 (x,y,z) == - z  + y  - x
                                Type: FunctionCalled f3
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMakePageEmpty12}
\begin{paste}{ugUserMakePageEmpty12}{ugUserMakePagePatch12}
\pastebutton{ugUserMakePageEmpty12}{\showpaste}
\tab{5}\spadcommand{f3\free{f3 }}
\end{paste}\end{patch}

\begin{patch}{ugUserMakePagePatch13}
\begin{paste}{ugUserMakePageFull13}{ugUserMakePageEmpty13}
\pastebutton{ugUserMakePageFull13}{\hidepaste}
\tab{5}\spadcommand{f3(3,0,-6)\free{f3 }}
\indentrel{3}\begin{verbatim}
   (13)  213
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMakePageEmpty13}
\begin{paste}{ugUserMakePageEmpty13}{ugUserMakePagePatch13}
\pastebutton{ugUserMakePageEmpty13}{\showpaste}
\tab{5}\spadcommand{f3(3,0,-6)\free{f3 }}
\end{paste}\end{patch}

\begin{patch}{ugUserMakePagePatch14}
\begin{paste}{ugUserMakePageFull14}{ugUserMakePageEmpty14}
\pastebutton{ugUserMakePageFull14}{\hidepaste}
\tab{5}\spadcommand{g: (Integer, Integer) -> Float\bound{g }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMakePageEmpty14}
\begin{paste}{ugUserMakePageEmpty14}{ugUserMakePagePatch14}
\pastebutton{ugUserMakePageEmpty14}{\showpaste}
\tab{5}\spadcommand{g: (Integer, Integer) -> Float\bound{g }}
\end{paste}\end{patch}

\begin{patch}{ugUserMakePagePatch15}
\begin{paste}{ugUserMakePageFull15}{ugUserMakePageEmpty15}
\pastebutton{ugUserMakePageFull15}{\hidepaste}
\tab{5}\spadcommand{D(sin(x-y)/cos(x+y),x)\bound{prev }}
\indentrel{3}\begin{verbatim}
         - sin(y - x)sin(y + x) + cos(y - x)cos(y + x)
   (15)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                                    2
                          cos(y + x)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMakePageEmpty15}
\begin{paste}{ugUserMakePageEmpty15}{ugUserMakePagePatch15}
\pastebutton{ugUserMakePageEmpty15}{\showpaste}
\tab{5}\spadcommand{D(sin(x-y)/cos(x+y),x)\bound{prev }}
\end{paste}\end{patch}

\begin{patch}{ugUserMakePagePatch16}
\begin{paste}{ugUserMakePageFull16}{ugUserMakePageEmpty16}
\pastebutton{ugUserMakePageFull16}{\hidepaste}
\tab{5}\spadcommand{function(\%,'g,'x,'y)\free{g }\free{prev }}
\indentrel{3}\begin{verbatim}
   (16)  g
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMakePageEmpty16}
\begin{paste}{ugUserMakePageEmpty16}{ugUserMakePagePatch16}
\pastebutton{ugUserMakePageEmpty16}{\showpaste}
\tab{5}\spadcommand{function(\%,'g,'x,'y)\free{g }\free{prev }}
\end{paste}\end{patch}

\begin{patch}{ugUserMakePagePatch17}
\begin{paste}{ugUserMakePageFull17}{ugUserMakePageEmpty17}
\pastebutton{ugUserMakePageFull17}{\hidepaste}
\tab{5}\spadcommand{g\free{g }}
\indentrel{3}\begin{verbatim}
   (17)
   g (x,y) ==
     - sin(y - x)sin(y + x) + cos(y - x)cos(y + x)
     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                                2
                      cos(y + x)
                                 Type: FunctionCalled g
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserMakePageEmpty17}
\begin{paste}{ugUserMakePageEmpty17}{ugUserMakePagePatch17}
\pastebutton{ugUserMakePageEmpty17}{\showpaste}
\tab{5}\spadcommand{g\free{g }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugUserBlocksPage}{ug06.ht}{Functions Defined with Blocks}
\pageto{notitle}{ugLangBlocksPage}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserBlocksPage}{6.15. Functions Defined with Blocks}
\beginscroll

You need not restrict yourself to functions that only fit on one line
or are written in a piece-wise manner.
The body of the function can be a block, as discussed in
\downlink{``Blocks''}{ugLangBlocksPage} 
in Section 5.2\ignore{ugLangBlocks}.

\labelSpace{1pc}
\xtc{
Here is a short function that swaps two elements of a list,
array or vector.
}{
\begin{spadsrc}[\bound{swap}]
swap(m,i,j) ==
  temp := m.i
  m.i := m.j
  m.j := temp
\end{spadsrc}
}
\xtc{
The significance of \userfun{swap} is that it has a destructive
effect on its first argument.
}{
\spadpaste{k := [1,2,3,4,5] \bound{k}}
}
\xtc{
}{
\spadpaste{swap(k,2,4) \free{l swap}\bound{swapk}}
}
\xtc{
You see that the second and fourth elements are interchanged.
}{
\spadpaste{k \free{swapk}}
}

\xtc{
Using this, we write a couple of different sort functions.
First, a simple bubble sort.
The operation \axiomOpFrom{\#}{List} returns the number of elements in
an aggregate.
}{
\begin{spadsrc}[\bound{bubbleSort}]
bubbleSort(m) ==
  n := #m
  for i in 1..(n-1) repeat
    for j in n..(i+1) by -1 repeat
      if m.j < m.(j-1) then swap(m,j,j-1)
  m
\end{spadsrc}
}
\xtc{
Let this be the list we want to sort.
}{
\spadpaste{m := [8,4,-3,9] \bound{m}}
}
\xtc{
This is the result of sorting.
}{
\spadpaste{bubbleSort(m) \free{m swap bubbleSort}\bound{sortm}}
}
\xtc{
Moreover, \axiom{m} is destructively changed to be the sorted version.
}{
\spadpaste{m \free{sortm}}
}

\xtc{
This function implements an insertion sort.
The basic idea is to traverse the list and insert the \eth{\axiom{i}}
element in its correct position among the \axiom{i-1} previous
elements.
Since we start at the beginning of the list, the list elements before the
\eth{\axiom{i}} element have already been placed in ascending order.
}{
\begin{spadsrc}[\bound{insertionSort}]
insertionSort(m) ==
  for i in 2..#m repeat
    j := i
    while j > 1 and m.j < m.(j-1) repeat
      swap(m,j,j-1)
      j := j - 1
  m
\end{spadsrc}
}
\xtc{
As with our bubble sort, this is a destructive function.
}{
\spadpaste{m := [8,4,-3,9] \bound{m1}}
}
\xtc{
}{
\spadpaste{insertionSort(m) \free{m1 swap insertionSort}\bound{sortm1}}
}
\xtc{
}{
\spadpaste{m \free{sortm1}}
}

Neither of the above functions is efficient for sorting large lists since
they reference elements by asking for the \eth{\axiom{j}} element of the
structure \axiom{m}.

\xtc{
Here is a more efficient bubble sort for lists.
}{
\begin{spadsrc}[\bound{bubbleSort2}]
bubbleSort2(m: List Integer): List Integer ==
  null m => m
  l := m
  while not null (r := l.rest) repeat
     r := bubbleSort2 r
     x := l.first
     if x < r.first then
       l.first := r.first
       r.first := x
     l.rest := r
     l := l.rest
  m
\end{spadsrc}
}
\xtc{
Try it out.
}{
\spadpaste{bubbleSort2 [3,7,2]\free{bubbleSort2}}
}

This definition is both recursive and iterative, and is tricky!
Unless you are {\it really} curious about this definition,
we suggest you skip immediately to the next section.

Here are the key points in the definition.  First notice that if you
are sorting a list with less than two elements, there is nothing to
do: just return the list.  This definition returns immediately if
there are zero elements, and skips the entire \axiom{while} loop if
there is just one element.

The second point to realize is that on each outer iteration, the
bubble sort ensures that the minimum element is propagated leftmost.
Each iteration of the \axiom{while} loop calls \userfun{bubbleSort2}
recursively to sort all but the first element.  When finished, the
minimum element is either in the first or second position.  The
conditional expression ensures that it comes first.  If it is in the
second, then a swap occurs.  In any case, the \axiomFun{rest} of the
original list must be updated to hold the result of the recursive
call.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserBlocksPagePatch1}
\begin{paste}{ugUserBlocksPageFull1}{ugUserBlocksPageEmpty1}
\pastebutton{ugUserBlocksPageFull1}{\hidepaste}
\tab{5}\spadcommand{swap(m,i,j) ==
  temp := m.i
  m.i := m.j
  m.j := temp
\bound{swap }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPageEmpty1}
\begin{paste}{ugUserBlocksPageEmpty1}{ugUserBlocksPagePatch1}
\pastebutton{ugUserBlocksPageEmpty1}{\showpaste}
\tab{5}\spadcommand{swap(m,i,j) ==
  temp := m.i
  m.i := m.j
  m.j := temp
\bound{swap }}
\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPagePatch2}
\begin{paste}{ugUserBlocksPageFull2}{ugUserBlocksPageEmpty2}
\pastebutton{ugUserBlocksPageFull2}{\hidepaste}
\tab{5}\spadcommand{k := [1,2,3,4,5]\bound{k }}
\indentrel{3}\begin{verbatim}
   (2)  [1,2,3,4,5]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPageEmpty2}
\begin{paste}{ugUserBlocksPageEmpty2}{ugUserBlocksPagePatch2}
\pastebutton{ugUserBlocksPageEmpty2}{\showpaste}
\tab{5}\spadcommand{k := [1,2,3,4,5]\bound{k }}
\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPagePatch3}
\begin{paste}{ugUserBlocksPageFull3}{ugUserBlocksPageEmpty3}
\pastebutton{ugUserBlocksPageFull3}{\hidepaste}
\tab{5}\spadcommand{swap(k,2,4)\free{l swap }\bound{swapk }}
\indentrel{3}\begin{verbatim}
   (3)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPageEmpty3}
\begin{paste}{ugUserBlocksPageEmpty3}{ugUserBlocksPagePatch3}
\pastebutton{ugUserBlocksPageEmpty3}{\showpaste}
\tab{5}\spadcommand{swap(k,2,4)\free{l swap }\bound{swapk }}
\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPagePatch4}
\begin{paste}{ugUserBlocksPageFull4}{ugUserBlocksPageEmpty4}
\pastebutton{ugUserBlocksPageFull4}{\hidepaste}
\tab{5}\spadcommand{k\free{swapk }}
\indentrel{3}\begin{verbatim}
   (4)  [1,4,3,2,5]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPageEmpty4}
\begin{paste}{ugUserBlocksPageEmpty4}{ugUserBlocksPagePatch4}
\pastebutton{ugUserBlocksPageEmpty4}{\showpaste}
\tab{5}\spadcommand{k\free{swapk }}
\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPagePatch5}
\begin{paste}{ugUserBlocksPageFull5}{ugUserBlocksPageEmpty5}
\pastebutton{ugUserBlocksPageFull5}{\hidepaste}
\tab{5}\spadcommand{bubbleSort(m) ==
  n := \#m
  for i in 1..(n-1) repeat
    for j in n..(i+1) by -1 repeat
      if m.j < m.(j-1) then swap(m,j,j-1)
  m
\bound{bubbleSort }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPageEmpty5}
\begin{paste}{ugUserBlocksPageEmpty5}{ugUserBlocksPagePatch5}
\pastebutton{ugUserBlocksPageEmpty5}{\showpaste}
\tab{5}\spadcommand{bubbleSort(m) ==
  n := \#m
  for i in 1..(n-1) repeat
    for j in n..(i+1) by -1 repeat
      if m.j < m.(j-1) then swap(m,j,j-1)
  m
\bound{bubbleSort }}
\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPagePatch6}
\begin{paste}{ugUserBlocksPageFull6}{ugUserBlocksPageEmpty6}
\pastebutton{ugUserBlocksPageFull6}{\hidepaste}
\tab{5}\spadcommand{m := [8,4,-3,9]\bound{m }}
\indentrel{3}\begin{verbatim}
   (6)  [8,4,- 3,9]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPageEmpty6}
\begin{paste}{ugUserBlocksPageEmpty6}{ugUserBlocksPagePatch6}
\pastebutton{ugUserBlocksPageEmpty6}{\showpaste}
\tab{5}\spadcommand{m := [8,4,-3,9]\bound{m }}
\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPagePatch7}
\begin{paste}{ugUserBlocksPageFull7}{ugUserBlocksPageEmpty7}
\pastebutton{ugUserBlocksPageFull7}{\hidepaste}
\tab{5}\spadcommand{bubbleSort(m)\free{m swap bubbleSort }\bound{sortm }}
\indentrel{3}\begin{verbatim}
   (7)  [- 3,4,8,9]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPageEmpty7}
\begin{paste}{ugUserBlocksPageEmpty7}{ugUserBlocksPagePatch7}
\pastebutton{ugUserBlocksPageEmpty7}{\showpaste}
\tab{5}\spadcommand{bubbleSort(m)\free{m swap bubbleSort }\bound{sortm }}
\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPagePatch8}
\begin{paste}{ugUserBlocksPageFull8}{ugUserBlocksPageEmpty8}
\pastebutton{ugUserBlocksPageFull8}{\hidepaste}
\tab{5}\spadcommand{m\free{sortm }}
\indentrel{3}\begin{verbatim}
   (8)  [- 3,4,8,9]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPageEmpty8}
\begin{paste}{ugUserBlocksPageEmpty8}{ugUserBlocksPagePatch8}
\pastebutton{ugUserBlocksPageEmpty8}{\showpaste}
\tab{5}\spadcommand{m\free{sortm }}
\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPagePatch9}
\begin{paste}{ugUserBlocksPageFull9}{ugUserBlocksPageEmpty9}
\pastebutton{ugUserBlocksPageFull9}{\hidepaste}
\tab{5}\spadcommand{insertionSort(m) ==
  for i in 2..\#m repeat
    j := i
    while j > 1 and m.j < m.(j-1) repeat
      swap(m,j,j-1)
      j := j - 1
  m
\bound{insertionSort }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPageEmpty9}
\begin{paste}{ugUserBlocksPageEmpty9}{ugUserBlocksPagePatch9}
\pastebutton{ugUserBlocksPageEmpty9}{\showpaste}
\tab{5}\spadcommand{insertionSort(m) ==
  for i in 2..\#m repeat
    j := i
    while j > 1 and m.j < m.(j-1) repeat
      swap(m,j,j-1)
      j := j - 1
  m
\bound{insertionSort }}
\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPagePatch10}
\begin{paste}{ugUserBlocksPageFull10}{ugUserBlocksPageEmpty10}
\pastebutton{ugUserBlocksPageFull10}{\hidepaste}
\tab{5}\spadcommand{m := [8,4,-3,9]\bound{m1 }}
\indentrel{3}\begin{verbatim}
   (10)  [8,4,- 3,9]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPageEmpty10}
\begin{paste}{ugUserBlocksPageEmpty10}{ugUserBlocksPagePatch10}
\pastebutton{ugUserBlocksPageEmpty10}{\showpaste}
\tab{5}\spadcommand{m := [8,4,-3,9]\bound{m1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPagePatch11}
\begin{paste}{ugUserBlocksPageFull11}{ugUserBlocksPageEmpty11}
\pastebutton{ugUserBlocksPageFull11}{\hidepaste}
\tab{5}\spadcommand{insertionSort(m)\free{m1 swap insertionSort }\bound{sortm1 }}
\indentrel{3}\begin{verbatim}
   (11)  [- 3,4,8,9]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPageEmpty11}
\begin{paste}{ugUserBlocksPageEmpty11}{ugUserBlocksPagePatch11}
\pastebutton{ugUserBlocksPageEmpty11}{\showpaste}
\tab{5}\spadcommand{insertionSort(m)\free{m1 swap insertionSort }\bound{sortm1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPagePatch12}
\begin{paste}{ugUserBlocksPageFull12}{ugUserBlocksPageEmpty12}
\pastebutton{ugUserBlocksPageFull12}{\hidepaste}
\tab{5}\spadcommand{m\free{sortm1 }}
\indentrel{3}\begin{verbatim}
   (12)  [- 3,4,8,9]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPageEmpty12}
\begin{paste}{ugUserBlocksPageEmpty12}{ugUserBlocksPagePatch12}
\pastebutton{ugUserBlocksPageEmpty12}{\showpaste}
\tab{5}\spadcommand{m\free{sortm1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPagePatch13}
\begin{paste}{ugUserBlocksPageFull13}{ugUserBlocksPageEmpty13}
\pastebutton{ugUserBlocksPageFull13}{\hidepaste}
\tab{5}\spadcommand{bubbleSort2(m: List Integer): List Integer ==
  null m => m
  l := m
  while not null (r := l.rest) repeat
     r := bubbleSort2 r
     x := l.first
     if x < r.first then
       l.first := r.first
       r.first := x
     l.rest := r
     l := l.rest
  m
\bound{bubbleSort2 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPageEmpty13}
\begin{paste}{ugUserBlocksPageEmpty13}{ugUserBlocksPagePatch13}
\pastebutton{ugUserBlocksPageEmpty13}{\showpaste}
\tab{5}\spadcommand{bubbleSort2(m: List Integer): List Integer ==
  null m => m
  l := m
  while not null (r := l.rest) repeat
     r := bubbleSort2 r
     x := l.first
     if x < r.first then
       l.first := r.first
       r.first := x
     l.rest := r
     l := l.rest
  m
\bound{bubbleSort2 }}
\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPagePatch14}
\begin{paste}{ugUserBlocksPageFull14}{ugUserBlocksPageEmpty14}
\pastebutton{ugUserBlocksPageFull14}{\hidepaste}
\tab{5}\spadcommand{bubbleSort2 [3,7,2]\free{bubbleSort2 }}
\indentrel{3}\begin{verbatim}
   (14)  [7,3,2]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserBlocksPageEmpty14}
\begin{paste}{ugUserBlocksPageEmpty14}{ugUserBlocksPagePatch14}
\pastebutton{ugUserBlocksPageEmpty14}{\showpaste}
\tab{5}\spadcommand{bubbleSort2 [3,7,2]\free{bubbleSort2 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugUserFreeLocalPage}{ug06.ht}{Free and Local Variables}
\pageto{notitle}{ugUserCachePage}
\pageto{notitle}{ugUserRecurPage}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserFreeLocalPage}{6.16. Free and Local Variables}
\beginscroll

When you want to refer to a variable that is not local to your
function, use a ``\axiom{free}'' declaration.  \spadkey{free}
Variables declared to be \axiom{free} are assumed to be defined
globally in the workspace.

\labelSpace{1pc}
\xtc{
This is a global workspace variable.
}{
\spadpaste{counter := 0 \bound{counter}}
}
\xtc{
This function refers to the global \axiom{counter}.
}{
\begin{spadsrc}[\free{counter}\bound{f}]
f() ==
  free counter
  counter := counter + 1
\end{spadsrc}
}
\xtc{
The global \axiom{counter} is incremented by \axiom{1}.
}{
\spadpaste{f() \free{f}\bound{f1}}
}
\xtc{
}{
\spadpaste{counter \free{f1}}
}

Usually Axiom can tell that you mean to refer to a global
variable and so \axiom{free} isn't always necessary.
However, for clarity and the sake of self-documentation, we encourage
you to use it.

Declare a variable to be ``\axiom{local}'' when you do not want to refer to
a global variable by the same name.

\xtc{
This function uses \axiom{counter} as a local variable.
}{
\begin{spadsrc}[\bound{g}]
g() ==
  local counter
  counter := 7
\end{spadsrc}
}
\xtc{
Apply the function.
}{
\spadpaste{g() \free{g}}
}
\xtc{
Check that the global value of \axiom{counter} is unchanged.
}{
\spadpaste{counter\free{g f1}}
}

Parameters to a function are local variables in the function.
Even if you issue a \axiom{free} declaration for a parameter, it is
still local.

What happens if you do not declare that a variable \axiom{x} in
the body of your function is \axiom{local} or \axiom{free}?
Well, Axiom decides on this basis:

\indent{4}
\beginitems
\item[1. ] Axiom scans your function line-by-line, from top-to-bottom.
The right-hand side of an assignment is looked at before the left-hand
side.
\item[2. ] If \axiom{x} is referenced before it is assigned a value, 
it is a \axiom{free} (global) variable.
\item[3. ] If \axiom{x} is assigned a value before it is referenced, 
it is a \axiom{local} variable.
\enditems
\indent{0}

\xtc{
Set two global variables to 1.
}{
\spadpaste{a := b := 1\bound{ab1}}
}
\xtc{
Refer to \axiom{a} before it is assigned a value, but
assign a value to \axiom{b} before it is referenced.
}{
\begin{spadsrc}[\bound{hh}]
h() ==
  b := a + 1
  a := b + a
\end{spadsrc}
}
\xtc{
Can you predict this result?
}{
\spadpaste{h() \free{ab1 hh}\bound{hhh}}
}
\xtc{
How about this one?
}{
\spadpaste{[a, b] \free{hhh}}
}

What happened?  In the first line of the function body for \axiom{h},
\axiom{a} is referenced on the right-hand side of the assignment.
Thus \axiom{a} is a free variable.  The variable \axiom{b} is not
referenced in that line, but it is assigned a value.  Thus \axiom{b}
is a local variable and is given the value \axiom{a + 1 = 2}.  In the
second line, the free variable \axiom{a} is assigned the value
\axiom{b + a}which equals \axiom{2 + 1 = 3.}  This is the value
returned by the function.  Since \axiom{a} was free in \userfun{h},
the global variable \axiom{a} has value \axiom{3.}  Since \axiom{b}
was local in \userfun{h}, the global variable \axiom{b} is
unchanged---it still has the value \axiom{1.}

It is good programming practice always to declare global variables.
However, by far the most common situation is to have local variables
in your functions.  No declaration is needed for this situation, but
be sure to initialize their values.

Be careful if you use free variables and you cache the value of
your function (see \downlink{``Caching Previously Computed Results''}
{ugUserCachePage} in Section 6.12\ignore{ugUserCache}).
Caching {\it only} checks if the values of the function arguments
are the same as in a function call previously seen.
It does not check if any of the free variables on which the
function depends have changed between function calls.
\xtc{
Turn on caching for \userfun{p}.
}{
\spadpaste{)set fun cache all p \bound{pcache}}
}
\xtc{
Define \userfun{p} to depend on the free variable \axiom{N}.
}{
\spadpaste{p(i,x) == ( free N; 
reduce( + , [ (x-i)**n for n in 1..N ] ) ) \free{pcache}\bound{pdef}}
}
\xtc{
Set the value of \axiom{N}.
}{
\spadpaste{N := 1 \bound{Nass}}
}
\xtc{
Evaluate \userfun{p} the first time.
}{
\spadpaste{p(0, x) \free{pdef Nass}\bound{pfirst}}
}
\xtc{
Change the value of \axiom{N}.
}{
\spadpaste{N := 2 \bound{Nass2}}
}
\xtc{
Evaluate \userfun{p} the second time.
}{
\spadpaste{p(0, x) \free{pfirst Nass2}}
}
If caching had been turned off, the second evaluation would have
reflected the changed value of \axiom{N}.
\xtc{
Turn off caching for \userfun{p}.
}{
\spadpaste{)set fun cache 0 p}
}

Axiom does not allow {\it fluid variables}, that is, variables
\spadglossSee{bound}{binding} by a function \spad{f} that can be
referenced by functions called by \spad{f}.

Values are passed to functions by \spadgloss{reference}: a pointer
to the value is passed rather than a copy of the value or a pointer to
a copy.

\xtc{
This is a global variable that is bound to a record object.
}{
\spadpaste{r : Record(i : Integer) := [1] \free{r}}
}
\xtc{
This function first modifies the one component of its
record argument and then rebinds the parameter to another
record.
}{
\begin{spadsrc}[\bound{resetRecord}]
resetRecord rr ==
  rr.i := 2
  rr := [10]
\end{spadsrc}
}
\xtc{
Pass \axiom{r} as an argument to \userfun{resetRecord}.
}{
\spadpaste{resetRecord r \free{r resetRecord}\bound{rr}}
}
\xtc{
The value of \axiom{r} was changed by the expression
\axiom{rr.i := 2} but not by \axiom{rr := [10]}.
}{
\spadpaste{r \free{rr}}
}

To conclude this section, we give an iterative definition of
a function that computes Fibonacci numbers.
This definition approximates the definition into which Axiom
transforms the recurrence relation definition of \userfun{fib} in
\downlink{``Recurrence Relations''}{ugUserRecurPage} 
in Section 6.13\ignore{ugUserRecur}.

\xtc{
Global variables
\axiom{past} and \axiom{present} are used
to hold the last computed Fibonacci numbers.
}{
\spadpaste{past := present := 1\bound{f0}}
}
\xtc{
Global variable \axiom{index} gives the
current index of \axiom{present}.
}{
\spadpaste{index := 2\bound{f1}\free{f0}}
}
\xtc{
Here is a recurrence relation defined in terms
of these three global variables.
}{
\begin{spadsrc}[\bound{f3}\free{f2}]
fib(n) ==
  free past, present, index
  n < 3 => 1
  n = index - 1 => past
  if n < index-1 then
    (past,present) := (1,1)
    index := 2
  while (index < n) repeat
    (past,present) := (present, past+present)
    index := index + 1
  present
\end{spadsrc}
}
\xtc{
Compute the infinite stream of Fibonacci numbers.
}{
\spadpaste{fibs := [fib(n) for n in 1..] \bound{fibs}\free{f3}}
}
\xtc{
What is the 1000th Fibonacci number?
}{
\spadpaste{fibs 1000 \free{fibs}}
}

As an exercise, we suggest you write a function in an iterative
style that computes the value of the recurrence relation
\texht{$p(n) = p(n-1) - 2 \, p(n-2) + 4 \, p(n-3)$}
{\axiom{p(n) = p(n-1) - 2*p(n-2) + 4*p(n-3)}}
having the initial values
\texht{$p(1) = 1,\, p(2) = 3 \hbox{ and } p(3) = 9.$}
{\axiom{p(1) = 1, p(2) = 3 {\rm and} p(3) = 9.}}
How would you write the function using an element
\axiomType{OneDimensionalArray} or \axiomType{Vector}
to hold the previously computed values?

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserFreeLocalPagePatch1}
\begin{paste}{ugUserFreeLocalPageFull1}{ugUserFreeLocalPageEmpty1}
\pastebutton{ugUserFreeLocalPageFull1}{\hidepaste}
\tab{5}\spadcommand{counter := 0\bound{counter }}
\indentrel{3}\begin{verbatim}
   (1)  0
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty1}
\begin{paste}{ugUserFreeLocalPageEmpty1}{ugUserFreeLocalPagePatch1}
\pastebutton{ugUserFreeLocalPageEmpty1}{\showpaste}
\tab{5}\spadcommand{counter := 0\bound{counter }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch2}
\begin{paste}{ugUserFreeLocalPageFull2}{ugUserFreeLocalPageEmpty2}
\pastebutton{ugUserFreeLocalPageFull2}{\hidepaste}
\tab{5}\spadcommand{f() ==
  free counter
  counter := counter + 1
\free{counter }\bound{f }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty2}
\begin{paste}{ugUserFreeLocalPageEmpty2}{ugUserFreeLocalPagePatch2}
\pastebutton{ugUserFreeLocalPageEmpty2}{\showpaste}
\tab{5}\spadcommand{f() ==
  free counter
  counter := counter + 1
\free{counter }\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch3}
\begin{paste}{ugUserFreeLocalPageFull3}{ugUserFreeLocalPageEmpty3}
\pastebutton{ugUserFreeLocalPageFull3}{\hidepaste}
\tab{5}\spadcommand{f()\free{f }\bound{f1 }}
\indentrel{3}\begin{verbatim}
   (3)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty3}
\begin{paste}{ugUserFreeLocalPageEmpty3}{ugUserFreeLocalPagePatch3}
\pastebutton{ugUserFreeLocalPageEmpty3}{\showpaste}
\tab{5}\spadcommand{f()\free{f }\bound{f1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch4}
\begin{paste}{ugUserFreeLocalPageFull4}{ugUserFreeLocalPageEmpty4}
\pastebutton{ugUserFreeLocalPageFull4}{\hidepaste}
\tab{5}\spadcommand{counter\free{f1 }}
\indentrel{3}\begin{verbatim}
   (4)  1
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty4}
\begin{paste}{ugUserFreeLocalPageEmpty4}{ugUserFreeLocalPagePatch4}
\pastebutton{ugUserFreeLocalPageEmpty4}{\showpaste}
\tab{5}\spadcommand{counter\free{f1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch5}
\begin{paste}{ugUserFreeLocalPageFull5}{ugUserFreeLocalPageEmpty5}
\pastebutton{ugUserFreeLocalPageFull5}{\hidepaste}
\tab{5}\spadcommand{g() ==
  local counter
  counter := 7
\bound{g }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty5}
\begin{paste}{ugUserFreeLocalPageEmpty5}{ugUserFreeLocalPagePatch5}
\pastebutton{ugUserFreeLocalPageEmpty5}{\showpaste}
\tab{5}\spadcommand{g() ==
  local counter
  counter := 7
\bound{g }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch6}
\begin{paste}{ugUserFreeLocalPageFull6}{ugUserFreeLocalPageEmpty6}
\pastebutton{ugUserFreeLocalPageFull6}{\hidepaste}
\tab{5}\spadcommand{g()\free{g }}
\indentrel{3}\begin{verbatim}
   (6)  7
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty6}
\begin{paste}{ugUserFreeLocalPageEmpty6}{ugUserFreeLocalPagePatch6}
\pastebutton{ugUserFreeLocalPageEmpty6}{\showpaste}
\tab{5}\spadcommand{g()\free{g }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch7}
\begin{paste}{ugUserFreeLocalPageFull7}{ugUserFreeLocalPageEmpty7}
\pastebutton{ugUserFreeLocalPageFull7}{\hidepaste}
\tab{5}\spadcommand{counter\free{g f1 }}
\indentrel{3}\begin{verbatim}
   (7)  1
                               Type: NonNegativeInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty7}
\begin{paste}{ugUserFreeLocalPageEmpty7}{ugUserFreeLocalPagePatch7}
\pastebutton{ugUserFreeLocalPageEmpty7}{\showpaste}
\tab{5}\spadcommand{counter\free{g f1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch8}
\begin{paste}{ugUserFreeLocalPageFull8}{ugUserFreeLocalPageEmpty8}
\pastebutton{ugUserFreeLocalPageFull8}{\hidepaste}
\tab{5}\spadcommand{a := b := 1\bound{ab1 }}
\indentrel{3}\begin{verbatim}
   (8)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty8}
\begin{paste}{ugUserFreeLocalPageEmpty8}{ugUserFreeLocalPagePatch8}
\pastebutton{ugUserFreeLocalPageEmpty8}{\showpaste}
\tab{5}\spadcommand{a := b := 1\bound{ab1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch9}
\begin{paste}{ugUserFreeLocalPageFull9}{ugUserFreeLocalPageEmpty9}
\pastebutton{ugUserFreeLocalPageFull9}{\hidepaste}
\tab{5}\spadcommand{h() ==
  b := a + 1
  a := b + a
\bound{hh }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty9}
\begin{paste}{ugUserFreeLocalPageEmpty9}{ugUserFreeLocalPagePatch9}
\pastebutton{ugUserFreeLocalPageEmpty9}{\showpaste}
\tab{5}\spadcommand{h() ==
  b := a + 1
  a := b + a
\bound{hh }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch10}
\begin{paste}{ugUserFreeLocalPageFull10}{ugUserFreeLocalPageEmpty10}
\pastebutton{ugUserFreeLocalPageFull10}{\hidepaste}
\tab{5}\spadcommand{h()\free{ab1 hh }\bound{hhh }}
\indentrel{3}\begin{verbatim}
   (10)  3
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty10}
\begin{paste}{ugUserFreeLocalPageEmpty10}{ugUserFreeLocalPagePatch10}
\pastebutton{ugUserFreeLocalPageEmpty10}{\showpaste}
\tab{5}\spadcommand{h()\free{ab1 hh }\bound{hhh }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch11}
\begin{paste}{ugUserFreeLocalPageFull11}{ugUserFreeLocalPageEmpty11}
\pastebutton{ugUserFreeLocalPageFull11}{\hidepaste}
\tab{5}\spadcommand{[a, b]\free{hhh }}
\indentrel{3}\begin{verbatim}
   (11)  [3,1]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty11}
\begin{paste}{ugUserFreeLocalPageEmpty11}{ugUserFreeLocalPagePatch11}
\pastebutton{ugUserFreeLocalPageEmpty11}{\showpaste}
\tab{5}\spadcommand{[a, b]\free{hhh }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch12}
\begin{paste}{ugUserFreeLocalPageFull12}{ugUserFreeLocalPageEmpty12}
\pastebutton{ugUserFreeLocalPageFull12}{\hidepaste}
\tab{5}\spadcommand{)set fun cache all p\bound{pcache }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty12}
\begin{paste}{ugUserFreeLocalPageEmpty12}{ugUserFreeLocalPagePatch12}
\pastebutton{ugUserFreeLocalPageEmpty12}{\showpaste}
\tab{5}\spadcommand{)set fun cache all p\bound{pcache }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch13}
\begin{paste}{ugUserFreeLocalPageFull13}{ugUserFreeLocalPageEmpty13}
\pastebutton{ugUserFreeLocalPageFull13}{\hidepaste}
\tab{5}\spadcommand{p(i,x) == ( free N; reduce( + , [ (x-i)**n for n in 1..N ] ) )\free{pcache }\bound{pdef }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty13}
\begin{paste}{ugUserFreeLocalPageEmpty13}{ugUserFreeLocalPagePatch13}
\pastebutton{ugUserFreeLocalPageEmpty13}{\showpaste}
\tab{5}\spadcommand{p(i,x) == ( free N; reduce( + , [ (x-i)**n for n in 1..N ] ) )\free{pcache }\bound{pdef }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch14}
\begin{paste}{ugUserFreeLocalPageFull14}{ugUserFreeLocalPageEmpty14}
\pastebutton{ugUserFreeLocalPageFull14}{\hidepaste}
\tab{5}\spadcommand{N := 1\bound{Nass }}
\indentrel{3}\begin{verbatim}
   (13)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty14}
\begin{paste}{ugUserFreeLocalPageEmpty14}{ugUserFreeLocalPagePatch14}
\pastebutton{ugUserFreeLocalPageEmpty14}{\showpaste}
\tab{5}\spadcommand{N := 1\bound{Nass }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch15}
\begin{paste}{ugUserFreeLocalPageFull15}{ugUserFreeLocalPageEmpty15}
\pastebutton{ugUserFreeLocalPageFull15}{\hidepaste}
\tab{5}\spadcommand{p(0, x)\free{pdef Nass }\bound{pfirst }}
\indentrel{3}\begin{verbatim}
   (14)  x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty15}
\begin{paste}{ugUserFreeLocalPageEmpty15}{ugUserFreeLocalPagePatch15}
\pastebutton{ugUserFreeLocalPageEmpty15}{\showpaste}
\tab{5}\spadcommand{p(0, x)\free{pdef Nass }\bound{pfirst }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch16}
\begin{paste}{ugUserFreeLocalPageFull16}{ugUserFreeLocalPageEmpty16}
\pastebutton{ugUserFreeLocalPageFull16}{\hidepaste}
\tab{5}\spadcommand{N := 2\bound{Nass2 }}
\indentrel{3}\begin{verbatim}
   (15)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty16}
\begin{paste}{ugUserFreeLocalPageEmpty16}{ugUserFreeLocalPagePatch16}
\pastebutton{ugUserFreeLocalPageEmpty16}{\showpaste}
\tab{5}\spadcommand{N := 2\bound{Nass2 }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch17}
\begin{paste}{ugUserFreeLocalPageFull17}{ugUserFreeLocalPageEmpty17}
\pastebutton{ugUserFreeLocalPageFull17}{\hidepaste}
\tab{5}\spadcommand{p(0, x)\free{pfirst Nass2 }}
\indentrel{3}\begin{verbatim}
   (16)  x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty17}
\begin{paste}{ugUserFreeLocalPageEmpty17}{ugUserFreeLocalPagePatch17}
\pastebutton{ugUserFreeLocalPageEmpty17}{\showpaste}
\tab{5}\spadcommand{p(0, x)\free{pfirst Nass2 }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch18}
\begin{paste}{ugUserFreeLocalPageFull18}{ugUserFreeLocalPageEmpty18}
\pastebutton{ugUserFreeLocalPageFull18}{\hidepaste}
\tab{5}\spadcommand{)set fun cache 0 p}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty18}
\begin{paste}{ugUserFreeLocalPageEmpty18}{ugUserFreeLocalPagePatch18}
\pastebutton{ugUserFreeLocalPageEmpty18}{\showpaste}
\tab{5}\spadcommand{)set fun cache 0 p}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch19}
\begin{paste}{ugUserFreeLocalPageFull19}{ugUserFreeLocalPageEmpty19}
\pastebutton{ugUserFreeLocalPageFull19}{\hidepaste}
\tab{5}\spadcommand{r : Record(i : Integer) := [1]\free{r }}
\indentrel{3}\begin{verbatim}
   (17)  [i= 1]
                               Type: Record(i: Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty19}
\begin{paste}{ugUserFreeLocalPageEmpty19}{ugUserFreeLocalPagePatch19}
\pastebutton{ugUserFreeLocalPageEmpty19}{\showpaste}
\tab{5}\spadcommand{r : Record(i : Integer) := [1]\free{r }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch20}
\begin{paste}{ugUserFreeLocalPageFull20}{ugUserFreeLocalPageEmpty20}
\pastebutton{ugUserFreeLocalPageFull20}{\hidepaste}
\tab{5}\spadcommand{resetRecord rr ==
  rr.i := 2
  rr := [10]
\bound{resetRecord }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty20}
\begin{paste}{ugUserFreeLocalPageEmpty20}{ugUserFreeLocalPagePatch20}
\pastebutton{ugUserFreeLocalPageEmpty20}{\showpaste}
\tab{5}\spadcommand{resetRecord rr ==
  rr.i := 2
  rr := [10]
\bound{resetRecord }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch21}
\begin{paste}{ugUserFreeLocalPageFull21}{ugUserFreeLocalPageEmpty21}
\pastebutton{ugUserFreeLocalPageFull21}{\hidepaste}
\tab{5}\spadcommand{resetRecord r\free{r resetRecord }\bound{rr }}
\indentrel{3}\begin{verbatim}
   (19)  [i= 10]
                               Type: Record(i: Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty21}
\begin{paste}{ugUserFreeLocalPageEmpty21}{ugUserFreeLocalPagePatch21}
\pastebutton{ugUserFreeLocalPageEmpty21}{\showpaste}
\tab{5}\spadcommand{resetRecord r\free{r resetRecord }\bound{rr }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch22}
\begin{paste}{ugUserFreeLocalPageFull22}{ugUserFreeLocalPageEmpty22}
\pastebutton{ugUserFreeLocalPageFull22}{\hidepaste}
\tab{5}\spadcommand{r\free{rr }}
\indentrel{3}\begin{verbatim}
   (20)  [i= 2]
                               Type: Record(i: Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty22}
\begin{paste}{ugUserFreeLocalPageEmpty22}{ugUserFreeLocalPagePatch22}
\pastebutton{ugUserFreeLocalPageEmpty22}{\showpaste}
\tab{5}\spadcommand{r\free{rr }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch23}
\begin{paste}{ugUserFreeLocalPageFull23}{ugUserFreeLocalPageEmpty23}
\pastebutton{ugUserFreeLocalPageFull23}{\hidepaste}
\tab{5}\spadcommand{past := present := 1\bound{f0 }}
\indentrel{3}\begin{verbatim}
   (21)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty23}
\begin{paste}{ugUserFreeLocalPageEmpty23}{ugUserFreeLocalPagePatch23}
\pastebutton{ugUserFreeLocalPageEmpty23}{\showpaste}
\tab{5}\spadcommand{past := present := 1\bound{f0 }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch24}
\begin{paste}{ugUserFreeLocalPageFull24}{ugUserFreeLocalPageEmpty24}
\pastebutton{ugUserFreeLocalPageFull24}{\hidepaste}
\tab{5}\spadcommand{index := 2\bound{f1 }\free{f0 }}
\indentrel{3}\begin{verbatim}
   (22)  2
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty24}
\begin{paste}{ugUserFreeLocalPageEmpty24}{ugUserFreeLocalPagePatch24}
\pastebutton{ugUserFreeLocalPageEmpty24}{\showpaste}
\tab{5}\spadcommand{index := 2\bound{f1 }\free{f0 }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch25}
\begin{paste}{ugUserFreeLocalPageFull25}{ugUserFreeLocalPageEmpty25}
\pastebutton{ugUserFreeLocalPageFull25}{\hidepaste}
\tab{5}\spadcommand{fib(n) ==
  free past, present, index
  n < 3 => 1
  n = index - 1 => past
  if n < index-1 then
    (past,present) := (1,1)
    index := 2
  while (index < n) repeat
    (past,present) := (present, past+present)
    index := index + 1
  present
\bound{f3 }\free{f2 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty25}
\begin{paste}{ugUserFreeLocalPageEmpty25}{ugUserFreeLocalPagePatch25}
\pastebutton{ugUserFreeLocalPageEmpty25}{\showpaste}
\tab{5}\spadcommand{fib(n) ==
  free past, present, index
  n < 3 => 1
  n = index - 1 => past
  if n < index-1 then
    (past,present) := (1,1)
    index := 2
  while (index < n) repeat
    (past,present) := (present, past+present)
    index := index + 1
  present
\bound{f3 }\free{f2 }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch26}
\begin{paste}{ugUserFreeLocalPageFull26}{ugUserFreeLocalPageEmpty26}
\pastebutton{ugUserFreeLocalPageFull26}{\hidepaste}
\tab{5}\spadcommand{fibs := [fib(n) for n in 1..]\bound{fibs }\free{f3 }}
\indentrel{3}\begin{verbatim}
   (24)  [1,1,2,3,5,8,13,21,34,55,...]
                           Type: Stream PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty26}
\begin{paste}{ugUserFreeLocalPageEmpty26}{ugUserFreeLocalPagePatch26}
\pastebutton{ugUserFreeLocalPageEmpty26}{\showpaste}
\tab{5}\spadcommand{fibs := [fib(n) for n in 1..]\bound{fibs }\free{f3 }}
\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPagePatch27}
\begin{paste}{ugUserFreeLocalPageFull27}{ugUserFreeLocalPageEmpty27}
\pastebutton{ugUserFreeLocalPageFull27}{\hidepaste}
\tab{5}\spadcommand{fibs 1000\free{fibs }}
\indentrel{3}\begin{verbatim}
   (25)
  434665576869374564356885276750406258025646605173717804_
   02481729089536555417949051890403879840079255169295922_
   59308032263477520968962323987332247116164299644090653_
   3187938298969649928516003704476137795166849228875
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserFreeLocalPageEmpty27}
\begin{paste}{ugUserFreeLocalPageEmpty27}{ugUserFreeLocalPagePatch27}
\pastebutton{ugUserFreeLocalPageEmpty27}{\showpaste}
\tab{5}\spadcommand{fibs 1000\free{fibs }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugUserAnonPage}{ug06.ht}{Anonymous Functions}
\pageto{notitle}{ugUserAnonExampPage}
\pageto{notitle}{ugUserAnonDeclarePage}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserAnonPage}{6.17. Anonymous Functions}
\beginscroll

\beginImportant
An {\it anonymous function} is a function that is
defined
by giving a list of parameters, the ``maps-to'' compound
symbol \axiomSyntax{+->} \texht{(from the mathematical symbol
$\mapsto$)}{},
and by an expression involving the parameters, the evaluation of
which determines the return value of the function.

\centerline{{{\tt ( \subscriptIt{parm}{1}, \subscriptIt{parm}{2}, 
\ldots, \subscriptIt{parm}{N} ) +-> {\it expression}}}}
\endImportant

You can apply an anonymous function in several ways.
\indent{4}
\beginitems
\item[1. ] Place the anonymous function definition in parentheses
directly followed by a list of arguments.
\item[2. ] Assign the anonymous function to a variable and then
use the variable name when you would normally use a function name.
\item[3. ] Use \axiomSyntax{==} to use the anonymous function 
definition as the arguments and body of a regular function definition.
\item[4. ] Have a named function contain a declared anonymous function 
and use the result returned by the named function.
\enditems
\indent{0}

\beginmenu
    \menudownlink{{6.17.1. Some Examples}}{ugUserAnonExampPage}
    \menudownlink{{6.17.2. Declaring Anonymous Functions}}
{ugUserAnonDeclarePage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugUserAnonExampPage}{ug06.ht}{Some Examples}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserAnonExampPage}{6.17.1. Some Examples}
\beginscroll

Anonymous functions are particularly useful for defining functions
``on the fly.'' That is, they are handy for simple functions that
are used only in one place.
In the following examples, we show how to write some simple
anonymous functions.

\xtc{
This is a simple absolute value function.
}{
\spadpaste{x +-> if x < 0 then -x else x \bound{anon0}}
}
\xtc{
}{
\spadpaste{abs1 := \% \free{anon0}\bound{abs1}}
}
\xtc{
This function returns {\tt true} if the absolute value of
the first argument is greater than the absolute value of the
second, {\tt false} otherwise.
}{
\spadpaste{(x,y) +-> abs1(x) > abs1(y) \bound{anon1}\free{abs1}}
}
\xtc{
We use the above function to ``sort'' a list of integers.
}{
\spadpaste{sort(\%,[3,9,-4,10,-3,-1,-9,5]) \free{anon1}}
}

\xtc{
This function returns \axiom{1} if \axiom{i + j} is even, 
\axiom{-1} otherwise.
}{
\spadpaste{ev := ( (i,j) +-> if even?(i+j) then 1 else -1) \bound{ev}}
}
\xtc{
We create a four-by-four matrix containing \axiom{1} or \axiom{-1}
depending on whether the row plus the column index is even or not.
}{
\spadpaste{matrix([[ev(row,col) for row in 1..4] for col in 1..4]) \free{ev}}
}

\xtc{
This function returns {\tt true} if a polynomial in \axiom{x} has multiple
roots, {\tt false} otherwise.
It is defined and applied in the same expression.
}{
\spadpaste{( p +-> not one?(gcd(p,D(p,x))) )(x**2+4*x+4)}
}

\xtc{
This and the next expression are equivalent.
}{
\spadpaste{g(x,y,z) == cos(x + sin(y + tan(z)))}
}
\xtc{
The one you use is a matter of taste.
}{
\spadpaste{g == (x,y,z) +-> cos(x + sin(y + tan(z)))}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserAnonExampPagePatch1}
\begin{paste}{ugUserAnonExampPageFull1}{ugUserAnonExampPageEmpty1}
\pastebutton{ugUserAnonExampPageFull1}{\hidepaste}
\tab{5}\spadcommand{x +-> if x < 0 then -x else x\bound{anon0 }}
\indentrel{3}\begin{verbatim}
   (1)
     x
   +-> 
     if x < 0
       then - x
       else x
                                Type: AnonymousFunction
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserAnonExampPageEmpty1}
\begin{paste}{ugUserAnonExampPageEmpty1}{ugUserAnonExampPagePatch1}
\pastebutton{ugUserAnonExampPageEmpty1}{\showpaste}
\tab{5}\spadcommand{x +-> if x < 0 then -x else x\bound{anon0 }}
\end{paste}\end{patch}

\begin{patch}{ugUserAnonExampPagePatch2}
\begin{paste}{ugUserAnonExampPageFull2}{ugUserAnonExampPageEmpty2}
\pastebutton{ugUserAnonExampPageFull2}{\hidepaste}
\tab{5}\spadcommand{abs1 := \%\free{anon0 }\bound{abs1 }}
\indentrel{3}\begin{verbatim}
   (2)
     x
   +-> 
     if x < 0
       then - x
       else x
                                Type: AnonymousFunction
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserAnonExampPageEmpty2}
\begin{paste}{ugUserAnonExampPageEmpty2}{ugUserAnonExampPagePatch2}
\pastebutton{ugUserAnonExampPageEmpty2}{\showpaste}
\tab{5}\spadcommand{abs1 := \%\free{anon0 }\bound{abs1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserAnonExampPagePatch3}
\begin{paste}{ugUserAnonExampPageFull3}{ugUserAnonExampPageEmpty3}
\pastebutton{ugUserAnonExampPageFull3}{\hidepaste}
\tab{5}\spadcommand{(x,y) +-> abs1(x) > abs1(y)\bound{anon1 }\free{abs1 }}
\indentrel{3}\begin{verbatim}
   (3)  (x,y) +-> abs1(y) < abs1(x)
                                Type: AnonymousFunction
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserAnonExampPageEmpty3}
\begin{paste}{ugUserAnonExampPageEmpty3}{ugUserAnonExampPagePatch3}
\pastebutton{ugUserAnonExampPageEmpty3}{\showpaste}
\tab{5}\spadcommand{(x,y) +-> abs1(x) > abs1(y)\bound{anon1 }\free{abs1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserAnonExampPagePatch4}
\begin{paste}{ugUserAnonExampPageFull4}{ugUserAnonExampPageEmpty4}
\pastebutton{ugUserAnonExampPageFull4}{\hidepaste}
\tab{5}\spadcommand{sort(\%,[3,9,-4,10,-3,-1,-9,5])\free{anon1 }}
\indentrel{3}\begin{verbatim}
   (4)  [10,- 9,9,5,- 4,- 3,3,- 1]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserAnonExampPageEmpty4}
\begin{paste}{ugUserAnonExampPageEmpty4}{ugUserAnonExampPagePatch4}
\pastebutton{ugUserAnonExampPageEmpty4}{\showpaste}
\tab{5}\spadcommand{sort(\%,[3,9,-4,10,-3,-1,-9,5])\free{anon1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserAnonExampPagePatch5}
\begin{paste}{ugUserAnonExampPageFull5}{ugUserAnonExampPageEmpty5}
\pastebutton{ugUserAnonExampPageFull5}{\hidepaste}
\tab{5}\spadcommand{ev := ( (i,j) +-> if even?(i+j) then 1 else -1)\bound{ev }}
\indentrel{3}\begin{verbatim}
   (5)
     (i,j)
   +-> 
     if even?(i + j)
       then 1
       else - 1
                                Type: AnonymousFunction
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserAnonExampPageEmpty5}
\begin{paste}{ugUserAnonExampPageEmpty5}{ugUserAnonExampPagePatch5}
\pastebutton{ugUserAnonExampPageEmpty5}{\showpaste}
\tab{5}\spadcommand{ev := ( (i,j) +-> if even?(i+j) then 1 else -1)\bound{ev }}
\end{paste}\end{patch}

\begin{patch}{ugUserAnonExampPagePatch6}
\begin{paste}{ugUserAnonExampPageFull6}{ugUserAnonExampPageEmpty6}
\pastebutton{ugUserAnonExampPageFull6}{\hidepaste}
\tab{5}\spadcommand{matrix([[ev(row,col) for row in 1..4] for col in 1..4])\free{ev }}
\indentrel{3}\begin{verbatim}
        Ú 1   - 1   1   - 1¿
        ³                  ³
        ³- 1   1   - 1   1 ³
   (6)  ³                  ³
        ³ 1   - 1   1   - 1³
        ³                  ³
        À- 1   1   - 1   1 Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserAnonExampPageEmpty6}
\begin{paste}{ugUserAnonExampPageEmpty6}{ugUserAnonExampPagePatch6}
\pastebutton{ugUserAnonExampPageEmpty6}{\showpaste}
\tab{5}\spadcommand{matrix([[ev(row,col) for row in 1..4] for col in 1..4])\free{ev }}
\end{paste}\end{patch}

\begin{patch}{ugUserAnonExampPagePatch7}
\begin{paste}{ugUserAnonExampPageFull7}{ugUserAnonExampPageEmpty7}
\pastebutton{ugUserAnonExampPageFull7}{\hidepaste}
\tab{5}\spadcommand{( p +-> not one?(gcd(p,D(p,x))) )(x**2+4*x+4)}
\indentrel{3}\begin{verbatim}
   (7)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserAnonExampPageEmpty7}
\begin{paste}{ugUserAnonExampPageEmpty7}{ugUserAnonExampPagePatch7}
\pastebutton{ugUserAnonExampPageEmpty7}{\showpaste}
\tab{5}\spadcommand{( p +-> not one?(gcd(p,D(p,x))) )(x**2+4*x+4)}
\end{paste}\end{patch}

\begin{patch}{ugUserAnonExampPagePatch8}
\begin{paste}{ugUserAnonExampPageFull8}{ugUserAnonExampPageEmpty8}
\pastebutton{ugUserAnonExampPageFull8}{\hidepaste}
\tab{5}\spadcommand{g(x,y,z) == cos(x + sin(y + tan(z)))}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserAnonExampPageEmpty8}
\begin{paste}{ugUserAnonExampPageEmpty8}{ugUserAnonExampPagePatch8}
\pastebutton{ugUserAnonExampPageEmpty8}{\showpaste}
\tab{5}\spadcommand{g(x,y,z) == cos(x + sin(y + tan(z)))}
\end{paste}\end{patch}

\begin{patch}{ugUserAnonExampPagePatch9}
\begin{paste}{ugUserAnonExampPageFull9}{ugUserAnonExampPageEmpty9}
\pastebutton{ugUserAnonExampPageFull9}{\hidepaste}
\tab{5}\spadcommand{g == (x,y,z) +-> cos(x + sin(y + tan(z)))}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserAnonExampPageEmpty9}
\begin{paste}{ugUserAnonExampPageEmpty9}{ugUserAnonExampPagePatch9}
\pastebutton{ugUserAnonExampPageEmpty9}{\showpaste}
\tab{5}\spadcommand{g == (x,y,z) +-> cos(x + sin(y + tan(z)))}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugUserAnonDeclarePage}{ug06.ht}{Declaring Anonymous Functions}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserAnonDeclarePage}{6.17.2. Declaring Anonymous Functions}
\beginscroll

If you declare any of the arguments you must declare all of them.
Thus,
\begin{verbatim}
(x: INT,y): FRAC INT +-> (x + 2*y)/(y - 1)
\end{verbatim}
is not legal.

\xtc{
This is an example of a fully declared anonymous
function.
The output shown just indicates that the object you created is a
particular kind of map, that is, function.
}{
\spadpaste{(x: INT,y: INT): FRAC INT +-> (x + 2*y)/(y - 1)}
}
\xtc{
Axiom allows you to declare the arguments and not declare
the return type.
}{
\spadpaste{(x: INT,y: INT) +-> (x + 2*y)/(y - 1)}
}
The return type is computed from the types of the arguments and the
body of the function.
You cannot declare the return type if you do not declare the arguments.
Therefore,
\begin{verbatim}
(x,y): FRAC INT +-> (x + 2*y)/(y - 1)
\end{verbatim}
is not legal.

\xtc{
This and the next expression are equivalent.
}{
\spadpaste{h(x: INT,y: INT): FRAC INT == (x + 2*y)/(y - 1)}
}
\xtc{
The one you use is a matter of taste.
}{
\spadpaste{h == (x: INT,y: INT): FRAC INT +-> (x + 2*y)/(y - 1)}
}

When should you declare an anonymous function?
\indent{4}
\beginitems
\item[1. ] If you use an anonymous function and Axiom can't figure
out what you are trying to do, declare the function.
\item[2. ] If the function has nontrivial argument types or a
nontrivial return type that
Axiom may be able to determine eventually, but you are not
willing to wait that long, declare the function.
\item[3. ] If the function will only be used for arguments of specific
types and it is not too much trouble to declare the function, do so.
\item[4. ] If you are using the anonymous function as an argument to
another function (such as \axiomFun{map} or \axiomFun{sort}),
consider declaring the function.
\item[5. ] If you define an anonymous function inside a named function,
you {\it must} declare the anonymous function.
\enditems
\indent{0}

\xtc{
This is an example of a named function for integers that returns a
function.
}{
\spadpaste{addx x == ((y: Integer): Integer +-> x + y) \bound{addx}}
}
\xtc{
We define \userfun{g} to be a function that adds \axiom{10} to its
argument.
}{
\spadpaste{g := addx 10 \free{addx}\bound{g}}
}
\xtc{
Try it out.
}{
\spadpaste{g 3 \free{g}}
}
\xtc{
}{
\spadpaste{g(-4) \free{g}}
}

An anonymous function cannot be recursive: since it does not have a
name, you cannot even call it within itself!
If you place an anonymous function inside a named function, the
anonymous function must be declared.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserAnonDeclarePagePatch1}
\begin{paste}{ugUserAnonDeclarePageFull1}{ugUserAnonDeclarePageEmpty1}
\pastebutton{ugUserAnonDeclarePageFull1}{\hidepaste}
\tab{5}\spadcommand{(x: INT,y: INT): FRAC INT +-> (x + 2*y)/(y - 1)}
\indentrel{3}\begin{verbatim}
   (1)  theMap(NIL)
          Type: ((Integer,Integer) -> Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserAnonDeclarePageEmpty1}
\begin{paste}{ugUserAnonDeclarePageEmpty1}{ugUserAnonDeclarePagePatch1}
\pastebutton{ugUserAnonDeclarePageEmpty1}{\showpaste}
\tab{5}\spadcommand{(x: INT,y: INT): FRAC INT +-> (x + 2*y)/(y - 1)}
\end{paste}\end{patch}

\begin{patch}{ugUserAnonDeclarePagePatch2}
\begin{paste}{ugUserAnonDeclarePageFull2}{ugUserAnonDeclarePageEmpty2}
\pastebutton{ugUserAnonDeclarePageFull2}{\hidepaste}
\tab{5}\spadcommand{(x: INT,y: INT) +-> (x + 2*y)/(y - 1)}
\indentrel{3}\begin{verbatim}
   (2)  theMap(NIL)
          Type: ((Integer,Integer) -> Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserAnonDeclarePageEmpty2}
\begin{paste}{ugUserAnonDeclarePageEmpty2}{ugUserAnonDeclarePagePatch2}
\pastebutton{ugUserAnonDeclarePageEmpty2}{\showpaste}
\tab{5}\spadcommand{(x: INT,y: INT) +-> (x + 2*y)/(y - 1)}
\end{paste}\end{patch}

\begin{patch}{ugUserAnonDeclarePagePatch3}
\begin{paste}{ugUserAnonDeclarePageFull3}{ugUserAnonDeclarePageEmpty3}
\pastebutton{ugUserAnonDeclarePageFull3}{\hidepaste}
\tab{5}\spadcommand{h(x: INT,y: INT): FRAC INT == (x + 2*y)/(y - 1)}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserAnonDeclarePageEmpty3}
\begin{paste}{ugUserAnonDeclarePageEmpty3}{ugUserAnonDeclarePagePatch3}
\pastebutton{ugUserAnonDeclarePageEmpty3}{\showpaste}
\tab{5}\spadcommand{h(x: INT,y: INT): FRAC INT == (x + 2*y)/(y - 1)}
\end{paste}\end{patch}

\begin{patch}{ugUserAnonDeclarePagePatch4}
\begin{paste}{ugUserAnonDeclarePageFull4}{ugUserAnonDeclarePageEmpty4}
\pastebutton{ugUserAnonDeclarePageFull4}{\hidepaste}
\tab{5}\spadcommand{h == (x: INT,y: INT): FRAC INT +-> (x + 2*y)/(y - 1)}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserAnonDeclarePageEmpty4}
\begin{paste}{ugUserAnonDeclarePageEmpty4}{ugUserAnonDeclarePagePatch4}
\pastebutton{ugUserAnonDeclarePageEmpty4}{\showpaste}
\tab{5}\spadcommand{h == (x: INT,y: INT): FRAC INT +-> (x + 2*y)/(y - 1)}
\end{paste}\end{patch}

\begin{patch}{ugUserAnonDeclarePagePatch5}
\begin{paste}{ugUserAnonDeclarePageFull5}{ugUserAnonDeclarePageEmpty5}
\pastebutton{ugUserAnonDeclarePageFull5}{\hidepaste}
\tab{5}\spadcommand{addx x == ((y: Integer): Integer +-> x + y)\bound{addx }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserAnonDeclarePageEmpty5}
\begin{paste}{ugUserAnonDeclarePageEmpty5}{ugUserAnonDeclarePagePatch5}
\pastebutton{ugUserAnonDeclarePageEmpty5}{\showpaste}
\tab{5}\spadcommand{addx x == ((y: Integer): Integer +-> x + y)\bound{addx }}
\end{paste}\end{patch}

\begin{patch}{ugUserAnonDeclarePagePatch6}
\begin{paste}{ugUserAnonDeclarePageFull6}{ugUserAnonDeclarePageEmpty6}
\pastebutton{ugUserAnonDeclarePageFull6}{\hidepaste}
\tab{5}\spadcommand{g := addx 10\free{addx }\bound{g }}
\indentrel{3}\begin{verbatim}
   (6)  theMap(LAMBDA_f647nv_704,826)
                             Type: (Integer -> Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserAnonDeclarePageEmpty6}
\begin{paste}{ugUserAnonDeclarePageEmpty6}{ugUserAnonDeclarePagePatch6}
\pastebutton{ugUserAnonDeclarePageEmpty6}{\showpaste}
\tab{5}\spadcommand{g := addx 10\free{addx }\bound{g }}
\end{paste}\end{patch}

\begin{patch}{ugUserAnonDeclarePagePatch7}
\begin{paste}{ugUserAnonDeclarePageFull7}{ugUserAnonDeclarePageEmpty7}
\pastebutton{ugUserAnonDeclarePageFull7}{\hidepaste}
\tab{5}\spadcommand{g 3\free{g }}
\indentrel{3}\begin{verbatim}
   (7)  13
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserAnonDeclarePageEmpty7}
\begin{paste}{ugUserAnonDeclarePageEmpty7}{ugUserAnonDeclarePagePatch7}
\pastebutton{ugUserAnonDeclarePageEmpty7}{\showpaste}
\tab{5}\spadcommand{g 3\free{g }}
\end{paste}\end{patch}

\begin{patch}{ugUserAnonDeclarePagePatch8}
\begin{paste}{ugUserAnonDeclarePageFull8}{ugUserAnonDeclarePageEmpty8}
\pastebutton{ugUserAnonDeclarePageFull8}{\hidepaste}
\tab{5}\spadcommand{g(-4)\free{g }}
\indentrel{3}\begin{verbatim}
   (8)  6
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserAnonDeclarePageEmpty8}
\begin{paste}{ugUserAnonDeclarePageEmpty8}{ugUserAnonDeclarePagePatch8}
\pastebutton{ugUserAnonDeclarePageEmpty8}{\showpaste}
\tab{5}\spadcommand{g(-4)\free{g }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugUserDatabasePage}{ug06.ht}{Example: A Database}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserDatabasePage}{6.18. Example: A Database}
\beginscroll

This example shows how you can use Axiom to organize a database of
lineage data and then query the database for relationships.

\labelSpace{1.5pc}
\xtc{
The database is entered as ``assertions'' that are really
pieces of a function definition.
}{
\spadpaste{children("albert") == ["albertJr","richard","diane"]\bound{d1}}
}
\xtc{
Each piece
\axiom{children(x) == y} means
``the children of \axiom{x} are \axiom{y}''.
}{
\spadpaste{children("richard") == ["douglas","daniel","susan"]
\free{d1}\bound{d2}}
}
\xtc{
This family tree thus spans four generations.
}{
\spadpaste{children("douglas") == ["dougie","valerie"]\free{d2}\bound{d3}}
}
\xtc{
Say ``no one else has children.''
}{
\spadpaste{children(x) == []\free{d3}\bound{d4}}
}

\xtc{
We need some functions for computing lineage.
Start with \axiom{childOf}.
}{
\spadpaste{childOf(x,y) == member?(x,children(y))\bound{d9}\free{d10}}
}
\xtc{
To find the \axiom{parentOf} someone,
you have to scan the database of
people applying \axiom{children}.
}{
\begin{spadsrc}[\bound{d8a}\free{d9}]
parentOf(x) ==
  for y in people repeat
    (if childOf(x,y) then return y)
  "unknown"
\end{spadsrc}
}
\xtc{
And a grandparent of \axiom{x} is just a parent of a parent of \axiom{x}.
}{
\spadpaste{grandParentOf(x) == parentOf parentOf x\bound{d8}\free{d8a}}
}
\xtc{
The grandchildren of \axiom{x}
are the people \axiom{y} such that
\axiom{x} is a grandparent of \axiom{y}.
}{
\spadpaste{grandchildren(x) == [y for y in people | grandParentOf(y) = x]
\free{d7}\bound{d8}}
}
\xtc{
Suppose you want to make a list of all great-grandparents.
Well, a great-grandparent is a grandparent of a person who has children.
}{
\begin{spadsrc}[\free{d6}\bound{d7}]
greatGrandParents == [x for x in people |
  reduce(_or,[not empty? children(y) for y in grandchildren(x)],false)]
\end{spadsrc}
}
\xtc{
Define \axiom{descendants} to include the parent as well.
}{
\begin{spadsrc}[\free{d5}\bound{d6}]
descendants(x) ==
  kids := children(x)
  null kids => [x]
  concat(x,reduce(concat,[descendants(y)
    for y in kids],[]))
\end{spadsrc}
}
\xtc{
Finally, we need a list of people.
Since all people are descendants of ``albert'', let's say so.
}{
\spadpaste{people == descendants "albert"\free{d4}\bound{d5}}
}

We have used \axiomSyntax{==} to define the database and some functions to
query the database.
But no computation is done until we ask for some information.
Then, once and for all, the functions are analyzed and compiled to machine
code for run-time efficiency.
Notice that no types are given anywhere in this example.
They are not needed.

\xtc{
Who are the grandchildren of ``richard''?
}{
\spadpaste{grandchildren "richard"\bound{d10}\free{d11}}
}
\xtc{
Who are the great-grandparents?
}{
\spadpaste{greatGrandParents\bound{d11}\free{d12}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserDatabasePagePatch1}
\begin{paste}{ugUserDatabasePageFull1}{ugUserDatabasePageEmpty1}
\pastebutton{ugUserDatabasePageFull1}{\hidepaste}
\tab{5}\spadcommand{children("albert") == ["albertJr","richard","diane"]\bound{d1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePageEmpty1}
\begin{paste}{ugUserDatabasePageEmpty1}{ugUserDatabasePagePatch1}
\pastebutton{ugUserDatabasePageEmpty1}{\showpaste}
\tab{5}\spadcommand{children("albert") == ["albertJr","richard","diane"]\bound{d1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePagePatch2}
\begin{paste}{ugUserDatabasePageFull2}{ugUserDatabasePageEmpty2}
\pastebutton{ugUserDatabasePageFull2}{\hidepaste}
\tab{5}\spadcommand{children("richard") == ["douglas","daniel","susan"]\free{d1 }\bound{d2 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePageEmpty2}
\begin{paste}{ugUserDatabasePageEmpty2}{ugUserDatabasePagePatch2}
\pastebutton{ugUserDatabasePageEmpty2}{\showpaste}
\tab{5}\spadcommand{children("richard") == ["douglas","daniel","susan"]\free{d1 }\bound{d2 }}
\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePagePatch3}
\begin{paste}{ugUserDatabasePageFull3}{ugUserDatabasePageEmpty3}
\pastebutton{ugUserDatabasePageFull3}{\hidepaste}
\tab{5}\spadcommand{children("douglas") == ["dougie","valerie"]\free{d2 }\bound{d3 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePageEmpty3}
\begin{paste}{ugUserDatabasePageEmpty3}{ugUserDatabasePagePatch3}
\pastebutton{ugUserDatabasePageEmpty3}{\showpaste}
\tab{5}\spadcommand{children("douglas") == ["dougie","valerie"]\free{d2 }\bound{d3 }}
\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePagePatch4}
\begin{paste}{ugUserDatabasePageFull4}{ugUserDatabasePageEmpty4}
\pastebutton{ugUserDatabasePageFull4}{\hidepaste}
\tab{5}\spadcommand{children(x) == []\free{d3 }\bound{d4 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePageEmpty4}
\begin{paste}{ugUserDatabasePageEmpty4}{ugUserDatabasePagePatch4}
\pastebutton{ugUserDatabasePageEmpty4}{\showpaste}
\tab{5}\spadcommand{children(x) == []\free{d3 }\bound{d4 }}
\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePagePatch5}
\begin{paste}{ugUserDatabasePageFull5}{ugUserDatabasePageEmpty5}
\pastebutton{ugUserDatabasePageFull5}{\hidepaste}
\tab{5}\spadcommand{childOf(x,y) == member?(x,children(y))\bound{d9 }\free{d10 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePageEmpty5}
\begin{paste}{ugUserDatabasePageEmpty5}{ugUserDatabasePagePatch5}
\pastebutton{ugUserDatabasePageEmpty5}{\showpaste}
\tab{5}\spadcommand{childOf(x,y) == member?(x,children(y))\bound{d9 }\free{d10 }}
\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePagePatch6}
\begin{paste}{ugUserDatabasePageFull6}{ugUserDatabasePageEmpty6}
\pastebutton{ugUserDatabasePageFull6}{\hidepaste}
\tab{5}\spadcommand{parentOf(x) ==
  for y in people repeat
    (if childOf(x,y) then return y)
  "unknown"
\bound{d8a }\free{d9 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePageEmpty6}
\begin{paste}{ugUserDatabasePageEmpty6}{ugUserDatabasePagePatch6}
\pastebutton{ugUserDatabasePageEmpty6}{\showpaste}
\tab{5}\spadcommand{parentOf(x) ==
  for y in people repeat
    (if childOf(x,y) then return y)
  "unknown"
\bound{d8a }\free{d9 }}
\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePagePatch7}
\begin{paste}{ugUserDatabasePageFull7}{ugUserDatabasePageEmpty7}
\pastebutton{ugUserDatabasePageFull7}{\hidepaste}
\tab{5}\spadcommand{grandParentOf(x) == parentOf parentOf x\bound{d8 }\free{d8a }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePageEmpty7}
\begin{paste}{ugUserDatabasePageEmpty7}{ugUserDatabasePagePatch7}
\pastebutton{ugUserDatabasePageEmpty7}{\showpaste}
\tab{5}\spadcommand{grandParentOf(x) == parentOf parentOf x\bound{d8 }\free{d8a }}
\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePagePatch8}
\begin{paste}{ugUserDatabasePageFull8}{ugUserDatabasePageEmpty8}
\pastebutton{ugUserDatabasePageFull8}{\hidepaste}
\tab{5}\spadcommand{grandchildren(x) == [y for y in people | grandParentOf(y) = x]\free{d7 }\bound{d8 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePageEmpty8}
\begin{paste}{ugUserDatabasePageEmpty8}{ugUserDatabasePagePatch8}
\pastebutton{ugUserDatabasePageEmpty8}{\showpaste}
\tab{5}\spadcommand{grandchildren(x) == [y for y in people | grandParentOf(y) = x]\free{d7 }\bound{d8 }}
\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePagePatch9}
\begin{paste}{ugUserDatabasePageFull9}{ugUserDatabasePageEmpty9}
\pastebutton{ugUserDatabasePageFull9}{\hidepaste}
\tab{5}\spadcommand{greatGrandParents == [x for x in people |
  reduce(_or,[not empty? children(y) for y in grandchildren(x)],false)]
\free{d6 }\bound{d7 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePageEmpty9}
\begin{paste}{ugUserDatabasePageEmpty9}{ugUserDatabasePagePatch9}
\pastebutton{ugUserDatabasePageEmpty9}{\showpaste}
\tab{5}\spadcommand{greatGrandParents == [x for x in people |
  reduce(_or,[not empty? children(y) for y in grandchildren(x)],false)]
\free{d6 }\bound{d7 }}
\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePagePatch10}
\begin{paste}{ugUserDatabasePageFull10}{ugUserDatabasePageEmpty10}
\pastebutton{ugUserDatabasePageFull10}{\hidepaste}
\tab{5}\spadcommand{descendants(x) ==
  kids := children(x)
  null kids => [x]
  concat(x,reduce(concat,[descendants(y)
    for y in kids],[]))
\free{d5 }\bound{d6 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePageEmpty10}
\begin{paste}{ugUserDatabasePageEmpty10}{ugUserDatabasePagePatch10}
\pastebutton{ugUserDatabasePageEmpty10}{\showpaste}
\tab{5}\spadcommand{descendants(x) ==
  kids := children(x)
  null kids => [x]
  concat(x,reduce(concat,[descendants(y)
    for y in kids],[]))
\free{d5 }\bound{d6 }}
\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePagePatch11}
\begin{paste}{ugUserDatabasePageFull11}{ugUserDatabasePageEmpty11}
\pastebutton{ugUserDatabasePageFull11}{\hidepaste}
\tab{5}\spadcommand{people == descendants "albert"\free{d4 }\bound{d5 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePageEmpty11}
\begin{paste}{ugUserDatabasePageEmpty11}{ugUserDatabasePagePatch11}
\pastebutton{ugUserDatabasePageEmpty11}{\showpaste}
\tab{5}\spadcommand{people == descendants "albert"\free{d4 }\bound{d5 }}
\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePagePatch12}
\begin{paste}{ugUserDatabasePageFull12}{ugUserDatabasePageEmpty12}
\pastebutton{ugUserDatabasePageFull12}{\hidepaste}
\tab{5}\spadcommand{grandchildren "richard"\bound{d10 }\free{d11 }}
\indentrel{3}\begin{verbatim}
   (12)  ["dougie","valerie"]
                                      Type: List String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePageEmpty12}
\begin{paste}{ugUserDatabasePageEmpty12}{ugUserDatabasePagePatch12}
\pastebutton{ugUserDatabasePageEmpty12}{\showpaste}
\tab{5}\spadcommand{grandchildren "richard"\bound{d10 }\free{d11 }}
\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePagePatch13}
\begin{paste}{ugUserDatabasePageFull13}{ugUserDatabasePageEmpty13}
\pastebutton{ugUserDatabasePageFull13}{\hidepaste}
\tab{5}\spadcommand{greatGrandParents\bound{d11 }\free{d12 }}
\indentrel{3}\begin{verbatim}
   (13)  ["albert"]
                                      Type: List String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserDatabasePageEmpty13}
\begin{paste}{ugUserDatabasePageEmpty13}{ugUserDatabasePagePatch13}
\pastebutton{ugUserDatabasePageEmpty13}{\showpaste}
\tab{5}\spadcommand{greatGrandParents\bound{d11 }\free{d12 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugUserTrianglePage}{ug06.ht}{Example: A Famous Triangle}
\pageto{notitle}{ugTypesExposePage}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserTrianglePage}{6.19. Example: A Famous Triangle}
\beginscroll

In this example we write some functions that display
Pascal's triangle.
It demonstrates the use of piece-wise definitions and some output
operations you probably haven't seen before.

\labelSpace{1pc}
\xtc{
To make these output operations
available, we have to \spadgloss{expose} the domain
\axiomType{OutputForm}.
See \downlink{``Exposing Domains and Packages''}{ugTypesExposePage} 
in Section 2.11\ignore{ugTypesExpose} for 
more information about exposing domains
and packages.
}{
\spadpaste{)set expose add constructor OutputForm \bound{expose}}
}
\xtc{
Define the values along the first
row and any column \axiom{i}.
}{
\spadpaste{pascal(1,i) == 1 \bound{pas1}}
}
\xtc{
Define the values for when the row
and column index \axiom{i} are equal.
Repeating the argument name indicates that
the two index values are equal.
}{
\spadpaste{pascal(n,n) == 1 \bound{pas2}\free{pas1}}
}
\xtc{
}{
\begin{spadsrc}[\bound{pas3}\free{pas1 pas2}]
pascal(i,j | 1 < i and i < j) ==
   pascal(i-1,j-1)+pascal(i,j-1)
\end{spadsrc}
}
Now that we have defined the coefficients in Pascal's triangle,
let's write a couple of one-liners to display it.
\xtc{
First, define a function that gives the \eth{\axiom{n}} row.
}{
\spadpaste{pascalRow(n) == [pascal(i,n) for i in 1..n] 
\bound{pascalRow}\free{pas3}}
}
\xtc{
Next, we write the function \userfun{displayRow}
to display the row, separating entries by blanks and centering.
}{
\spadpaste{displayRow(n) == output center blankSeparate pascalRow(n) 
\free{pascalRow}\bound{displayRow}\free{expose}}
}
%
Here we have used three output operations.
Operation \axiomFunFrom{output}{OutputForm}
displays the printable form of objects on the screen,
\axiomFunFrom{center}{OutputForm} centers a printable form in the
width of the screen, and \axiomFunFrom{blankSeparate}{OutputForm} 
takes a list of printable forms and inserts a blank between 
successive elements.
\xtc{
Look at the result.
}{
\spadpaste{for i in 1..7 repeat displayRow i \free{displayRow}}
}
Being purists, we find this less than satisfactory.
Traditionally, elements of Pascal's triangle are centered between
the left and right elements on the line above.
%
\xtc{
To fix this misalignment, we go back and
redefine \userfun{pascalRow} to right adjust the entries within the
triangle within a width of four characters.
}{
\spadpaste{pascalRow(n) == [right(pascal(i,n),4) for i in 1..n] 
\bound{pascalRow2}}
}
%
\xtc{
Finally let's look at our purely reformatted triangle.
}{
\spadpaste{for i in 1..7 repeat displayRow i \free{pascalRow2}
\free{displayRow}}
}
\xtc{
Unexpose \axiomType{OutputForm} so we don't get unexpected
results later.
}{
\spadpaste{)set expose drop constructor OutputForm}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserTrianglePagePatch1}
\begin{paste}{ugUserTrianglePageFull1}{ugUserTrianglePageEmpty1}
\pastebutton{ugUserTrianglePageFull1}{\hidepaste}
\tab{5}\spadcommand{)set expose add constructor OutputForm\bound{expose }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserTrianglePageEmpty1}
\begin{paste}{ugUserTrianglePageEmpty1}{ugUserTrianglePagePatch1}
\pastebutton{ugUserTrianglePageEmpty1}{\showpaste}
\tab{5}\spadcommand{)set expose add constructor OutputForm\bound{expose }}
\end{paste}\end{patch}

\begin{patch}{ugUserTrianglePagePatch2}
\begin{paste}{ugUserTrianglePageFull2}{ugUserTrianglePageEmpty2}
\pastebutton{ugUserTrianglePageFull2}{\hidepaste}
\tab{5}\spadcommand{pascal(1,i) == 1\bound{pas1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserTrianglePageEmpty2}
\begin{paste}{ugUserTrianglePageEmpty2}{ugUserTrianglePagePatch2}
\pastebutton{ugUserTrianglePageEmpty2}{\showpaste}
\tab{5}\spadcommand{pascal(1,i) == 1\bound{pas1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserTrianglePagePatch3}
\begin{paste}{ugUserTrianglePageFull3}{ugUserTrianglePageEmpty3}
\pastebutton{ugUserTrianglePageFull3}{\hidepaste}
\tab{5}\spadcommand{pascal(n,n) == 1\bound{pas2 }\free{pas1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserTrianglePageEmpty3}
\begin{paste}{ugUserTrianglePageEmpty3}{ugUserTrianglePagePatch3}
\pastebutton{ugUserTrianglePageEmpty3}{\showpaste}
\tab{5}\spadcommand{pascal(n,n) == 1\bound{pas2 }\free{pas1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserTrianglePagePatch4}
\begin{paste}{ugUserTrianglePageFull4}{ugUserTrianglePageEmpty4}
\pastebutton{ugUserTrianglePageFull4}{\hidepaste}
\tab{5}\spadcommand{pascal(i,j | 1 < i and i < j) ==
   pascal(i-1,j-1)+pascal(i,j-1)
\bound{pas3 }\free{pas1 pas2 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserTrianglePageEmpty4}
\begin{paste}{ugUserTrianglePageEmpty4}{ugUserTrianglePagePatch4}
\pastebutton{ugUserTrianglePageEmpty4}{\showpaste}
\tab{5}\spadcommand{pascal(i,j | 1 < i and i < j) ==
   pascal(i-1,j-1)+pascal(i,j-1)
\bound{pas3 }\free{pas1 pas2 }}
\end{paste}\end{patch}

\begin{patch}{ugUserTrianglePagePatch5}
\begin{paste}{ugUserTrianglePageFull5}{ugUserTrianglePageEmpty5}
\pastebutton{ugUserTrianglePageFull5}{\hidepaste}
\tab{5}\spadcommand{pascalRow(n) == [pascal(i,n) for i in 1..n]\bound{pascalRow }\free{pas3 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserTrianglePageEmpty5}
\begin{paste}{ugUserTrianglePageEmpty5}{ugUserTrianglePagePatch5}
\pastebutton{ugUserTrianglePageEmpty5}{\showpaste}
\tab{5}\spadcommand{pascalRow(n) == [pascal(i,n) for i in 1..n]\bound{pascalRow }\free{pas3 }}
\end{paste}\end{patch}

\begin{patch}{ugUserTrianglePagePatch6}
\begin{paste}{ugUserTrianglePageFull6}{ugUserTrianglePageEmpty6}
\pastebutton{ugUserTrianglePageFull6}{\hidepaste}
\tab{5}\spadcommand{displayRow(n) == output center blankSeparate pascalRow(n)\free{pascalRow }\bound{displayRow }\free{expose }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserTrianglePageEmpty6}
\begin{paste}{ugUserTrianglePageEmpty6}{ugUserTrianglePagePatch6}
\pastebutton{ugUserTrianglePageEmpty6}{\showpaste}
\tab{5}\spadcommand{displayRow(n) == output center blankSeparate pascalRow(n)\free{pascalRow }\bound{displayRow }\free{expose }}
\end{paste}\end{patch}

\begin{patch}{ugUserTrianglePagePatch7}
\begin{paste}{ugUserTrianglePageFull7}{ugUserTrianglePageEmpty7}
\pastebutton{ugUserTrianglePageFull7}{\hidepaste}
\tab{5}\spadcommand{for i in 1..7 repeat displayRow i\free{displayRow }}
\indentrel{3}\begin{verbatim}
                                   1
                                  1 1
                                 1 2 1
                                1 3 3 1
                               1 4 6 4 1
                             1 5 10 10 5 1
                            1 6 15 20 15 6 1
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserTrianglePageEmpty7}
\begin{paste}{ugUserTrianglePageEmpty7}{ugUserTrianglePagePatch7}
\pastebutton{ugUserTrianglePageEmpty7}{\showpaste}
\tab{5}\spadcommand{for i in 1..7 repeat displayRow i\free{displayRow }}
\end{paste}\end{patch}

\begin{patch}{ugUserTrianglePagePatch8}
\begin{paste}{ugUserTrianglePageFull8}{ugUserTrianglePageEmpty8}
\pastebutton{ugUserTrianglePageFull8}{\hidepaste}
\tab{5}\spadcommand{pascalRow(n) == [right(pascal(i,n),4) for i in 1..n]\bound{pascalRow2 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserTrianglePageEmpty8}
\begin{paste}{ugUserTrianglePageEmpty8}{ugUserTrianglePagePatch8}
\pastebutton{ugUserTrianglePageEmpty8}{\showpaste}
\tab{5}\spadcommand{pascalRow(n) == [right(pascal(i,n),4) for i in 1..n]\bound{pascalRow2 }}
\end{paste}\end{patch}

\begin{patch}{ugUserTrianglePagePatch9}
\begin{paste}{ugUserTrianglePageFull9}{ugUserTrianglePageEmpty9}
\pastebutton{ugUserTrianglePageFull9}{\hidepaste}
\tab{5}\spadcommand{for i in 1..7 repeat displayRow i\free{pascalRow2 }\free{displayRow }}
\indentrel{3}\begin{verbatim}
                                     1
                                  1    1
                                1    2    1
                             1    3    3    1
                           1    4    6    4    1
                        1    5   10   10    5    1
                      1    6   15   20   15    6    1
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserTrianglePageEmpty9}
\begin{paste}{ugUserTrianglePageEmpty9}{ugUserTrianglePagePatch9}
\pastebutton{ugUserTrianglePageEmpty9}{\showpaste}
\tab{5}\spadcommand{for i in 1..7 repeat displayRow i\free{pascalRow2 }\free{displayRow }}
\end{paste}\end{patch}

\begin{patch}{ugUserTrianglePagePatch10}
\begin{paste}{ugUserTrianglePageFull10}{ugUserTrianglePageEmpty10}
\pastebutton{ugUserTrianglePageFull10}{\hidepaste}
\tab{5}\spadcommand{)set expose drop constructor OutputForm}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserTrianglePageEmpty10}
\begin{paste}{ugUserTrianglePageEmpty10}{ugUserTrianglePagePatch10}
\pastebutton{ugUserTrianglePageEmpty10}{\showpaste}
\tab{5}\spadcommand{)set expose drop constructor OutputForm}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugUserPalPage}{ug06.ht}{Example: Testing for Palindromes}
\pageto{notitle}{ugUserTrianglePage}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserPalPage}{6.20. Example: Testing for Palindromes}
\beginscroll


In this section we define a function \userfun{pal?} that tests whether
its argument is a {\it palindrome}, that is, something that reads the
same backwards and forwards.  For example, the string ``Madam I'm
Adam'' is a palindrome (excluding blanks and punctuation) and so is
the number \axiom{123454321.}  The definition works for any datatype
that has \axiom{n} components that are accessed by the indices
\axiom{1\ldots n}.

\xtc{
Here is the definition for \userfun{pal?}.
It is simply a call to an auxiliary function called
\userfun{palAux?}.
We are following the convention of ending a function's name with
\axiomSyntax{?} if the function returns a \axiomType{Boolean} value.
}{
\spadpaste{pal? s ==  palAux?(s,1,\#s) \bound{pal}}
}
\xtc{
Here is \userfun{palAux?}.
It works by comparing elements that are equidistant from the start and end
of the object.
}{
\begin{spadsrc}[\bound{palAux}]
palAux?(s,i,j) ==
  j > i =>
    (s.i = s.j) and palAux?(s,i+1,i-1)
  true
\end{spadsrc}
}
\xtc{
Try \userfun{pal?} on some examples.
First, a string.
}{
\spadpaste{pal? "Oxford"  \free{pal palAux}}
}
\xtc{
A list of polynomials.
}{
\spadpaste{pal? [4,a,x-1,0,x-1,a,4]  \free{pal palAux}}
}
\xtc{
A list of integers from the example in
\texht{the last section.}{\downlink{``A Famous Triangle''}
{ugUserTrianglePage} in Section 6.19\ignore{ugUserTriangle}.}
}{
\spadpaste{pal? [1,6,15,20,15,6,1] \free{pal palAux}}
}
\xtc{
To use \userfun{pal?} on an integer, first convert it to a string.
}{
\spadpaste{pal?(1441::String)\free{pal palAux}}
}
\xtc{
Compute an infinite stream of decimal numbers,
each of which is an obvious palindrome.
}{
\spadpaste{ones := [reduce(+,[10**j for j in 0..i]) for i in 1..]
\free{pal palAux}\bound{pal5}}
}
\xtc{
How about their squares?
}{
\spadpaste{squares := [x**2 for x in ones]\free{pal5}\bound{pal6}}
}
\xtc{
Well, let's test them all!
}{
\spadpaste{[pal?(x::String) for x in squares]\free{pal6}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserPalPagePatch1}
\begin{paste}{ugUserPalPageFull1}{ugUserPalPageEmpty1}
\pastebutton{ugUserPalPageFull1}{\hidepaste}
\tab{5}\spadcommand{pal? s == palAux?(s,1,\#s)\bound{pal }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPalPageEmpty1}
\begin{paste}{ugUserPalPageEmpty1}{ugUserPalPagePatch1}
\pastebutton{ugUserPalPageEmpty1}{\showpaste}
\tab{5}\spadcommand{pal? s == palAux?(s,1,\#s)\bound{pal }}
\end{paste}\end{patch}

\begin{patch}{ugUserPalPagePatch2}
\begin{paste}{ugUserPalPageFull2}{ugUserPalPageEmpty2}
\pastebutton{ugUserPalPageFull2}{\hidepaste}
\tab{5}\spadcommand{palAux?(s,i,j) ==
  j > i =>
    (s.i = s.j) and palAux?(s,i+1,i-1)
  true
\bound{palAux }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPalPageEmpty2}
\begin{paste}{ugUserPalPageEmpty2}{ugUserPalPagePatch2}
\pastebutton{ugUserPalPageEmpty2}{\showpaste}
\tab{5}\spadcommand{palAux?(s,i,j) ==
  j > i =>
    (s.i = s.j) and palAux?(s,i+1,i-1)
  true
\bound{palAux }}
\end{paste}\end{patch}

\begin{patch}{ugUserPalPagePatch3}
\begin{paste}{ugUserPalPageFull3}{ugUserPalPageEmpty3}
\pastebutton{ugUserPalPageFull3}{\hidepaste}
\tab{5}\spadcommand{pal? "Oxford"\free{pal palAux }}
\indentrel{3}\begin{verbatim}
   (3)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPalPageEmpty3}
\begin{paste}{ugUserPalPageEmpty3}{ugUserPalPagePatch3}
\pastebutton{ugUserPalPageEmpty3}{\showpaste}
\tab{5}\spadcommand{pal? "Oxford"\free{pal palAux }}
\end{paste}\end{patch}

\begin{patch}{ugUserPalPagePatch4}
\begin{paste}{ugUserPalPageFull4}{ugUserPalPageEmpty4}
\pastebutton{ugUserPalPageFull4}{\hidepaste}
\tab{5}\spadcommand{pal? [4,a,x-1,0,x-1,a,4]\free{pal palAux }}
\indentrel{3}\begin{verbatim}
   (4)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPalPageEmpty4}
\begin{paste}{ugUserPalPageEmpty4}{ugUserPalPagePatch4}
\pastebutton{ugUserPalPageEmpty4}{\showpaste}
\tab{5}\spadcommand{pal? [4,a,x-1,0,x-1,a,4]\free{pal palAux }}
\end{paste}\end{patch}

\begin{patch}{ugUserPalPagePatch5}
\begin{paste}{ugUserPalPageFull5}{ugUserPalPageEmpty5}
\pastebutton{ugUserPalPageFull5}{\hidepaste}
\tab{5}\spadcommand{pal? [1,6,15,20,15,6,1]\free{pal palAux }}
\indentrel{3}\begin{verbatim}
   (5)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPalPageEmpty5}
\begin{paste}{ugUserPalPageEmpty5}{ugUserPalPagePatch5}
\pastebutton{ugUserPalPageEmpty5}{\showpaste}
\tab{5}\spadcommand{pal? [1,6,15,20,15,6,1]\free{pal palAux }}
\end{paste}\end{patch}

\begin{patch}{ugUserPalPagePatch6}
\begin{paste}{ugUserPalPageFull6}{ugUserPalPageEmpty6}
\pastebutton{ugUserPalPageFull6}{\hidepaste}
\tab{5}\spadcommand{pal?(1441::String)\free{pal palAux }}
\indentrel{3}\begin{verbatim}
   (6)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPalPageEmpty6}
\begin{paste}{ugUserPalPageEmpty6}{ugUserPalPagePatch6}
\pastebutton{ugUserPalPageEmpty6}{\showpaste}
\tab{5}\spadcommand{pal?(1441::String)\free{pal palAux }}
\end{paste}\end{patch}

\begin{patch}{ugUserPalPagePatch7}
\begin{paste}{ugUserPalPageFull7}{ugUserPalPageEmpty7}
\pastebutton{ugUserPalPageFull7}{\hidepaste}
\tab{5}\spadcommand{ones := [reduce(+,[10**j for j in 0..i]) for i in 1..]\free{pal palAux }\bound{pal5 }}
\indentrel{3}\begin{verbatim}
   (7)
   [11, 111, 1111, 11111, 111111, 1111111, 11111111,
    111111111, 1111111111, 11111111111, ...]
                           Type: Stream PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPalPageEmpty7}
\begin{paste}{ugUserPalPageEmpty7}{ugUserPalPagePatch7}
\pastebutton{ugUserPalPageEmpty7}{\showpaste}
\tab{5}\spadcommand{ones := [reduce(+,[10**j for j in 0..i]) for i in 1..]\free{pal palAux }\bound{pal5 }}
\end{paste}\end{patch}

\begin{patch}{ugUserPalPagePatch8}
\begin{paste}{ugUserPalPageFull8}{ugUserPalPageEmpty8}
\pastebutton{ugUserPalPageFull8}{\hidepaste}
\tab{5}\spadcommand{squares := [x**2 for x in ones]\free{pal5 }\bound{pal6 }}
\indentrel{3}\begin{verbatim}
   (8)
   [121, 12321, 1234321, 123454321, 12345654321,
    1234567654321, 123456787654321, 12345678987654321,
    1234567900987654321, 123456790120987654321, ...]
                           Type: Stream PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPalPageEmpty8}
\begin{paste}{ugUserPalPageEmpty8}{ugUserPalPagePatch8}
\pastebutton{ugUserPalPageEmpty8}{\showpaste}
\tab{5}\spadcommand{squares := [x**2 for x in ones]\free{pal5 }\bound{pal6 }}
\end{paste}\end{patch}

\begin{patch}{ugUserPalPagePatch9}
\begin{paste}{ugUserPalPageFull9}{ugUserPalPageEmpty9}
\pastebutton{ugUserPalPageFull9}{\hidepaste}
\tab{5}\spadcommand{[pal?(x::String) for x in squares]\free{pal6 }}
\indentrel{3}\begin{verbatim}
   (9)
   [true,true,true,true,true,true,true,true,true,true,...]
                                   Type: Stream Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserPalPageEmpty9}
\begin{paste}{ugUserPalPageEmpty9}{ugUserPalPagePatch9}
\pastebutton{ugUserPalPageEmpty9}{\showpaste}
\tab{5}\spadcommand{[pal?(x::String) for x in squares]\free{pal6 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugUserRulesPage}{ug06.ht}{Rules and Pattern Matching}
\begin{chunk}{ug06.ht}
\begin{page}{ugUserRulesPage}{6.21. Rules and Pattern Matching}
\beginscroll

A common mathematical formula is
\texht{\narrowDisplay{%
\log(x) + \log(y) = \log(x y) \quad\forall \, x \hbox{\ and\ } y.}}{
\axiom{log(x) + log(y) == log(x * y)} for any \axiom{x} and \axiom{y}.}
The presence of
\texht{``$\forall$''}{the word ``any''}
indicates that \axiom{x} and \axiom{y} can stand for arbitrary mathematical
expressions in the above formula.
You can use such mathematical formulas in Axiom to specify ``rewrite
rules''.
Rewrite rules are objects in Axiom that can be assigned to variables for
later use, often for the purpose of simplification.
Rewrite rules look like ordinary function definitions except that they are
preceded by the reserved word \axiom{rule}.
\spadkey{rule}
For example, a rewrite rule for the above formula is:
\begin{verbatim}
rule log(x) + log(y) == log(x * y)
\end{verbatim}
Like function definitions, no action is taken when a rewrite rule is issued.
Think of rewrite rules as functions that take one argument.
When a rewrite rule \axiom{A = B} is applied to an argument \axiom{f}, its
meaning is: ``rewrite every subexpression of \axiom{f} that {\it matches}
\axiom{A} by \axiom{B.}''
The left-hand side of a rewrite rule is called a \spadgloss{pattern}; its
right-side side is called its \spadgloss{substitution}.

\xtc{
Create a rewrite rule named \userfun{logrule}.
The generated symbol beginning with a \axiomSyntax{\%} is a place-holder
for any other terms that might occur in the sum.
}{
\spadpaste{logrule := rule log(x) + log(y) == log(x * y) \bound{logrule}}
}
\xtc{
Create an expression with logarithms.
}{
\spadpaste{f := log sin x + log x \bound{f}}
}
\xtc{
Apply \userfun{logrule} to \axiom{f}.
}{
\spadpaste{logrule f \free{f}\free{logrule}}
}

The meaning of our example rewrite rule is:
``for all expressions \axiom{x} and \axiom{y}, rewrite
\axiom{log(x) + log(y)} by \axiom{log(x * y)}.''
Patterns generally have both operation names
(here, \axiomFun{log} and \axiomOp{+})
and variables (here, \axiom{x} and \axiom{y}).
By default, every operation name stands for itself.
Thus \axiomFun{log}  matches only ``\axiom{log}'' and not any
other operation such as \axiomFun{sin}.
On the other hand, variables do not stand for themselves.
Rather, a variable denotes a
{\it pattern variable} that is free to match any expression whatsoever.

When a rewrite rule is applied, a process called \spadgloss{pattern
matching} goes to work by systematically scanning the subexpressions
of the argument.  When a subexpression is found that ``matches'' the
pattern, the subexpression is replaced by the right-hand side of the
rule.  The details of what happens will be covered later.

The customary Axiom notation for patterns is actually a shorthand for
a longer, more general notation.  Pattern variables can be made
explicit by using a percent (\axiomSyntax{\%}) as the first character
of the variable name.  To say that a name stands for itself, you can
prefix that name with a quote operator (\axiomSyntax{'}).  Although
the current Axiom parser does not let you quote an operation name,
this more general notation gives you an alternate way of giving the
same rewrite rule:
\begin{verbatim}
rule log(%x) + log(%y) == log(x * y)
\end{verbatim}
This longer notation gives you patterns that the
standard notation won't handle.
For example, the rule
\texht{\typeout{check this example}}{}
\begin{verbatim}
rule %f(c * 'x) ==  c*%f(x)
\end{verbatim}
means ``for all \axiom{f} and \axiom{c}, replace \axiom{f(y)} by
\axiom{c * f(x)} when \axiom{y} is the product of \axiom{c}
and the explicit variable \axiom{x}.''

Thus the pattern can have several adornments on the names that appear there.
Normally, all these adornments are dropped in the substitution on the
right-hand side.

To summarize:

\beginImportant
To enter a single rule in Axiom, use the following syntax:
\spadkey{rule}
\centerline{{{\tt rule {\it leftHandSide} == {\it rightHandSide}}}}
The {\it leftHandSide} is a pattern to be matched and
the {\it rightHandSide} is its substitution.
The rule is an object of type \axiomType{RewriteRule} that can be
assigned to a variable and applied to expressions to transform them.
\endImportant

Rewrite rules can be collected into rulesets so that a set of rules
can be applied at once.  Here is another simplification rule for
logarithms.  \texht{\narrowDisplay{y \log(x) = \log(x^y) \quad\forall
\, x \hbox{\ and\ } y.}}{ \axiom{y * log(x) == log(x ** y)} for any
\axiom{x} and \axiom{y}.}  If instead of giving a single rule
following the reserved word \axiom{rule} you give a ``pile'' of rules,
you create what is called a {\it ruleset.}  Like rules, rulesets are
objects in Axiom and can be assigned to variables.  You will find it
useful to group commonly used rules into input files, and read them in
as needed.
\xtc{
Create a ruleset named \axiom{logrules}.
}{
\begin{spadsrc}[\bound{logrules}]
logrules := rule
  log(x) + log(y) == log(x * y)
  y * log x       == log(x ** y)
\end{spadsrc}
}
\xtc{
Again, create an expression \axiom{f} containing logarithms.
}{
\spadpaste{f := a * log(sin x) - 2 * log x \bound{f1}}
}
\xtc{
Apply the ruleset \userfun{logrules} to \axiom{f}.
}{
\spadpaste{logrules f \free{f1}\free{logrules}}
}

We have allowed pattern variables to match arbitrary expressions in
the above examples.  Often you want a variable only to match
expressions satisfying some predicate.  For example, we may want to
apply the transformation \texht{\narrowDisplay{y \log(x) =
\log(x^y)}}{\axiom{y * log(x) == log(x ** y)}} only when \axiom{y} is
an integer.
%
The way to restrict a pattern variable \axiom{y} by a predicate
\axiom{f(y)} is by using a vertical bar \axiomSyntax{|}, which means
``such that,'' in much the same way it is used in function
definitions.  You do this only once, but at the earliest (meaning
deepest and leftmost) part of the pattern.
\xtc{
This restricts the logarithmic rule to create integer exponents only.
}{
\begin{spadsrc}[\bound{logrules2}]
logrules2 := rule
  log(x) + log(y)          == log(x * y)
  (y | integer? y) * log x == log(x ** y)
\end{spadsrc}
}
\xtc{
Compare this with the result of applying the previous set of rules.
}{
\spadpaste{f \free{f1}}
}
\xtc{
}{
\spadpaste{logrules2 f \free{f1}\free{logrules2}}
}
You should be aware that you might need to apply a function like
\spadfun{integer} within your predicate expression to actually apply
the test function.
\xtc{
Here we use \spadfun{integer} because \spad{n} has
type \spadtype{Expression Integer} but \spadfun{even?} is an operation
defined on integers.
}{
\spadpaste{
evenRule := rule cos(x)**(n | integer? n and even? integer n)==
(1-sin(x)**2)**(n/2) \bound{evenRule}}
}
\xtc{
Here is the application of the rule.
}{
\spadpaste{evenRule( cos(x)**2 ) \free{evenRule}}
}
\xtc{
This is an example of some of the usual identities involving products of
sines and cosines.
}{
\begin{spadsrc}[\bound{sinCosProducts}]
sinCosProducts == rule
  sin(x) * sin(y) == (cos(x-y) - cos(x + y))/2
  cos(x) * cos(y) == (cos(x-y) + cos(x+y))/2
  sin(x) * cos(y) == (sin(x-y) + sin(x + y))/2
\end{spadsrc}
}
\xtc{
}{
\spadpaste{g := sin(a)*sin(b) + cos(b)*cos(a) + sin(2*a)*cos(2*a) 
\bound{g}}
}
\xtc{
}{
\spadpaste{sinCosProducts g \free{sinCosProducts g}}
}

Another qualification you will often want to use is to allow a pattern
to match an identity element.  Using the pattern \axiom{x + y}, for
example, neither \axiom{x} nor \axiom{y} matches the expression
\axiom{0}.  Similarly, if a pattern contains a product \axiom{x*y} or
an exponentiation \axiom{x**y}, then neither \axiom{x} or \axiom{y}
matches \axiom{1}.

\xtc{
If identical elements were matched, pattern matching would generally loop.
Here is an expansion rule for exponentials.
}{
\spadpaste{exprule := rule exp(a + b) == exp(a) * exp(b)\bound{exprule}}
}
\xtc{
This rule would cause infinite rewriting on this if either \axiom{a} or
\axiom{b} were allowed to match \axiom{0}.
}{
\spadpaste{exprule exp x \free{exprule}}
}

There are occasions when you do want a pattern variable in a sum or
product to match \axiom{0} or \axiom{1}.  If so, prefix its name with
a \axiomSyntax{?} whenever it appears in a left-hand side of a rule.
For example, consider the following rule for the exponential integral:
\texht{\narrowDisplay{\int \left(\frac{y+e^x}{x}\right)\: dx = \int
\frac{y}{x}\: dx + \hbox{\rm Ei}(x) \quad\forall \, x \hbox{\ and\ }
y.}}{ \axiom{integral((y + exp x)/x, x) == integral(y/x, x) + Ei x}
for any \axiom{x} and \axiom{y}.}  This rule is valid for \axiom{y =
0}.  One solution is to create a \axiomType{Ruleset} with two rules,
one with and one without \axiom{y}.  A better solution is to use an
``optional'' pattern variable.

\xtc{
Define rule \axiom{eirule} with
a pattern variable \axiom{?y} to indicate
that an expression may or may not occur.
}{
\spadpaste{eirule := rule integral((?y + exp x)/x,x) == 
integral(y/x,x) + Ei x \bound{eirule}}
}
\xtc{
Apply rule \axiom{eirule} to an integral without this term.
}{
\spadpaste{eirule integral(exp u/u, u) \free{eirule}}
}
\xtc{
Apply rule \axiom{eirule} to an integral with this term.
}{
\spadpaste{eirule integral(sin u + exp u/u, u) \free{eirule}}
}

Here is one final adornment you will find useful.  When matching a
pattern of the form \axiom{x + y} to an expression containing a long
sum of the form \axiom{a +\ldots+ b}, there is no way to predict in
advance which subset of the sum matches \axiom{x} and which matches
\axiom{y}.  Aside from efficiency, this is generally unimportant since
the rule holds for any possible combination of matches for \axiom{x}
and \axiom{y}.  In some situations, however, you may want to say which
pattern variable is a sum (or product) of several terms, and which
should match only a single term.  To do this, put a prefix colon
\axiomSyntax{:} before the pattern variable that you want to match
multiple terms.

\xtc{
The remaining rules involve operators \axiom{u} and \axiom{v}.
}{
\spadpaste{u := operator 'u \bound{u}}
}
\xtc{
These definitions tell Axiom that
\axiom{u} and \axiom{v} are formal operators to be used in expressions.
}{
\spadpaste{v := operator 'v \bound{v}}
}
\xtc{
First define \axiom{myRule}
with no restrictions on the pattern variables
\axiom{x} and \axiom{y}.
}{
\spadpaste{myRule := rule u(x + y) == u x + v y \free{u v}\bound{m}}
}
\xtc{
Apply \axiom{myRule} to an expression.
}{
\spadpaste{myRule u(a + b + c + d) \free{m}}
}
\xtc{
Define \axiom{myOtherRule} to match several terms
so that the rule gets applied recursively.
}{
\spadpaste{myOtherRule := rule u(:x + y) == u x + v y \free{u v}\bound{m2}}
}
\xtc{
Apply \axiom{myOtherRule} to the same expression.
}{
\spadpaste{myOtherRule u(a + b + c + d) \free{m2}}
}


Here are some final remarks on pattern matching.
Pattern matching provides a very useful paradigm for solving
certain classes of problems, namely, those that involve
transformations of one form to another and back.
However, it is important to recognize its limitations.

First, pattern matching slows down as the number of rules you have to
apply increases.  Thus it is good practice to organize the sets of
rules you use optimally so that irrelevant rules are never included.

Second, careless use of pattern matching can lead to wrong answers.
You should avoid using pattern matching to handle hidden algebraic
relationships that can go undetected by other programs.  As a simple
example, a symbol such as ``J'' can easily be used to represent the
square root of \axiom{-1} or some other important algebraic quantity.
Many algorithms branch on whether an expression is zero or not, then
divide by that expression if it is not.  If you fail to simplify an
expression involving powers of \axiom{J} to \axiom{-1,} algorithms may
incorrectly assume an expression is non-zero, take a wrong branch, and
produce a meaningless result.

Pattern matching should also not be used as a substitute for a domain.
In Axiom, objects of one domain are transformed to objects of other
domains using well-defined \axiomFun{coerce} operations.
Pattern matching should be used on objects that are all the same type.
Thus if your application can be handled by type \axiomType{Expression} in
Axiom and you think you need pattern matching, consider this choice
carefully.
You may well be better served by extending an existing domain
or by building a new domain of objects for your application.
\endscroll
\autobuttons
\end{page}

\begin{patch}{ugUserRulesPagePatch1}
\begin{paste}{ugUserRulesPageFull1}{ugUserRulesPageEmpty1}
\pastebutton{ugUserRulesPageFull1}{\hidepaste}
\tab{5}\spadcommand{logrule := rule log(x) + log(y) == log(x * y)\bound{logrule }}
\indentrel{3}\begin{verbatim}
   (1)  log(y) + log(x) + %B == log(x y) + %B
  Type: RewriteRule(Integer,Integer,Expression Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty1}
\begin{paste}{ugUserRulesPageEmpty1}{ugUserRulesPagePatch1}
\pastebutton{ugUserRulesPageEmpty1}{\showpaste}
\tab{5}\spadcommand{logrule := rule log(x) + log(y) == log(x * y)\bound{logrule }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch2}
\begin{paste}{ugUserRulesPageFull2}{ugUserRulesPageEmpty2}
\pastebutton{ugUserRulesPageFull2}{\hidepaste}
\tab{5}\spadcommand{f := log sin x + log x\bound{f }}
\indentrel{3}\begin{verbatim}
   (2)  log(sin(x)) + log(x)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty2}
\begin{paste}{ugUserRulesPageEmpty2}{ugUserRulesPagePatch2}
\pastebutton{ugUserRulesPageEmpty2}{\showpaste}
\tab{5}\spadcommand{f := log sin x + log x\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch3}
\begin{paste}{ugUserRulesPageFull3}{ugUserRulesPageEmpty3}
\pastebutton{ugUserRulesPageFull3}{\hidepaste}
\tab{5}\spadcommand{logrule f\free{f }\free{logrule }}
\indentrel{3}\begin{verbatim}
   (3)  log(x sin(x))
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty3}
\begin{paste}{ugUserRulesPageEmpty3}{ugUserRulesPagePatch3}
\pastebutton{ugUserRulesPageEmpty3}{\showpaste}
\tab{5}\spadcommand{logrule f\free{f }\free{logrule }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch4}
\begin{paste}{ugUserRulesPageFull4}{ugUserRulesPageEmpty4}
\pastebutton{ugUserRulesPageFull4}{\hidepaste}
\tab{5}\spadcommand{logrules := rule
  log(x) + log(y) == log(x * y)
  y * log x       == log(x ** y)
\bound{logrules }}
\indentrel{3}\begin{verbatim}
   (4)
   {log(y) + log(x) + %C == log(x y) + %C,
                     y
    y log(x) == log(x )}
      Type: Ruleset(Integer,Integer,Expression Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty4}
\begin{paste}{ugUserRulesPageEmpty4}{ugUserRulesPagePatch4}
\pastebutton{ugUserRulesPageEmpty4}{\showpaste}
\tab{5}\spadcommand{logrules := rule
  log(x) + log(y) == log(x * y)
  y * log x       == log(x ** y)
\bound{logrules }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch5}
\begin{paste}{ugUserRulesPageFull5}{ugUserRulesPageEmpty5}
\pastebutton{ugUserRulesPageFull5}{\hidepaste}
\tab{5}\spadcommand{f := a * log(sin x) - 2 * log x\bound{f1 }}
\indentrel{3}\begin{verbatim}
   (5)  a log(sin(x)) - 2log(x)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty5}
\begin{paste}{ugUserRulesPageEmpty5}{ugUserRulesPagePatch5}
\pastebutton{ugUserRulesPageEmpty5}{\showpaste}
\tab{5}\spadcommand{f := a * log(sin x) - 2 * log x\bound{f1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch6}
\begin{paste}{ugUserRulesPageFull6}{ugUserRulesPageEmpty6}
\pastebutton{ugUserRulesPageFull6}{\hidepaste}
\tab{5}\spadcommand{logrules f\free{f1 }\free{logrules }}
\indentrel{3}\begin{verbatim}
                  a
            sin(x)
   (6)  log(ÄÄÄÄÄÄÄ)
                2
               x
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty6}
\begin{paste}{ugUserRulesPageEmpty6}{ugUserRulesPagePatch6}
\pastebutton{ugUserRulesPageEmpty6}{\showpaste}
\tab{5}\spadcommand{logrules f\free{f1 }\free{logrules }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch7}
\begin{paste}{ugUserRulesPageFull7}{ugUserRulesPageEmpty7}
\pastebutton{ugUserRulesPageFull7}{\hidepaste}
\tab{5}\spadcommand{logrules2 := rule
  log(x) + log(y)          == log(x * y)
  (y | integer? y) * log x == log(x ** y)
\bound{logrules2 }}
\indentrel{3}\begin{verbatim}
   (7)
   {log(y) + log(x) + %E == log(x y) + %E,
                     y
    y log(x) == log(x )}
      Type: Ruleset(Integer,Integer,Expression Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty7}
\begin{paste}{ugUserRulesPageEmpty7}{ugUserRulesPagePatch7}
\pastebutton{ugUserRulesPageEmpty7}{\showpaste}
\tab{5}\spadcommand{logrules2 := rule
  log(x) + log(y)          == log(x * y)
  (y | integer? y) * log x == log(x ** y)
\bound{logrules2 }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch8}
\begin{paste}{ugUserRulesPageFull8}{ugUserRulesPageEmpty8}
\pastebutton{ugUserRulesPageFull8}{\hidepaste}
\tab{5}\spadcommand{f\free{f1 }}
\indentrel{3}\begin{verbatim}
   (8)  a log(sin(x)) - 2log(x)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty8}
\begin{paste}{ugUserRulesPageEmpty8}{ugUserRulesPagePatch8}
\pastebutton{ugUserRulesPageEmpty8}{\showpaste}
\tab{5}\spadcommand{f\free{f1 }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch9}
\begin{paste}{ugUserRulesPageFull9}{ugUserRulesPageEmpty9}
\pastebutton{ugUserRulesPageFull9}{\hidepaste}
\tab{5}\spadcommand{logrules2 f\free{f1 }\free{logrules2 }}
\indentrel{3}\begin{verbatim}
                             1
   (9)  a log(sin(x)) + log(ÄÄ)
                             2
                            x
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty9}
\begin{paste}{ugUserRulesPageEmpty9}{ugUserRulesPagePatch9}
\pastebutton{ugUserRulesPageEmpty9}{\showpaste}
\tab{5}\spadcommand{logrules2 f\free{f1 }\free{logrules2 }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch10}
\begin{paste}{ugUserRulesPageFull10}{ugUserRulesPageEmpty10}
\pastebutton{ugUserRulesPageFull10}{\hidepaste}
\tab{5}\spadcommand{evenRule := rule cos(x)**(n | integer? n and even? integer n)==(1-sin(x)**2)**(n/2)\bound{evenRule }}
\indentrel{3}\begin{verbatim}
                                   n
                                   Ä
               n             2     2
   (10)  cos(x)  == (- sin(x)  + 1)
  Type: RewriteRule(Integer,Integer,Expression Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty10}
\begin{paste}{ugUserRulesPageEmpty10}{ugUserRulesPagePatch10}
\pastebutton{ugUserRulesPageEmpty10}{\showpaste}
\tab{5}\spadcommand{evenRule := rule cos(x)**(n | integer? n and even? integer n)==(1-sin(x)**2)**(n/2)\bound{evenRule }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch11}
\begin{paste}{ugUserRulesPageFull11}{ugUserRulesPageEmpty11}
\pastebutton{ugUserRulesPageFull11}{\hidepaste}
\tab{5}\spadcommand{evenRule( cos(x)**2 )\free{evenRule }}
\indentrel{3}\begin{verbatim}
                 2
   (11)  - sin(x)  + 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty11}
\begin{paste}{ugUserRulesPageEmpty11}{ugUserRulesPagePatch11}
\pastebutton{ugUserRulesPageEmpty11}{\showpaste}
\tab{5}\spadcommand{evenRule( cos(x)**2 )\free{evenRule }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch12}
\begin{paste}{ugUserRulesPageFull12}{ugUserRulesPageEmpty12}
\pastebutton{ugUserRulesPageFull12}{\hidepaste}
\tab{5}\spadcommand{sinCosProducts == rule
  sin(x) * sin(y) == (cos(x-y) - cos(x + y))/2
  cos(x) * cos(y) == (cos(x-y) + cos(x+y))/2
  sin(x) * cos(y) == (sin(x-y) + sin(x + y))/2
\bound{sinCosProducts }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty12}
\begin{paste}{ugUserRulesPageEmpty12}{ugUserRulesPagePatch12}
\pastebutton{ugUserRulesPageEmpty12}{\showpaste}
\tab{5}\spadcommand{sinCosProducts == rule
  sin(x) * sin(y) == (cos(x-y) - cos(x + y))/2
  cos(x) * cos(y) == (cos(x-y) + cos(x+y))/2
  sin(x) * cos(y) == (sin(x-y) + sin(x + y))/2
\bound{sinCosProducts }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch13}
\begin{paste}{ugUserRulesPageFull13}{ugUserRulesPageEmpty13}
\pastebutton{ugUserRulesPageFull13}{\hidepaste}
\tab{5}\spadcommand{g := sin(a)*sin(b) + cos(b)*cos(a) + sin(2*a)*cos(2*a)\bound{g }}
\indentrel{3}\begin{verbatim}
   (13)  sin(a)sin(b) + cos(2a)sin(2a) + cos(a)cos(b)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty13}
\begin{paste}{ugUserRulesPageEmpty13}{ugUserRulesPagePatch13}
\pastebutton{ugUserRulesPageEmpty13}{\showpaste}
\tab{5}\spadcommand{g := sin(a)*sin(b) + cos(b)*cos(a) + sin(2*a)*cos(2*a)\bound{g }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch14}
\begin{paste}{ugUserRulesPageFull14}{ugUserRulesPageEmpty14}
\pastebutton{ugUserRulesPageFull14}{\hidepaste}
\tab{5}\spadcommand{sinCosProducts g\free{sinCosProducts g }}
\indentrel{3}\begin{verbatim}
         sin(4a) + 2cos(b - a)
   (14)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                   2
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty14}
\begin{paste}{ugUserRulesPageEmpty14}{ugUserRulesPagePatch14}
\pastebutton{ugUserRulesPageEmpty14}{\showpaste}
\tab{5}\spadcommand{sinCosProducts g\free{sinCosProducts g }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch15}
\begin{paste}{ugUserRulesPageFull15}{ugUserRulesPageEmpty15}
\pastebutton{ugUserRulesPageFull15}{\hidepaste}
\tab{5}\spadcommand{exprule := rule exp(a + b) == exp(a) * exp(b)\bound{exprule }}
\indentrel{3}\begin{verbatim}
           b + a      a  b
   (15)  %e      == %e %e
  Type: RewriteRule(Integer,Integer,Expression Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty15}
\begin{paste}{ugUserRulesPageEmpty15}{ugUserRulesPagePatch15}
\pastebutton{ugUserRulesPageEmpty15}{\showpaste}
\tab{5}\spadcommand{exprule := rule exp(a + b) == exp(a) * exp(b)\bound{exprule }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch16}
\begin{paste}{ugUserRulesPageFull16}{ugUserRulesPageEmpty16}
\pastebutton{ugUserRulesPageFull16}{\hidepaste}
\tab{5}\spadcommand{exprule exp x\free{exprule }}
\indentrel{3}\begin{verbatim}
           x
   (16)  %e
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty16}
\begin{paste}{ugUserRulesPageEmpty16}{ugUserRulesPagePatch16}
\pastebutton{ugUserRulesPageEmpty16}{\showpaste}
\tab{5}\spadcommand{exprule exp x\free{exprule }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch17}
\begin{paste}{ugUserRulesPageFull17}{ugUserRulesPageEmpty17}
\pastebutton{ugUserRulesPageFull17}{\hidepaste}
\tab{5}\spadcommand{eirule := rule integral((?y + exp x)/x,x) == integral(y/x,x) + Ei x\bound{eirule }}
\indentrel{3}\begin{verbatim}
            x   %N
          Ú¿  %e   + y                   y
   (17)   ³   ÄÄÄÄÄÄÄÄ d%N  == 'integral(Ä,x) + 'Ei(x)
         ÀÙ      %N                      x
  Type: RewriteRule(Integer,Integer,Expression Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty17}
\begin{paste}{ugUserRulesPageEmpty17}{ugUserRulesPagePatch17}
\pastebutton{ugUserRulesPageEmpty17}{\showpaste}
\tab{5}\spadcommand{eirule := rule integral((?y + exp x)/x,x) == integral(y/x,x) + Ei x\bound{eirule }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch18}
\begin{paste}{ugUserRulesPageFull18}{ugUserRulesPageEmpty18}
\pastebutton{ugUserRulesPageFull18}{\hidepaste}
\tab{5}\spadcommand{eirule integral(exp u/u, u)\free{eirule }}
\indentrel{3}\begin{verbatim}
   (18)  Ei(u)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty18}
\begin{paste}{ugUserRulesPageEmpty18}{ugUserRulesPagePatch18}
\pastebutton{ugUserRulesPageEmpty18}{\showpaste}
\tab{5}\spadcommand{eirule integral(exp u/u, u)\free{eirule }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch19}
\begin{paste}{ugUserRulesPageFull19}{ugUserRulesPageEmpty19}
\pastebutton{ugUserRulesPageFull19}{\hidepaste}
\tab{5}\spadcommand{eirule integral(sin u + exp u/u, u)\free{eirule }}
\indentrel{3}\begin{verbatim}
            u
          Ú¿
   (19)   ³   sin(%N)d%N  + Ei(u)
         ÀÙ
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty19}
\begin{paste}{ugUserRulesPageEmpty19}{ugUserRulesPagePatch19}
\pastebutton{ugUserRulesPageEmpty19}{\showpaste}
\tab{5}\spadcommand{eirule integral(sin u + exp u/u, u)\free{eirule }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch20}
\begin{paste}{ugUserRulesPageFull20}{ugUserRulesPageEmpty20}
\pastebutton{ugUserRulesPageFull20}{\hidepaste}
\tab{5}\spadcommand{u := operator 'u\bound{u }}
\indentrel{3}\begin{verbatim}
   (20)  u
                                    Type: BasicOperator
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty20}
\begin{paste}{ugUserRulesPageEmpty20}{ugUserRulesPagePatch20}
\pastebutton{ugUserRulesPageEmpty20}{\showpaste}
\tab{5}\spadcommand{u := operator 'u\bound{u }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch21}
\begin{paste}{ugUserRulesPageFull21}{ugUserRulesPageEmpty21}
\pastebutton{ugUserRulesPageFull21}{\hidepaste}
\tab{5}\spadcommand{v := operator 'v\bound{v }}
\indentrel{3}\begin{verbatim}
   (21)  v
                                    Type: BasicOperator
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty21}
\begin{paste}{ugUserRulesPageEmpty21}{ugUserRulesPagePatch21}
\pastebutton{ugUserRulesPageEmpty21}{\showpaste}
\tab{5}\spadcommand{v := operator 'v\bound{v }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch22}
\begin{paste}{ugUserRulesPageFull22}{ugUserRulesPageEmpty22}
\pastebutton{ugUserRulesPageFull22}{\hidepaste}
\tab{5}\spadcommand{myRule := rule u(x + y) == u x + v y\free{u v }\bound{m }}
\indentrel{3}\begin{verbatim}
   (22)  u(y + x) == 'v(y) + 'u(x)
  Type: RewriteRule(Integer,Integer,Expression Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty22}
\begin{paste}{ugUserRulesPageEmpty22}{ugUserRulesPagePatch22}
\pastebutton{ugUserRulesPageEmpty22}{\showpaste}
\tab{5}\spadcommand{myRule := rule u(x + y) == u x + v y\free{u v }\bound{m }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch23}
\begin{paste}{ugUserRulesPageFull23}{ugUserRulesPageEmpty23}
\pastebutton{ugUserRulesPageFull23}{\hidepaste}
\tab{5}\spadcommand{myRule u(a + b + c + d)\free{m }}
\indentrel{3}\begin{verbatim}
   (23)  v(d + c + b) + u(a)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty23}
\begin{paste}{ugUserRulesPageEmpty23}{ugUserRulesPagePatch23}
\pastebutton{ugUserRulesPageEmpty23}{\showpaste}
\tab{5}\spadcommand{myRule u(a + b + c + d)\free{m }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch24}
\begin{paste}{ugUserRulesPageFull24}{ugUserRulesPageEmpty24}
\pastebutton{ugUserRulesPageFull24}{\hidepaste}
\tab{5}\spadcommand{myOtherRule := rule u(:x + y) == u x + v y\free{u v }\bound{m2 }}
\indentrel{3}\begin{verbatim}
   (24)  u(y + x) == 'v(y) + 'u(x)
  Type: RewriteRule(Integer,Integer,Expression Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty24}
\begin{paste}{ugUserRulesPageEmpty24}{ugUserRulesPagePatch24}
\pastebutton{ugUserRulesPageEmpty24}{\showpaste}
\tab{5}\spadcommand{myOtherRule := rule u(:x + y) == u x + v y\free{u v }\bound{m2 }}
\end{paste}\end{patch}

\begin{patch}{ugUserRulesPagePatch25}
\begin{paste}{ugUserRulesPageFull25}{ugUserRulesPageEmpty25}
\pastebutton{ugUserRulesPageFull25}{\hidepaste}
\tab{5}\spadcommand{myOtherRule u(a + b + c + d)\free{m2 }}
\indentrel{3}\begin{verbatim}
   (25)  v(c) + v(b) + v(a) + u(d)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugUserRulesPageEmpty25}
\begin{paste}{ugUserRulesPageEmpty25}{ugUserRulesPagePatch25}
\pastebutton{ugUserRulesPageEmpty25}{\showpaste}
\tab{5}\spadcommand{myOtherRule u(a + b + c + d)\free{m2 }}
\end{paste}\end{patch}

\end{chunk}
\chapter{Users Guide Chapter 7 (ug07.ht)}
\begin{chunk}{ug07.ht}
\newcommand{\optArg}[1]{{{\tt [}{#1}{\tt ]}}}
\newcommand{\argDef}[1]{{\tt ({#1})}}
\newcommand{\funSyntax}[2]{\axiomFun{#1}{\tt ({\small\it{#2}})}}
\newcommand{\funArgs}[1]{{\tt ({\small\it {#1}})}\newline}

\end{chunk}
\pagetitle{ugGraphPage}{ug07.ht}{Graphics}
\pageto{notitle}{ugGraphTwoDPage}
\pageto{notitle}{ugGraphThreeDPage}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphPage}{7. Graphics}
\beginscroll

%

This chapter shows how to use the Axiom graphics facilities under the
X Window System.  Axiom has \twodim{} and \threedim{} drawing and
rendering packages that allow the drawing, coloring, transforming,
mapping, clipping, and combining of graphic output from Axiom
computations.  This facility is particularly useful for investigating
problems in areas such as topology.  The graphics package is capable
of plotting functions of one or more variables or plotting parametric
surfaces and curves.  Various coordinate systems are also available,
such as polar and spherical.

A graph is displayed in a viewport window and it has a control-panel
that uses interactive mouse commands.  PostScript and other output
forms are available so that Axiom images can be printed or used by
other programs.\footnote{PostScript is a trademark of Adobe Systems
Incorporated, registered in the United States.}

\beginmenu
    \menudownlink{{7.1. Two-Dimensional Graphics}}{ugGraphTwoDPage}
    \menudownlink{{7.2. Three-Dimensional Graphics}}{ugGraphThreeDPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugGraphTwoDPage}{ug07.ht}{Two-Dimensional Graphics}
\pageto{notitle}{ugGraphTwoDPlotPage}
\pageto{notitle}{ugGraphTwoDParPage}
\pageto{notitle}{ugGraphTwoDPlanePage}
\pageto{notitle}{ugGraphTwoDOptionsPage}
\pageto{notitle}{ugGraphColorPage}
\pageto{notitle}{ugGraphColorPalettePage}
\pageto{notitle}{ugGraphTwoDControlPage}
\pageto{notitle}{ugGraphTwoDopsPage}
\pageto{notitle}{ugGraphTwoDbuildPage}
\pageto{notitle}{ugGraphTwoDappendPage}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphTwoDPage}{7.1. Two-Dimensional Graphics}
\beginscroll
%
The Axiom \twodim{} graphics package provides the ability to
display
%
\indent{4}
\beginitems
%
\item[-] curves defined by functions of a single real variable
%
\item[-] curves defined by parametric equations
%
\item[-] implicit non-singular curves defined by polynomial equations
%
\item[-] planar graphs generated from lists of point components.
\enditems
\indent{0}
These graphs
can be modified by specifying various options, such as
calculating points in the polar
coordinate system or changing the size of the graph viewport window.

\beginmenu
\menudownlink{{7.1.1. Plotting Two-Dimensional Functions of One Variable}}
{ugGraphTwoDPlotPage}
\menudownlink{{7.1.2. Plotting Two-Dimensional Parametric Plane Curves}}
{ugGraphTwoDParPage}
\menudownlink{{7.1.3. Plotting Plane Algebraic Curves}}
{ugGraphTwoDPlanePage}
\menudownlink{{7.1.4. Two-Dimensional Options}}{ugGraphTwoDOptionsPage}
\menudownlink{{7.1.5. Color}}{ugGraphColorPage}
\menudownlink{{7.1.6. Palette}}{ugGraphColorPalettePage}
\menudownlink{{7.1.7. Two-Dimensional Control-Panel}}
{ugGraphTwoDControlPage}
\menudownlink{{7.1.8. Operations for Two-Dimensional Graphics}}
{ugGraphTwoDopsPage}
\menudownlink{{7.1.9. Addendum: Building Two-Dimensional Graphs}}
{ugGraphTwoDbuildPage}
\menudownlink{
{7.1.10. Addendum: Appending a Graph to a Viewport Window 
Containing a Graph}}{ugGraphTwoDappendPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugGraphTwoDPlotPage}{ug07.ht}
{Plotting Two-Dimensional Functions of One Variable}
\pageto{notitle}{ugGraphTwoDOptionsPage}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphTwoDPlotPage}
{7.1.1. Plotting Two-Dimensional Functions of One Variable}
\beginscroll

The first kind of \twodim{} graph is that of a curve defined by a
function \axiom{y = f(x)} over a finite interval of the \axiom{x}
axis.

%
\beginImportant
The general format for drawing a function defined by a formula
\axiom{f(x)} is:
%
\centerline{{{\tt draw(f(x), x = a..b, {\it options})}}}
where \axiom{a..b} defines the range of \axiom{x}, and where
{\it options} prescribes zero or more options as described in
\downlink{``Two-Dimensional Options''}{ugGraphTwoDOptionsPage} 
in Section 7.1.4\ignore{ugGraphTwoDOptions}.
An example of an option is \axiom{curveColor == bright red().}
An alternative format involving functions \axiom{f} and \axiom{g}
is also available.
\endImportant

A simple way to plot a function is to use a formula.  The first
argument is the formula.  For the second argument, write the name of
the independent variable (here, \axiom{x}), followed by an
\spadSyntax{=}, and the range of values.

\psXtc{
Display this formula over the range
\texht{$0 \leq x \leq 6$}{0 <= x <= 6}.
Axiom converts your formula to a compiled
function so that the results can be computed
quickly and efficiently.
}{
\graphpaste{draw(sin(tan(x)) - tan(sin(x)),x = 0..6)}
}{
\epsffile[0 0 295 295]{../ps/2d1vara.ps}
}

Notice that Axiom compiled the function before the graph was put
on the screen.

\psXtc{
Here is the same graph on a different interval.
This time we give the graph a title.
}{
\graphpaste{draw(sin(tan(x)) - tan(sin(x)),x = 10..16)}
}{
%window was 300 x 300
\epsffile[0 0 295 295]{../ps/2d1varb.ps}
}
%
Once again the formula is converted to a compiled function before
any points were computed.
If you want to graph the same function on several intervals, it is
a good idea to define the function first so that the function has
to be compiled only once.
\xtc{
This time we first define the function.
}{
\spadpaste{f(x) == (x-1)*(x-2)*(x-3) \bound{f}}
}
\psXtc{
To draw the function, the first argument is its name
and the second is just the range with no independent variable.
}{
\graphpaste{draw(f, 0..4) \free{f}}
}{
\epsffile[0 0 295 295]{../ps/2d1vard.ps}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugGraphTwoDPlotPagePatch1}
\begin{paste}{ugGraphTwoDPlotPageFull1}{ugGraphTwoDPlotPageEmpty1}
\pastebutton{ugGraphTwoDPlotPageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(sin(tan(x)) - tan(sin(x)),x = 0..6)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphtwodplotpage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphtwodplotpage1}}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDPlotPageEmpty1}
\begin{paste}{ugGraphTwoDPlotPageEmpty1}{ugGraphTwoDPlotPagePatch1}
\pastebutton{ugGraphTwoDPlotPageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(sin(tan(x)) - tan(sin(x)),x = 0..6)}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDPlotPagePatch2}
\begin{paste}{ugGraphTwoDPlotPageFull2}{ugGraphTwoDPlotPageEmpty2}
\pastebutton{ugGraphTwoDPlotPageFull2}{\hidepaste}
\tab{5}\spadgraph{draw(sin(tan(x)) - tan(sin(x)),x = 10..16)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphtwodplotpage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphtwodplotpage2}}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDPlotPageEmpty2}
\begin{paste}{ugGraphTwoDPlotPageEmpty2}{ugGraphTwoDPlotPagePatch2}
\pastebutton{ugGraphTwoDPlotPageEmpty2}{\showpaste}
\tab{5}\spadgraph{draw(sin(tan(x)) - tan(sin(x)),x = 10..16)}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDPlotPagePatch3}
\begin{paste}{ugGraphTwoDPlotPageFull3}{ugGraphTwoDPlotPageEmpty3}
\pastebutton{ugGraphTwoDPlotPageFull3}{\hidepaste}
\tab{5}\spadcommand{f(x) == (x-1)*(x-2)*(x-3)\bound{f }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDPlotPageEmpty3}
\begin{paste}{ugGraphTwoDPlotPageEmpty3}{ugGraphTwoDPlotPagePatch3}
\pastebutton{ugGraphTwoDPlotPageEmpty3}{\showpaste}
\tab{5}\spadcommand{f(x) == (x-1)*(x-2)*(x-3)\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDPlotPagePatch4}
\begin{paste}{ugGraphTwoDPlotPageFull4}{ugGraphTwoDPlotPageEmpty4}
\pastebutton{ugGraphTwoDPlotPageFull4}{\hidepaste}
\tab{5}\spadgraph{draw(f, 0..4)\free{f }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphtwodplotpage4.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphtwodplotpage4}}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDPlotPageEmpty4}
\begin{paste}{ugGraphTwoDPlotPageEmpty4}{ugGraphTwoDPlotPagePatch4}
\pastebutton{ugGraphTwoDPlotPageEmpty4}{\showpaste}
\tab{5}\spadgraph{draw(f, 0..4)\free{f }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugGraphTwoDParPage}{ug07.ht}
{Plotting 2D Parametric Plane Curves}
\pageto{notitle}{ugGraphThreeDOptionsPage}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphTwoDParPage}
{7.1.2. Plotting 2D Parametric Plane Curves}
\beginscroll

The second kind of \twodim{} graph is that of
curves produced by parametric equations.
Let \axiom{x = f(t)} and \axiom{y = g(t)} be formulas or two
functions \axiom{f} and \axiom{g} as the parameter \axiom{t} ranges
over an interval \axiom{[a,b]}.
The function \axiomFun{curve} takes the two functions \axiom{f} and
\axiom{g} as its parameters.

\beginImportant
The general format for drawing a \twodim{} plane curve defined by
parametric formulas \axiom{x = f(t)} and \axiom{y = g(t)} is:
%
\centerline{{{\tt draw(curve(f(t), g(t)), t = a..b, {\it options})}}}
where \axiom{a..b} defines the range of the independent variable \axiom{t},
and where {\it options} prescribes zero or more options as
described in 
\downlink{``Three-Dimensional Options''}{ugGraphThreeDOptionsPage} 
in Section 7.2.4\ignore{ugGraphThreeDOptions}.
An example of an option is \axiom{curveColor == bright red().}
\endImportant

Here's an example:

\psXtc{
Define a parametric curve using a range involving
\axiom{\%pi}, Axiom's way of saying \texht{$\pi$}{``pi''}.
For parametric curves, Axiom compiles two
functions, one for each of the functions \axiom{f} and \axiom{g}.
}{
\graphpaste{draw(curve(sin(t)*sin(2*t)*sin(3*t), 
sin(4*t)*sin(5*t)*sin(6*t)), t = 0..2*\%pi)}
}{
\epsffile[0 0 295 295]{../ps/2dppca.ps}
}
%
%
\psXtc{
The title may be an arbitrary string and is an
optional argument to the \axiomFun{draw} command.
}{
\graphpaste{draw(curve(cos(t), sin(t)), t = 0..2*\%pi)}
}{
\epsffile[0 0 295 295]{../ps/2dppcb.ps}
}
%
If you plan on plotting \axiom{x = f(t)}, \axiom{y = g(t)} as \axiom{t} 
ranges over several intervals, you may want to define functions 
\axiom{f} and \axiom{g} first, so
that they need not be recompiled every time you create a new graph.
Here's an example:
\xtc{
As before, you can first define the functions you wish to draw.
}{
\spadpaste{f(t:DFLOAT):DFLOAT == sin(3*t/4) \bound{f}}
}
\xtc{
Axiom compiles them to map \axiomType{DoubleFloat}
values to \axiomType{DoubleFloat} values.
}{
\spadpaste{g(t:DFLOAT):DFLOAT == sin(t) \bound{g}}
}

\psXtc{
Give to {\tt curve} the names of the functions,
then write the range without the name of the
independent variable.
}{
\graphpaste{draw(curve(f,g),0..\%pi) \free{f g}}
}{
\epsffile[0 0 295 295]{../ps/2dppcc.ps}
}
%
%
\psXtc{
Here is another look at the same curve but over a different
range. Notice that \axiom{f} and \axiom{g} are not recompiled.
Also note that Axiom provides a default title based on
the first function specified in \axiomFun{curve}.
}{
\graphpaste{draw(curve(f,g),-4*\%pi..4*\%pi) \free{f g}}
}{
\epsffile[0 0 295 295]{../ps/2dppce.ps}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugGraphTwoDParPagePatch1}
\begin{paste}{ugGraphTwoDParPageFull1}{ugGraphTwoDParPageEmpty1}
\pastebutton{ugGraphTwoDParPageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(curve(sin(t)*sin(2*t)*sin(3*t), sin(4*t)*sin(5*t)*sin(6*t)), t = 0..2*\%pi)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphtwodparpage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphtwodparpage1}}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDParPageEmpty1}
\begin{paste}{ugGraphTwoDParPageEmpty1}{ugGraphTwoDParPagePatch1}
\pastebutton{ugGraphTwoDParPageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(curve(sin(t)*sin(2*t)*sin(3*t), sin(4*t)*sin(5*t)*sin(6*t)), t = 0..2*\%pi)}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDParPagePatch2}
\begin{paste}{ugGraphTwoDParPageFull2}{ugGraphTwoDParPageEmpty2}
\pastebutton{ugGraphTwoDParPageFull2}{\hidepaste}
\tab{5}\spadgraph{draw(curve(cos(t), sin(t)), t = 0..2*\%pi)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphtwodparpage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphtwodparpage2}}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDParPageEmpty2}
\begin{paste}{ugGraphTwoDParPageEmpty2}{ugGraphTwoDParPagePatch2}
\pastebutton{ugGraphTwoDParPageEmpty2}{\showpaste}
\tab{5}\spadgraph{draw(curve(cos(t), sin(t)), t = 0..2*\%pi)}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDParPagePatch3}
\begin{paste}{ugGraphTwoDParPageFull3}{ugGraphTwoDParPageEmpty3}
\pastebutton{ugGraphTwoDParPageFull3}{\hidepaste}
\tab{5}\spadcommand{f(t:DFLOAT):DFLOAT == sin(3*t/4)\bound{f }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDParPageEmpty3}
\begin{paste}{ugGraphTwoDParPageEmpty3}{ugGraphTwoDParPagePatch3}
\pastebutton{ugGraphTwoDParPageEmpty3}{\showpaste}
\tab{5}\spadcommand{f(t:DFLOAT):DFLOAT == sin(3*t/4)\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDParPagePatch4}
\begin{paste}{ugGraphTwoDParPageFull4}{ugGraphTwoDParPageEmpty4}
\pastebutton{ugGraphTwoDParPageFull4}{\hidepaste}
\tab{5}\spadcommand{g(t:DFLOAT):DFLOAT == sin(t)\bound{g }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDParPageEmpty4}
\begin{paste}{ugGraphTwoDParPageEmpty4}{ugGraphTwoDParPagePatch4}
\pastebutton{ugGraphTwoDParPageEmpty4}{\showpaste}
\tab{5}\spadcommand{g(t:DFLOAT):DFLOAT == sin(t)\bound{g }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDParPagePatch5}
\begin{paste}{ugGraphTwoDParPageFull5}{ugGraphTwoDParPageEmpty5}
\pastebutton{ugGraphTwoDParPageFull5}{\hidepaste}
\tab{5}\spadgraph{draw(curve(f,g),0..\%pi)\free{f g }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphtwodparpage5.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphtwodparpage5}}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDParPageEmpty5}
\begin{paste}{ugGraphTwoDParPageEmpty5}{ugGraphTwoDParPagePatch5}
\pastebutton{ugGraphTwoDParPageEmpty5}{\showpaste}
\tab{5}\spadgraph{draw(curve(f,g),0..\%pi)\free{f g }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDParPagePatch6}
\begin{paste}{ugGraphTwoDParPageFull6}{ugGraphTwoDParPageEmpty6}
\pastebutton{ugGraphTwoDParPageFull6}{\hidepaste}
\tab{5}\spadgraph{draw(curve(f,g),-4*\%pi..4*\%pi)\free{f g }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphtwodparpage6.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphtwodparpage6}}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDParPageEmpty6}
\begin{paste}{ugGraphTwoDParPageEmpty6}{ugGraphTwoDParPagePatch6}
\pastebutton{ugGraphTwoDParPageEmpty6}{\showpaste}
\tab{5}\spadgraph{draw(curve(f,g),-4*\%pi..4*\%pi)\free{f g }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugGraphTwoDPlanePage}{ug07.ht}{Plotting Plane Algebraic Curves}
\pageto{notitle}{ugGraphTwoDOptionsPage}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphTwoDPlanePage}{7.1.3. Plotting Plane Algebraic Curves}
\beginscroll

A third kind of \twodim{} graph is a non-singular ``solution curve''
in a rectangular region of the plane.
A solution curve is a curve defined by a polynomial equation
\axiom{p(x,y) = 0}.
Non-singular means that the curve is ``smooth'' in that it does not
cross itself or come to a point (cusp).
Algebraically, this means that for any point \axiom{(x,y)} on the curve,
that is, a point such that \axiom{p(x,y) = 0}, the partial derivatives
\texht{${{\partial p}\over{\partial x}}(x,y)$ and
${{\partial p}\over{\partial y}}(x,y)$}{\axiom{dp/dx(x,y)}
and \axiom{dp/dy(a,b)}}
are not both zero.

%
\beginImportant
The general format for drawing a non-singular solution curve
given by a polynomial of the form \axiom{p(x,y) = 0} is:
%
\centerline{{{\tt draw(p(x,y) = 0, x, y, range == [a..b, c..d], 
{\it options})}}}
where the second and third arguments name the first and second
independent variables of \axiom{p}.
A {\tt range} option is always given to designate a bounding
rectangular region of the plane \texht{$a \leq x \leq b, c \leq y
\leq d$}{a <= x <= b, c <= y <= d}.
Zero or more additional options as described in
\downlink{``Two-Dimensional Options''}{ugGraphTwoDOptionsPage} 
in Section 7.1.4\ignore{ugGraphTwoDOptions} 
may be given.
\endImportant

\xtc{
We require that the polynomial has rational or integral coefficients.
Here is an algebraic curve example (``Cartesian ovals''):
}{
\spadpaste{p := ((x**2 + y**2 + 1) - 8*x)**2 - 
(8*(x**2 + y**2 + 1)-4*x-1) \bound{p}}
}

\psXtc{
The first argument is always expressed as an equation of the form 
\axiom{p = 0} where \axiom{p} is a polynomial.
}{
\graphpaste{draw(p = 0, x, y, range == [-1..11, -7..7]) \free{p}}
}{
\epsffile[0 0 295 295]{../ps/2dpaca.ps}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugGraphTwoDPlanePagePatch1}
\begin{paste}{ugGraphTwoDPlanePageFull1}{ugGraphTwoDPlanePageEmpty1}
\pastebutton{ugGraphTwoDPlanePageFull1}{\hidepaste}
\tab{5}\spadcommand{p := ((x**2 + y**2 + 1) - 8*x)**2 - (8*(x**2 + y**2 + 1)-4*x-1)\bound{p }}
\indentrel{3}\begin{verbatim}
   (1)
    4      2            2    4      3      2
   y  + (2x  - 16x - 6)y  + x  - 16x  + 58x  - 12x - 6
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDPlanePageEmpty1}
\begin{paste}{ugGraphTwoDPlanePageEmpty1}{ugGraphTwoDPlanePagePatch1}
\pastebutton{ugGraphTwoDPlanePageEmpty1}{\showpaste}
\tab{5}\spadcommand{p := ((x**2 + y**2 + 1) - 8*x)**2 - (8*(x**2 + y**2 + 1)-4*x-1)\bound{p }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDPlanePagePatch2}
\begin{paste}{ugGraphTwoDPlanePageFull2}{ugGraphTwoDPlanePageEmpty2}
\pastebutton{ugGraphTwoDPlanePageFull2}{\hidepaste}
\tab{5}\spadgraph{draw(p = 0, x, y, range == [-1..11, -7..7])\free{p }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphtwodplanepage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphtwodplanepage2}}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDPlanePageEmpty2}
\begin{paste}{ugGraphTwoDPlanePageEmpty2}{ugGraphTwoDPlanePagePatch2}
\pastebutton{ugGraphTwoDPlanePageEmpty2}{\showpaste}
\tab{5}\spadgraph{draw(p = 0, x, y, range == [-1..11, -7..7])\free{p }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugGraphTwoDOptionsPage}{ug07.ht}{Two-Dimensional Options}
\pageto{notitle}{ugGraphColorPage}
\pageto{notitle}{ugGraphColorPalettePage}
\pageto{notitle}{ugGraphColorPage}
\pageto{notitle}{ugGraphColorPalettePage}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphTwoDOptionsPage}{7.1.4. Two-Dimensional Options}
\beginscroll

The \axiomFun{draw} commands take an optional list of options,
such as {\tt title} shown above.
Each option is given by the syntax: {\it name} {\tt ==} {\it value}.
Here is a list of the available options in the order that they are
described below.

\table{ {adaptive} {clip} {unit} {clip} {curveColor} {range}
{toScale} {pointColor} {coordinates}}

The \axiom{adaptive} option turns adaptive plotting on or off.
Adaptive plotting uses an algorithm that traverses a graph and computes
more points for those parts of the graph with high curvature.
The higher the curvature of a region is, the more points the algorithm
computes.
%
%
\psXtc{
The {\tt adaptive} option is normally on.
Here we turn it off.
}{
\graphpaste{draw(sin(1/x),x=-2*\%pi..2*\%pi, adaptive == false)}
}{
\epsffile[0 0 295 295]{../ps/2doptad.ps}
}
%
%
\psXtc{
The {\tt clip} option turns clipping on or off.
If on, large values are cut off according to
\axiomFunFrom{clipPointsDefault}{GraphicsDefaults}.
}{
\graphpaste{draw(tan(x),x=-2*\%pi..2*\%pi, clip == true)}
}{
\epsffile[0 0 295 295]{../ps/2doptcp.ps}
}
%
%
\psXtc{
Option {\tt toScale} does plotting to scale if {\tt true} or uses
the entire viewport if {\tt false}.
The default can be determined using
\axiomFunFrom{drawToScale}{GraphicsDefaults}.
}{
\graphpaste{draw(sin(x),x=-\%pi..\%pi, toScale == true, unit == [1.0,1.0])}
}{
\epsffile[0 0 295 295]{../ps/2doptsc.ps}
}
%
%
\psXtc{
Option {\tt clip} with a range sets point clipping of a graph within the
ranges specified in the list \axiom{[x range,y range]}.
If only one range is specified, clipping applies to the y-axis.
}{
\graphpaste{draw(sec(x),x=-2*\%pi..2*\%pi, 
clip == [-2*\%pi..2*\%pi,-\%pi..\%pi], unit == [1.0,1.0])}
}{
\epsffile[0 0 295 295]{../ps/2doptcpr.ps}
}
%
\psXtc{
Option {\tt curveColor} sets the color of the graph curves or 
lines to be the indicated palette color
(see \downlink{``Color''}{ugGraphColorPage} in Section 
7.1.5\ignore{ugGraphColor} and 
\downlink{``Palette''}{ugGraphColorPalettePage} 
in Section 7.1.6\ignore{ugGraphColorPalette}).
}{
\graphpaste{draw(sin(x),x=-\%pi..\%pi, curveColor == bright red())}
}{
\epsffile[0 0 295 295]{../ps/2doptcvc.ps}
}
%
\psXtc{
Option {\tt pointColor}
sets the color of the graph points to the indicated
palette color
(see \downlink{``Color''}{ugGraphColorPage} 
in Section 7.1.5\ignore{ugGraphColor} and 
\downlink{``Palette''}{ugGraphColorPalettePage} 
in Section 7.1.6\ignore{ugGraphColorPalette}).
}{
\graphpaste{draw(sin(x),x=-\%pi..\%pi, pointColor == pastel yellow())}
}{
\epsffile[0 0 295 295]{../ps/2doptptc.ps}
}
%
\psXtc{
Option {\tt unit} sets the intervals at which the axis units are plotted
according to the indicated steps [\axiom{x} interval, \axiom{y} interval].
}{
\graphpaste{draw(curve(9*sin(3*t/4),8*sin(t)), 
t = -4*\%pi..4*\%pi, unit == [2.0,1.0])}
}{
\epsffile[0 0 295 295]{../ps/2doptut.ps}
}
%
%
\psXtc{
Option {\tt range} sets the range of variables in a graph to be
within the ranges
for solving plane algebraic curve plots.
}{
\graphpaste{draw(y**2 + y - (x**3 - x) = 0, x, y, 
range == [-2..2,-2..1], unit==[1.0,1.0])}
}{
\epsffile[0 0 295 295]{../ps/2doptrga.ps}
}
%
%
\psXtc{
A second example of a solution plot.
}{
\graphpaste{draw(x**2 + y**2 = 1, x, y, 
range == [-3/2..3/2,-3/2..3/2], unit==[0.5,0.5])}
}{
\epsffile[0 0 295 295]{../ps/2doptrgb.ps}
}
%
%
\psXtc{
Option \axiom{coordinates} indicates the coordinate system
in which the graph
is plotted.
The default is to use the Cartesian coordinate system.
For more details, see 
\downlink{``Coordinate System Transformations''}{ugGraphCoordPage} in 
Section 7.2.7\ignore{ugGraphCoord} \texht{.}{or
\axiomType{CoordinateSystems}.}
}{
\graphpaste{draw(curve(sin(5*t),t),t=0..2*\%pi, coordinates == polar)}
}{
\epsffile[0 0 295 295]{../ps/2doptplr.ps}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugGraphTwoDOptionsPagePatch1}
\begin{paste}{ugGraphTwoDOptionsPageFull1}{ugGraphTwoDOptionsPageEmpty1}
\pastebutton{ugGraphTwoDOptionsPageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(sin(1/x),x=-2*\%pi..2*\%pi, adaptive == false)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphtwodoptionspage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphtwodoptionspage1}}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDOptionsPageEmpty1}
\begin{paste}{ugGraphTwoDOptionsPageEmpty1}{ugGraphTwoDOptionsPagePatch1}
\pastebutton{ugGraphTwoDOptionsPageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(sin(1/x),x=-2*\%pi..2*\%pi, adaptive == false)}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDOptionsPagePatch2}
\begin{paste}{ugGraphTwoDOptionsPageFull2}{ugGraphTwoDOptionsPageEmpty2}
\pastebutton{ugGraphTwoDOptionsPageFull2}{\hidepaste}
\tab{5}\spadgraph{draw(tan(x),x=-2*\%pi..2*\%pi, clip == true)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphtwodoptionspage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphtwodoptionspage2}}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDOptionsPageEmpty2}
\begin{paste}{ugGraphTwoDOptionsPageEmpty2}{ugGraphTwoDOptionsPagePatch2}
\pastebutton{ugGraphTwoDOptionsPageEmpty2}{\showpaste}
\tab{5}\spadgraph{draw(tan(x),x=-2*\%pi..2*\%pi, clip == true)}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDOptionsPagePatch3}
\begin{paste}{ugGraphTwoDOptionsPageFull3}{ugGraphTwoDOptionsPageEmpty3}
\pastebutton{ugGraphTwoDOptionsPageFull3}{\hidepaste}
\tab{5}\spadgraph{draw(sin(x),x=-\%pi..\%pi, toScale == true, unit == [1.0,1.0])}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphtwodoptionspage3.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphtwodoptionspage3}}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDOptionsPageEmpty3}
\begin{paste}{ugGraphTwoDOptionsPageEmpty3}{ugGraphTwoDOptionsPagePatch3}
\pastebutton{ugGraphTwoDOptionsPageEmpty3}{\showpaste}
\tab{5}\spadgraph{draw(sin(x),x=-\%pi..\%pi, toScale == true, unit == [1.0,1.0])}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDOptionsPagePatch4}
\begin{paste}{ugGraphTwoDOptionsPageFull4}{ugGraphTwoDOptionsPageEmpty4}
\pastebutton{ugGraphTwoDOptionsPageFull4}{\hidepaste}
\tab{5}\spadgraph{draw(sec(x),x=-2*\%pi..2*\%pi, clip == [-2*\%pi..2*\%pi,-\%pi..\%pi], unit == [1.0,1.0])}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphtwodoptionspage4.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphtwodoptionspage4}}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDOptionsPageEmpty4}
\begin{paste}{ugGraphTwoDOptionsPageEmpty4}{ugGraphTwoDOptionsPagePatch4}
\pastebutton{ugGraphTwoDOptionsPageEmpty4}{\showpaste}
\tab{5}\spadgraph{draw(sec(x),x=-2*\%pi..2*\%pi, clip == [-2*\%pi..2*\%pi,-\%pi..\%pi], unit == [1.0,1.0])}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDOptionsPagePatch5}
\begin{paste}{ugGraphTwoDOptionsPageFull5}{ugGraphTwoDOptionsPageEmpty5}
\pastebutton{ugGraphTwoDOptionsPageFull5}{\hidepaste}
\tab{5}\spadgraph{draw(sin(x),x=-\%pi..\%pi, curveColor == bright red())}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphtwodoptionspage5.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphtwodoptionspage5}}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDOptionsPageEmpty5}
\begin{paste}{ugGraphTwoDOptionsPageEmpty5}{ugGraphTwoDOptionsPagePatch5}
\pastebutton{ugGraphTwoDOptionsPageEmpty5}{\showpaste}
\tab{5}\spadgraph{draw(sin(x),x=-\%pi..\%pi, curveColor == bright red())}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDOptionsPagePatch6}
\begin{paste}{ugGraphTwoDOptionsPageFull6}{ugGraphTwoDOptionsPageEmpty6}
\pastebutton{ugGraphTwoDOptionsPageFull6}{\hidepaste}
\tab{5}\spadgraph{draw(sin(x),x=-\%pi..\%pi, pointColor == pastel yellow())}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphtwodoptionspage6.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphtwodoptionspage6}}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDOptionsPageEmpty6}
\begin{paste}{ugGraphTwoDOptionsPageEmpty6}{ugGraphTwoDOptionsPagePatch6}
\pastebutton{ugGraphTwoDOptionsPageEmpty6}{\showpaste}
\tab{5}\spadgraph{draw(sin(x),x=-\%pi..\%pi, pointColor == pastel yellow())}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDOptionsPagePatch7}
\begin{paste}{ugGraphTwoDOptionsPageFull7}{ugGraphTwoDOptionsPageEmpty7}
\pastebutton{ugGraphTwoDOptionsPageFull7}{\hidepaste}
\tab{5}\spadgraph{draw(curve(9*sin(3*t/4),8*sin(t)), t = -4*\%pi..4*\%pi, unit == [2.0,1.0])}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphtwodoptionspage7.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphtwodoptionspage7}}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDOptionsPageEmpty7}
\begin{paste}{ugGraphTwoDOptionsPageEmpty7}{ugGraphTwoDOptionsPagePatch7}
\pastebutton{ugGraphTwoDOptionsPageEmpty7}{\showpaste}
\tab{5}\spadgraph{draw(curve(9*sin(3*t/4),8*sin(t)), t = -4*\%pi..4*\%pi, unit == [2.0,1.0])}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDOptionsPagePatch8}
\begin{paste}{ugGraphTwoDOptionsPageFull8}{ugGraphTwoDOptionsPageEmpty8}
\pastebutton{ugGraphTwoDOptionsPageFull8}{\hidepaste}
\tab{5}\spadgraph{draw(y**2 + y - (x**3 - x) = 0, x, y, range == [-2..2,-2..1], unit==[1.0,1.0])}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphtwodoptionspage8.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphtwodoptionspage8}}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDOptionsPageEmpty8}
\begin{paste}{ugGraphTwoDOptionsPageEmpty8}{ugGraphTwoDOptionsPagePatch8}
\pastebutton{ugGraphTwoDOptionsPageEmpty8}{\showpaste}
\tab{5}\spadgraph{draw(y**2 + y - (x**3 - x) = 0, x, y, range == [-2..2,-2..1], unit==[1.0,1.0])}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDOptionsPagePatch9}
\begin{paste}{ugGraphTwoDOptionsPageFull9}{ugGraphTwoDOptionsPageEmpty9}
\pastebutton{ugGraphTwoDOptionsPageFull9}{\hidepaste}
\tab{5}\spadgraph{draw(x**2 + y**2 = 1, x, y, range == [-3/2..3/2,-3/2..3/2], unit==[0.5,0.5])}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphtwodoptionspage9.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphtwodoptionspage9}}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDOptionsPageEmpty9}
\begin{paste}{ugGraphTwoDOptionsPageEmpty9}{ugGraphTwoDOptionsPagePatch9}
\pastebutton{ugGraphTwoDOptionsPageEmpty9}{\showpaste}
\tab{5}\spadgraph{draw(x**2 + y**2 = 1, x, y, range == [-3/2..3/2,-3/2..3/2], unit==[0.5,0.5])}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDOptionsPagePatch10}
\begin{paste}{ugGraphTwoDOptionsPageFull10}{ugGraphTwoDOptionsPageEmpty10}
\pastebutton{ugGraphTwoDOptionsPageFull10}{\hidepaste}
\tab{5}\spadgraph{draw(curve(sin(5*t),t),t=0..2*\%pi, coordinates == polar)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphtwodoptionspage10.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphtwodoptionspage10}}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDOptionsPageEmpty10}
\begin{paste}{ugGraphTwoDOptionsPageEmpty10}{ugGraphTwoDOptionsPagePatch10}
\pastebutton{ugGraphTwoDOptionsPageEmpty10}{\showpaste}
\tab{5}\spadgraph{draw(curve(sin(5*t),t),t=0..2*\%pi, coordinates == polar)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugGraphColorPage}{ug07.ht}{Color}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphColorPage}{7.1.5. Color}
\beginscroll

The domain \axiomType{Color} provides operations for manipulating
colors in \twodim{} graphs.  Colors are objects of \axiomType{Color}.
Each color has a {\it hue} and a {\it weight}.  Hues are represented
by integers that range from \axiom{1} to the
\axiomFunFrom{numberOfHues()}{Color}, normally \axiom{27}.  Weights
are floats and have the value \axiom{1.0} by default.

\indent{0}
\beginitems
%
\item[\axiomFun{color}]\funArgs{integer}
creates a color of hue {\it integer} and weight \axiom{1.0}.
%
\item[\axiomFun{hue}]\funArgs{color}
returns the hue of {\it color} as an integer.
%
\item[\axiomFun{red}]\funArgs{},
\funSyntax{blue}{},
\funSyntax{green}{}, and \funSyntax{yellow}{}
create colors of that hue with weight \axiom{1.0}.
%
\item[\subscriptIt{color}{1} {\tt +} \subscriptIt{color}{2}] returns the
color that results from additively combining the indicated
\subscriptIt{color}{1} and \subscriptIt{color}{2}.
Color addition is not commutative: changing the order of the arguments
produces different results.
%
\item[{\it integer} {\tt *} {\it color}]
changes the weight of {\it color} by {\it integer}
without affecting its hue.
For example,
\axiom{red() + 3*yellow()} produces a color closer to yellow than to red.
Color multiplication is not associative: changing the order of grouping
produces different results.
\enditems
\indent{0}
%
\psXtc{
These functions can be used to change the point and curve colors
for two- and \threedim{} graphs.
Use the {\tt pointColor} option for points.
}{
\graphpaste{draw(x**2,x=-1..1,pointColor == green())}
}{
\epsffile[0 0 295 295]{../ps/23dcola.ps}
}
%
\psXtc{
Use the {\tt curveColor} option for curves.
}{
\graphpaste{draw(x**2,x=-1..1,curveColor == color(13) + 2*blue())}
}{
\epsffile[0 0 295 295]{../ps/23dcolb.ps}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugGraphColorPagePatch1}
\begin{paste}{ugGraphColorPageFull1}{ugGraphColorPageEmpty1}
\pastebutton{ugGraphColorPageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(x**2,x=-1..1,pointColor == green())}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphcolorpage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphcolorpage1}}
\end{paste}\end{patch}

\begin{patch}{ugGraphColorPageEmpty1}
\begin{paste}{ugGraphColorPageEmpty1}{ugGraphColorPagePatch1}
\pastebutton{ugGraphColorPageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(x**2,x=-1..1,pointColor == green())}
\end{paste}\end{patch}

\begin{patch}{ugGraphColorPagePatch2}
\begin{paste}{ugGraphColorPageFull2}{ugGraphColorPageEmpty2}
\pastebutton{ugGraphColorPageFull2}{\hidepaste}
\tab{5}\spadgraph{draw(x**2,x=-1..1,curveColor == color(13) + 2*blue())}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphcolorpage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphcolorpage2}}
\end{paste}\end{patch}

\begin{patch}{ugGraphColorPageEmpty2}
\begin{paste}{ugGraphColorPageEmpty2}{ugGraphColorPagePatch2}
\pastebutton{ugGraphColorPageEmpty2}{\showpaste}
\tab{5}\spadgraph{draw(x**2,x=-1..1,curveColor == color(13) + 2*blue())}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugGraphColorPalettePage}{ug07.ht}{Palette}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphColorPalettePage}{7.1.6. Palette}
\beginscroll

Domain \axiomType{Palette} is the domain of shades of colors:
\axiomFun{dark}, \axiomFun{dim}, \axiomFun{bright}, 
\axiomFun{pastel}, and \axiomFun{light},
designated by the integers \axiom{1} through \axiom{5}, respectively.
\xtc{
Colors are normally ``bright.''
}{
\spadpaste{shade red()}
}
\xtc{
To change the shade of a color, apply the name of a shade to it.
}{
\spadpaste{myFavoriteColor := dark blue() \bound{mfc}}
}
\xtc{
The expression \axiom{shade(color)}
returns the value of a shade of \axiom{color}.
}{
\spadpaste{shade myFavoriteColor \free{mfc}}
}
\xtc{
The expression \axiom{hue(color)} returns its hue.
}{
\spadpaste{hue myFavoriteColor \free{mfc}}
}
\psXtc{
Palettes can be used in specifying colors in \twodim{} graphs.
}{
\graphpaste{draw(x**2,x=-1..1,curveColor == dark blue())}
}{
\epsffile[0 0 295 295]{../ps/23dpal.ps}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugGraphColorPalettePagePatch1}
\begin{paste}{ugGraphColorPalettePageFull1}{ugGraphColorPalettePageEmpty1}
\pastebutton{ugGraphColorPalettePageFull1}{\hidepaste}
\tab{5}\spadcommand{shade red()}
\indentrel{3}\begin{verbatim}
   (1)  3
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphColorPalettePageEmpty1}
\begin{paste}{ugGraphColorPalettePageEmpty1}{ugGraphColorPalettePagePatch1}
\pastebutton{ugGraphColorPalettePageEmpty1}{\showpaste}
\tab{5}\spadcommand{shade red()}
\end{paste}\end{patch}

\begin{patch}{ugGraphColorPalettePagePatch2}
\begin{paste}{ugGraphColorPalettePageFull2}{ugGraphColorPalettePageEmpty2}
\pastebutton{ugGraphColorPalettePageFull2}{\hidepaste}
\tab{5}\spadcommand{myFavoriteColor := dark blue()\bound{mfc }}
\indentrel{3}\begin{verbatim}
   (2)  [Hue: 22  Weight: 1.0] from the Dark palette
                                          Type: Palette
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphColorPalettePageEmpty2}
\begin{paste}{ugGraphColorPalettePageEmpty2}{ugGraphColorPalettePagePatch2}
\pastebutton{ugGraphColorPalettePageEmpty2}{\showpaste}
\tab{5}\spadcommand{myFavoriteColor := dark blue()\bound{mfc }}
\end{paste}\end{patch}

\begin{patch}{ugGraphColorPalettePagePatch3}
\begin{paste}{ugGraphColorPalettePageFull3}{ugGraphColorPalettePageEmpty3}
\pastebutton{ugGraphColorPalettePageFull3}{\hidepaste}
\tab{5}\spadcommand{shade myFavoriteColor\free{mfc }}
\indentrel{3}\begin{verbatim}
   (3)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphColorPalettePageEmpty3}
\begin{paste}{ugGraphColorPalettePageEmpty3}{ugGraphColorPalettePagePatch3}
\pastebutton{ugGraphColorPalettePageEmpty3}{\showpaste}
\tab{5}\spadcommand{shade myFavoriteColor\free{mfc }}
\end{paste}\end{patch}

\begin{patch}{ugGraphColorPalettePagePatch4}
\begin{paste}{ugGraphColorPalettePageFull4}{ugGraphColorPalettePageEmpty4}
\pastebutton{ugGraphColorPalettePageFull4}{\hidepaste}
\tab{5}\spadcommand{hue myFavoriteColor\free{mfc }}
\indentrel{3}\begin{verbatim}
   (4)  Hue: 22  Weight: 1.0
                                            Type: Color
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphColorPalettePageEmpty4}
\begin{paste}{ugGraphColorPalettePageEmpty4}{ugGraphColorPalettePagePatch4}
\pastebutton{ugGraphColorPalettePageEmpty4}{\showpaste}
\tab{5}\spadcommand{hue myFavoriteColor\free{mfc }}
\end{paste}\end{patch}

\begin{patch}{ugGraphColorPalettePagePatch5}
\begin{paste}{ugGraphColorPalettePageFull5}{ugGraphColorPalettePageEmpty5}
\pastebutton{ugGraphColorPalettePageFull5}{\hidepaste}
\tab{5}\spadgraph{draw(x**2,x=-1..1,curveColor == dark blue())}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphcolorpalettepage5.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphcolorpalettepage5}}
\end{paste}\end{patch}

\begin{patch}{ugGraphColorPalettePageEmpty5}
\begin{paste}{ugGraphColorPalettePageEmpty5}{ugGraphColorPalettePagePatch5}
\pastebutton{ugGraphColorPalettePageEmpty5}{\showpaste}
\tab{5}\spadgraph{draw(x**2,x=-1..1,curveColor == dark blue())}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugGraphTwoDControlPage}{ug07.ht}{Two-Dimensional Control-Panel}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphTwoDControlPage}{7.1.7. Two-Dimensional Control-Panel}
\beginscroll
Once you have created a viewport, move your mouse to the viewport and click
with your left mouse button to display a control-panel.
The panel is displayed on the side of the viewport closest to
where you clicked.  Each of the buttons which toggle on and off show the
current state of the graph.


\subsubsection{Transformations}

Object transformations are executed from the control-panel by 
mouse-activated potentiometer windows.
%
\indent{0}
\beginitems

\item[Scale:] To scale a graph, click on a mouse button within the
{\bf Scale} window in the upper left corner of the control-panel.  The
axes along which the scaling is to occur are indicated by setting the
toggles above the arrow.  With {\tt X On} and {\tt Y On} appearing,
both axes are selected and scaling is uniform.  If either is not
selected, for example, if {\tt X Off} appears, scaling is non-uniform.

\item[Translate:] To translate a graph, click the mouse in the {\bf
Translate} window in the direction you wish the graph to move.  This
window is located in the upper right corner of the control-panel.
Along the top of the {\bf Translate} window are two buttons for
selecting the direction of translation.  Translation along both
coordinate axes results when {\tt X On} and {\tt Y On} appear or along
one axis when one is on, for example, {\tt X On} and {\tt Y Off}
appear.
\enditems
\indent{0}

\subsubsection{Messages}

The window directly below the transformation potentiometer windows is
used to display system messages relating to the viewport and the
control-panel.  The following format is displayed: \newline

\centerline{{[scaleX, scaleY] \axiom{>}
graph\axiom{<} [translateX, translateY] \newline}}
The two values to the left show the scale factor along the {\tt X} and
{\tt Y} coordinate axes.  The two values to the right show the
distance of translation from the center in the {\tt X} and {\tt Y}
directions.  The number in the center shows which graph in the
viewport this data pertains to.  When multiple graphs exist in the
same viewport, the graph must be selected (see ``Multiple Graphs,''
below) in order for its transformation data to be shown, otherwise the
number is 1.

\subsubsection{Multiple Graphs}

The {\bf Graphs} window contains buttons that allow the placement of
\twodim{} graphs into one of nine available slots in any other
\twodim{} viewport.  In the center of the window are numeral buttons
from one to nine that show whether a graph is displayed in the
viewport.  Below each number button is a button showing whether a
graph that is present is selected for application of some
transformation.  When the caret symbol is displayed, then the graph in
that slot will be manipulated.  Initially, the graph for which the
viewport is created occupies the first slot, is displayed, and is
selected.

%
\indent{0}
\beginitems

\item[Clear:] The {\bf Clear} button deselects every viewport graph
slot.  A graph slot is reselected by selecting the button below its
number.

\item[Query:] The {\bf Query} button is used to display the scale and
translate data for the indicated graph.  When this button is selected
the message ``Click on the graph to query'' appears.  Select a slot
number button from the {\bf Graphs} window. The scaling factor and
translation offset of the graph are then displayed in the message
window.

\item[Pick:] The {\bf Pick} button is used to select a graph to be
placed or dropped into the indicated viewport.  When this button is
selected, the message ``Click on the graph to pick'' appears.  Click
on the slot with the graph number of the desired graph.  The graph
information is held waiting for you to execute a {\bf Drop} in some
other graph.

\item[Drop:]  Once a graph has been picked up using the {\bf Pick} button,
the {\bf Drop} button places it into a new viewport slot.
The message ``Click on the graph to drop'' appears in the message
window when the {\bf Drop} button is selected.
By selecting one of the slot number buttons in the {\bf Graphs}
window, the graph currently being held is dropped into this slot
and displayed.
\enditems
\indent{0}

\subsubsection{Buttons}

%
\indent{0}
\beginitems
%
\item[Axes] turns the coordinate axes on or off.
%
\item[Units] turns the units along the {\tt x}
and {\tt y} axis on or off.
%
\item[Box] encloses the area of the viewport graph
in a bounding box, or removes the box if already enclosed.
%
\item[Pts] turns on or off the display of points.
%
\item[Lines] turns on or off the display
of lines connecting points.
%
\item[PS] writes the current viewport contents to
a file {\bf axiom2D.ps} or to a name specified in the user's {\bf
.Xdefaults} file.
The file is placed in the directory from which Axiom or the {\bf
viewalone} program was invoked.
%
\item[Reset] resets the object transformation
characteristics and attributes back to their initial states.
%
\item[Hide] makes the control-panel disappear.
%
\item[Quit] queries whether the current viewport
session should be terminated.
\enditems
\indent{0}

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugGraphTwoDopsPage}{ug07.ht}
{Operations for Two-Dimensional Graphics}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphTwoDopsPage}
{7.1.8. Operations for Two-Dimensional Graphics}
\beginscroll

Here is a summary of useful Axiom operations for \twodim{}
graphics.
Each operation name is followed by a list of arguments.
Each argument is written as a variable informally named according
to the type of the argument (for example, {\it integer}).
If appropriate, a default value for an argument is given in
parentheses immediately following the name.

%
\texht{\bgroup\hbadness = 10001\sloppy}{}
\indent{0}
\beginitems
%
\item[\axiomFun{adaptive}]\funArgs{\optArg{boolean\argDef{true}}}
sets or indicates whether graphs are plotted
according to the adaptive refinement algorithm.

\item[\axiomFun{axesColorDefault}]\funArgs{\optArg{color\argDef{dark
blue()}}} sets or indicates the default color of the axes in a
\twodim{} graph viewport.

\item[\axiomFun{clipPointsDefault}]\funArgs{\optArg{boolean\argDef{false}}}
sets or
indicates whether point clipping is
to be applied as the default for graph plots.
%
\item[\axiomFun{drawToScale}]\funArgs{\optArg{boolean\argDef{false}}}
sets or
indicates whether the plot of a graph
is ``to scale'' or uses the entire viewport space as the default.

\item[\axiomFun{lineColorDefault}]\funArgs{\optArg{color\argDef{pastel
yellow()}}} sets or indicates the default color of the lines or curves
in a \twodim{} graph viewport.

\item[\axiomFun{maxPoints}]\funArgs{\optArg{integer\argDef{500}}}
sets or indicates
the default maximum number of
possible points to be used when constructing a \twodim{} graph.
%
\item[\axiomFun{minPoints}]\funArgs{\optArg{integer\argDef{21}}}
sets or indicates the default minimum number of
possible points to be used when constructing a \twodim{} graph.

\item[\axiomFun{pointColorDefault}]\funArgs{\optArg{color\argDef{bright
red()}}} sets or indicates the default color of the points in a
\twodim{} graph viewport.

\item[\axiomFun{pointSizeDefault}]\funArgs{\optArg{integer\argDef{5}}}
sets or indicates the default size of the
dot used to plot points in a \twodim{} graph.
%
\item[\axiomFun{screenResolution}]\funArgs{\optArg{integer\argDef{600}}}
sets or indicates the default screen
resolution constant used in setting the computation limit of adaptively
generated curve plots.

\item[\axiomFun{unitsColorDefault}]\funArgs{\optArg{color\argDef{dim
green()}}} sets or indicates the default color of the unit labels in a
\twodim{} graph viewport.

\item[\axiomFun{viewDefaults}]\funArgs{}
resets the default settings for the following
attributes:  point color, line color, axes color, units color, point size,
viewport upper left-hand corner position, and the viewport size.

\item[\axiomFun{viewPosDefault}]\funArgs{\optArg{list\argDef{[100,100]}}}
sets or indicates the default position of the upper left-hand corner
of a \twodim{} viewport, relative to the display root window.  The
upper left-hand corner of the display is considered to be at the (0,
0) position.

\item[\axiomFun{viewSizeDefault}]\funArgs{\optArg{list\argDef{[200,200]}}}
sets or indicates the default size in which two dimensional viewport
windows are shown.  It is defined by a width and then a height.

\item[\axiomFun{viewWriteAvailable}]\funArgs{\optArg{list\argDef{["pixmap",
"bitmap", "postscript", \"image"}}} indicates the possible file types
that can be created with the
\axiomFunFrom{write}{TwoDimensionalViewport} function.

\item[\axiomFun{viewWriteDefault}]
\funArgs{\optArg{list\argDef{[]}}}
sets or indicates the default types of files, in
addition to the {\bf data} file, that are created when a
\axiomFun{write} function is executed on a viewport.

\item[\axiomFun{units}]\funArgs{viewport, integer\argDef{1},
string\argDef{"off"}} turns the units on or off for the graph with
index {\it integer}.

\item[\axiomFun{axes}]
\funArgs{viewport, integer\argDef{1}, string\argDef{"on"}}
turns the axes on
or off for the graph with index {\it integer}.
%
\item[\axiomFun{close}]\funArgs{viewport}
closes {\it viewport}.
%
\item[\axiomFun{connect}]
\funArgs{viewport, integer\argDef{1}, string\argDef{"on"}}
declares whether lines
connecting the points are displayed or not.
%
\item[\axiomFun{controlPanel}]\funArgs{viewport, string\argDef{"off"}}
declares
whether the \twodim{} control-panel is automatically displayed
or not.
%
\item[\axiomFun{graphs}]\funArgs{viewport}
returns a list
describing the state of each graph.
If the graph state is not being used this is shown by {\tt "undefined"},
otherwise a description of the graph's contents is shown.
%
\item[\axiomFun{graphStates}]\funArgs{viewport}
displays
a list of all the graph states available for {\it viewport}, giving the
values for every property.
%
\item[\axiomFun{key}]\funArgs{viewport}
returns the process
ID number for {\it viewport}.
%
\item[\axiomFun{move}]\funArgs{viewport,
\subscriptText{integer}{x}(viewPosDefault),
\subscriptText{integer}{y}(viewPosDefault)}
moves {\it viewport} on the screen so that the
upper left-hand corner of {\it viewport} is at the position {\it (x,y)}.
%
\item[\axiomFun{options}]\funArgs{\it viewport}
returns a list
of all the \axiomType{DrawOption}s used by {\it viewport}.
%
\item[\axiomFun{points}]
\funArgs{viewport, integer\argDef{1}, string\argDef{"on"}}
specifies whether the graph points for graph {\it integer} are
to be displayed or not.
%
\item[\axiomFun{region}]
\funArgs{viewport, integer\argDef{1}, string\argDef{"off"}}
declares whether graph {\it integer} is or is not to be displayed
with a bounding rectangle.
%
\item[\axiomFun{reset}]\funArgs{viewport}
resets all the properties of {\it viewport}.
%
\item[\axiomFun{resize}]\funArgs{viewport,
\subscriptText{integer}{width}, \subscriptText{integer}{height}}
resizes {\it viewport} with a new {\it width} and {\it height}.
%
\item[\axiomFun{scale}]\
funArgs{viewport, \subscriptText{integer}{n}\argDef{1},
\subscriptText{integer}{x}
\argDef{0.9}, \subscriptText{integer}{y}\argDef{0.9}}
scales values for the
{\it x} and {\it y} coordinates of graph {\it n}.
%
\item[\axiomFun{show}]
\funArgs{viewport, \subscriptText{integer}{n}\argDef{1},
string\argDef{"on"}}
indicates if graph {\it n} is shown or not.
%
\item[\axiomFun{title}]\funArgs{viewport, string\argDef{"Axiom 2D"}}
designates the title for {\it viewport}.
%
\item[\axiomFun{translate}]\funArgs{viewport,
\subscriptText{integer}{n}\argDef{1},
\subscriptText{float}{x}
\argDef{0.0}, \subscriptText{float}{y}\argDef{0.0}}
causes graph {\it n} to be moved {\it x} 
and {\it y} units in the respective directions.
%
\item[\axiomFun{write}]\funArgs{viewport, 
\subscriptText{string}{directory},
\optArg{strings}}
if no third argument is given, writes the 
{\bf data} file onto the directory
with extension {\bf data}.
The third argument can be a single string 
or a list of strings with some or
all the entries {\tt "pixmap"}, {\tt "bitmap"}, 
{\tt "postscript"}, and
{\tt "image"}.
\enditems
\indent{0}
\texht{\egroup}{}

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugGraphTwoDbuildPage}{ug07.ht}
{Addendum: Building Two-Dimensional Graphs}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphTwoDbuildPage}
{7.1.9. Addendum: Building Two-Dimensional Graphs}
\beginscroll

In this section we demonstrate how to create \twodim{} graphs from
lists of points and give an example showing how to read the lists
of points from a file.

\subsubsection{Creating a Two-Dimensional Viewport from a List of Points}

Axiom creates lists of points in a \twodim{} viewport by utilizing the
\axiomType{GraphImage} and \axiomType{TwoDimensionalViewport} domains.
In this example, the \axiomFunFrom{makeGraphImage}{GraphImage}
function takes a list of lists of points parameter, a list of colors
for each point in the graph, a list of colors for each line in the
graph, and a list of sizes for each point in the graph.

\xtc{
The following expressions create a list of lists of points which will 
be read by Axiom and made into a \twodim{} viewport.
}{
\spadpaste{p1 := point [1,1]\$(Point DFLOAT) \bound{p1}}
}
\xtc{
}{
\spadpaste{p2 := point [0,1]\$(Point DFLOAT) \bound{p2}}
}
\xtc{
}{
\spadpaste{p3 := point [0,0]\$(Point DFLOAT) \bound{p3}}
}
\xtc{
}{
\spadpaste{p4 := point [1,0]\$(Point DFLOAT) \bound{p4}}
}
\xtc{
}{
\spadpaste{p5 := point [1,.5]\$(Point DFLOAT) \bound{p5}}
}
\xtc{
}{
\spadpaste{p6 := point [.5,0]\$(Point DFLOAT) \bound{p6}}
}
\xtc{
}{
\spadpaste{p7 := point [0,0.5]\$(Point DFLOAT) \bound{p7}}
}
\xtc{
}{
\spadpaste{p8 := point [.5,1]\$(Point DFLOAT) \bound{p8}}
}
\xtc{
}{
\spadpaste{p9 := point [.25,.25]\$(Point DFLOAT) \bound{p9}}
}
\xtc{
}{
\spadpaste{p10 := point [.25,.75]\$(Point DFLOAT) \bound{p10}}
}
\xtc{
}{
\spadpaste{p11 := point [.75,.75]\$(Point DFLOAT) \bound{p11}}
}
\xtc{
}{
\spadpaste{p12 := point [.75,.25]\$(Point DFLOAT) \bound{p12}}
}
\xtc{
Finally, here is the list.
}{
\spadpaste{llp := [[p1,p2], [p2,p3], [p3,p4], [p4,p1], [p5,p6], [p6,p7], 
[p7,p8], [p8,p5], [p9,p10], [p10,p11], [p11,p12], [p12,p9]] 
\free{p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12} \bound{llp}}
}
\xtc{
Now we set the point sizes for all components of the graph.
}{
\spadpaste{size1 := 6::PositiveInteger \bound{size1}}
}
\xtc{
}{
}
\xtc{
}{
\spadpaste{size2 := 8::PositiveInteger \bound{size2}}
}
\xtc{
}{
\spadpaste{size3 := 10::PositiveInteger \bound{size3}}
}
\xtc{
}{
\spadpaste{lsize := [size1, size1, size1, size1, size2, size2, size2, 
size2, size3, size3, size3, size3] \bound{lsize} \free{size1 size2 size3}}
}
\xtc{
Here are the colors for the points.
}{
\spadpaste{pc1 := pastel red() \bound{pc1}}
}
\xtc{
}{
\spadpaste{pc2 := dim green() \bound{pc2}}
}
\xtc{
}{
\spadpaste{pc3 := pastel yellow() \bound{pc3}}
}
\xtc{
}{
\spadpaste{lpc := [pc1, pc1, pc1, pc1, pc2, pc2, pc2, pc2, pc3, pc3, 
pc3, pc3] \free{pc1 pc2 pc3} \bound{lpc}}
}
\xtc{
Here are the colors for the lines.
}{
\spadpaste{lc := [pastel blue(), light yellow(), dim green(), 
bright red(), light green(), dim yellow(), bright blue(), 
dark red(), pastel red(), light blue(), dim green(), 
light yellow()] \bound{lc}}
}
\xtc{
Now the \axiomType{GraphImage} is created according to the component
specifications indicated above.
}{
\spadpaste{g := makeGraphImage(llp,lpc,lc,lsize)\$GRIMAGE 
\bound{g} \free{llp lpc lc lsize}}
}
\psXtc{
The \axiomFunFrom{makeViewport2D}{TwoDimensionalViewport} function now
creates a \axiomType{TwoDimensionalViewport} for this graph according to the
list of options specified within the brackets.
}{
\graphpaste{makeViewport2D(g,[title("Lines")])\$VIEW2D \free{g}}
}{
%
}
%See Figure #.#.
\xtc{
This example demonstrates the use of the \axiomType{GraphImage}
functions \axiomFunFrom{component}{GraphImage} and
\axiomFunFrom{appendPoint}{GraphImage} in adding points to an empty
\axiomType{GraphImage}.
}{
\spadpaste{)clear all \bound{clearAll}}
}
\xtc{
}{
\spadpaste{g := graphImage()\$GRIMAGE \bound{Sg}\free{clearAll}}
}
\xtc{
}{
\spadpaste{p1 := point [0,0]\$(Point DFLOAT) \bound{Sp1}}
}
\xtc{
}{
\spadpaste{p2 := point [.25,.25]\$(Point DFLOAT) \bound{Sp2}}
}
\xtc{
}{
\spadpaste{p3 := point [.5,.5]\$(Point DFLOAT) \bound{Sp3}}
}
\xtc{
}{
\spadpaste{p4 := point [.75,.75]\$(Point DFLOAT) \bound{Sp4}}
}
\xtc{
}{
\spadpaste{p5 := point [1,1]\$(Point DFLOAT) \bound{Sp5}}
}
\xtc{
}{
\spadpaste{component(g,p1)\$GRIMAGE\free{Sg Sp1}\bound{gp1}}
}
\xtc{
}{
\spadpaste{component(g,p2)\$GRIMAGE\free{Sg Sp2}\bound{gp2}}
}
\xtc{
}{
\spadpaste{appendPoint(g,p3)\$GRIMAGE\free{gp1 gp2 Sp3}\bound{gp3}}
}
\xtc{
}{
\spadpaste{appendPoint(g,p4)\$GRIMAGE\free{gp3 Sp4}\bound{gp4}}
}
\xtc{
}{
\spadpaste{appendPoint(g,p5)\$GRIMAGE\free{gp4 Sp5}\bound{gp5}}
}
\xtc{
}{
\spadpaste{g1 := makeGraphImage(g)\$GRIMAGE \bound{Sg1} \free{gp5}}
}
\psXtc{
Here is the graph.
}{
\graphpaste{makeViewport2D(g1,[title("Graph Points")])\$VIEW2D \free{Sg1}}
}{
%
}
%
%See Figure #.#.
%
\xtc{
A list of points can also be made into a \axiomType{GraphImage} by
using the operation \axiomFunFrom{coerce}{GraphImage}.  It is
equivalent to adding each point to \axiom{g2} using
\axiomFunFrom{component}{GraphImage}.
}{
\spadpaste{g2 := coerce([[p1],[p2],[p3],[p4],[p5]])\$GRIMAGE  
\free{Sp1 Sp2 Sp3 Sp4 Sp5} \bound{Sg2}}
}
\xtc{
Now, create an empty \axiomType{TwoDimensionalViewport}.
}{
\spadpaste{v := viewport2D()\$VIEW2D \bound{Sv}}
}
\xtc{
}{
\spadpaste{options(v,[title("Just Points")])\$VIEW2D \free{Sv}\bound{Svo}}
}
\xtc{
Place the graph into the viewport.
}{
\spadpaste{putGraph(v,g2,1)\$VIEW2D \free{Sg2 Svo}\bound{Svog2}}
}
\psXtc{
Take a look.
}{
\graphpaste{makeViewport2D(v)\$VIEW2D \free{Svog2}}
}{
%
}

%See Figure #.#.

\subsubsection{Creating a Two-Dimensional Viewport of a 
List of Points from a File}

The following three functions read a list of points from a file and
then draw the points and the connecting lines. The points are stored
in the file in readable form as floating point numbers (specifically,
\axiomType{DoubleFloat} values) as an alternating stream of \axiom{x}-
and \axiom{y}-values. For example,
\begin{verbatim}
0.0 0.0     1.0 1.0     2.0 4.0
3.0 9.0     4.0 16.0    5.0 25.0
\end{verbatim}

\beginImportant
  
\noindent
{\tt 1.\ \ \ drawPoints(lp:List\ Point\ DoubleFloat):VIEW2D\ ==}\newline
{\tt 2.\ \ \ \ \ g\ :=\ graphImage()\$GRIMAGE}\newline
{\tt 3.\ \ \ \ \ for\ p\ in\ lp\ repeat}\newline
{\tt 4.\ \ \ \ \ \ \ 
component(g,p,pointColorDefault(),lineColorDefault(),}\newline
{\tt 5.\ \ \ \ \ \ \ \ \ pointSizeDefault())}\newline
{\tt 6.\ \ \ \ \ gi\ :=\ makeGraphImage(g)\$GRIMAGE}\newline
{\tt 7.\ \ \ \ \ makeViewport2D(gi,[title("Points")])\$VIEW2D}\newline
{\tt 8.\ \ \ }\newline
{\tt 9.\ \ \ drawLines(lp:List\ Point\ DoubleFloat):VIEW2D\ ==}\newline
{\tt 10.\ \ \ \ g\ :=\ graphImage()\$GRIMAGE}\newline
{\tt 11.\ \ \ \ 
component(g,\ lp,\ pointColorDefault(),\ lineColorDefault(),}\newline
{\tt 12.\ \ \ \ \ \ pointSizeDefault())\$GRIMAGE}\newline
{\tt 13.\ \ \ \ gi\ :=\ makeGraphImage(g)\$GRIMAGE}\newline
{\tt 14.\ \ \ \ makeViewport2D(gi,[title("Points")])\$VIEW2D}\newline
{\tt 15.\ \ }\newline
{\tt 16.\ \ plotData2D(name,\ title)\ ==}\newline
{\tt 17.\ \ \ \ f:File(DFLOAT)\ :=\ open(name,"input")}\newline
{\tt 18.\ \ \ \ lp:LIST(Point\ DFLOAT)\ :=\ empty()}\newline
{\tt 19.\ \ \ \ 
while\ ((x\ :=\ readIfCan!(f))\ case\ DFLOAT)\ repeat}\newline
{\tt 20.\ \ \ \ \ \ y\ :\ DFLOAT\ :=\ read!(f)}\newline
{\tt 21.\ \ \ \ \ \ 
lp\ :=\ cons(point\ [x,y]\$(Point\ DFLOAT),\ lp)}\newline
{\tt 22.\ \ \ \ \ \ lp}\newline
{\tt 23.\ \ \ \ close!(f)}\newline
{\tt 24.\ \ \ \ drawPoints(lp)}\newline
{\tt 25.\ \ \ \ drawLines(lp)}\newline
\endImportant
%
This command will actually create the viewport and the graph if
the point data is in the file \axiom{"file.data"}.
\beginImportant
  
\noindent
{\tt 1.\ \ \ plotData2D("file.data",\ "2D\ Data\ Plot")}\newline
\endImportant

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugGraphTwoDbuildPagePatch1}
\begin{paste}{ugGraphTwoDbuildPageFull1}{ugGraphTwoDbuildPageEmpty1}
\pastebutton{ugGraphTwoDbuildPageFull1}{\hidepaste}
\tab{5}\spadcommand{p1 := point [1,1]$(Point DFLOAT)\bound{p1 }}
\indentrel{3}\begin{verbatim}
   (1)  [1.0,1.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty1}
\begin{paste}{ugGraphTwoDbuildPageEmpty1}{ugGraphTwoDbuildPagePatch1}
\pastebutton{ugGraphTwoDbuildPageEmpty1}{\showpaste}
\tab{5}\spadcommand{p1 := point [1,1]$(Point DFLOAT)\bound{p1 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch2}
\begin{paste}{ugGraphTwoDbuildPageFull2}{ugGraphTwoDbuildPageEmpty2}
\pastebutton{ugGraphTwoDbuildPageFull2}{\hidepaste}
\tab{5}\spadcommand{p2 := point [0,1]$(Point DFLOAT)\bound{p2 }}
\indentrel{3}\begin{verbatim}
   (2)  [0.0,1.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty2}
\begin{paste}{ugGraphTwoDbuildPageEmpty2}{ugGraphTwoDbuildPagePatch2}
\pastebutton{ugGraphTwoDbuildPageEmpty2}{\showpaste}
\tab{5}\spadcommand{p2 := point [0,1]$(Point DFLOAT)\bound{p2 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch3}
\begin{paste}{ugGraphTwoDbuildPageFull3}{ugGraphTwoDbuildPageEmpty3}
\pastebutton{ugGraphTwoDbuildPageFull3}{\hidepaste}
\tab{5}\spadcommand{p3 := point [0,0]$(Point DFLOAT)\bound{p3 }}
\indentrel{3}\begin{verbatim}
   (3)  [0.0,0.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty3}
\begin{paste}{ugGraphTwoDbuildPageEmpty3}{ugGraphTwoDbuildPagePatch3}
\pastebutton{ugGraphTwoDbuildPageEmpty3}{\showpaste}
\tab{5}\spadcommand{p3 := point [0,0]$(Point DFLOAT)\bound{p3 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch4}
\begin{paste}{ugGraphTwoDbuildPageFull4}{ugGraphTwoDbuildPageEmpty4}
\pastebutton{ugGraphTwoDbuildPageFull4}{\hidepaste}
\tab{5}\spadcommand{p4 := point [1,0]$(Point DFLOAT)\bound{p4 }}
\indentrel{3}\begin{verbatim}
   (4)  [1.0,0.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty4}
\begin{paste}{ugGraphTwoDbuildPageEmpty4}{ugGraphTwoDbuildPagePatch4}
\pastebutton{ugGraphTwoDbuildPageEmpty4}{\showpaste}
\tab{5}\spadcommand{p4 := point [1,0]$(Point DFLOAT)\bound{p4 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch5}
\begin{paste}{ugGraphTwoDbuildPageFull5}{ugGraphTwoDbuildPageEmpty5}
\pastebutton{ugGraphTwoDbuildPageFull5}{\hidepaste}
\tab{5}\spadcommand{p5 := point [1,.5]$(Point DFLOAT)\bound{p5 }}
\indentrel{3}\begin{verbatim}
   (5)  [1.0,0.5]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty5}
\begin{paste}{ugGraphTwoDbuildPageEmpty5}{ugGraphTwoDbuildPagePatch5}
\pastebutton{ugGraphTwoDbuildPageEmpty5}{\showpaste}
\tab{5}\spadcommand{p5 := point [1,.5]$(Point DFLOAT)\bound{p5 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch6}
\begin{paste}{ugGraphTwoDbuildPageFull6}{ugGraphTwoDbuildPageEmpty6}
\pastebutton{ugGraphTwoDbuildPageFull6}{\hidepaste}
\tab{5}\spadcommand{p6 := point [.5,0]$(Point DFLOAT)\bound{p6 }}
\indentrel{3}\begin{verbatim}
   (6)  [0.5,0.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty6}
\begin{paste}{ugGraphTwoDbuildPageEmpty6}{ugGraphTwoDbuildPagePatch6}
\pastebutton{ugGraphTwoDbuildPageEmpty6}{\showpaste}
\tab{5}\spadcommand{p6 := point [.5,0]$(Point DFLOAT)\bound{p6 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch7}
\begin{paste}{ugGraphTwoDbuildPageFull7}{ugGraphTwoDbuildPageEmpty7}
\pastebutton{ugGraphTwoDbuildPageFull7}{\hidepaste}
\tab{5}\spadcommand{p7 := point [0,0.5]$(Point DFLOAT)\bound{p7 }}
\indentrel{3}\begin{verbatim}
   (7)  [0.0,0.5]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty7}
\begin{paste}{ugGraphTwoDbuildPageEmpty7}{ugGraphTwoDbuildPagePatch7}
\pastebutton{ugGraphTwoDbuildPageEmpty7}{\showpaste}
\tab{5}\spadcommand{p7 := point [0,0.5]$(Point DFLOAT)\bound{p7 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch8}
\begin{paste}{ugGraphTwoDbuildPageFull8}{ugGraphTwoDbuildPageEmpty8}
\pastebutton{ugGraphTwoDbuildPageFull8}{\hidepaste}
\tab{5}\spadcommand{p8 := point [.5,1]$(Point DFLOAT)\bound{p8 }}
\indentrel{3}\begin{verbatim}
   (8)  [0.5,1.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty8}
\begin{paste}{ugGraphTwoDbuildPageEmpty8}{ugGraphTwoDbuildPagePatch8}
\pastebutton{ugGraphTwoDbuildPageEmpty8}{\showpaste}
\tab{5}\spadcommand{p8 := point [.5,1]$(Point DFLOAT)\bound{p8 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch9}
\begin{paste}{ugGraphTwoDbuildPageFull9}{ugGraphTwoDbuildPageEmpty9}
\pastebutton{ugGraphTwoDbuildPageFull9}{\hidepaste}
\tab{5}\spadcommand{p9 := point [.25,.25]$(Point DFLOAT)\bound{p9 }}
\indentrel{3}\begin{verbatim}
   (9)  [0.25,0.25]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty9}
\begin{paste}{ugGraphTwoDbuildPageEmpty9}{ugGraphTwoDbuildPagePatch9}
\pastebutton{ugGraphTwoDbuildPageEmpty9}{\showpaste}
\tab{5}\spadcommand{p9 := point [.25,.25]$(Point DFLOAT)\bound{p9 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch10}
\begin{paste}{ugGraphTwoDbuildPageFull10}{ugGraphTwoDbuildPageEmpty10}
\pastebutton{ugGraphTwoDbuildPageFull10}{\hidepaste}
\tab{5}\spadcommand{p10 := point [.25,.75]$(Point DFLOAT)\bound{p10 }}
\indentrel{3}\begin{verbatim}
   (10)  [0.25,0.75]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty10}
\begin{paste}{ugGraphTwoDbuildPageEmpty10}{ugGraphTwoDbuildPagePatch10}
\pastebutton{ugGraphTwoDbuildPageEmpty10}{\showpaste}
\tab{5}\spadcommand{p10 := point [.25,.75]$(Point DFLOAT)\bound{p10 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch11}
\begin{paste}{ugGraphTwoDbuildPageFull11}{ugGraphTwoDbuildPageEmpty11}
\pastebutton{ugGraphTwoDbuildPageFull11}{\hidepaste}
\tab{5}\spadcommand{p11 := point [.75,.75]$(Point DFLOAT)\bound{p11 }}
\indentrel{3}\begin{verbatim}
   (11)  [0.75,0.75]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty11}
\begin{paste}{ugGraphTwoDbuildPageEmpty11}{ugGraphTwoDbuildPagePatch11}
\pastebutton{ugGraphTwoDbuildPageEmpty11}{\showpaste}
\tab{5}\spadcommand{p11 := point [.75,.75]$(Point DFLOAT)\bound{p11 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch12}
\begin{paste}{ugGraphTwoDbuildPageFull12}{ugGraphTwoDbuildPageEmpty12}
\pastebutton{ugGraphTwoDbuildPageFull12}{\hidepaste}
\tab{5}\spadcommand{p12 := point [.75,.25]$(Point DFLOAT)\bound{p12 }}
\indentrel{3}\begin{verbatim}
   (12)  [0.75,0.25]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty12}
\begin{paste}{ugGraphTwoDbuildPageEmpty12}{ugGraphTwoDbuildPagePatch12}
\pastebutton{ugGraphTwoDbuildPageEmpty12}{\showpaste}
\tab{5}\spadcommand{p12 := point [.75,.25]$(Point DFLOAT)\bound{p12 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch13}
\begin{paste}{ugGraphTwoDbuildPageFull13}{ugGraphTwoDbuildPageEmpty13}
\pastebutton{ugGraphTwoDbuildPageFull13}{\hidepaste}
\tab{5}\spadcommand{llp := [[p1,p2], [p2,p3], [p3,p4], [p4,p1], [p5,p6], [p6,p7], [p7,p8], [p8,p5], [p9,p10], [p10,p11], [p11,p12], [p12,p9]]\free{p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 }\bound{llp }}
\indentrel{3}\begin{verbatim}
   (13)
   [[[1.0,1.0],[0.0,1.0]], [[0.0,1.0],[0.0,0.0]],
    [[0.0,0.0],[1.0,0.0]], [[1.0,0.0],[1.0,1.0]],
    [[1.0,0.5],[0.5,0.0]], [[0.5,0.0],[0.0,0.5]],
    [[0.0,0.5],[0.5,1.0]], [[0.5,1.0],[1.0,0.5]],
    [[0.25,0.25],[0.25,0.75]], [[0.25,0.75],[0.75,0.75]],
    [[0.75,0.75],[0.75,0.25]], [[0.75,0.25],[0.25,0.25]]]
                      Type: List List Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty13}
\begin{paste}{ugGraphTwoDbuildPageEmpty13}{ugGraphTwoDbuildPagePatch13}
\pastebutton{ugGraphTwoDbuildPageEmpty13}{\showpaste}
\tab{5}\spadcommand{llp := [[p1,p2], [p2,p3], [p3,p4], [p4,p1], [p5,p6], [p6,p7], [p7,p8], [p8,p5], [p9,p10], [p10,p11], [p11,p12], [p12,p9]]\free{p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 }\bound{llp }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch14}
\begin{paste}{ugGraphTwoDbuildPageFull14}{ugGraphTwoDbuildPageEmpty14}
\pastebutton{ugGraphTwoDbuildPageFull14}{\hidepaste}
\tab{5}\spadcommand{size1 := 6::PositiveInteger\bound{size1 }}
\indentrel{3}\begin{verbatim}
   (14)  6
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty14}
\begin{paste}{ugGraphTwoDbuildPageEmpty14}{ugGraphTwoDbuildPagePatch14}
\pastebutton{ugGraphTwoDbuildPageEmpty14}{\showpaste}
\tab{5}\spadcommand{size1 := 6::PositiveInteger\bound{size1 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch15}
\begin{paste}{ugGraphTwoDbuildPageFull15}{ugGraphTwoDbuildPageEmpty15}
\pastebutton{ugGraphTwoDbuildPageFull15}{\hidepaste}
\tab{5}\spadcommand{size2 := 8::PositiveInteger\bound{size2 }}
\indentrel{3}\begin{verbatim}
   (15)  8
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty15}
\begin{paste}{ugGraphTwoDbuildPageEmpty15}{ugGraphTwoDbuildPagePatch15}
\pastebutton{ugGraphTwoDbuildPageEmpty15}{\showpaste}
\tab{5}\spadcommand{size2 := 8::PositiveInteger\bound{size2 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch16}
\begin{paste}{ugGraphTwoDbuildPageFull16}{ugGraphTwoDbuildPageEmpty16}
\pastebutton{ugGraphTwoDbuildPageFull16}{\hidepaste}
\tab{5}\spadcommand{size3 := 10::PositiveInteger\bound{size3 }}
\indentrel{3}\begin{verbatim}
   (16)  10
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty16}
\begin{paste}{ugGraphTwoDbuildPageEmpty16}{ugGraphTwoDbuildPagePatch16}
\pastebutton{ugGraphTwoDbuildPageEmpty16}{\showpaste}
\tab{5}\spadcommand{size3 := 10::PositiveInteger\bound{size3 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch17}
\begin{paste}{ugGraphTwoDbuildPageFull17}{ugGraphTwoDbuildPageEmpty17}
\pastebutton{ugGraphTwoDbuildPageFull17}{\hidepaste}
\tab{5}\spadcommand{lsize := [size1, size1, size1, size1, size2, size2, size2, size2, size3, size3, size3, size3]\bound{lsize }\free{size1 size2 size3 }}
\indentrel{3}\begin{verbatim}
   (17)  [6,6,6,6,8,8,8,8,10,10,10,10]
                             Type: List PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty17}
\begin{paste}{ugGraphTwoDbuildPageEmpty17}{ugGraphTwoDbuildPagePatch17}
\pastebutton{ugGraphTwoDbuildPageEmpty17}{\showpaste}
\tab{5}\spadcommand{lsize := [size1, size1, size1, size1, size2, size2, size2, size2, size3, size3, size3, size3]\bound{lsize }\free{size1 size2 size3 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch18}
\begin{paste}{ugGraphTwoDbuildPageFull18}{ugGraphTwoDbuildPageEmpty18}
\pastebutton{ugGraphTwoDbuildPageFull18}{\hidepaste}
\tab{5}\spadcommand{pc1 := pastel red()\bound{pc1 }}
\indentrel{3}\begin{verbatim}
   (18)  [Hue: 1  Weight: 1.0] from the Pastel palette
                                          Type: Palette
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty18}
\begin{paste}{ugGraphTwoDbuildPageEmpty18}{ugGraphTwoDbuildPagePatch18}
\pastebutton{ugGraphTwoDbuildPageEmpty18}{\showpaste}
\tab{5}\spadcommand{pc1 := pastel red()\bound{pc1 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch19}
\begin{paste}{ugGraphTwoDbuildPageFull19}{ugGraphTwoDbuildPageEmpty19}
\pastebutton{ugGraphTwoDbuildPageFull19}{\hidepaste}
\tab{5}\spadcommand{pc2 := dim green()\bound{pc2 }}
\indentrel{3}\begin{verbatim}
   (19)  [Hue: 14  Weight: 1.0] from the Dim palette
                                          Type: Palette
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty19}
\begin{paste}{ugGraphTwoDbuildPageEmpty19}{ugGraphTwoDbuildPagePatch19}
\pastebutton{ugGraphTwoDbuildPageEmpty19}{\showpaste}
\tab{5}\spadcommand{pc2 := dim green()\bound{pc2 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch20}
\begin{paste}{ugGraphTwoDbuildPageFull20}{ugGraphTwoDbuildPageEmpty20}
\pastebutton{ugGraphTwoDbuildPageFull20}{\hidepaste}
\tab{5}\spadcommand{pc3 := pastel yellow()\bound{pc3 }}
\indentrel{3}\begin{verbatim}
   (20)  [Hue: 11  Weight: 1.0] from the Pastel palette
                                          Type: Palette
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty20}
\begin{paste}{ugGraphTwoDbuildPageEmpty20}{ugGraphTwoDbuildPagePatch20}
\pastebutton{ugGraphTwoDbuildPageEmpty20}{\showpaste}
\tab{5}\spadcommand{pc3 := pastel yellow()\bound{pc3 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch21}
\begin{paste}{ugGraphTwoDbuildPageFull21}{ugGraphTwoDbuildPageEmpty21}
\pastebutton{ugGraphTwoDbuildPageFull21}{\hidepaste}
\tab{5}\spadcommand{lpc := [pc1, pc1, pc1, pc1, pc2, pc2, pc2, pc2, pc3, pc3, pc3, pc3]\free{pc1 pc2 pc3 }\bound{lpc }}
\indentrel{3}\begin{verbatim}
   (21)
   [[Hue: 1  Weight: 1.0] from the Pastel palette,
    [Hue: 1  Weight: 1.0] from the Pastel palette,
    [Hue: 1  Weight: 1.0] from the Pastel palette,
    [Hue: 1  Weight: 1.0] from the Pastel palette,
    [Hue: 14  Weight: 1.0] from the Dim palette,
    [Hue: 14  Weight: 1.0] from the Dim palette,
    [Hue: 14  Weight: 1.0] from the Dim palette,
    [Hue: 14  Weight: 1.0] from the Dim palette,
    [Hue: 11  Weight: 1.0] from the Pastel palette,
    [Hue: 11  Weight: 1.0] from the Pastel palette,
    [Hue: 11  Weight: 1.0] from the Pastel palette,
    [Hue: 11  Weight: 1.0] from the Pastel palette]
                                     Type: List Palette
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty21}
\begin{paste}{ugGraphTwoDbuildPageEmpty21}{ugGraphTwoDbuildPagePatch21}
\pastebutton{ugGraphTwoDbuildPageEmpty21}{\showpaste}
\tab{5}\spadcommand{lpc := [pc1, pc1, pc1, pc1, pc2, pc2, pc2, pc2, pc3, pc3, pc3, pc3]\free{pc1 pc2 pc3 }\bound{lpc }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch22}
\begin{paste}{ugGraphTwoDbuildPageFull22}{ugGraphTwoDbuildPageEmpty22}
\pastebutton{ugGraphTwoDbuildPageFull22}{\hidepaste}
\tab{5}\spadcommand{lc := [pastel blue(), light yellow(), dim green(), bright red(), light green(), dim yellow(), bright blue(), dark red(), pastel red(), light blue(), dim green(), light yellow()]\bound{lc }}
\indentrel{3}\begin{verbatim}
   (22)
   [[Hue: 22  Weight: 1.0] from the Pastel palette,
    [Hue: 11  Weight: 1.0] from the Light palette,
    [Hue: 14  Weight: 1.0] from the Dim palette,
    [Hue: 1  Weight: 1.0] from the Bright palette,
    [Hue: 14  Weight: 1.0] from the Light palette,
    [Hue: 11  Weight: 1.0] from the Dim palette,
    [Hue: 22  Weight: 1.0] from the Bright palette,
    [Hue: 1  Weight: 1.0] from the Dark palette,
    [Hue: 1  Weight: 1.0] from the Pastel palette,
    [Hue: 22  Weight: 1.0] from the Light palette,
    [Hue: 14  Weight: 1.0] from the Dim palette,
    [Hue: 11  Weight: 1.0] from the Light palette]
                                     Type: List Palette
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty22}
\begin{paste}{ugGraphTwoDbuildPageEmpty22}{ugGraphTwoDbuildPagePatch22}
\pastebutton{ugGraphTwoDbuildPageEmpty22}{\showpaste}
\tab{5}\spadcommand{lc := [pastel blue(), light yellow(), dim green(), bright red(), light green(), dim yellow(), bright blue(), dark red(), pastel red(), light blue(), dim green(), light yellow()]\bound{lc }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch23}
\begin{paste}{ugGraphTwoDbuildPageFull23}{ugGraphTwoDbuildPageEmpty23}
\pastebutton{ugGraphTwoDbuildPageFull23}{\hidepaste}
\tab{5}\spadcommand{g := makeGraphImage(llp,lpc,lc,lsize)$GRIMAGE\bound{g }\free{llp lpc lc lsize }}
\indentrel{3}\begin{verbatim}
   (23)  Graph with 12 point lists
                                       Type: GraphImage
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty23}
\begin{paste}{ugGraphTwoDbuildPageEmpty23}{ugGraphTwoDbuildPagePatch23}
\pastebutton{ugGraphTwoDbuildPageEmpty23}{\showpaste}
\tab{5}\spadcommand{g := makeGraphImage(llp,lpc,lc,lsize)$GRIMAGE\bound{g }\free{llp lpc lc lsize }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch24}
\begin{paste}{ugGraphTwoDbuildPageFull24}{ugGraphTwoDbuildPageEmpty24}
\pastebutton{ugGraphTwoDbuildPageFull24}{\hidepaste}
\tab{5}\spadgraph{makeViewport2D(g,[title("Lines")])$VIEW2D\free{g }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphtwodbuildpage24.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphtwodbuildpage24}}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty24}
\begin{paste}{ugGraphTwoDbuildPageEmpty24}{ugGraphTwoDbuildPagePatch24}
\pastebutton{ugGraphTwoDbuildPageEmpty24}{\showpaste}
\tab{5}\spadgraph{makeViewport2D(g,[title("Lines")])$VIEW2D\free{g }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch25}
\begin{paste}{ugGraphTwoDbuildPageFull25}{ugGraphTwoDbuildPageEmpty25}
\pastebutton{ugGraphTwoDbuildPageFull25}{\hidepaste}
\tab{5}\spadcommand{)clear all\bound{clearAll }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty25}
\begin{paste}{ugGraphTwoDbuildPageEmpty25}{ugGraphTwoDbuildPagePatch25}
\pastebutton{ugGraphTwoDbuildPageEmpty25}{\showpaste}
\tab{5}\spadcommand{)clear all\bound{clearAll }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch26}
\begin{paste}{ugGraphTwoDbuildPageFull26}{ugGraphTwoDbuildPageEmpty26}
\pastebutton{ugGraphTwoDbuildPageFull26}{\hidepaste}
\tab{5}\spadcommand{g := graphImage()$GRIMAGE\bound{Sg }\free{clearAll }}
\indentrel{3}\begin{verbatim}
   (1)  Graph with 0 point lists
                                       Type: GraphImage
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty26}
\begin{paste}{ugGraphTwoDbuildPageEmpty26}{ugGraphTwoDbuildPagePatch26}
\pastebutton{ugGraphTwoDbuildPageEmpty26}{\showpaste}
\tab{5}\spadcommand{g := graphImage()$GRIMAGE\bound{Sg }\free{clearAll }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch27}
\begin{paste}{ugGraphTwoDbuildPageFull27}{ugGraphTwoDbuildPageEmpty27}
\pastebutton{ugGraphTwoDbuildPageFull27}{\hidepaste}
\tab{5}\spadcommand{p1 := point [0,0]$(Point DFLOAT)\bound{Sp1 }}
\indentrel{3}\begin{verbatim}
   (2)  [0.0,0.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty27}
\begin{paste}{ugGraphTwoDbuildPageEmpty27}{ugGraphTwoDbuildPagePatch27}
\pastebutton{ugGraphTwoDbuildPageEmpty27}{\showpaste}
\tab{5}\spadcommand{p1 := point [0,0]$(Point DFLOAT)\bound{Sp1 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch28}
\begin{paste}{ugGraphTwoDbuildPageFull28}{ugGraphTwoDbuildPageEmpty28}
\pastebutton{ugGraphTwoDbuildPageFull28}{\hidepaste}
\tab{5}\spadcommand{p2 := point [.25,.25]$(Point DFLOAT)\bound{Sp2 }}
\indentrel{3}\begin{verbatim}
   (3)  [0.25,0.25]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty28}
\begin{paste}{ugGraphTwoDbuildPageEmpty28}{ugGraphTwoDbuildPagePatch28}
\pastebutton{ugGraphTwoDbuildPageEmpty28}{\showpaste}
\tab{5}\spadcommand{p2 := point [.25,.25]$(Point DFLOAT)\bound{Sp2 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch29}
\begin{paste}{ugGraphTwoDbuildPageFull29}{ugGraphTwoDbuildPageEmpty29}
\pastebutton{ugGraphTwoDbuildPageFull29}{\hidepaste}
\tab{5}\spadcommand{p3 := point [.5,.5]$(Point DFLOAT)\bound{Sp3 }}
\indentrel{3}\begin{verbatim}
   (4)  [0.5,0.5]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty29}
\begin{paste}{ugGraphTwoDbuildPageEmpty29}{ugGraphTwoDbuildPagePatch29}
\pastebutton{ugGraphTwoDbuildPageEmpty29}{\showpaste}
\tab{5}\spadcommand{p3 := point [.5,.5]$(Point DFLOAT)\bound{Sp3 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch30}
\begin{paste}{ugGraphTwoDbuildPageFull30}{ugGraphTwoDbuildPageEmpty30}
\pastebutton{ugGraphTwoDbuildPageFull30}{\hidepaste}
\tab{5}\spadcommand{p4 := point [.75,.75]$(Point DFLOAT)\bound{Sp4 }}
\indentrel{3}\begin{verbatim}
   (5)  [0.75,0.75]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty30}
\begin{paste}{ugGraphTwoDbuildPageEmpty30}{ugGraphTwoDbuildPagePatch30}
\pastebutton{ugGraphTwoDbuildPageEmpty30}{\showpaste}
\tab{5}\spadcommand{p4 := point [.75,.75]$(Point DFLOAT)\bound{Sp4 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch31}
\begin{paste}{ugGraphTwoDbuildPageFull31}{ugGraphTwoDbuildPageEmpty31}
\pastebutton{ugGraphTwoDbuildPageFull31}{\hidepaste}
\tab{5}\spadcommand{p5 := point [1,1]$(Point DFLOAT)\bound{Sp5 }}
\indentrel{3}\begin{verbatim}
   (6)  [1.0,1.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty31}
\begin{paste}{ugGraphTwoDbuildPageEmpty31}{ugGraphTwoDbuildPagePatch31}
\pastebutton{ugGraphTwoDbuildPageEmpty31}{\showpaste}
\tab{5}\spadcommand{p5 := point [1,1]$(Point DFLOAT)\bound{Sp5 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch32}
\begin{paste}{ugGraphTwoDbuildPageFull32}{ugGraphTwoDbuildPageEmpty32}
\pastebutton{ugGraphTwoDbuildPageFull32}{\hidepaste}
\tab{5}\spadcommand{component(g,p1)$GRIMAGE\free{Sg Sp1 }\bound{gp1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty32}
\begin{paste}{ugGraphTwoDbuildPageEmpty32}{ugGraphTwoDbuildPagePatch32}
\pastebutton{ugGraphTwoDbuildPageEmpty32}{\showpaste}
\tab{5}\spadcommand{component(g,p1)$GRIMAGE\free{Sg Sp1 }\bound{gp1 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch33}
\begin{paste}{ugGraphTwoDbuildPageFull33}{ugGraphTwoDbuildPageEmpty33}
\pastebutton{ugGraphTwoDbuildPageFull33}{\hidepaste}
\tab{5}\spadcommand{component(g,p2)$GRIMAGE\free{Sg Sp2 }\bound{gp2 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty33}
\begin{paste}{ugGraphTwoDbuildPageEmpty33}{ugGraphTwoDbuildPagePatch33}
\pastebutton{ugGraphTwoDbuildPageEmpty33}{\showpaste}
\tab{5}\spadcommand{component(g,p2)$GRIMAGE\free{Sg Sp2 }\bound{gp2 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch34}
\begin{paste}{ugGraphTwoDbuildPageFull34}{ugGraphTwoDbuildPageEmpty34}
\pastebutton{ugGraphTwoDbuildPageFull34}{\hidepaste}
\tab{5}\spadcommand{appendPoint(g,p3)$GRIMAGE\free{gp1 gp2 Sp3 }\bound{gp3 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty34}
\begin{paste}{ugGraphTwoDbuildPageEmpty34}{ugGraphTwoDbuildPagePatch34}
\pastebutton{ugGraphTwoDbuildPageEmpty34}{\showpaste}
\tab{5}\spadcommand{appendPoint(g,p3)$GRIMAGE\free{gp1 gp2 Sp3 }\bound{gp3 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch35}
\begin{paste}{ugGraphTwoDbuildPageFull35}{ugGraphTwoDbuildPageEmpty35}
\pastebutton{ugGraphTwoDbuildPageFull35}{\hidepaste}
\tab{5}\spadcommand{appendPoint(g,p4)$GRIMAGE\free{gp3 Sp4 }\bound{gp4 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty35}
\begin{paste}{ugGraphTwoDbuildPageEmpty35}{ugGraphTwoDbuildPagePatch35}
\pastebutton{ugGraphTwoDbuildPageEmpty35}{\showpaste}
\tab{5}\spadcommand{appendPoint(g,p4)$GRIMAGE\free{gp3 Sp4 }\bound{gp4 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch36}
\begin{paste}{ugGraphTwoDbuildPageFull36}{ugGraphTwoDbuildPageEmpty36}
\pastebutton{ugGraphTwoDbuildPageFull36}{\hidepaste}
\tab{5}\spadcommand{appendPoint(g,p5)$GRIMAGE\free{gp4 Sp5 }\bound{gp5 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty36}
\begin{paste}{ugGraphTwoDbuildPageEmpty36}{ugGraphTwoDbuildPagePatch36}
\pastebutton{ugGraphTwoDbuildPageEmpty36}{\showpaste}
\tab{5}\spadcommand{appendPoint(g,p5)$GRIMAGE\free{gp4 Sp5 }\bound{gp5 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch37}
\begin{paste}{ugGraphTwoDbuildPageFull37}{ugGraphTwoDbuildPageEmpty37}
\pastebutton{ugGraphTwoDbuildPageFull37}{\hidepaste}
\tab{5}\spadcommand{g1 := makeGraphImage(g)$GRIMAGE\bound{Sg1 }\free{gp5 }}
\indentrel{3}\begin{verbatim}
   (12)  Graph with 2 point lists
                                       Type: GraphImage
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty37}
\begin{paste}{ugGraphTwoDbuildPageEmpty37}{ugGraphTwoDbuildPagePatch37}
\pastebutton{ugGraphTwoDbuildPageEmpty37}{\showpaste}
\tab{5}\spadcommand{g1 := makeGraphImage(g)$GRIMAGE\bound{Sg1 }\free{gp5 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch38}
\begin{paste}{ugGraphTwoDbuildPageFull38}{ugGraphTwoDbuildPageEmpty38}
\pastebutton{ugGraphTwoDbuildPageFull38}{\hidepaste}
\tab{5}\spadgraph{makeViewport2D(g1,[title("Graph Points")])$VIEW2D\free{Sg1 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphtwodbuildpage38.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphtwodbuildpage38}}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty38}
\begin{paste}{ugGraphTwoDbuildPageEmpty38}{ugGraphTwoDbuildPagePatch38}
\pastebutton{ugGraphTwoDbuildPageEmpty38}{\showpaste}
\tab{5}\spadgraph{makeViewport2D(g1,[title("Graph Points")])$VIEW2D\free{Sg1 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch39}
\begin{paste}{ugGraphTwoDbuildPageFull39}{ugGraphTwoDbuildPageEmpty39}
\pastebutton{ugGraphTwoDbuildPageFull39}{\hidepaste}
\tab{5}\spadcommand{g2 := coerce([[p1],[p2],[p3],[p4],[p5]])$GRIMAGE\free{Sp1 Sp2 Sp3 Sp4 Sp5 }\bound{Sg2 }}
\indentrel{3}\begin{verbatim}
   (14)  Graph with 5 point lists
                                       Type: GraphImage
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty39}
\begin{paste}{ugGraphTwoDbuildPageEmpty39}{ugGraphTwoDbuildPagePatch39}
\pastebutton{ugGraphTwoDbuildPageEmpty39}{\showpaste}
\tab{5}\spadcommand{g2 := coerce([[p1],[p2],[p3],[p4],[p5]])$GRIMAGE\free{Sp1 Sp2 Sp3 Sp4 Sp5 }\bound{Sg2 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch40}
\begin{paste}{ugGraphTwoDbuildPageFull40}{ugGraphTwoDbuildPageEmpty40}
\pastebutton{ugGraphTwoDbuildPageFull40}{\hidepaste}
\tab{5}\spadcommand{v := viewport2D()$VIEW2D\bound{Sv }}
\indentrel{3}\begin{verbatim}
   (15)
   Closed or Undefined TwoDimensionalViewport: "AXIOM2D"
                           Type: TwoDimensionalViewport
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty40}
\begin{paste}{ugGraphTwoDbuildPageEmpty40}{ugGraphTwoDbuildPagePatch40}
\pastebutton{ugGraphTwoDbuildPageEmpty40}{\showpaste}
\tab{5}\spadcommand{v := viewport2D()$VIEW2D\bound{Sv }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch41}
\begin{paste}{ugGraphTwoDbuildPageFull41}{ugGraphTwoDbuildPageEmpty41}
\pastebutton{ugGraphTwoDbuildPageFull41}{\hidepaste}
\tab{5}\spadcommand{options(v,[title("Just Points")])$VIEW2D\free{Sv }\bound{Svo }}
\indentrel{3}\begin{verbatim}
   (16)
   Closed or Undefined TwoDimensionalViewport: "AXIOM2D"
                           Type: TwoDimensionalViewport
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty41}
\begin{paste}{ugGraphTwoDbuildPageEmpty41}{ugGraphTwoDbuildPagePatch41}
\pastebutton{ugGraphTwoDbuildPageEmpty41}{\showpaste}
\tab{5}\spadcommand{options(v,[title("Just Points")])$VIEW2D\free{Sv }\bound{Svo }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch42}
\begin{paste}{ugGraphTwoDbuildPageFull42}{ugGraphTwoDbuildPageEmpty42}
\pastebutton{ugGraphTwoDbuildPageFull42}{\hidepaste}
\tab{5}\spadcommand{putGraph(v,g2,1)$VIEW2D\free{Sg2 Svo }\bound{Svog2 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty42}
\begin{paste}{ugGraphTwoDbuildPageEmpty42}{ugGraphTwoDbuildPagePatch42}
\pastebutton{ugGraphTwoDbuildPageEmpty42}{\showpaste}
\tab{5}\spadcommand{putGraph(v,g2,1)$VIEW2D\free{Sg2 Svo }\bound{Svog2 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPagePatch43}
\begin{paste}{ugGraphTwoDbuildPageFull43}{ugGraphTwoDbuildPageEmpty43}
\pastebutton{ugGraphTwoDbuildPageFull43}{\hidepaste}
\tab{5}\spadgraph{makeViewport2D(v)$VIEW2D\free{Svog2 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphtwodbuildpage43.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphtwodbuildpage43}}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDbuildPageEmpty43}
\begin{paste}{ugGraphTwoDbuildPageEmpty43}{ugGraphTwoDbuildPagePatch43}
\pastebutton{ugGraphTwoDbuildPageEmpty43}{\showpaste}
\tab{5}\spadgraph{makeViewport2D(v)$VIEW2D\free{Svog2 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugGraphTwoDappendPage}{ug07.ht}
{Addendum: Appending a Graph to a Viewport Window Containing a Graph}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphTwoDappendPage}
{7.1.10. Addendum: Appending a Graph to a Viewport 
Window Containing a Graph}
\beginscroll

This section demonstrates how to append a \twodim{} graph to a
viewport already containing other graphs.  The default \axiomFun{draw}
command places a graph into the first \axiomType{GraphImage} slot
position of the \axiomType{TwoDimensionalViewport}.

\xtc{
This graph is in the first slot in its viewport.
}{
\spadpaste{v1 := draw(sin(x),x=0..2*\%pi) \bound{v1}}
}
\xtc{
So is this graph.
}{
\spadpaste{v2 := draw(cos(x),x=0..2*\%pi, curveColor==light red()) 
\bound{v2}}
}
\xtc{
The operation \axiomFunFrom{getGraph}{TwoDimensionalViewport}
retrieves the \axiomType{GraphImage} \axiom{g1} from the first slot 
position in the viewport \axiom{v1}.
}{
\spadpaste{g1 := getGraph(v1,1) \bound{g1}\free{v1}}
}
\xtc{
Now \axiomFunFrom{putGraph}{TwoDimensionalViewport}
places \axiom{g1} into the the second slot position of \axiom{v2}.
}{
\spadpaste{putGraph(v2,g1,2) \bound{v22}\free{g1 v2}}
}
\psXtc{
Display the new \axiomType{TwoDimensionalViewport} containing both graphs.
}{
\graphpaste{makeViewport2D(v2) \free{v22}}
}{
%
}
%
%See Figure #.#.
%

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugGraphTwoDappendPagePatch1}
\begin{paste}{ugGraphTwoDappendPageFull1}{ugGraphTwoDappendPageEmpty1}
\pastebutton{ugGraphTwoDappendPageFull1}{\hidepaste}
\tab{5}\spadcommand{v1 := draw(sin(x),x=0..2*\%pi)\bound{v1 }}
\indentrel{3}\begin{verbatim}
   (1)  TwoDimensionalViewport: "sin x"
                           Type: TwoDimensionalViewport
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDappendPageEmpty1}
\begin{paste}{ugGraphTwoDappendPageEmpty1}{ugGraphTwoDappendPagePatch1}
\pastebutton{ugGraphTwoDappendPageEmpty1}{\showpaste}
\tab{5}\spadcommand{v1 := draw(sin(x),x=0..2*\%pi)\bound{v1 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDappendPagePatch2}
\begin{paste}{ugGraphTwoDappendPageFull2}{ugGraphTwoDappendPageEmpty2}
\pastebutton{ugGraphTwoDappendPageFull2}{\hidepaste}
\tab{5}\spadcommand{v2 := draw(cos(x),x=0..2*\%pi, curveColor==light red())\bound{v2 }}
\indentrel{3}\begin{verbatim}
   (2)  TwoDimensionalViewport: "cos x"
                           Type: TwoDimensionalViewport
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDappendPageEmpty2}
\begin{paste}{ugGraphTwoDappendPageEmpty2}{ugGraphTwoDappendPagePatch2}
\pastebutton{ugGraphTwoDappendPageEmpty2}{\showpaste}
\tab{5}\spadcommand{v2 := draw(cos(x),x=0..2*\%pi, curveColor==light red())\bound{v2 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDappendPagePatch3}
\begin{paste}{ugGraphTwoDappendPageFull3}{ugGraphTwoDappendPageEmpty3}
\pastebutton{ugGraphTwoDappendPageFull3}{\hidepaste}
\tab{5}\spadcommand{g1 := getGraph(v1,1)\bound{g1 }\free{v1 }}
\indentrel{3}\begin{verbatim}
   (3)  Graph with 1 point list
                                       Type: GraphImage
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDappendPageEmpty3}
\begin{paste}{ugGraphTwoDappendPageEmpty3}{ugGraphTwoDappendPagePatch3}
\pastebutton{ugGraphTwoDappendPageEmpty3}{\showpaste}
\tab{5}\spadcommand{g1 := getGraph(v1,1)\bound{g1 }\free{v1 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDappendPagePatch4}
\begin{paste}{ugGraphTwoDappendPageFull4}{ugGraphTwoDappendPageEmpty4}
\pastebutton{ugGraphTwoDappendPageFull4}{\hidepaste}
\tab{5}\spadcommand{putGraph(v2,g1,2)\bound{v22 }\free{g1 v2 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDappendPageEmpty4}
\begin{paste}{ugGraphTwoDappendPageEmpty4}{ugGraphTwoDappendPagePatch4}
\pastebutton{ugGraphTwoDappendPageEmpty4}{\showpaste}
\tab{5}\spadcommand{putGraph(v2,g1,2)\bound{v22 }\free{g1 v2 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDappendPagePatch5}
\begin{paste}{ugGraphTwoDappendPageFull5}{ugGraphTwoDappendPageEmpty5}
\pastebutton{ugGraphTwoDappendPageFull5}{\hidepaste}
\tab{5}\spadgraph{makeViewport2D(v2)\free{v22 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphtwodappendpage5.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphtwodappendpage5}}
\end{paste}\end{patch}

\begin{patch}{ugGraphTwoDappendPageEmpty5}
\begin{paste}{ugGraphTwoDappendPageEmpty5}{ugGraphTwoDappendPagePatch5}
\pastebutton{ugGraphTwoDappendPageEmpty5}{\showpaste}
\tab{5}\spadgraph{makeViewport2D(v2)\free{v22 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugGraphThreeDPage}{ug07.ht}{Three-Dimensional Graphics}
\pageto{notitle}{ugGraphThreeDPlotPage}
\pageto{notitle}{ugGraphThreeDParmPage}
\pageto{notitle}{ugGraphThreeDParPage}
\pageto{notitle}{ugGraphThreeDOptionsPage}
\pageto{notitle}{ugGraphMakeObjectPage}
\pageto{notitle}{ugGraphThreeDBuildPage}
\pageto{notitle}{ugGraphCoordPage}
\pageto{notitle}{ugGraphClipPage}
\pageto{notitle}{ugGraphThreeDControlPage}
\pageto{notitle}{ugGraphThreeDopsPage}
\pageto{notitle}{ugXdefaultsPage}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphThreeDPage}{7.2. Three-Dimensional Graphics}
\beginscroll
%
The Axiom \threedim{} graphics package provides the ability to
%
\indent{4}
\beginitems
%
\item[-] generate surfaces defined by a function of two real variables
%
\item[-] generate space curves and tubes defined by parametric equations
%
\item[-] generate surfaces defined by parametric equations
\enditems
\indent{0}
These graphs can be modified by using various options, such as calculating
points in the spherical coordinate system or changing the polygon grid size
of a surface.

\beginmenu
    \menudownlink{
{7.2.1. Plotting Three-Dimensional Functions of Two Variables}}
{ugGraphThreeDPlotPage}
    \menudownlink{
{7.2.2. Plotting Three-Dimensional Parametric Space Curves}}
{ugGraphThreeDParmPage}
    \menudownlink{
{7.2.3. Plotting Three-Dimensional Parametric Surfaces}}
{ugGraphThreeDParPage}
    \menudownlink{
{7.2.4. Three-Dimensional Options}}{ugGraphThreeDOptionsPage}
    \menudownlink{
{7.2.5. The makeObject Command}}{ugGraphMakeObjectPage}
    \menudownlink{
{7.2.6. Building Three-Dimensional Objects From Primitives}}
{ugGraphThreeDBuildPage}
    \menudownlink{
{7.2.7. Coordinate System Transformations}}{ugGraphCoordPage}
    \menudownlink{
{7.2.8. Three-Dimensional Clipping}}{ugGraphClipPage}
    \menudownlink{
{7.2.9. Three-Dimensional Control-Panel}}
{ugGraphThreeDControlPage}
    \menudownlink{
{7.2.10. Operations for Three-Dimensional Graphics}}
{ugGraphThreeDopsPage}
    \menudownlink{
{7.2.11. Customization using .Xdefaults}}{ugXdefaultsPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugGraphThreeDPlotPage}{ug07.ht}
{Plotting Three-Dimensional Functions of Two Variables}
\pageto{notitle}{ugGraphThreeDOptionsPage}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphThreeDPlotPage}
{7.2.1. Plotting Three-Dimensional Functions of Two Variables}
\beginscroll

The simplest \threedim{} graph is that of a surface defined by a function
of two variables, \axiom{z = f(x,y)}.


\beginImportant

The general format for drawing a surface defined by a formula
\axiom{f(x,y)} of two variables \axiom{x} and \axiom{y} is:

\centerline{{{\tt draw(f(x,y), x = a..b, y = c..d, {\it options})}}}
where \axiom{a..b} and \axiom{c..d} define the range of \axiom{x}
and \axiom{y}, and where {\it options} prescribes zero or more
options as described in 
\downlink{``Three-Dimensional Options''}{ugGraphThreeDOptionsPage} 
in Section 7.2.4\ignore{ugGraphThreeDOptions}.
An example of an option is \axiom{title == "Title of Graph".}
An alternative format involving a function \axiom{f} is also
available.
\endImportant

%
\psXtc{
The simplest way to plot a function of two variables is to use a formula.
With formulas you always precede the range specifications with
the variable name and an \spadSyntax{=} sign.
}{
\graphpaste{draw(cos(x*y),x=-3..3,y=-3..3)}
}{
\epsffile[0 0 295 295]{../ps/3d2vara.ps}
}
%
\xtc{
If you intend to use a function more than once,
or it is long and complex, then first
give its definition to Axiom.
}{
\spadpaste{f(x,y) == sin(x)*cos(y) \bound{f}}
}
%
%
\psXtc{
To draw the function, just give its name and drop the variables
from the range specifications.
Axiom compiles your function for efficient computation
of data for the graph.
Notice that Axiom uses the text of your function as a
default title.
}{
\graphpaste{draw(f,-\%pi..\%pi,-\%pi..\%pi) \free{f}}
}{
\epsffile[0 0 295 295]{../ps/3d2varb.ps}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugGraphThreeDPlotPagePatch1}
\begin{paste}{ugGraphThreeDPlotPageFull1}{ugGraphThreeDPlotPageEmpty1}
\pastebutton{ugGraphThreeDPlotPageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(cos(x*y),x=-3..3,y=-3..3)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphthreedplotpage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphthreedplotpage1}}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDPlotPageEmpty1}
\begin{paste}{ugGraphThreeDPlotPageEmpty1}{ugGraphThreeDPlotPagePatch1}
\pastebutton{ugGraphThreeDPlotPageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(cos(x*y),x=-3..3,y=-3..3)}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDPlotPagePatch2}
\begin{paste}{ugGraphThreeDPlotPageFull2}{ugGraphThreeDPlotPageEmpty2}
\pastebutton{ugGraphThreeDPlotPageFull2}{\hidepaste}
\tab{5}\spadcommand{f(x,y) == sin(x)*cos(y)\bound{f }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDPlotPageEmpty2}
\begin{paste}{ugGraphThreeDPlotPageEmpty2}{ugGraphThreeDPlotPagePatch2}
\pastebutton{ugGraphThreeDPlotPageEmpty2}{\showpaste}
\tab{5}\spadcommand{f(x,y) == sin(x)*cos(y)\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDPlotPagePatch3}
\begin{paste}{ugGraphThreeDPlotPageFull3}{ugGraphThreeDPlotPageEmpty3}
\pastebutton{ugGraphThreeDPlotPageFull3}{\hidepaste}
\tab{5}\spadgraph{draw(f,-\%pi..\%pi,-\%pi..\%pi)\free{f }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphthreedplotpage3.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphthreedplotpage3}}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDPlotPageEmpty3}
\begin{paste}{ugGraphThreeDPlotPageEmpty3}{ugGraphThreeDPlotPagePatch3}
\pastebutton{ugGraphThreeDPlotPageEmpty3}{\showpaste}
\tab{5}\spadgraph{draw(f,-\%pi..\%pi,-\%pi..\%pi)\free{f }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugGraphThreeDParmPage}{ug07.ht}
{Plotting Three-Dimensional Parametric Space Curves}
\pageto{notitle}{ugGraphThreeDOptionsPage}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphThreeDParmPage}
{7.2.2. Plotting Three-Dimensional Parametric Space Curves}
\beginscroll

A second kind of \threedim{} graph is a \threedim{} space curve
defined by the parametric equations for \axiom{x(t)}, \axiom{y(t)},
and \axiom{z(t)} as a function of an independent variable \axiom{t}.

%
\beginImportant
The general format for drawing a \threedim{} space curve defined by
parametric formulas \axiom{x = f(t)}, \axiom{y = g(t)}, and
\axiom{z = h(t)} is:
%
\centerline{{{\tt draw(curve(f(t),g(t),h(t)), t = a..b, {\it options})}}}
where \axiom{a..b} defines the range of the independent variable
\axiom{t}, and where {\it options} prescribes zero or more options
as described in 
\downlink{``Three-Dimensional Options''}{ugGraphThreeDOptionsPage} 
in Section 7.2.4\ignore{ugGraphThreeDOptions}.
An example of an option is \axiom{title == "Title of Graph".}
An alternative format involving functions \axiom{f}, \axiom{g} and
\axiom{h} is also available.
\endImportant

%
\psXtc{
If you use explicit formulas to draw a space curve, always precede
the range specification with the variable name and an
\spadSyntax{=} sign.
}{
\graphpaste{draw(curve(5*cos(t), 5*sin(t),t), t=-12..12)}
}{
\epsffile[0 0 295 295]{../ps/3dpsca.ps}
}
%
\xtc{
Alternatively, you can draw space curves by referring to functions.
}{
\spadpaste{i1(t:DFLOAT):DFLOAT == sin(t)*cos(3*t/5) \bound{i1}}
}
\xtc{
This is useful if the functions are to be used more than once \ldots
}{
\spadpaste{i2(t:DFLOAT):DFLOAT == cos(t)*cos(3*t/5) \bound{i2}}
}
\xtc{
or if the functions are long and complex.
}{
\spadpaste{i3(t:DFLOAT):DFLOAT == cos(t)*sin(3*t/5) \bound{i3}}
}
%
%
\psXtc{
Give the names of the functions and
drop the variable name specification in the second argument.
Again, Axiom supplies a default title.
}{
\graphpaste{draw(curve(i1,i2,i3),0..15*\%pi) \free{i1 i2 i3}}
}{
\epsffile[0 0 295 295]{../ps/3dpscb.ps}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugGraphThreeDParmPagePatch1}
\begin{paste}{ugGraphThreeDParmPageFull1}{ugGraphThreeDParmPageEmpty1}
\pastebutton{ugGraphThreeDParmPageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(curve(5*cos(t), 5*sin(t),t), t=-12..12)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphthreedparmpage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphthreedparmpage1}}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDParmPageEmpty1}
\begin{paste}{ugGraphThreeDParmPageEmpty1}{ugGraphThreeDParmPagePatch1}
\pastebutton{ugGraphThreeDParmPageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(curve(5*cos(t), 5*sin(t),t), t=-12..12)}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDParmPagePatch2}
\begin{paste}{ugGraphThreeDParmPageFull2}{ugGraphThreeDParmPageEmpty2}
\pastebutton{ugGraphThreeDParmPageFull2}{\hidepaste}
\tab{5}\spadcommand{i1(t:DFLOAT):DFLOAT == sin(t)*cos(3*t/5)\bound{i1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDParmPageEmpty2}
\begin{paste}{ugGraphThreeDParmPageEmpty2}{ugGraphThreeDParmPagePatch2}
\pastebutton{ugGraphThreeDParmPageEmpty2}{\showpaste}
\tab{5}\spadcommand{i1(t:DFLOAT):DFLOAT == sin(t)*cos(3*t/5)\bound{i1 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDParmPagePatch3}
\begin{paste}{ugGraphThreeDParmPageFull3}{ugGraphThreeDParmPageEmpty3}
\pastebutton{ugGraphThreeDParmPageFull3}{\hidepaste}
\tab{5}\spadcommand{i2(t:DFLOAT):DFLOAT == cos(t)*cos(3*t/5)\bound{i2 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDParmPageEmpty3}
\begin{paste}{ugGraphThreeDParmPageEmpty3}{ugGraphThreeDParmPagePatch3}
\pastebutton{ugGraphThreeDParmPageEmpty3}{\showpaste}
\tab{5}\spadcommand{i2(t:DFLOAT):DFLOAT == cos(t)*cos(3*t/5)\bound{i2 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDParmPagePatch4}
\begin{paste}{ugGraphThreeDParmPageFull4}{ugGraphThreeDParmPageEmpty4}
\pastebutton{ugGraphThreeDParmPageFull4}{\hidepaste}
\tab{5}\spadcommand{i3(t:DFLOAT):DFLOAT == cos(t)*sin(3*t/5)\bound{i3 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDParmPageEmpty4}
\begin{paste}{ugGraphThreeDParmPageEmpty4}{ugGraphThreeDParmPagePatch4}
\pastebutton{ugGraphThreeDParmPageEmpty4}{\showpaste}
\tab{5}\spadcommand{i3(t:DFLOAT):DFLOAT == cos(t)*sin(3*t/5)\bound{i3 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDParmPagePatch5}
\begin{paste}{ugGraphThreeDParmPageFull5}{ugGraphThreeDParmPageEmpty5}
\pastebutton{ugGraphThreeDParmPageFull5}{\hidepaste}
\tab{5}\spadgraph{draw(curve(i1,i2,i3),0..15*\%pi)\free{i1 i2 i3 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphthreedparmpage5.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphthreedparmpage5}}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDParmPageEmpty5}
\begin{paste}{ugGraphThreeDParmPageEmpty5}{ugGraphThreeDParmPagePatch5}
\pastebutton{ugGraphThreeDParmPageEmpty5}{\showpaste}
\tab{5}\spadgraph{draw(curve(i1,i2,i3),0..15*\%pi)\free{i1 i2 i3 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugGraphThreeDParPage}{ug07.ht}
{Plotting 3D Parametric Surfaces}
\pageto{notitle}{ugGraphThreeDOptionsPage}
\pageto{notitle}{ugGraphCoordPage}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphThreeDParPage}
{7.2.3. Plotting 3D Parametric Surfaces}
\beginscroll

A third kind of \threedim{} graph is a surface defined by
parametric equations for \axiom{x(u,v)}, \axiom{y(u,v)}, and
\axiom{z(u,v)} of two independent variables \axiom{u} and \axiom{v}.

%
\beginImportant
The general format for drawing a \threedim{} graph defined by
parametric formulas \axiom{x = f(u,v)}, \axiom{y = g(u,v)},
and \axiom{z = h(u,v)} is:
%
\centerline{{{\tt draw(surface(f(u,v),g(u,v),h(u,v)), 
u = a..b, v = c..d, {\it options})}}}
where \axiom{a..b} and \axiom{c..d} define the range of the
independent variables \axiom{u} and \axiom{v}, and where
{\it options} prescribes zero or more options as described in
\downlink{``Three-Dimensional Options''}{ugGraphThreeDOptionsPage} 
in Section 7.2.4\ignore{ugGraphThreeDOptions}.
An example of an option is \axiom{title == "Title of Graph".}
An alternative format involving functions \axiom{f}, \axiom{g} and
\axiom{h} is also available.
\endImportant

%
\psXtc{
This example draws a graph of a surface plotted using the
parabolic cylindrical coordinate system option.
The values of the functions supplied to \axiomFun{surface} are
interpreted in coordinates as given by a {\tt coordinates} option,
here as parabolic cylindrical coordinates (see
\downlink{``Coordinate System Transformations''}{ugGraphCoordPage} 
in Section 7.2.7\ignore{ugGraphCoord}).
}{
\graphpaste{draw(surface(u*cos(v), u*sin(v), v*cos(u)), 
u=-4..4, v=0..\%pi, coordinates== parabolicCylindrical)}
}{
\epsffile[0 0 295 295]{../ps/3dpsa.ps}
}
%
Again, you can graph these parametric surfaces using functions,
if the functions are long and complex.
\xtc{
Here we declare the types of arguments and values to be of type
\axiomType{DoubleFloat}.
}{
\spadpaste{n1(u:DFLOAT,v:DFLOAT):DFLOAT == u*cos(v) \bound{n1}}
}
\xtc{
As shown by previous examples, these declarations are necessary.
}{
\spadpaste{n2(u:DFLOAT,v:DFLOAT):DFLOAT == u*sin(v) \bound{n2}}
}
\xtc{
In either case, Axiom compiles the functions
when needed to graph a result.
}{
\spadpaste{n3(u:DFLOAT,v:DFLOAT):DFLOAT == u \bound{n3}}
}
\xtc{
Without these declarations, you have to suffix floats
with \axiom{@DFLOAT} to get a \axiomType{DoubleFloat} result.
However, a call here with an unadorned float 
produces a \axiomType{DoubleFloat}.
}{
\spadpaste{n3(0.5,1.0)\free{n3}}
}
%
%
\psXtc{
Draw the surface by referencing the function names, this time
choosing the toroidal coordinate system.
}{
\graphpaste{draw(surface(n1,n2,n3), 1..4, 1..2*\%pi, 
coordinates == toroidal(1\$DFLOAT)) \free{n1 n2 n3}}
}{
\epsffile[0 0 295 295]{../ps/3dpsb.ps}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugGraphThreeDParPagePatch1}
\begin{paste}{ugGraphThreeDParPageFull1}{ugGraphThreeDParPageEmpty1}
\pastebutton{ugGraphThreeDParPageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(surface(u*cos(v), u*sin(v), v*cos(u)), u=-4..4, v=0..\%pi, coordinates== parabolicCylindrical)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphthreedparpage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphthreedparpage1}}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDParPageEmpty1}
\begin{paste}{ugGraphThreeDParPageEmpty1}{ugGraphThreeDParPagePatch1}
\pastebutton{ugGraphThreeDParPageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(surface(u*cos(v), u*sin(v), v*cos(u)), u=-4..4, v=0..\%pi, coordinates== parabolicCylindrical)}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDParPagePatch2}
\begin{paste}{ugGraphThreeDParPageFull2}{ugGraphThreeDParPageEmpty2}
\pastebutton{ugGraphThreeDParPageFull2}{\hidepaste}
\tab{5}\spadcommand{n1(u:DFLOAT,v:DFLOAT):DFLOAT == u*cos(v)\bound{n1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDParPageEmpty2}
\begin{paste}{ugGraphThreeDParPageEmpty2}{ugGraphThreeDParPagePatch2}
\pastebutton{ugGraphThreeDParPageEmpty2}{\showpaste}
\tab{5}\spadcommand{n1(u:DFLOAT,v:DFLOAT):DFLOAT == u*cos(v)\bound{n1 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDParPagePatch3}
\begin{paste}{ugGraphThreeDParPageFull3}{ugGraphThreeDParPageEmpty3}
\pastebutton{ugGraphThreeDParPageFull3}{\hidepaste}
\tab{5}\spadcommand{n2(u:DFLOAT,v:DFLOAT):DFLOAT == u*sin(v)\bound{n2 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDParPageEmpty3}
\begin{paste}{ugGraphThreeDParPageEmpty3}{ugGraphThreeDParPagePatch3}
\pastebutton{ugGraphThreeDParPageEmpty3}{\showpaste}
\tab{5}\spadcommand{n2(u:DFLOAT,v:DFLOAT):DFLOAT == u*sin(v)\bound{n2 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDParPagePatch4}
\begin{paste}{ugGraphThreeDParPageFull4}{ugGraphThreeDParPageEmpty4}
\pastebutton{ugGraphThreeDParPageFull4}{\hidepaste}
\tab{5}\spadcommand{n3(u:DFLOAT,v:DFLOAT):DFLOAT == u\bound{n3 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDParPageEmpty4}
\begin{paste}{ugGraphThreeDParPageEmpty4}{ugGraphThreeDParPagePatch4}
\pastebutton{ugGraphThreeDParPageEmpty4}{\showpaste}
\tab{5}\spadcommand{n3(u:DFLOAT,v:DFLOAT):DFLOAT == u\bound{n3 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDParPagePatch5}
\begin{paste}{ugGraphThreeDParPageFull5}{ugGraphThreeDParPageEmpty5}
\pastebutton{ugGraphThreeDParPageFull5}{\hidepaste}
\tab{5}\spadcommand{n3(0.5,1.0)\free{n3 }}
\indentrel{3}\begin{verbatim}
   (5)  0.5
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDParPageEmpty5}
\begin{paste}{ugGraphThreeDParPageEmpty5}{ugGraphThreeDParPagePatch5}
\pastebutton{ugGraphThreeDParPageEmpty5}{\showpaste}
\tab{5}\spadcommand{n3(0.5,1.0)\free{n3 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDParPagePatch6}
\begin{paste}{ugGraphThreeDParPageFull6}{ugGraphThreeDParPageEmpty6}
\pastebutton{ugGraphThreeDParPageFull6}{\hidepaste}
\tab{5}\spadgraph{draw(surface(n1,n2,n3), 1..4, 1..2*\%pi, coordinates == toroidal(1$DFLOAT))\free{n1 n2 n3 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphthreedparpage6.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphthreedparpage6}}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDParPageEmpty6}
\begin{paste}{ugGraphThreeDParPageEmpty6}{ugGraphThreeDParPagePatch6}
\pastebutton{ugGraphThreeDParPageEmpty6}{\showpaste}
\tab{5}\spadgraph{draw(surface(n1,n2,n3), 1..4, 1..2*\%pi, coordinates == toroidal(1$DFLOAT))\free{n1 n2 n3 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugGraphThreeDOptionsPage}{ug07.ht}{Three-Dimensional Options}
\pageto{notitle}{ugGraphCoordPage}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphThreeDOptionsPage}{7.2.4. Three-Dimensional Options}
\beginscroll

The \axiomFun{draw} commands optionally take an optional list of
options such as {\tt coordinates} as shown in the last example.  Each
option is given by the syntax: \axiom{name} {\tt ==} \axiom{value}.
Here is a list of the available options in the order that they are
described below:

\table{ {title} {coordinates} {var1Steps} {style} {tubeRadius} {var2Steps}
{colorFunction} {tubePoints} {space}}

\psXtc{
The option \axiom{title} gives your graph a title.
}{
\graphpaste{draw(cos(x*y),x=0..2*\%pi,y=0..\%pi,title == "Title of Graph") }
}{
\epsffile[0 0 295 295]{../ps/3doptttl.ps}
}
%
\psXtc{
The \axiom{style} determines which of four rendering algorithms is used for
the graph.
The choices are
{\tt "wireMesh"}, {\tt "solid"}, {\tt "shade"}, and {\tt "smooth"}.
}{
\graphpaste{draw(cos(x*y),x=-3..3,y=-3..3, style=="smooth", 
title=="Smooth Option")}
}{
\epsffile[0 0 295 295]{../ps/3doptsty.ps}
}
%

In all but the wire-mesh style, polygons in a surface or tube plot
are normally colored in a graph according to their
\axiom{z}-coordinate value.  Space curves are colored according to their
parametric variable value.
To change this, you can give a coloring function.
The coloring function is sampled across the range of its arguments, then
normalized onto the standard Axiom colormap.

\xtc{
A function of one variable  makes the color depend on the
value of the parametric variable specified for a tube plot.
}{
\spadpaste{color1(t) == t \bound{colorFxn1}}
}
\psXtc{
}{
\graphpaste{draw(curve(sin(t), cos(t),0), t=0..2*\%pi, 
tubeRadius == .3, colorFunction == color1) \free{colorFxn1}}
}{
\epsffile[0 0 295 295]{../ps/3doptcf1.ps}
}
%
\xtc{
A function of two variables makes the color depend on the
values of the independent variables.
}{
\spadpaste{color2(u,v) == u**2 - v**2 \bound{colorFxn2}}
}
\psXtc{
Use the option {\tt colorFunction} for special coloring.
}{
\graphpaste{draw(cos(u*v), u=-3..3, v=-3..3, 
colorFunction == color2) \free{colorFxn2}}
}{
\epsffile[0 0 295 295]{../ps/3doptcf2.ps}
}
%
\xtc{
With a three variable function, the
color also depends on the value of the function.
}{
\spadpaste{color3(x,y,fxy) == sin(x*fxy) + cos(y*fxy) \bound{colorFxn3}}
}
\psXtc{
}{
\graphpaste{draw(cos(x*y), x=-3..3, y=-3..3, colorFunction == color3) 
\free{colorFxn3}}
}{
\epsffile[0 0 295 295]{../ps/3doptcf3.ps}
}
%
Normally the Cartesian coordinate system is used.
To change this, use the {\tt coordinates} option.
For details, see 
\downlink{``Coordinate System Transformations''}{ugGraphCoordPage} 
in Section 7.2.7\ignore{ugGraphCoord}.
%
%
\xtc{
}{
\spadpaste{m(u:DFLOAT,v:DFLOAT):DFLOAT == 1 \bound{m}}
}
\psXtc{
Use the spherical
coordinate system.
}{
\graphpaste{draw(m, 0..2*\%pi,0..\%pi, coordinates == spherical, 
style=="shade") \free{m}}
}{
\epsffile[0 0 295 295]{../ps/3doptcrd.ps}
}
%
Space curves may be displayed as tubes with polygonal cross sections.
Two options, {\tt tubeRadius} and {\tt tubePoints},  control the size and
shape of this cross section.
%
\psXtc{
The {\tt tubeRadius} option specifies the radius of the tube that
encircles the specified space curve.
}{
\graphpaste{draw(curve(sin(t),cos(t),0),t=0..2*\%pi, style=="shade", 
tubeRadius == .3)}
}{
\epsffile[0 0 295 295]{../ps/3doptrad.ps}
}
%
%
\psXtc{
The {\tt tubePoints} option specifies the number of vertices
defining the polygon that is used to create a tube around the
specified space curve.
The larger this number is, the more cylindrical the tube becomes.
}{
\graphpaste{draw(curve(sin(t), cos(t), 0), t=0..2*\%pi, style=="shade", 
tubeRadius == .25, tubePoints == 3)}
}{
\epsffile[0 0 295 295]{../ps/3doptpts.ps}
}
%
%
%
\psXtc{
Options \axiomFunFrom{var1Steps}{DrawOption} and
\axiomFunFrom{var2Steps}{DrawOption} specify the number of intervals into
which the grid defining a surface plot is subdivided with respect to the
first and second parameters of the surface function(s).
}{
\graphpaste{draw(cos(x*y),x=-3..3,y=-3..3, style=="shade", var1Steps == 30, 
var2Steps == 30)}
}{
\epsffile[0 0 295 295]{../ps/3doptvb.ps}
}
%
The {\tt space} option
of a \axiomFun{draw} command lets you build multiple graphs in three space.
To use this option, first create an empty three-space object,
then use the {\tt space} option thereafter.
There is no restriction as to the number or kinds
of graphs that can be combined this way.
\xtc{
Create an empty three-space object.
}{
\spadpaste{s := create3Space()\$(ThreeSpace DFLOAT) \bound{s}}
}
%
%
\xtc{
}{
\spadpaste{m(u:DFLOAT,v:DFLOAT):DFLOAT == 1 \bound{m}}
}
\psXtc{
Add a graph to this three-space object.
The new graph destructively inserts the graph
into \axiom{s}.
}{
\graphpaste{
draw(m,0..\%pi,0..2*\%pi, coordinates == spherical, space == s) \free{s m}}
}{
\epsffile[0 0 295 295]{../ps/3dmult1a.ps}
}
%
%
\psXtc{
Add a second graph to \axiom{s}.
}{
\graphpaste{v := draw(curve(1.5*sin(t), 1.5*cos(t),0), t=0..2*\%pi, 
tubeRadius == .25, space == s) \free{s} \bound{v}}
}{
\epsffile[0 0 295 295]{../ps/3dmult1b.ps}
}
%
A three-space object can also be obtained from an existing 
\threedim{} viewport
using the \axiomFunFrom{subspace}{ThreeSpace} command.
You can then use \axiomFun{makeViewport3D} to create a viewport window.
\xtc{
Assign to \axiom{subsp} the three-space object in viewport \axiom{v}.
}{
\spadpaste{subsp := subspace v \free{v} \bound{su}}
}
\xtc{
Reset the space component of \axiom{v} to the value of \axiom{subsp}.
}{
\spadpaste{subspace(v, subsp) \bound{sp} \free{su}}
}
\noOutputXtc{
Create a viewport window from a three-space object.
}{
\graphpaste{makeViewport3D(subsp,"Graphs") \free{sp}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugGraphThreeDOptionsPagePatch1}
\begin{paste}{ugGraphThreeDOptionsPageFull1}{ugGraphThreeDOptionsPageEmpty1}
\pastebutton{ugGraphThreeDOptionsPageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(cos(x*y),x=0..2*\%pi,y=0..\%pi,title == "Title of Graph")}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/ugGraphThreeDOptionsPage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/ugGraphThreeDOptionsPage1}}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPageEmpty1}
\begin{paste}{ugGraphThreeDOptionsPageEmpty1}{ugGraphThreeDOptionsPagePatch1}
\pastebutton{ugGraphThreeDOptionsPageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(cos(x*y),x=0..2*\%pi,y=0..\%pi,title == "Title of Graph")}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPagePatch2}
\begin{paste}{ugGraphThreeDOptionsPageFull2}{ugGraphThreeDOptionsPageEmpty2}
\pastebutton{ugGraphThreeDOptionsPageFull2}{\hidepaste}
\tab{5}\spadgraph{draw(cos(x*y),x=-3..3,y=-3..3, style=="smooth", title=="Smooth Option")}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphthreedoptionspage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphthreedoptionspage2}}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPageEmpty2}
\begin{paste}{ugGraphThreeDOptionsPageEmpty2}{ugGraphThreeDOptionsPagePatch2}
\pastebutton{ugGraphThreeDOptionsPageEmpty2}{\showpaste}
\tab{5}\spadgraph{draw(cos(x*y),x=-3..3,y=-3..3, style=="smooth", title=="Smooth Option")}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPagePatch3}
\begin{paste}{ugGraphThreeDOptionsPageFull3}{ugGraphThreeDOptionsPageEmpty3}
\pastebutton{ugGraphThreeDOptionsPageFull3}{\hidepaste}
\tab{5}\spadcommand{color1(t) == t\bound{colorFxn1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPageEmpty3}
\begin{paste}{ugGraphThreeDOptionsPageEmpty3}{ugGraphThreeDOptionsPagePatch3}
\pastebutton{ugGraphThreeDOptionsPageEmpty3}{\showpaste}
\tab{5}\spadcommand{color1(t) == t\bound{colorFxn1 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPagePatch4}
\begin{paste}{ugGraphThreeDOptionsPageFull4}{ugGraphThreeDOptionsPageEmpty4}
\pastebutton{ugGraphThreeDOptionsPageFull4}{\hidepaste}
\tab{5}\spadgraph{draw(curve(sin(t), cos(t),0), t=0..2*\%pi, tubeRadius == .3, colorFunction == color1)\free{colorFxn1 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphthreedoptionspage4.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphthreedoptionspage4}}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPageEmpty4}
\begin{paste}{ugGraphThreeDOptionsPageEmpty4}{ugGraphThreeDOptionsPagePatch4}
\pastebutton{ugGraphThreeDOptionsPageEmpty4}{\showpaste}
\tab{5}\spadgraph{draw(curve(sin(t), cos(t),0), t=0..2*\%pi, tubeRadius == .3, colorFunction == color1)\free{colorFxn1 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPagePatch5}
\begin{paste}{ugGraphThreeDOptionsPageFull5}{ugGraphThreeDOptionsPageEmpty5}
\pastebutton{ugGraphThreeDOptionsPageFull5}{\hidepaste}
\tab{5}\spadcommand{color2(u,v) == u**2 - v**2\bound{colorFxn2 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPageEmpty5}
\begin{paste}{ugGraphThreeDOptionsPageEmpty5}{ugGraphThreeDOptionsPagePatch5}
\pastebutton{ugGraphThreeDOptionsPageEmpty5}{\showpaste}
\tab{5}\spadcommand{color2(u,v) == u**2 - v**2\bound{colorFxn2 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPagePatch6}
\begin{paste}{ugGraphThreeDOptionsPageFull6}{ugGraphThreeDOptionsPageEmpty6}
\pastebutton{ugGraphThreeDOptionsPageFull6}{\hidepaste}
\tab{5}\spadgraph{draw(cos(u*v), u=-3..3, v=-3..3, colorFunction == color2)\free{colorFxn2 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphthreedoptionspage6.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphthreedoptionspage6}}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPageEmpty6}
\begin{paste}{ugGraphThreeDOptionsPageEmpty6}{ugGraphThreeDOptionsPagePatch6}
\pastebutton{ugGraphThreeDOptionsPageEmpty6}{\showpaste}
\tab{5}\spadgraph{draw(cos(u*v), u=-3..3, v=-3..3, colorFunction == color2)\free{colorFxn2 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPagePatch7}
\begin{paste}{ugGraphThreeDOptionsPageFull7}{ugGraphThreeDOptionsPageEmpty7}
\pastebutton{ugGraphThreeDOptionsPageFull7}{\hidepaste}
\tab{5}\spadcommand{color3(x,y,fxy) == sin(x*fxy) + cos(y*fxy)\bound{colorFxn3 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPageEmpty7}
\begin{paste}{ugGraphThreeDOptionsPageEmpty7}{ugGraphThreeDOptionsPagePatch7}
\pastebutton{ugGraphThreeDOptionsPageEmpty7}{\showpaste}
\tab{5}\spadcommand{color3(x,y,fxy) == sin(x*fxy) + cos(y*fxy)\bound{colorFxn3 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPagePatch8}
\begin{paste}{ugGraphThreeDOptionsPageFull8}{ugGraphThreeDOptionsPageEmpty8}
\pastebutton{ugGraphThreeDOptionsPageFull8}{\hidepaste}
\tab{5}\spadgraph{draw(cos(x*y), x=-3..3, y=-3..3, colorFunction == color3)\free{colorFxn3 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphthreedoptionspage8.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphthreedoptionspage8}}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPageEmpty8}
\begin{paste}{ugGraphThreeDOptionsPageEmpty8}{ugGraphThreeDOptionsPagePatch8}
\pastebutton{ugGraphThreeDOptionsPageEmpty8}{\showpaste}
\tab{5}\spadgraph{draw(cos(x*y), x=-3..3, y=-3..3, colorFunction == color3)\free{colorFxn3 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPagePatch9}
\begin{paste}{ugGraphThreeDOptionsPageFull9}{ugGraphThreeDOptionsPageEmpty9}
\pastebutton{ugGraphThreeDOptionsPageFull9}{\hidepaste}
\tab{5}\spadcommand{m(u:DFLOAT,v:DFLOAT):DFLOAT == 1\bound{m }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPageEmpty9}
\begin{paste}{ugGraphThreeDOptionsPageEmpty9}{ugGraphThreeDOptionsPagePatch9}
\pastebutton{ugGraphThreeDOptionsPageEmpty9}{\showpaste}
\tab{5}\spadcommand{m(u:DFLOAT,v:DFLOAT):DFLOAT == 1\bound{m }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPagePatch10}
\begin{paste}{ugGraphThreeDOptionsPageFull10}{ugGraphThreeDOptionsPageEmpty10}
\pastebutton{ugGraphThreeDOptionsPageFull10}{\hidepaste}
\tab{5}\spadgraph{draw(m, 0..2*\%pi,0..\%pi, coordinates == spherical, style=="shade")\free{m }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/ugGraphThreeDOptionsPage10.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/ugGraphThreeDOptionsPage10}}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPageEmpty10}
\begin{paste}{ugGraphThreeDOptionsPageEmpty10}{ugGraphThreeDOptionsPagePatch10}
\pastebutton{ugGraphThreeDOptionsPageEmpty10}{\showpaste}
\tab{5}\spadgraph{draw(m, 0..2*\%pi,0..\%pi, coordinates == spherical, style=="shade")\free{m }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPagePatch11}
\begin{paste}{ugGraphThreeDOptionsPageFull11}{ugGraphThreeDOptionsPageEmpty11}
\pastebutton{ugGraphThreeDOptionsPageFull11}{\hidepaste}
\tab{5}\spadgraph{draw(curve(sin(t),cos(t),0),t=0..2*\%pi, style=="shade", tubeRadius == .3)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphthreedoptionspage11.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphthreedoptionspage11}}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPageEmpty11}
\begin{paste}{ugGraphThreeDOptionsPageEmpty11}{ugGraphThreeDOptionsPagePatch11}
\pastebutton{ugGraphThreeDOptionsPageEmpty11}{\showpaste}
\tab{5}\spadgraph{draw(curve(sin(t),cos(t),0),t=0..2*\%pi, style=="shade", tubeRadius == .3)}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPagePatch12}
\begin{paste}{ugGraphThreeDOptionsPageFull12}{ugGraphThreeDOptionsPageEmpty12}
\pastebutton{ugGraphThreeDOptionsPageFull12}{\hidepaste}
\tab{5}\spadgraph{draw(curve(sin(t), cos(t), 0), t=0..2*\%pi, style=="shade", tubeRadius == .25, tubePoints == 3)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphthreedoptionspage12.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphthreedoptionspage12}}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPageEmpty12}
\begin{paste}{ugGraphThreeDOptionsPageEmpty12}{ugGraphThreeDOptionsPagePatch12}
\pastebutton{ugGraphThreeDOptionsPageEmpty12}{\showpaste}
\tab{5}\spadgraph{draw(curve(sin(t), cos(t), 0), t=0..2*\%pi, style=="shade", tubeRadius == .25, tubePoints == 3)}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPagePatch13}
\begin{paste}{ugGraphThreeDOptionsPageFull13}{ugGraphThreeDOptionsPageEmpty13}
\pastebutton{ugGraphThreeDOptionsPageFull13}{\hidepaste}
\tab{5}\spadgraph{draw(cos(x*y),x=-3..3,y=-3..3, style=="shade", var1Steps == 30, var2Steps == 30)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphthreedoptionspage13.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphthreedoptionspage13}}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPageEmpty13}
\begin{paste}{ugGraphThreeDOptionsPageEmpty13}{ugGraphThreeDOptionsPagePatch13}
\pastebutton{ugGraphThreeDOptionsPageEmpty13}{\showpaste}
\tab{5}\spadgraph{draw(cos(x*y),x=-3..3,y=-3..3, style=="shade", var1Steps == 30, var2Steps == 30)}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPagePatch14}
\begin{paste}{ugGraphThreeDOptionsPageFull14}{ugGraphThreeDOptionsPageEmpty14}
\pastebutton{ugGraphThreeDOptionsPageFull14}{\hidepaste}
\tab{5}\spadcommand{s := create3Space()$(ThreeSpace DFLOAT)\bound{s }}
\indentrel{3}\begin{verbatim}
   (14)  3-Space with 0 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPageEmpty14}
\begin{paste}{ugGraphThreeDOptionsPageEmpty14}{ugGraphThreeDOptionsPagePatch14}
\pastebutton{ugGraphThreeDOptionsPageEmpty14}{\showpaste}
\tab{5}\spadcommand{s := create3Space()$(ThreeSpace DFLOAT)\bound{s }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPagePatch15}
\begin{paste}{ugGraphThreeDOptionsPageFull15}{ugGraphThreeDOptionsPageEmpty15}
\pastebutton{ugGraphThreeDOptionsPageFull15}{\hidepaste}
\tab{5}\spadcommand{m(u:DFLOAT,v:DFLOAT):DFLOAT == 1\bound{m }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPageEmpty15}
\begin{paste}{ugGraphThreeDOptionsPageEmpty15}{ugGraphThreeDOptionsPagePatch15}
\pastebutton{ugGraphThreeDOptionsPageEmpty15}{\showpaste}
\tab{5}\spadcommand{m(u:DFLOAT,v:DFLOAT):DFLOAT == 1\bound{m }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPagePatch16}
\begin{paste}{ugGraphThreeDOptionsPageFull16}{ugGraphThreeDOptionsPageEmpty16}
\pastebutton{ugGraphThreeDOptionsPageFull16}{\hidepaste}
\tab{5}\spadgraph{draw(m,0..\%pi,0..2*\%pi, coordinates == spherical, space == s)\free{s m }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphthreedoptionspage16.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphthreedoptionspage16}}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPageEmpty16}
\begin{paste}{ugGraphThreeDOptionsPageEmpty16}{ugGraphThreeDOptionsPagePatch16}
\pastebutton{ugGraphThreeDOptionsPageEmpty16}{\showpaste}
\tab{5}\spadgraph{draw(m,0..\%pi,0..2*\%pi, coordinates == spherical, space == s)\free{s m }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPagePatch17}
\begin{paste}{ugGraphThreeDOptionsPageFull17}{ugGraphThreeDOptionsPageEmpty17}
\pastebutton{ugGraphThreeDOptionsPageFull17}{\hidepaste}
\tab{5}\spadgraph{v := draw(curve(1.5*sin(t), 1.5*cos(t),0), t=0..2*\%pi, tubeRadius == .25, space == s)\free{s }\bound{v }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphthreedoptionspage17.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphthreedoptionspage17}}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPageEmpty17}
\begin{paste}{ugGraphThreeDOptionsPageEmpty17}{ugGraphThreeDOptionsPagePatch17}
\pastebutton{ugGraphThreeDOptionsPageEmpty17}{\showpaste}
\tab{5}\spadgraph{v := draw(curve(1.5*sin(t), 1.5*cos(t),0), t=0..2*\%pi, tubeRadius == .25, space == s)\free{s }\bound{v }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPagePatch18}
\begin{paste}{ugGraphThreeDOptionsPageFull18}{ugGraphThreeDOptionsPageEmpty18}
\pastebutton{ugGraphThreeDOptionsPageFull18}{\hidepaste}
\tab{5}\spadcommand{subsp := subspace v\free{v }\bound{su }}
\indentrel{3}\begin{verbatim}
   (18)  3-Space with 2 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPageEmpty18}
\begin{paste}{ugGraphThreeDOptionsPageEmpty18}{ugGraphThreeDOptionsPagePatch18}
\pastebutton{ugGraphThreeDOptionsPageEmpty18}{\showpaste}
\tab{5}\spadcommand{subsp := subspace v\free{v }\bound{su }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPagePatch19}
\begin{paste}{ugGraphThreeDOptionsPageFull19}{ugGraphThreeDOptionsPageEmpty19}
\pastebutton{ugGraphThreeDOptionsPageFull19}{\hidepaste}
\tab{5}\spadcommand{subspace(v, subsp)\bound{sp }\free{su }}
\indentrel{3}\begin{verbatim}
   (19)
   Closed or Undefined ThreeDimensionalViewport: "AXIOM3D"
                         Type: ThreeDimensionalViewport
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPageEmpty19}
\begin{paste}{ugGraphThreeDOptionsPageEmpty19}{ugGraphThreeDOptionsPagePatch19}
\pastebutton{ugGraphThreeDOptionsPageEmpty19}{\showpaste}
\tab{5}\spadcommand{subspace(v, subsp)\bound{sp }\free{su }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPagePatch20}
\begin{paste}{ugGraphThreeDOptionsPageFull20}{ugGraphThreeDOptionsPageEmpty20}
\pastebutton{ugGraphThreeDOptionsPageFull20}{\hidepaste}
\tab{5}\spadgraph{makeViewport3D(subsp,"Graphs")\free{sp }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphthreedoptionspage20.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphthreedoptionspage20}}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDOptionsPageEmpty20}
\begin{paste}{ugGraphThreeDOptionsPageEmpty20}{ugGraphThreeDOptionsPagePatch20}
\pastebutton{ugGraphThreeDOptionsPageEmpty20}{\showpaste}
\tab{5}\spadgraph{makeViewport3D(subsp,"Graphs")\free{sp }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugGraphMakeObjectPage}{ug07.ht}{The makeObject Command}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphMakeObjectPage}{7.2.5. The makeObject Command}
\beginscroll

An alternate way to create multiple graphs is to use
\axiomFun{makeObject}.
The \axiomFun{makeObject} command is similar to the \axiomFun{draw}
command, except that it returns a three-space object rather than a
\axiomType{ThreeDimensionalViewport}.
In fact, \axiomFun{makeObject} is called by the \axiomFun{draw}
command to create the \axiomType{ThreeSpace} then
\axiomFunFrom{makeViewport3D}{ThreeDimensionalViewport} to create a
viewport window.

\xtc{
}{
\spadpaste{m(u:DFLOAT,v:DFLOAT):DFLOAT == 1 \bound{m}}
}
\noOutputXtc{
Do the last example a new way.
First use \axiomFun{makeObject} to
create a three-space object \axiom{sph}.
}{
\spadpaste{sph := makeObject(m, 0..\%pi, 0..2*\%pi, 
coordinates==spherical)\bound{sph}\free{m}}
}
\noOutputXtc{
Add a second object to \axiom{sph}.
}{
\spadpaste{makeObject(curve(1.5*sin(t), 1.5*cos(t), 0), 
t=0..2*\%pi, space == sph, tubeRadius == .25) \free{sph}\bound{v1}}
}
\noOutputXtc{
Create and display a viewport
containing \axiom{sph}.
}{
\graphpaste{makeViewport3D(sph,"Multiple Objects") \free{v1}}
}

Note that an undefined \axiomType{ThreeSpace} parameter declared in a
\axiomFun{makeObject} or \axiomFun{draw} command results in an error.
Use the \axiomFunFrom{create3Space}{ThreeSpace} function to define a
\axiomType{ThreeSpace}, or obtain a \axiomType{ThreeSpace} that has been
previously generated before including it in a command line.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugGraphMakeObjectPagePatch1}
\begin{paste}{ugGraphMakeObjectPageFull1}{ugGraphMakeObjectPageEmpty1}
\pastebutton{ugGraphMakeObjectPageFull1}{\hidepaste}
\tab{5}\spadcommand{m(u:DFLOAT,v:DFLOAT):DFLOAT == 1\bound{m }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphMakeObjectPageEmpty1}
\begin{paste}{ugGraphMakeObjectPageEmpty1}{ugGraphMakeObjectPagePatch1}
\pastebutton{ugGraphMakeObjectPageEmpty1}{\showpaste}
\tab{5}\spadcommand{m(u:DFLOAT,v:DFLOAT):DFLOAT == 1\bound{m }}
\end{paste}\end{patch}

\begin{patch}{ugGraphMakeObjectPagePatch2}
\begin{paste}{ugGraphMakeObjectPageFull2}{ugGraphMakeObjectPageEmpty2}
\pastebutton{ugGraphMakeObjectPageFull2}{\hidepaste}
\tab{5}\spadcommand{sph := makeObject(m, 0..\%pi, 0..2*\%pi, coordinates==spherical)\bound{sph }\free{m }}
\indentrel{3}\begin{verbatim}
   (2)  3-Space with 1 component
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphMakeObjectPageEmpty2}
\begin{paste}{ugGraphMakeObjectPageEmpty2}{ugGraphMakeObjectPagePatch2}
\pastebutton{ugGraphMakeObjectPageEmpty2}{\showpaste}
\tab{5}\spadcommand{sph := makeObject(m, 0..\%pi, 0..2*\%pi, coordinates==spherical)\bound{sph }\free{m }}
\end{paste}\end{patch}

\begin{patch}{ugGraphMakeObjectPagePatch3}
\begin{paste}{ugGraphMakeObjectPageFull3}{ugGraphMakeObjectPageEmpty3}
\pastebutton{ugGraphMakeObjectPageFull3}{\hidepaste}
\tab{5}\spadcommand{makeObject(curve(1.5*sin(t), 1.5*cos(t), 0), t=0..2*\%pi, space == sph, tubeRadius == .25)\free{sph }\bound{v1 }}
\indentrel{3}\begin{verbatim}
   (3)  3-Space with 2 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphMakeObjectPageEmpty3}
\begin{paste}{ugGraphMakeObjectPageEmpty3}{ugGraphMakeObjectPagePatch3}
\pastebutton{ugGraphMakeObjectPageEmpty3}{\showpaste}
\tab{5}\spadcommand{makeObject(curve(1.5*sin(t), 1.5*cos(t), 0), t=0..2*\%pi, space == sph, tubeRadius == .25)\free{sph }\bound{v1 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphMakeObjectPagePatch4}
\begin{paste}{ugGraphMakeObjectPageFull4}{ugGraphMakeObjectPageEmpty4}
\pastebutton{ugGraphMakeObjectPageFull4}{\hidepaste}
\tab{5}\spadgraph{makeViewport3D(sph,"Multiple Objects")\free{v1 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphmakeobjectpage4.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphmakeobjectpage4}}
\end{paste}\end{patch}

\begin{patch}{ugGraphMakeObjectPageEmpty4}
\begin{paste}{ugGraphMakeObjectPageEmpty4}{ugGraphMakeObjectPagePatch4}
\pastebutton{ugGraphMakeObjectPageEmpty4}{\showpaste}
\tab{5}\spadgraph{makeViewport3D(sph,"Multiple Objects")\free{v1 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugGraphThreeDBuildPage}{ug07.ht}
{Building 3D Objects From Primitives}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphThreeDBuildPage}
{7.2.6. Building 3D Objects From Primitives}
\beginscroll

Rather than using the \axiomFun{draw} and \axiomFun{makeObject} commands,
you can create \threedim{} graphs from primitives.
Operation \axiomFunFrom{create3Space}{ThreeSpace} creates a
three-space object to which points, curves and polygons
can be added using the operations from the \axiomType{ThreeSpace}
domain.
The resulting object can then be displayed in a viewport using
\axiomFunFrom{makeViewport3D}{ThreeDimensionalViewport}.

\xtc{
Create the empty three-space object \axiom{space}.
}{
\spadpaste{space := create3Space()\$(ThreeSpace DFLOAT) \bound{space}}
}

Objects can be sent to this \axiom{space} using the operations
exported by the \axiomType{ThreeSpace} domain.
The following examples place curves into \axiom{space}.

\xtc{
Add these eight curves to the space.
}{
\spadpaste{closedCurve(space,[[0,30,20], [0,30,30], [0,40,30], 
[0,40,100], [0,30,100],[0,30,110], [0,60,110], [0,60,100], 
[0,50,100], [0,50,30], [0,60,30], [0,60,20]]) \bound{curve1} 
\free{space}}
}
\xtc{
}{
\spadpaste{closedCurve(space,[[80,0,30], [80,0,100], [70,0,110], 
[40,0,110], [30,0,100], [30,0,90], [40,0,90], [40,0,95], 
[45,0,100], [65,0,100], [70,0,95], [70,0,35]]) \bound{curve2} 
\free{space}}
}
\xtc{
}{
\spadpaste{closedCurve(space,[[70,0,35], [65,0,30], [45,0,30], 
[40,0,35], [40,0,60], [50,0,60], [50,0,70], [30,0,70], [30,0,30], 
[40,0,20], [70,0,20], [80,0,30]]) \bound{curve3} \free{space}}
}
\xtc{
}{
\spadpaste{closedCurve(space,[[0,70,20], [0,70,110], [0,110,110], 
[0,120,100], [0,120,70], [0,115,65], [0,120,60], [0,120,30], 
[0,110,20], [0,80,20], [0,80,30], [0,80,20]]) \bound{curve4} \free{space}}
}
\xtc{
}{
\spadpaste{closedCurve(space,[[0,105,30], [0,110,35], [0,110,55], 
[0,105,60], [0,80,60], [0,80,70], [0,105,70], [0,110,75], 
[0,110,95], [0,105,100], [0,80,100], [0,80,20], [0,80,30]]) 
\bound{curve5} \free{space}}
}
\xtc{
}{
\spadpaste{closedCurve(space,[[140,0,20], [140,0,110], [130,0,110], 
[90,0,20], [101,0,20],[114,0,50], [130,0,50], [130,0,60], [119,0,60], 
[130,0,85], [130,0,20]]) \bound{curve6} \free{space}}
}
\xtc{
}{
\spadpaste{closedCurve(space,[[0,140,20], [0,140,110], [0,150,110], 
[0,170,50], [0,190,110], [0,200,110], [0,200,20], [0,190,20], 
[0,190,75], [0,175,35], [0,165,35],[0,150,75], [0,150,20]]) 
\bound{curve7} \free{space}}
}
\xtc{
}{
\spadpaste{closedCurve(space,[[200,0,20], [200,0,110], [189,0,110], 
[160,0,45], [160,0,110], [150,0,110], [150,0,20], [161,0,20], 
[190,0,85], [190,0,20]]) \bound{curve8} \free{space}}
}
\psXtc{
Create and display the viewport using \axiomFun{makeViewport3D}.
Options may also be given but here are displayed as a list with values
enclosed in parentheses.
}{
\graphpaste{makeViewport3D(space, title == "Letters") 
\free{space curve1 curve2 curve3 curve4 curve5 curve6 curve7 curve8}}
}{
\epsffile[0 0 295 295]{../ps/3dbuilda.ps}
}

\subsubsection{Cube Example}

As a second example of the use of primitives, we generate a cube using a
polygon mesh.
It is important to use a consistent orientation of the polygons for
correct generation of \threedim{} objects.

\xtc{
Again start with an empty three-space object.
}{
\spadpaste{spaceC := create3Space()\$(ThreeSpace DFLOAT) \bound{spaceC}}
}
\xtc{
For convenience,
give \axiomType{DoubleFloat} values \axiom{+1} and \axiom{-1} names.
}{
\spadpaste{x: DFLOAT := 1 \bound{x}}
}
\xtc{
}{
\spadpaste{y: DFLOAT := -1 \bound{y}}
}
\xtc{
Define the vertices of the cube.
}{
\spadpaste{a := point [x,x,y,1::DFLOAT]\$(Point DFLOAT) \bound{a} 
\free{x y}}
}
\xtc{
}{
\spadpaste{b := point [y,x,y,4::DFLOAT]\$(Point DFLOAT) \bound{b} 
\free{x y}}
}
\xtc{
}{
\spadpaste{c := point [y,x,x,8::DFLOAT]\$(Point DFLOAT) \bound{c} 
\free{x y}}
}
\xtc{
}{
\spadpaste{d := point [x,x,x,12::DFLOAT]\$(Point DFLOAT) \bound{d} 
\free{x y}}
}
\xtc{
}{
\spadpaste{e := point [x,y,y,16::DFLOAT]\$(Point DFLOAT) \bound{e} 
\free{x y}}
}
\xtc{
}{
\spadpaste{f := point [y,y,y,20::DFLOAT]\$(Point DFLOAT) \bound{f} 
\free{x y}}
}
\xtc{
}{
\spadpaste{g := point [y,y,x,24::DFLOAT]\$(Point DFLOAT) \bound{g} 
\free{x y}}
}
\xtc{
}{
\spadpaste{h := point [x,y,x,27::DFLOAT]\$(Point DFLOAT) \bound{h} 
\free{x y}}
}
\xtc{
Add the faces of the cube as polygons to the space using a
consistent orientation.
}{
\spadpaste{polygon(spaceC,[d,c,g,h]) \free{d c g h spaceC} \bound{pol1}}
}
\xtc{
}{
\spadpaste{polygon(spaceC,[d,h,e,a]) \free{d h e a spaceC} \bound{pol2}}
}
\xtc{
}{
\spadpaste{polygon(spaceC,[c,d,a,b]) \free{c d a b spaceC} \bound{pol3}}
}
\xtc{
}{
\spadpaste{polygon(spaceC,[g,c,b,f]) \free{g c b f spaceC} \bound{pol4}}
}
\xtc{
}{
\spadpaste{polygon(spaceC,[h,g,f,e]) \free{h g f e spaceC} \bound{pol5}}
}
\xtc{
}{
\spadpaste{polygon(spaceC,[e,f,b,a]) \free{e f b a spaceC} \bound{pol6}}
}
\psXtc{
Create and display the viewport.
}{
\graphpaste{makeViewport3D(spaceC, title == "Cube") 
\free{pol1 pol2 pol3 pol4 pol5 pol6}}
}{
\epsffile[0 0 295 295]{../ps/3dbuildb.ps}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugGraphThreeDBuildPagePatch1}
\begin{paste}{ugGraphThreeDBuildPageFull1}{ugGraphThreeDBuildPageEmpty1}
\pastebutton{ugGraphThreeDBuildPageFull1}{\hidepaste}
\tab{5}\spadcommand{space := create3Space()$(ThreeSpace DFLOAT)\bound{space }}
\indentrel{3}\begin{verbatim}
   (1)  3-Space with 0 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty1}
\begin{paste}{ugGraphThreeDBuildPageEmpty1}{ugGraphThreeDBuildPagePatch1}
\pastebutton{ugGraphThreeDBuildPageEmpty1}{\showpaste}
\tab{5}\spadcommand{space := create3Space()$(ThreeSpace DFLOAT)\bound{space }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch2}
\begin{paste}{ugGraphThreeDBuildPageFull2}{ugGraphThreeDBuildPageEmpty2}
\pastebutton{ugGraphThreeDBuildPageFull2}{\hidepaste}
\tab{5}\spadcommand{closedCurve(space,[[0,30,20], [0,30,30], [0,40,30], [0,40,100], [0,30,100],[0,30,110], [0,60,110], [0,60,100], [0,50,100], [0,50,30], [0,60,30], [0,60,20]])\bound{curve1 }\free{space }}
\indentrel{3}\begin{verbatim}
   (2)  3-Space with 1 component
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty2}
\begin{paste}{ugGraphThreeDBuildPageEmpty2}{ugGraphThreeDBuildPagePatch2}
\pastebutton{ugGraphThreeDBuildPageEmpty2}{\showpaste}
\tab{5}\spadcommand{closedCurve(space,[[0,30,20], [0,30,30], [0,40,30], [0,40,100], [0,30,100],[0,30,110], [0,60,110], [0,60,100], [0,50,100], [0,50,30], [0,60,30], [0,60,20]])\bound{curve1 }\free{space }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch3}
\begin{paste}{ugGraphThreeDBuildPageFull3}{ugGraphThreeDBuildPageEmpty3}
\pastebutton{ugGraphThreeDBuildPageFull3}{\hidepaste}
\tab{5}\spadcommand{closedCurve(space,[[80,0,30], [80,0,100], [70,0,110], [40,0,110], [30,0,100], [30,0,90], [40,0,90], [40,0,95], [45,0,100], [65,0,100], [70,0,95], [70,0,35]])\bound{curve2 }\free{space }}
\indentrel{3}\begin{verbatim}
   (3)  3-Space with 2 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty3}
\begin{paste}{ugGraphThreeDBuildPageEmpty3}{ugGraphThreeDBuildPagePatch3}
\pastebutton{ugGraphThreeDBuildPageEmpty3}{\showpaste}
\tab{5}\spadcommand{closedCurve(space,[[80,0,30], [80,0,100], [70,0,110], [40,0,110], [30,0,100], [30,0,90], [40,0,90], [40,0,95], [45,0,100], [65,0,100], [70,0,95], [70,0,35]])\bound{curve2 }\free{space }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch4}
\begin{paste}{ugGraphThreeDBuildPageFull4}{ugGraphThreeDBuildPageEmpty4}
\pastebutton{ugGraphThreeDBuildPageFull4}{\hidepaste}
\tab{5}\spadcommand{closedCurve(space,[[70,0,35], [65,0,30], [45,0,30], [40,0,35], [40,0,60], [50,0,60], [50,0,70], [30,0,70], [30,0,30], [40,0,20], [70,0,20], [80,0,30]])\bound{curve3 }\free{space }}
\indentrel{3}\begin{verbatim}
   (4)  3-Space with 3 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty4}
\begin{paste}{ugGraphThreeDBuildPageEmpty4}{ugGraphThreeDBuildPagePatch4}
\pastebutton{ugGraphThreeDBuildPageEmpty4}{\showpaste}
\tab{5}\spadcommand{closedCurve(space,[[70,0,35], [65,0,30], [45,0,30], [40,0,35], [40,0,60], [50,0,60], [50,0,70], [30,0,70], [30,0,30], [40,0,20], [70,0,20], [80,0,30]])\bound{curve3 }\free{space }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch5}
\begin{paste}{ugGraphThreeDBuildPageFull5}{ugGraphThreeDBuildPageEmpty5}
\pastebutton{ugGraphThreeDBuildPageFull5}{\hidepaste}
\tab{5}\spadcommand{closedCurve(space,[[0,70,20], [0,70,110], [0,110,110], [0,120,100], [0,120,70], [0,115,65], [0,120,60], [0,120,30], [0,110,20], [0,80,20], [0,80,30], [0,80,20]])\bound{curve4 }\free{space }}
\indentrel{3}\begin{verbatim}
   (5)  3-Space with 4 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty5}
\begin{paste}{ugGraphThreeDBuildPageEmpty5}{ugGraphThreeDBuildPagePatch5}
\pastebutton{ugGraphThreeDBuildPageEmpty5}{\showpaste}
\tab{5}\spadcommand{closedCurve(space,[[0,70,20], [0,70,110], [0,110,110], [0,120,100], [0,120,70], [0,115,65], [0,120,60], [0,120,30], [0,110,20], [0,80,20], [0,80,30], [0,80,20]])\bound{curve4 }\free{space }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch6}
\begin{paste}{ugGraphThreeDBuildPageFull6}{ugGraphThreeDBuildPageEmpty6}
\pastebutton{ugGraphThreeDBuildPageFull6}{\hidepaste}
\tab{5}\spadcommand{closedCurve(space,[[0,105,30], [0,110,35], [0,110,55], [0,105,60], [0,80,60], [0,80,70], [0,105,70], [0,110,75], [0,110,95], [0,105,100], [0,80,100], [0,80,20], [0,80,30]])\bound{curve5 }\free{space }}
\indentrel{3}\begin{verbatim}
   (6)  3-Space with 5 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty6}
\begin{paste}{ugGraphThreeDBuildPageEmpty6}{ugGraphThreeDBuildPagePatch6}
\pastebutton{ugGraphThreeDBuildPageEmpty6}{\showpaste}
\tab{5}\spadcommand{closedCurve(space,[[0,105,30], [0,110,35], [0,110,55], [0,105,60], [0,80,60], [0,80,70], [0,105,70], [0,110,75], [0,110,95], [0,105,100], [0,80,100], [0,80,20], [0,80,30]])\bound{curve5 }\free{space }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch7}
\begin{paste}{ugGraphThreeDBuildPageFull7}{ugGraphThreeDBuildPageEmpty7}
\pastebutton{ugGraphThreeDBuildPageFull7}{\hidepaste}
\tab{5}\spadcommand{closedCurve(space,[[140,0,20], [140,0,110], [130,0,110], [90,0,20], [101,0,20],[114,0,50], [130,0,50], [130,0,60], [119,0,60], [130,0,85], [130,0,20]])\bound{curve6 }\free{space }}
\indentrel{3}\begin{verbatim}
   (7)  3-Space with 6 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty7}
\begin{paste}{ugGraphThreeDBuildPageEmpty7}{ugGraphThreeDBuildPagePatch7}
\pastebutton{ugGraphThreeDBuildPageEmpty7}{\showpaste}
\tab{5}\spadcommand{closedCurve(space,[[140,0,20], [140,0,110], [130,0,110], [90,0,20], [101,0,20],[114,0,50], [130,0,50], [130,0,60], [119,0,60], [130,0,85], [130,0,20]])\bound{curve6 }\free{space }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch8}
\begin{paste}{ugGraphThreeDBuildPageFull8}{ugGraphThreeDBuildPageEmpty8}
\pastebutton{ugGraphThreeDBuildPageFull8}{\hidepaste}
\tab{5}\spadcommand{closedCurve(space,[[0,140,20], [0,140,110], [0,150,110], [0,170,50], [0,190,110], [0,200,110], [0,200,20], [0,190,20], [0,190,75], [0,175,35], [0,165,35],[0,150,75], [0,150,20]])\bound{curve7 }\free{space }}
\indentrel{3}\begin{verbatim}
   (8)  3-Space with 7 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty8}
\begin{paste}{ugGraphThreeDBuildPageEmpty8}{ugGraphThreeDBuildPagePatch8}
\pastebutton{ugGraphThreeDBuildPageEmpty8}{\showpaste}
\tab{5}\spadcommand{closedCurve(space,[[0,140,20], [0,140,110], [0,150,110], [0,170,50], [0,190,110], [0,200,110], [0,200,20], [0,190,20], [0,190,75], [0,175,35], [0,165,35],[0,150,75], [0,150,20]])\bound{curve7 }\free{space }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch9}
\begin{paste}{ugGraphThreeDBuildPageFull9}{ugGraphThreeDBuildPageEmpty9}
\pastebutton{ugGraphThreeDBuildPageFull9}{\hidepaste}
\tab{5}\spadcommand{closedCurve(space,[[200,0,20], [200,0,110], [189,0,110], [160,0,45], [160,0,110], [150,0,110], [150,0,20], [161,0,20], [190,0,85], [190,0,20]])\bound{curve8 }\free{space }}
\indentrel{3}\begin{verbatim}
   (9)  3-Space with 8 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty9}
\begin{paste}{ugGraphThreeDBuildPageEmpty9}{ugGraphThreeDBuildPagePatch9}
\pastebutton{ugGraphThreeDBuildPageEmpty9}{\showpaste}
\tab{5}\spadcommand{closedCurve(space,[[200,0,20], [200,0,110], [189,0,110], [160,0,45], [160,0,110], [150,0,110], [150,0,20], [161,0,20], [190,0,85], [190,0,20]])\bound{curve8 }\free{space }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch10}
\begin{paste}{ugGraphThreeDBuildPageFull10}{ugGraphThreeDBuildPageEmpty10}
\pastebutton{ugGraphThreeDBuildPageFull10}{\hidepaste}
\tab{5}\spadgraph{makeViewport3D(space, title == "Letters")\free{space curve1 curve2 curve3 curve4 curve5 curve6 curve7 curve8 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphthreedbuildpage10.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphthreedbuildpage10}}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty10}
\begin{paste}{ugGraphThreeDBuildPageEmpty10}{ugGraphThreeDBuildPagePatch10}
\pastebutton{ugGraphThreeDBuildPageEmpty10}{\showpaste}
\tab{5}\spadgraph{makeViewport3D(space, title == "Letters")\free{space curve1 curve2 curve3 curve4 curve5 curve6 curve7 curve8 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch11}
\begin{paste}{ugGraphThreeDBuildPageFull11}{ugGraphThreeDBuildPageEmpty11}
\pastebutton{ugGraphThreeDBuildPageFull11}{\hidepaste}
\tab{5}\spadcommand{spaceC := create3Space()$(ThreeSpace DFLOAT)\bound{spaceC }}
\indentrel{3}\begin{verbatim}
   (11)  3-Space with 0 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty11}
\begin{paste}{ugGraphThreeDBuildPageEmpty11}{ugGraphThreeDBuildPagePatch11}
\pastebutton{ugGraphThreeDBuildPageEmpty11}{\showpaste}
\tab{5}\spadcommand{spaceC := create3Space()$(ThreeSpace DFLOAT)\bound{spaceC }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch12}
\begin{paste}{ugGraphThreeDBuildPageFull12}{ugGraphThreeDBuildPageEmpty12}
\pastebutton{ugGraphThreeDBuildPageFull12}{\hidepaste}
\tab{5}\spadcommand{x: DFLOAT := 1\bound{x }}
\indentrel{3}\begin{verbatim}
   (12)  1.0
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty12}
\begin{paste}{ugGraphThreeDBuildPageEmpty12}{ugGraphThreeDBuildPagePatch12}
\pastebutton{ugGraphThreeDBuildPageEmpty12}{\showpaste}
\tab{5}\spadcommand{x: DFLOAT := 1\bound{x }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch13}
\begin{paste}{ugGraphThreeDBuildPageFull13}{ugGraphThreeDBuildPageEmpty13}
\pastebutton{ugGraphThreeDBuildPageFull13}{\hidepaste}
\tab{5}\spadcommand{y: DFLOAT := -1\bound{y }}
\indentrel{3}\begin{verbatim}
   (13)  - 1.0
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty13}
\begin{paste}{ugGraphThreeDBuildPageEmpty13}{ugGraphThreeDBuildPagePatch13}
\pastebutton{ugGraphThreeDBuildPageEmpty13}{\showpaste}
\tab{5}\spadcommand{y: DFLOAT := -1\bound{y }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch14}
\begin{paste}{ugGraphThreeDBuildPageFull14}{ugGraphThreeDBuildPageEmpty14}
\pastebutton{ugGraphThreeDBuildPageFull14}{\hidepaste}
\tab{5}\spadcommand{a := point [x,x,y,1::DFLOAT]$(Point DFLOAT)\bound{a }\free{x y }}
\indentrel{3}\begin{verbatim}
   (14)  [1.0,1.0,- 1.0,1.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty14}
\begin{paste}{ugGraphThreeDBuildPageEmpty14}{ugGraphThreeDBuildPagePatch14}
\pastebutton{ugGraphThreeDBuildPageEmpty14}{\showpaste}
\tab{5}\spadcommand{a := point [x,x,y,1::DFLOAT]$(Point DFLOAT)\bound{a }\free{x y }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch15}
\begin{paste}{ugGraphThreeDBuildPageFull15}{ugGraphThreeDBuildPageEmpty15}
\pastebutton{ugGraphThreeDBuildPageFull15}{\hidepaste}
\tab{5}\spadcommand{b := point [y,x,y,4::DFLOAT]$(Point DFLOAT)\bound{b }\free{x y }}
\indentrel{3}\begin{verbatim}
   (15)  [- 1.0,1.0,- 1.0,4.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty15}
\begin{paste}{ugGraphThreeDBuildPageEmpty15}{ugGraphThreeDBuildPagePatch15}
\pastebutton{ugGraphThreeDBuildPageEmpty15}{\showpaste}
\tab{5}\spadcommand{b := point [y,x,y,4::DFLOAT]$(Point DFLOAT)\bound{b }\free{x y }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch16}
\begin{paste}{ugGraphThreeDBuildPageFull16}{ugGraphThreeDBuildPageEmpty16}
\pastebutton{ugGraphThreeDBuildPageFull16}{\hidepaste}
\tab{5}\spadcommand{c := point [y,x,x,8::DFLOAT]$(Point DFLOAT)\bound{c }\free{x y }}
\indentrel{3}\begin{verbatim}
   (16)  [- 1.0,1.0,1.0,8.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty16}
\begin{paste}{ugGraphThreeDBuildPageEmpty16}{ugGraphThreeDBuildPagePatch16}
\pastebutton{ugGraphThreeDBuildPageEmpty16}{\showpaste}
\tab{5}\spadcommand{c := point [y,x,x,8::DFLOAT]$(Point DFLOAT)\bound{c }\free{x y }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch17}
\begin{paste}{ugGraphThreeDBuildPageFull17}{ugGraphThreeDBuildPageEmpty17}
\pastebutton{ugGraphThreeDBuildPageFull17}{\hidepaste}
\tab{5}\spadcommand{d := point [x,x,x,12::DFLOAT]$(Point DFLOAT)\bound{d }\free{x y }}
\indentrel{3}\begin{verbatim}
   (17)  [1.0,1.0,1.0,12.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty17}
\begin{paste}{ugGraphThreeDBuildPageEmpty17}{ugGraphThreeDBuildPagePatch17}
\pastebutton{ugGraphThreeDBuildPageEmpty17}{\showpaste}
\tab{5}\spadcommand{d := point [x,x,x,12::DFLOAT]$(Point DFLOAT)\bound{d }\free{x y }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch18}
\begin{paste}{ugGraphThreeDBuildPageFull18}{ugGraphThreeDBuildPageEmpty18}
\pastebutton{ugGraphThreeDBuildPageFull18}{\hidepaste}
\tab{5}\spadcommand{e := point [x,y,y,16::DFLOAT]$(Point DFLOAT)\bound{e }\free{x y }}
\indentrel{3}\begin{verbatim}
   (18)  [1.0,- 1.0,- 1.0,16.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty18}
\begin{paste}{ugGraphThreeDBuildPageEmpty18}{ugGraphThreeDBuildPagePatch18}
\pastebutton{ugGraphThreeDBuildPageEmpty18}{\showpaste}
\tab{5}\spadcommand{e := point [x,y,y,16::DFLOAT]$(Point DFLOAT)\bound{e }\free{x y }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch19}
\begin{paste}{ugGraphThreeDBuildPageFull19}{ugGraphThreeDBuildPageEmpty19}
\pastebutton{ugGraphThreeDBuildPageFull19}{\hidepaste}
\tab{5}\spadcommand{f := point [y,y,y,20::DFLOAT]$(Point DFLOAT)\bound{f }\free{x y }}
\indentrel{3}\begin{verbatim}
   (19)  [- 1.0,- 1.0,- 1.0,20.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty19}
\begin{paste}{ugGraphThreeDBuildPageEmpty19}{ugGraphThreeDBuildPagePatch19}
\pastebutton{ugGraphThreeDBuildPageEmpty19}{\showpaste}
\tab{5}\spadcommand{f := point [y,y,y,20::DFLOAT]$(Point DFLOAT)\bound{f }\free{x y }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch20}
\begin{paste}{ugGraphThreeDBuildPageFull20}{ugGraphThreeDBuildPageEmpty20}
\pastebutton{ugGraphThreeDBuildPageFull20}{\hidepaste}
\tab{5}\spadcommand{g := point [y,y,x,24::DFLOAT]$(Point DFLOAT)\bound{g }\free{x y }}
\indentrel{3}\begin{verbatim}
   (20)  [- 1.0,- 1.0,1.0,24.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty20}
\begin{paste}{ugGraphThreeDBuildPageEmpty20}{ugGraphThreeDBuildPagePatch20}
\pastebutton{ugGraphThreeDBuildPageEmpty20}{\showpaste}
\tab{5}\spadcommand{g := point [y,y,x,24::DFLOAT]$(Point DFLOAT)\bound{g }\free{x y }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch21}
\begin{paste}{ugGraphThreeDBuildPageFull21}{ugGraphThreeDBuildPageEmpty21}
\pastebutton{ugGraphThreeDBuildPageFull21}{\hidepaste}
\tab{5}\spadcommand{h := point [x,y,x,27::DFLOAT]$(Point DFLOAT)\bound{h }\free{x y }}
\indentrel{3}\begin{verbatim}
   (21)  [1.0,- 1.0,1.0,27.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty21}
\begin{paste}{ugGraphThreeDBuildPageEmpty21}{ugGraphThreeDBuildPagePatch21}
\pastebutton{ugGraphThreeDBuildPageEmpty21}{\showpaste}
\tab{5}\spadcommand{h := point [x,y,x,27::DFLOAT]$(Point DFLOAT)\bound{h }\free{x y }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch22}
\begin{paste}{ugGraphThreeDBuildPageFull22}{ugGraphThreeDBuildPageEmpty22}
\pastebutton{ugGraphThreeDBuildPageFull22}{\hidepaste}
\tab{5}\spadcommand{polygon(spaceC,[d,c,g,h])\free{d c g h spaceC }\bound{pol1 }}
\indentrel{3}\begin{verbatim}
   (22)  3-Space with 1 component
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty22}
\begin{paste}{ugGraphThreeDBuildPageEmpty22}{ugGraphThreeDBuildPagePatch22}
\pastebutton{ugGraphThreeDBuildPageEmpty22}{\showpaste}
\tab{5}\spadcommand{polygon(spaceC,[d,c,g,h])\free{d c g h spaceC }\bound{pol1 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch23}
\begin{paste}{ugGraphThreeDBuildPageFull23}{ugGraphThreeDBuildPageEmpty23}
\pastebutton{ugGraphThreeDBuildPageFull23}{\hidepaste}
\tab{5}\spadcommand{polygon(spaceC,[d,h,e,a])\free{d h e a spaceC }\bound{pol2 }}
\indentrel{3}\begin{verbatim}
   (23)  3-Space with 2 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty23}
\begin{paste}{ugGraphThreeDBuildPageEmpty23}{ugGraphThreeDBuildPagePatch23}
\pastebutton{ugGraphThreeDBuildPageEmpty23}{\showpaste}
\tab{5}\spadcommand{polygon(spaceC,[d,h,e,a])\free{d h e a spaceC }\bound{pol2 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch24}
\begin{paste}{ugGraphThreeDBuildPageFull24}{ugGraphThreeDBuildPageEmpty24}
\pastebutton{ugGraphThreeDBuildPageFull24}{\hidepaste}
\tab{5}\spadcommand{polygon(spaceC,[c,d,a,b])\free{c d a b spaceC }\bound{pol3 }}
\indentrel{3}\begin{verbatim}
   (24)  3-Space with 3 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty24}
\begin{paste}{ugGraphThreeDBuildPageEmpty24}{ugGraphThreeDBuildPagePatch24}
\pastebutton{ugGraphThreeDBuildPageEmpty24}{\showpaste}
\tab{5}\spadcommand{polygon(spaceC,[c,d,a,b])\free{c d a b spaceC }\bound{pol3 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch25}
\begin{paste}{ugGraphThreeDBuildPageFull25}{ugGraphThreeDBuildPageEmpty25}
\pastebutton{ugGraphThreeDBuildPageFull25}{\hidepaste}
\tab{5}\spadcommand{polygon(spaceC,[g,c,b,f])\free{g c b f spaceC }\bound{pol4 }}
\indentrel{3}\begin{verbatim}
   (25)  3-Space with 4 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty25}
\begin{paste}{ugGraphThreeDBuildPageEmpty25}{ugGraphThreeDBuildPagePatch25}
\pastebutton{ugGraphThreeDBuildPageEmpty25}{\showpaste}
\tab{5}\spadcommand{polygon(spaceC,[g,c,b,f])\free{g c b f spaceC }\bound{pol4 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch26}
\begin{paste}{ugGraphThreeDBuildPageFull26}{ugGraphThreeDBuildPageEmpty26}
\pastebutton{ugGraphThreeDBuildPageFull26}{\hidepaste}
\tab{5}\spadcommand{polygon(spaceC,[h,g,f,e])\free{h g f e spaceC }\bound{pol5 }}
\indentrel{3}\begin{verbatim}
   (26)  3-Space with 5 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty26}
\begin{paste}{ugGraphThreeDBuildPageEmpty26}{ugGraphThreeDBuildPagePatch26}
\pastebutton{ugGraphThreeDBuildPageEmpty26}{\showpaste}
\tab{5}\spadcommand{polygon(spaceC,[h,g,f,e])\free{h g f e spaceC }\bound{pol5 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch27}
\begin{paste}{ugGraphThreeDBuildPageFull27}{ugGraphThreeDBuildPageEmpty27}
\pastebutton{ugGraphThreeDBuildPageFull27}{\hidepaste}
\tab{5}\spadcommand{polygon(spaceC,[e,f,b,a])\free{e f b a spaceC }\bound{pol6 }}
\indentrel{3}\begin{verbatim}
   (27)  3-Space with 6 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty27}
\begin{paste}{ugGraphThreeDBuildPageEmpty27}{ugGraphThreeDBuildPagePatch27}
\pastebutton{ugGraphThreeDBuildPageEmpty27}{\showpaste}
\tab{5}\spadcommand{polygon(spaceC,[e,f,b,a])\free{e f b a spaceC }\bound{pol6 }}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPagePatch28}
\begin{paste}{ugGraphThreeDBuildPageFull28}{ugGraphThreeDBuildPageEmpty28}
\pastebutton{ugGraphThreeDBuildPageFull28}{\hidepaste}
\tab{5}\spadgraph{makeViewport3D(spaceC, title == "Cube")\free{pol1 pol2 pol3 pol4 pol5 pol6 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphthreedbuildpage28.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphthreedbuildpage28}}
\end{paste}\end{patch}

\begin{patch}{ugGraphThreeDBuildPageEmpty28}
\begin{paste}{ugGraphThreeDBuildPageEmpty28}{ugGraphThreeDBuildPagePatch28}
\pastebutton{ugGraphThreeDBuildPageEmpty28}{\showpaste}
\tab{5}\spadgraph{makeViewport3D(spaceC, title == "Cube")\free{pol1 pol2 pol3 pol4 pol5 pol6 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugGraphCoordPage}{ug07.ht}{Coordinate System Transformations}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphCoordPage}{7.2.7. Coordinate System Transformations}
\beginscroll

The \axiomType{CoordinateSystems} package provides coordinate
transformation functions that map a given data point from the
coordinate system specified into the Cartesian coordinate system.  The
default coordinate system, given a triplet \axiom{(f(u,v), u, v)},
assumes that \axiom{z = f(u, v)}, \axiom{x = u} and \axiom{y = v},
that is, reads the coordinates in \axiom{(z, x, y)} order.

\xtc{
}{
\spadpaste{m(u:DFLOAT,v:DFLOAT):DFLOAT == u**2 \bound{m}}
}
%
\psXtc{
Graph plotted in default coordinate system.
}{
\graphpaste{draw(m,0..3,0..5) \free{m}}
}{
\epsffile[0 0 295 295]{../ps/defcoord.ps}
}

The \axiom{z} coordinate comes first since the first argument of the
\axiomFun{draw} command gives its values.  In general, the coordinate
systems Axiom provides, or any that you make up, must provide a map to
an \axiom{(x, y, z)} triplet in order to be compatible with the
\axiomFunFrom{coordinates}{DrawOption} \axiomType{DrawOption}.  Here
is an example.

\xtc{
Define the identity function.
}{
\spadpaste{cartesian(point:Point DFLOAT):Point DFLOAT == point 
\bound{cart}}
}
\psXtc{
Pass \axiom{cartesian} as the \axiomFunFrom{coordinates}{DrawOption}
parameter to the \axiomFun{draw} command.
}{
\graphpaste{draw(m,0..3,0..5,coordinates==cartesian) \free{m cart}}
}{
\epsffile[0 0 295 295]{../ps/cartcoord.ps}
}
%

What happened?  The option {\tt coordinates == cartesian} directs
Axiom to treat the dependent variable \axiom{m} defined by
\texht{$m=u^2$}{m=u**2} as the \axiom{x} coordinate.  Thus the triplet
of values \axiom{(m, u, v)} is transformed to coordinates 
\axiom{(x, y, z)} and so we get the graph of \texht{$x=y^2$}{x=y**2}.

Here is another example.
The \axiomFunFrom{cylindrical}{CoordinateSystems} transform takes
input of the form \axiom{(w,u,v)}, interprets it in the order
\texht{($r$,$\theta$,$z$)}{(\axiom{r}, \axiom{theta}, \axiom{z})}
and maps it to the Cartesian coordinates
\texht{$x=r\cos(\theta)$, $y=r\sin(\theta)$, $z=z$}
{\axiom{x = r * cos(theta)}, \axiom{y = r * sin(theta)}, \axiom{z = z}}
in which
\texht{$r$}{\axiom{r}} is the radius,
\texht{$\theta$}{\axiom{theta}} is the angle and
\texht{$z$}{\axiom{z}} is the z-coordinate.
\xtc{
An example using the \axiomFunFrom{cylindrical}{CoordinateSystems}
coordinates for the constant \axiom{r = 3}.
}{
\spadpaste{f(u:DFLOAT,v:DFLOAT):DFLOAT == 3 \bound{f}}
}
\psXtc{
Graph plotted in cylindrical coordinates.
}{
\graphpaste{draw(f,0..\%pi,0..6,coordinates==cylindrical) \free{f}}
}{
\epsffile[0 0 295 295]{../ps/cylcoord.ps}
}

Suppose you would like to specify \smath{z} as a function of \smath{r}
and \texht{$\theta$}{\axiom{theta}} instead of just \smath{r}?  Well,
you still can use the \axiomFun{cylindrical} Axiom transformation but
we have to reorder the triplet before passing it to the
transformation.

\xtc{
First, let's create a point to
work with and call it \axiom{pt} with some color \axiom{col}.
}{
\spadpaste{col := 5 \bound{c}}
}
\xtc{
}{
\spadpaste{pt := point[1,2,3,col]\$(Point DFLOAT) \free{c} \bound{pt}}
}
The reordering you want is
\texht{$(z,r, \theta)$}{\axiom{(z,r,theta)}} to
\texht{$(r, \theta,z)$}{\axiom{(r,theta,z)}}
so that the first element is moved to the third element, while the second
and third elements move forward and the color element does not change.
\xtc{
Define a function \userfun{reorder} to reorder the point elements.
}{
\spadpaste{
reorder(p:Point DFLOAT):Point DFLOAT == point[p.2, p.3, p.1, p.4] 
\bound{freo}}
}
\xtc{
The function moves the second and third elements
forward but the color does not change.
}{
\spadpaste{reorder pt \free{pt freo}}
}
\xtc{
The function \userfun{newmap} converts our reordered version of
the cylindrical coordinate system to the standard
\texht{$(x,y,z)$}{\axiom{(x,y,z)}} Cartesian system.
}{
\spadpaste{
newmap(pt:Point DFLOAT):Point DFLOAT == cylindrical(reorder pt) 
\free{freo} \bound{fnewmap}}
}
\xtc{
}{
\spadpaste{newmap pt \free{fnewmap pt} \bound{new}}
}
%
\psXtc{
Graph the same function \axiom{f} using the coordinate mapping 
of the function \axiom{newmap}, so it is now interpreted as
\texht{$z=3$}{\axiom{z = 3}}:
}{
\graphpaste{draw(f,0..3,0..2*\%pi,coordinates==newmap) \free{f new}}
}{
\epsffile[0 0 295 295]{../ps/newmap.ps}
}

{\texht{\sloppy}{}
The \axiomType{CoordinateSystems} package exports the following
operations:
\axiomFun{bipolar},
\axiomFun{bipolarCylindrical},
\axiomFun{cartesian},
\axiomFun{conical},
\axiomFun{cylindrical},
\axiomFun{elliptic},
\axiomFun{ellipticCylindrical},
\axiomFun{oblateSpheroidal},
\axiomFun{parabolic},
\axiomFun{parabolicCylindrical},
\axiomFun{paraboloidal},
\axiomFun{polar},
\axiomFun{prolateSpheroidal},
\axiomFun{spherical}, and
\axiomFun{toroidal}.
Use \Browse{} or the \spadcmd{)show} system command
to get more information.

}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugGraphCoordPagePatch1}
\begin{paste}{ugGraphCoordPageFull1}{ugGraphCoordPageEmpty1}
\pastebutton{ugGraphCoordPageFull1}{\hidepaste}
\tab{5}\spadcommand{m(u:DFLOAT,v:DFLOAT):DFLOAT == u**2\bound{m }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPageEmpty1}
\begin{paste}{ugGraphCoordPageEmpty1}{ugGraphCoordPagePatch1}
\pastebutton{ugGraphCoordPageEmpty1}{\showpaste}
\tab{5}\spadcommand{m(u:DFLOAT,v:DFLOAT):DFLOAT == u**2\bound{m }}
\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPagePatch2}
\begin{paste}{ugGraphCoordPageFull2}{ugGraphCoordPageEmpty2}
\pastebutton{ugGraphCoordPageFull2}{\hidepaste}
\tab{5}\spadgraph{draw(m,0..3,0..5)\free{m }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphcoordpage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphcoordpage2}}
\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPageEmpty2}
\begin{paste}{ugGraphCoordPageEmpty2}{ugGraphCoordPagePatch2}
\pastebutton{ugGraphCoordPageEmpty2}{\showpaste}
\tab{5}\spadgraph{draw(m,0..3,0..5)\free{m }}
\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPagePatch3}
\begin{paste}{ugGraphCoordPageFull3}{ugGraphCoordPageEmpty3}
\pastebutton{ugGraphCoordPageFull3}{\hidepaste}
\tab{5}\spadcommand{cartesian(point:Point DFLOAT):Point DFLOAT == point\bound{cart }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPageEmpty3}
\begin{paste}{ugGraphCoordPageEmpty3}{ugGraphCoordPagePatch3}
\pastebutton{ugGraphCoordPageEmpty3}{\showpaste}
\tab{5}\spadcommand{cartesian(point:Point DFLOAT):Point DFLOAT == point\bound{cart }}
\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPagePatch4}
\begin{paste}{ugGraphCoordPageFull4}{ugGraphCoordPageEmpty4}
\pastebutton{ugGraphCoordPageFull4}{\hidepaste}
\tab{5}\spadgraph{draw(m,0..3,0..5,coordinates==cartesian)\free{m cart }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphcoordpage4.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphcoordpage4}}
\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPageEmpty4}
\begin{paste}{ugGraphCoordPageEmpty4}{ugGraphCoordPagePatch4}
\pastebutton{ugGraphCoordPageEmpty4}{\showpaste}
\tab{5}\spadgraph{draw(m,0..3,0..5,coordinates==cartesian)\free{m cart }}
\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPagePatch5}
\begin{paste}{ugGraphCoordPageFull5}{ugGraphCoordPageEmpty5}
\pastebutton{ugGraphCoordPageFull5}{\hidepaste}
\tab{5}\spadcommand{f(u:DFLOAT,v:DFLOAT):DFLOAT == 3\bound{f }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPageEmpty5}
\begin{paste}{ugGraphCoordPageEmpty5}{ugGraphCoordPagePatch5}
\pastebutton{ugGraphCoordPageEmpty5}{\showpaste}
\tab{5}\spadcommand{f(u:DFLOAT,v:DFLOAT):DFLOAT == 3\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPagePatch6}
\begin{paste}{ugGraphCoordPageFull6}{ugGraphCoordPageEmpty6}
\pastebutton{ugGraphCoordPageFull6}{\hidepaste}
\tab{5}\spadgraph{draw(f,0..\%pi,0..6,coordinates==cylindrical)\free{f }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphcoordpage6.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphcoordpage6}}
\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPageEmpty6}
\begin{paste}{ugGraphCoordPageEmpty6}{ugGraphCoordPagePatch6}
\pastebutton{ugGraphCoordPageEmpty6}{\showpaste}
\tab{5}\spadgraph{draw(f,0..\%pi,0..6,coordinates==cylindrical)\free{f }}
\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPagePatch7}
\begin{paste}{ugGraphCoordPageFull7}{ugGraphCoordPageEmpty7}
\pastebutton{ugGraphCoordPageFull7}{\hidepaste}
\tab{5}\spadcommand{col := 5\bound{c }}
\indentrel{3}\begin{verbatim}
   (7)  5
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPageEmpty7}
\begin{paste}{ugGraphCoordPageEmpty7}{ugGraphCoordPagePatch7}
\pastebutton{ugGraphCoordPageEmpty7}{\showpaste}
\tab{5}\spadcommand{col := 5\bound{c }}
\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPagePatch8}
\begin{paste}{ugGraphCoordPageFull8}{ugGraphCoordPageEmpty8}
\pastebutton{ugGraphCoordPageFull8}{\hidepaste}
\tab{5}\spadcommand{pt := point[1,2,3,col]$(Point DFLOAT)\free{c }\bound{pt }}
\indentrel{3}\begin{verbatim}
   (8)  [1.0,2.0,3.0,5.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPageEmpty8}
\begin{paste}{ugGraphCoordPageEmpty8}{ugGraphCoordPagePatch8}
\pastebutton{ugGraphCoordPageEmpty8}{\showpaste}
\tab{5}\spadcommand{pt := point[1,2,3,col]$(Point DFLOAT)\free{c }\bound{pt }}
\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPagePatch9}
\begin{paste}{ugGraphCoordPageFull9}{ugGraphCoordPageEmpty9}
\pastebutton{ugGraphCoordPageFull9}{\hidepaste}
\tab{5}\spadcommand{reorder(p:Point DFLOAT):Point DFLOAT == point[p.2, p.3, p.1, p.4]\bound{freo }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPageEmpty9}
\begin{paste}{ugGraphCoordPageEmpty9}{ugGraphCoordPagePatch9}
\pastebutton{ugGraphCoordPageEmpty9}{\showpaste}
\tab{5}\spadcommand{reorder(p:Point DFLOAT):Point DFLOAT == point[p.2, p.3, p.1, p.4]\bound{freo }}
\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPagePatch10}
\begin{paste}{ugGraphCoordPageFull10}{ugGraphCoordPageEmpty10}
\pastebutton{ugGraphCoordPageFull10}{\hidepaste}
\tab{5}\spadcommand{reorder pt\free{pt freo }}
\indentrel{3}\begin{verbatim}
   (10)  [2.0,3.0,1.0,5.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPageEmpty10}
\begin{paste}{ugGraphCoordPageEmpty10}{ugGraphCoordPagePatch10}
\pastebutton{ugGraphCoordPageEmpty10}{\showpaste}
\tab{5}\spadcommand{reorder pt\free{pt freo }}
\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPagePatch11}
\begin{paste}{ugGraphCoordPageFull11}{ugGraphCoordPageEmpty11}
\pastebutton{ugGraphCoordPageFull11}{\hidepaste}
\tab{5}\spadcommand{newmap(pt:Point DFLOAT):Point DFLOAT == cylindrical(reorder pt)\free{freo }\bound{fnewmap }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPageEmpty11}
\begin{paste}{ugGraphCoordPageEmpty11}{ugGraphCoordPagePatch11}
\pastebutton{ugGraphCoordPageEmpty11}{\showpaste}
\tab{5}\spadcommand{newmap(pt:Point DFLOAT):Point DFLOAT == cylindrical(reorder pt)\free{freo }\bound{fnewmap }}
\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPagePatch12}
\begin{paste}{ugGraphCoordPageFull12}{ugGraphCoordPageEmpty12}
\pastebutton{ugGraphCoordPageFull12}{\hidepaste}
\tab{5}\spadcommand{newmap pt\free{fnewmap pt }\bound{new }}
\indentrel{3}\begin{verbatim}
   (12)
   [- 1.9799849932008908,0.28224001611973443,1.0,5.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPageEmpty12}
\begin{paste}{ugGraphCoordPageEmpty12}{ugGraphCoordPagePatch12}
\pastebutton{ugGraphCoordPageEmpty12}{\showpaste}
\tab{5}\spadcommand{newmap pt\free{fnewmap pt }\bound{new }}
\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPagePatch13}
\begin{paste}{ugGraphCoordPageFull13}{ugGraphCoordPageEmpty13}
\pastebutton{ugGraphCoordPageFull13}{\hidepaste}
\tab{5}\spadgraph{draw(f,0..3,0..2*\%pi,coordinates==newmap)\free{f new }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphcoordpage13.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphcoordpage13}}
\end{paste}\end{patch}

\begin{patch}{ugGraphCoordPageEmpty13}
\begin{paste}{ugGraphCoordPageEmpty13}{ugGraphCoordPagePatch13}
\pastebutton{ugGraphCoordPageEmpty13}{\showpaste}
\tab{5}\spadgraph{draw(f,0..3,0..2*\%pi,coordinates==newmap)\free{f new }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugGraphClipPage}{ug07.ht}{Three-Dimensional Clipping}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphClipPage}{7.2.8. Three-Dimensional Clipping}
\beginscroll

A \threedim{} graph can be explicitly clipped within the \axiomFun{draw}
command by indicating a minimum and maximum threshold for the
given function definition.
These thresholds can be defined using the Axiom \axiomFun{min}
and \axiomFun{max} functions.
\xtc{
}{
\begin{spadsrc}[\bound{g}]
gamma(x,y) ==
  g := Gamma complex(x,y)
  point [x, y, max( min(real g, 4), -4), argument g]
\end{spadsrc}
}
\psXtc{
Here is an example that clips
the gamma function in order to eliminate the extreme divergence it creates.
}{
\graphpaste{
draw(gamma,-\%pi..\%pi,-\%pi..\%pi,var1Steps==50,var2Steps==50) \free{g}}
}{
\epsffile[0 0 295 295]{../ps/clipgamma.ps}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugGraphClipPagePatch1}
\begin{paste}{ugGraphClipPageFull1}{ugGraphClipPageEmpty1}
\pastebutton{ugGraphClipPageFull1}{\hidepaste}
\tab{5}\spadcommand{gamma(x,y) ==
  g := Gamma complex(x,y)
  point [x, y, max( min(real g, 4), -4), argument g]
\bound{g }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugGraphClipPageEmpty1}
\begin{paste}{ugGraphClipPageEmpty1}{ugGraphClipPagePatch1}
\pastebutton{ugGraphClipPageEmpty1}{\showpaste}
\tab{5}\spadcommand{gamma(x,y) ==
  g := Gamma complex(x,y)
  point [x, y, max( min(real g, 4), -4), argument g]
\bound{g }}
\end{paste}\end{patch}

\begin{patch}{ugGraphClipPagePatch2}
\begin{paste}{ugGraphClipPageFull2}{ugGraphClipPageEmpty2}
\pastebutton{ugGraphClipPageFull2}{\hidepaste}
\tab{5}\spadgraph{draw(gamma,-\%pi..\%pi,-\%pi..\%pi,var1Steps==50,var2Steps==50)\free{g }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/uggraphclippage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/uggraphclippage2}}
\end{paste}\end{patch}

\begin{patch}{ugGraphClipPageEmpty2}
\begin{paste}{ugGraphClipPageEmpty2}{ugGraphClipPagePatch2}
\pastebutton{ugGraphClipPageEmpty2}{\showpaste}
\tab{5}\spadgraph{draw(gamma,-\%pi..\%pi,-\%pi..\%pi,var1Steps==50,var2Steps==50)\free{g }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugGraphThreeDControlPage}{ug07.ht}
{Three-Dimensional Control-Panel}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphThreeDControlPage}
{7.2.9. Three-Dimensional Control-Panel}
\beginscroll
Once you have created a viewport, move your mouse to the viewport and
click with your left mouse button.  This displays a control-panel on
the side of the viewport that is closest to where you clicked.

\subsubsection{Transformations}

We recommend you first select the {\bf Bounds} button while
executing transformations since the bounding box displayed
indicates the object's position as it changes.
%
\indent{0}
\beginitems
%
\item[Rotate:]  A rotation transformation occurs by clicking the mouse
within the {\bf Rotate} window in the upper left corner of the
control-panel.
The rotation is computed in spherical coordinates, using the
horizontal mouse position to increment or decrement the value of
the longitudinal angle \texht{$\theta$}{\axiom{theta}} within the
range of 0 to \texht{2$\pi$}{2*pi} and the vertical mouse position
to increment or decrement the value of the latitudinal angle
\texht{$\phi$}{\axiom{phi}} within the range of \texht{-$\pi$}{pi}
to \texht{$\pi$}{pi}.
The active mode of rotation is displayed in green on a color
monitor or in clear text on a black and white monitor, while the
inactive mode is displayed in red for color display or a mottled
pattern for black and white.
%
\indent{0}
\beginitems

\item[origin:] The {\bf origin} button indicates that the rotation is
to occur with respect to the origin of the viewing space, that is
indicated by the axes.

\item[object:]  The {\bf object} button indicates that the
rotation is to occur with respect to the center of volume of the object,
independent of the axes' origin position.
\enditems
\indent{0}
%
\item[Scale:]  A scaling transformation occurs by clicking the mouse
within the {\bf Scale} window in the upper center of the
control-panel, containing a zoom arrow.
The axes along which the scaling is to occur are indicated by
selecting the appropriate button above the zoom arrow window.
The selected axes are displayed in green on a color monitor or in
clear text on a black and white monitor, while the unselected axes
are displayed in red for a color display or a mottled pattern for
black and white.
%
\indent{0}
\beginitems
%
\item[uniform:]  Uniform scaling along the {\tt x}, {\tt y}
and {\tt z} axes occurs when all the axes buttons are selected.

\item[non-uniform:] If any of the axes buttons are not selected,
non-uniform scaling occurs, that is, scaling occurs only in the
direction of the axes that are selected.
\enditems
\indent{0}

\item[Translate:] Translation occurs by indicating with the mouse in
the {\bf Translate} window the direction you want the graph to move.
This window is located in the upper right corner of the control-panel
and contains a potentiometer with crossed arrows pointing up, down,
left and right.  Along the top of the {\bf Translate} window are three
buttons ({\bf XY}, {\bf XZ}, and {\bf YZ}) indicating the three
orthographic projection planes.  Each orientates the group as a view
into that plane.  Any translation of the graph occurs only along this
plane.
\enditems
\indent{0}

\subsubsection{Messages}

The window directly below the potentiometer windows for
transformations is used to display system messages relating to the
viewport, the control-panel and the current graph displaying status.

\subsubsection{Colormap}

Directly below the message window is the colormap range indicator
window.  The Axiom Colormap shows a sampling of the spectrum from
which hues can be drawn to represent the colors of a surface.  The
Colormap is composed of five shades for each of the hues along this
spectrum.  By moving the markers above and below the Colormap, the
range of hues that are used to color the existing surface are set.
The bottom marker shows the hue for the low end of the color range and
the top marker shows the hue for the upper end of the range.  Setting
the bottom and top markers at the same hue results in monochromatic
smooth shading of the graph when {\bf Smooth} mode is selected.  At
each end of the Colormap are {\bf +} and {\bf -} buttons.  When
clicked on, these increment or decrement the top or bottom marker.

\subsubsection{Buttons}

Below the Colormap window and to the left are located various
buttons that determine the characteristics of a graph.
The buttons along the bottom and right hand side all have special
meanings; the remaining buttons in the first row indicate the mode
or style used to display the graph.
The second row are toggles that turn on or off a property of the
graph.
On a color monitor, the property is on if green (clear text, on a
monochrome monitor) and off if red (mottled pattern, on a
monochrome monitor).
Here is a list of their functions.
%
\indent{0}
\beginitems

\item[Wire] displays surface and tube plots as a wireframe image in a
single color (blue) with no hidden surfaces removed, or displays space
curve plots in colors based upon their parametric variables.  This is
the fastest mode for displaying a graph.  This is very useful when you
want to find a good orientation of your graph.

\item[Solid] displays the graph with hidden
surfaces removed, drawing each polygon beginning with the furthest
from the viewer.
The edges of the polygons are displayed in the hues specified by
the range in the Colormap window.
%
\item[Shade] displays the graph with hidden
surfaces removed and with the polygons shaded, drawing each
polygon beginning with the furthest from the viewer.
Polygons are shaded in the hues specified by the range in the
Colormap window using the Phong illumination model.
%
\item[Smooth] displays the graph using a
renderer that computes the graph one line at a time.
The location and color of the graph at each visible point on the
screen are determined and displayed using the Phong illumination
model.
Smooth shading is done in one of two ways, depending on the range
selected in the colormap window and the number of colors available
from the hardware and/or window manager.
When the top and bottom markers of the colormap range are set to
different hues, the graph is rendered by dithering between the
transitions in color hue.
When the top and bottom markers of the colormap range are set to
the same hue, the graph is rendered using the Phong smooth shading
model.
However, if enough colors cannot be allocated for this purpose,
the renderer reverts to the color dithering method until a
sufficient color supply is available.
For this reason, it may not be possible to render multiple Phong
smooth shaded graphs at the same time on some systems.

\item[Bounds] encloses the entire volume of the viewgraph within a
bounding box, or removes the box if previously selected.  The region
that encloses the entire volume of the viewport graph is displayed.

\item[Axes] displays Cartesian
coordinate axes of the space, or turns them off if previously selected.

\item[Outline] causes quadrilateral polygons forming the graph surface
to be outlined in black when the graph is displayed in {\bf Shade}
mode.

\item[BW] converts a color viewport to black and white, or vice-versa.
When this button is selected the control-panel and viewport switch to
an immutable colormap composed of a range of grey scale patterns or
tiles that are used wherever shading is necessary.

\item[Light] takes you to a control-panel described below.
%
\item[ViewVolume] takes you to another control-panel as described below.

\item[Save] creates a menu of the possible file types that can be
written using the control-panel.  The {\bf Exit} button leaves the
save menu.  The {\bf Pixmap} button writes an Axiom pixmap of the
current viewport contents.  The file is called {\bf axiom3D.pixmap}
and is located in the directory from which Axiom or {\bf viewalone}
was started.  The {\bf PS} button writes the current viewport contents
to PostScript output rather than to the viewport window.  By default
the file is called {\bf axiom3D.ps}; however, if a file name is
specified in the user's {\bf .Xdefaults} file it is used.  The file is
placed in the directory from which the Axiom or {\bf viewalone}
session was begun.  See also the
\axiomFunFrom{write}{ThreeDimensionalViewport} function.

\item[Reset] returns the object transformation
characteristics back to their initial states.
%
\item[Hide] causes the control-panel for the
corresponding viewport to disappear from the screen.
%
\item[Quit]  queries whether the current viewport
session should be terminated.
\enditems
\indent{0}

\subsubsection{Light}

The {\bf Light} button changes the control-panel into the
{\bf Lighting Control-Panel}.  At the top of this panel, the three axes
are shown with the same orientation as the object.  A light vector from
the origin of the axes shows the current position of the light source
relative to the object.  At the bottom of the panel is an {\bf Abort}
button that cancels any changes to the lighting that were made, and a
{\bf Return} button that carries out the current set of lighting changes
on the graph.
%
\indent{0}
\beginitems
%
\item[XY:]  The {\bf XY} lighting axes window is below the
{\bf Lighting Control-Panel} title and to the left.
This changes the light vector within the {\bf XY} view plane.
%
\item[Z:]  The {\bf Z} lighting axis window is below the
{\bf Lighting Control-Panel} title and in the center.  This
changes the {\bf Z}
location of the light vector.
%
\item[Intensity:]
Below the {\bf Lighting Control-Panel} title
and to the right is the light intensity meter.
Moving the intensity indicator down decreases the amount of
light emitted from the light source.
When the indicator is at the top of the meter the light source is
emitting at 100\% intensity.
At the bottom of the meter the light source is emitting at a level
slightly above ambient lighting.
\enditems
\indent{0}

\subsubsection{View Volume}

The {\bf View Volume} button changes the control-panel into
the {\bf Viewing Volume Panel}.
At the bottom of the viewing panel is an {\bf Abort} button that
cancels any changes to the viewing volume that were made and a
{\it Return} button that carries out the current set of
viewing changes to the graph.

\indent{0}
\beginitems

\item[Eye Reference:] At the top of this panel is the {\bf Eye
Reference} window.  It shows a planar projection of the viewing
pyramid from the eye of the viewer relative to the location of the
object.  This has a bounding region represented by the rectangle on
the left.  Below the object rectangle is the {\bf Hither} window.  By
moving the slider in this window the hither clipping plane sets the
front of the view volume.  As a result of this depth clipping all
points of the object closer to the eye than this hither plane are not
shown.  The {\bf Eye Distance} slider to the right of the {\bf Hither}
slider is used to change the degree of perspective in the image.

\item[Clip Volume:] The {\bf Clip Volume} window is at the bottom of
the {\bf Viewing Volume Panel}.  On the right is a {\bf Settings}
menu.  In this menu are buttons to select viewing attributes.
Selecting the {\bf Perspective} button computes the image using
perspective projection.  The {\bf Show Region} button indicates
whether the clipping region of the volume is to be drawn in the
viewport and the {\bf Clipping On} button shows whether the view
volume clipping is to be in effect when the image is drawn.  The left
side of the {\bf Clip Volume} window shows the clipping boundary of
the graph.  Moving the knobs along the {\bf X}, {\bf Y}, and {\bf Z}
sliders adjusts the volume of the clipping region accordingly.
\enditems
\indent{0}

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugGraphThreeDopsPage}{ug07.ht}
{Operations for Three-Dimensional Graphics}
\begin{chunk}{ug07.ht}
\begin{page}{ugGraphThreeDopsPage}
{7.2.10. Operations for Three-Dimensional Graphics}
\beginscroll

Here is a summary of useful Axiom operations for \threedim{} graphics.
Each operation name is followed by a list of arguments.  Each argument
is written as a variable informally named according to the type of the
argument (for example, {\it integer}).  If appropriate, a default
value for an argument is given in parentheses immediately following
the name.

%
\texht{\bgroup\hbadness = 10001\sloppy}{}
\indent{0}
\beginitems
%
\item[\axiomFun{adaptive3D?}]\funArgs{}
tests whether space curves are to be plotted
according to the
adaptive refinement algorithm.

%
\item[\axiomFun{axes}]\funArgs{viewport, string\argDef{"on"}}
turns the axes on and off.

%
\item[\axiomFun{close}]\funArgs{viewport}
closes the viewport.

%
\item[\axiomFun{colorDef}]\funArgs{viewport,
\subscriptIt{color}{1}\argDef{1}, \subscriptIt{color}{2}\argDef{27}}
sets the colormap
range to be from
\subscriptIt{color}{1} to \subscriptIt{color}{2}.

%
\item[\axiomFun{controlPanel}]\funArgs{viewport, string\argDef{"off"}}
declares whether the
control-panel for the viewport is to be displayed or not.

%
\item[\axiomFun{diagonals}]\funArgs{viewport, string\argDef{"off"}}
declares whether the
polygon outline includes the diagonals or not.

%
\item[\axiomFun{drawStyle}]\funArgs{viewport, style}
selects which of four drawing styles
are used: {\tt "wireMesh", "solid", "shade",} or {\tt "smooth".}

%
\item[\axiomFun{eyeDistance}]\funArgs{viewport,float\argDef{500}}
sets the distance of the eye from the origin of the object
for use in the \axiomFunFrom{perspective}{ThreeDimensionalViewport}.

%
\item[\axiomFun{key}]\funArgs{viewport}
returns the operating
system process ID number for the viewport.

%
\item[\axiomFun{lighting}]\funArgs{viewport,
\subscriptText{float}{x}\argDef{-0.5},
\subscriptText{float}{y}\argDef{0.5}, \subscriptText{float}{z}\argDef{0.5}}
sets the Cartesian
coordinates of the light source.

%
\item[\axiomFun{modifyPointData}]\funArgs{viewport,integer,point}
replaces the coordinates of the point with
the index {\it integer} with {\it point}.

%
\item[\axiomFun{move}]\funArgs{viewport,
\subscriptText{integer}{x}\argDef{viewPosDefault},
\subscriptText{integer}{y}\argDef{viewPosDefault}}
moves the upper
left-hand corner of the viewport to screen position
\allowbreak
({\small \subscriptText{integer}{x}, \subscriptText{integer}{y}}).

%
\item[\axiomFun{options}]\funArgs{viewport}
returns a list of all current draw options.

%
\item[\axiomFun{outlineRender}]\funArgs{viewport, string\argDef{"off"}}
turns polygon outlining
off or on when drawing in {\tt "shade"} mode.

%
\item[\axiomFun{perspective}]\funArgs{viewport, string\argDef{"on"}}
turns perspective
viewing on and off.

%
\item[\axiomFun{reset}]\funArgs{viewport}
resets the attributes of a viewport to their
initial settings.

%
\item[\axiomFun{resize}]\funArgs{viewport,
\subscriptText{integer}{width} \argDef{viewSizeDefault},
\subscriptText{integer}{height} \argDef{viewSizeDefault}}
resets the width and height
values for a viewport.

%
\item[\axiomFun{rotate}]\funArgs{viewport,
\subscriptText{number}{\texht{$\theta$}{\axiom{theta}}}
\argDef{viewThetaDefault},
\subscriptText{number}{\texht{$\phi$}{\axiom{phi}}}
\argDef{viewPhiDefault}}
rotates the viewport by rotation angles for longitude
({\it \texht{$\theta$}{\axiom{theta}}}) and
latitude ({\it \texht{$\phi$}{\axiom{phi}}}).
Angles designate radians if given as floats, or degrees if given
as integers.

%
\item[\axiomFun{setAdaptive3D}]\funArgs{boolean\argDef{true}}
sets whether space curves are to be plotted
according to the adaptive
refinement algorithm.

%
\item[\axiomFun{setMaxPoints3D}]\funArgs{integer\argDef{1000}}
 sets the default maximum number of possible
points to be used when constructing a \threedim{} space curve.

%
\item[\axiomFun{setMinPoints3D}]\funArgs{integer\argDef{49}}
sets the default minimum number of possible
points to be used when constructing a \threedim{} space curve.

%
\item[\axiomFun{setScreenResolution3D}]\funArgs{integer\argDef{500}}
sets the default screen resolution constant
used in setting the computation limit of adaptively
generated \threedim{} space curve plots.

%
\item[\axiomFun{showRegion}]\funArgs{viewport, string\argDef{"off"}}
declares whether the bounding
box of a graph is shown or not.
%
\item[\axiomFun{subspace}]\funArgs{viewport}
returns the space component.
%
\item[\axiomFun{subspace}]\funArgs{viewport, subspace}
resets the space component
to {\it subspace}.

%
\item[\axiomFun{title}]\funArgs{viewport, string}
gives the viewport the
title {\it string}.

%
\item[\axiomFun{translate}]\funArgs{viewport,
\subscriptText{float}{x}\argDef{viewDeltaXDefault},
\subscriptText{float}{y}\argDef{viewDeltaYDefault}}
translates the object horizontally and vertically 
relative to the center of the viewport.

%
\item[\axiomFun{intensity}]\funArgs{viewport,float\argDef{1.0}}
resets the intensity {\it I} of the light source,
\texht{$0 \le I \le 1.$}{{\it 0 \le I \le 1}.}

%
\item[\axiomFun{tubePointsDefault}]\funArgs{\optArg{integer\argDef{6}}}
sets or indicates the default number of
vertices defining the polygon that is used to create a tube around
a space curve.

%
\item[\axiomFun{tubeRadiusDefault}]\funArgs{\optArg{float\argDef{0.5}}}
sets or indicates the default radius of
the tube that encircles a space curve.

%
\item[\axiomFun{var1StepsDefault}]\funArgs{\optArg{integer\argDef{27}}}
sets or indicates the default number of
increments into which the grid defining a surface plot is subdivided with
respect to the first parameter declared in the surface function.

%
\item[\axiomFun{var2StepsDefault}]\funArgs{\optArg{integer\argDef{27}}}
sets or indicates the default number of
increments into which the grid defining a surface plot is subdivided with
respect to the second parameter declared in the surface function.

%
\item[\axiomFun{viewDefaults}]\funArgs{{\tt [}\subscriptText{integer}{%
point}, \subscriptText{integer}{line}, \subscriptText{integer}{axes},
\subscriptText{integer}{units}, \subscriptText{float}{point},
\allowbreak\subscriptText{list}{position},
\subscriptText{list}{size}{\tt ]}}
resets the default settings for the
point color, line color, axes color, units color, point size,
viewport upper left-hand corner position, and the viewport size.

%
\item[\axiomFun{viewDeltaXDefault}]\funArgs{\optArg{float\argDef{0}}}
resets the default horizontal offset
from the center of the viewport, or returns the 
current default offset if no argument is given.

%
\item[\axiomFun{viewDeltaYDefault}]\funArgs{\optArg{float\argDef{0}}}
resets the default vertical offset
from the center of the viewport, or returns the 
current default offset if no argument is given.

%
\item[\axiomFun{viewPhiDefault}]\funArgs{\optArg{float
\argDef{-\texht{$\pi$}{{\it pi}}/4}}}
resets the default latitudinal view angle,
or returns the current default angle if no argument is given.
\texht{$\phi$}{{\it phi}} is set to this value.

%
\item[\axiomFun{viewpoint}]\funArgs{viewport, \subscriptText{float}{x},
\subscriptText{float}{y}, \subscriptText{float}{z}}
sets the viewing position in Cartesian coordinates.

%
\item[\axiomFun{viewpoint}]\funArgs{viewport,
\subscriptText{float}{\texht{$\theta$}{\axiom{theta}}},
\subscriptText{Float}{\texht{$\phi$}{\axiom{phi}}}}
sets the viewing position in spherical coordinates.

%
\item[\axiomFun{viewpoint}]\funArgs{viewport,
\subscriptText{Float}{\texht{$\theta$}{\axiom{theta}}},
\subscriptText{Float}{\texht{$\phi$}{\axiom{phi}}},
\subscriptText{Float}{scaleFactor},
\subscriptText{Float}{xOffset}, \subscriptText{Float}{yOffset}}
sets the viewing position in spherical coordinates,
the scale factor, and offsets.
\texht{$\theta$}{{\it theta}} (longitude) and
\texht{$\phi$}{{\it phi}} (latitude) are in radians.

%
\item[\axiomFun{viewPosDefault}]\funArgs{\optArg{list\argDef{[0,0]}}}
sets or indicates the position of the upper
left-hand corner of a \twodim{} viewport, relative to the display root
window (the upper left-hand corner of the display is \axiom{[0, 0]}).

%
\item[\axiomFun{viewSizeDefault}]\funArgs{\optArg{list\argDef{[400,400]}}}
sets or indicates the width and height dimensions
of a viewport.

%
\item[\axiomFun{viewThetaDefault}]
\funArgs{\optArg{float\argDef{\texht{$\pi$}{{\it pi}}/4}}}
resets the default longitudinal view angle,
or returns the current default angle if no argument is given.
When a parameter is specified, the default longitudinal view angle
\texht{$\theta$}{{\it theta}} is set to this value.

%
\item[\axiomFun{viewWriteAvailable}]
\funArgs{\optArg{list\argDef{["pixmap",
"bitmap", "postscript", "image"}}}
indicates the possible file types
that can be created with the 
\axiomFunFrom{write}{ThreeDimensionalViewport} function.

%
\item[\axiomFun{viewWriteDefault}]\funArgs{\optArg{list\argDef{[]}}}
sets or indicates the default types of files
that are created in addition to the {\bf data} file when a
\axiomFunFrom{write}{ThreeDimensionalViewport} command
is executed on a viewport.

%
\item[\axiomFun{viewScaleDefault}]\funArgs{\optArg{float}}
sets the default scaling factor, or returns
the current factor if no argument is given.

%
\item[\axiomFun{write}]\funArgs{viewport, directory, \optArg{option}}
writes the file {\bf data} for {\it viewport}
in the directory {\it directory}.
An optional third argument specifies a file type (one of {\tt
pixmap}, {\tt bitmap}, {\tt postscript}, or {\tt image}), or a
list of file types.
An additional file is written for each file type listed.

%
\item[\axiomFun{scale}]\funArgs{viewport, float\argDef{2.5}}
specifies the scaling factor.
\enditems
\indent{0}
\texht{\egroup}{}

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugXdefaultsPage}{ug07.ht}{Customization using .Xdefaults}
\begin{chunk}{ug07.ht}
\begin{page}{ugXdefaultsPage}{7.2.11. Customization using .Xdefaults}
\beginscroll

Both the \twodim{} and \threedim{} drawing facilities consult
the {\bf .Xdefaults} file for various defaults.
The list of defaults that are recognized by the graphing routines
is discussed in this section.
These defaults are preceded by {\tt Axiom.3D.}
for \threedim{} viewport defaults, {\tt Axiom.2D.}
for \twodim{} viewport defaults, or {\tt Axiom*} (no dot) for
those defaults that are acceptable to either viewport type.

%
\indent{0}
\beginitems
%
\item[{\tt Axiom*buttonFont:\ \it font}] \ \newline
This indicates which
font type is used for the button text on the control-panel.
\xdefault{Rom11}
%
\item[{\tt Axiom.2D.graphFont:\ \it font}] \quad (2D only) \newline
This indicates
which font type is used for displaying the graph numbers and
slots in the {\bf Graphs} section of the \twodim{} control-panel.
\xdefault{Rom22}
%
\item[{\tt Axiom.3D.headerFont:\ \it font}] \ \newline
This indicates which
font type is used for the axes labels and potentiometer
header names on \threedim{} viewport windows.
This is also used for \twodim{} control-panels for indicating
which font type is used for potentionmeter header names and
multiple graph title headers.
%for example, {\tt Axiom.2D.headerFont: 8x13}.
\xdefault{Itl14}
%
\item[{\tt Axiom*inverse:\ \it switch}] \ \newline
This indicates whether the
background color is to be inverted from white to black.
If {\tt on}, the graph viewports use black as the background
color.
If {\tt off} or no declaration is made, the graph viewports use a
white background.
\xdefault{off}
%
\item[{\tt Axiom.3D.lightingFont:\ \it font}] \quad (3D only) \newline
This indicates which font type is used for the {\bf x},
{\bf y}, and {\bf z} labels of the two lighting axes potentiometers, 
and for the {\bf Intensity} title on the lighting control-panel.
\xdefault{Rom10}
%
\item[
{\tt Axiom.2D.messageFont, Axiom.3D.messageFont:\ \it font}] \ \newline
These indicate the font type
to be used for the text in the control-panel message window.
\xdefault{Rom14}
%
\item[{\tt Axiom*monochrome:\ \it switch}] \ \newline
This indicates whether the
graph viewports are to be displayed as if the monitor is black and
white, that is, a 1 bit plane.
If {\tt on} is specified, the viewport display is black and white.
If {\tt off} is specified, or no declaration for this default is
given, the viewports are displayed in the normal fashion for the
monitor in use.
\xdefault{off}
%
\item[{\tt Axiom.2D.postScript:\ \it filename}] \ \newline
This specifies
the name of the file that is generated when a 2D PostScript graph
is saved.
\xdefault{axiom2D.ps}
%
\item[{\tt Axiom.3D.postScript:\ \it filename}] \ \newline
This specifies
the name of the file that is generated when a 3D PostScript graph
is saved.
\xdefault{axiom3D.ps}
%
\item[{\tt Axiom*titleFont \it font}] \ \newline
This
indicates which font type is used
for the title text and, for \threedim{} graphs,
in the lighting and viewing-volume control-panel windows.
\xdefault{Rom14}
%
\item[{\tt Axiom.2D.unitFont:\ \it font}] \quad (2D only) \newline
This indicates
which font type is used for displaying the unit labels on
\twodim{} viewport graphs.
\xdefault{6x10}
%
\item[{\tt Axiom.3D.volumeFont:\ \it font}] \quad (3D only) \newline
This indicates which font type is used for the {\bf x},
{\bf y}, and {\bf z} labels of the clipping region sliders; for the
{\bf Perspective}, {\bf Show Region}, and {\bf Clipping On} buttons under
{\bf Settings}, and above the windows for the {\bf Hither} and
{\bf Eye Distance} sliders in the {\bf Viewing Volume Panel} of the
\threedim{} control-panel.
\xdefault{Rom8}
\enditems
\indent{0}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\chapter{Users Guide Chapter 8 (ug08.ht)}
\pagetitle{ugProblemPage}{ug08.ht}{Advanced Problem Solving}
\pageto{notitle}{ugProblemNumericPage}
\pageto{notitle}{ugProblemFactorPage}
\pageto{notitle}{ugProblemSymRootPage}
\pageto{notitle}{ugProblemEigenPage}
\pageto{notitle}{ugProblemLinPolEqnPage}
\pageto{notitle}{ugProblemLimitsPage}
\pageto{notitle}{ugProblemLaplacePage}
\pageto{notitle}{ugProblemIntegrationPage}
\pageto{notitle}{ugProblemSeriesPage}
\pageto{notitle}{ugProblemDEQPage}
\pageto{notitle}{ugProblemFinitePage}
\pageto{notitle}{ugProblemIdealPage}
\pageto{notitle}{ugProblemGaloisPage}
\pageto{notitle}{ugProblemGeneticPage}
\begin{chunk}{ug08.ht}
\begin{page}{ugProblemPage}{8. Advanced Problem Solving}
\beginscroll

In this chapter we describe techniques useful in solving advanced problems
with Axiom.

\beginmenu
    \menudownlink{{8.1. Numeric Functions}}
{ugProblemNumericPage}
    \menudownlink{{8.2. Polynomial Factorization}}
{ugProblemFactorPage}
    \menudownlink{{8.3. Manipulating Symbolic Roots of a Polynomial}}
{ugProblemSymRootPage}
    \menudownlink{{8.4. Computation of Eigenvalues and Eigenvectors}}
{ugProblemEigenPage}
    \menudownlink{{8.5. Solution of Linear and Polynomial Equations}}
{ugProblemLinPolEqnPage}
    \menudownlink{{8.6. Limits}}
{ugProblemLimitsPage}
    \menudownlink{{8.7. Laplace Transforms}}
{ugProblemLaplacePage}
    \menudownlink{{8.8. Integration}}
{ugProblemIntegrationPage}
    \menudownlink{{8.9. Working with Power Series}}
{ugProblemSeriesPage}
    \menudownlink{{8.10. Solution of Differential Equations}}
{ugProblemDEQPage}
    \menudownlink{{8.11. Finite Fields}}
{ugProblemFinitePage}
    \menudownlink{{8.12. Primary Decomposition of Ideals}}
{ugProblemIdealPage}
    \menudownlink{{8.13. Computation of Galois Groups}}
{ugProblemGaloisPage}
    \menudownlink{
{8.14. Non-Associative Algebras and Modelling Genetic Laws}}
{ugProblemGeneticPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugProblemNumericPage}{ug08.ht}{Numeric Functions}
\pagepic{ps/v71ugproblemnumericpage.eps}{ugProblemNumericPage}{0.50}
\pagefrom{Axiom Number Types}{NumberPage}
\pagefrom{Complex}{ComplexXmpPage}
\pageto{An Overview of Axiom}{ugIntroPage}
\pageto{Float}{FloatXmpPage}
\pageto{DoubleFloat}{DoubleFloatXmpPage}
\begin{chunk}{ug08.ht}
\begin{page}{ugProblemNumericPage}{8.1. Numeric Functions}
\beginscroll
Axiom provides two basic floating-point types: \axiomType{Float} and
\axiomType{DoubleFloat}.  This section describes how to use numerical
operations defined on these types and the related complex types.

As we mentioned in \downlink{``An Overview of Axiom''}{ugIntroPage} in
Chapter 1\ignore{ugIntro}, the \axiomType{Float} type is
a software implementation of floating-point numbers in which the
exponent and the significand may have any number of digits.  See
\downlink{`Float'}{FloatXmpPage}\ignore{Float} for detailed
information about this domain.  The \axiomType{DoubleFloat} (see
\downlink{`DoubleFloat'}{DoubleFloatXmpPage}\ignore{DoubleFloat}) is
usually a hardware implementation of floating point numbers,
corresponding to machine double precision.  The types
\axiomType{Complex Float} and \axiomType{Complex DoubleFloat} are the
corresponding software implementations of complex floating-point
numbers.  In this section the term {\it floating-point type} means any
of these four types.

The floating-point types implement the basic elementary functions.
These include (where \axiomSyntax{\$} means
\axiomType{DoubleFloat},
\axiomType{Float},
\axiomType{Complex DoubleFloat}, or
\axiomType{Complex Float}):

\noindent
\axiomFun{exp},  \axiomFun{log}: \axiom{\$ -> \$} \newline
\axiomFun{sin},  \axiomFun{cos}, \axiomFun{tan}, \axiomFun{cot}, 
\axiomFun{sec}, \axiomFun{csc}: \axiom{\$ -> \$} \newline
\axiomFun{sin},  \axiomFun{cos}, \axiomFun{tan}, \axiomFun{cot}, 
\axiomFun{sec}, \axiomFun{csc}: \axiom{\$ -> \$}  \newline
\axiomFun{asin}, \axiomFun{acos}, \axiomFun{atan}, \axiomFun{acot}, 
\axiomFun{asec}, \axiomFun{acsc}: \axiom{\$ -> \$}  \newline
\axiomFun{sinh},  \axiomFun{cosh}, \axiomFun{tanh}, \axiomFun{coth}, 
\axiomFun{sech}, \axiomFun{csch}: \axiom{\$ -> \$}  \newline
\axiomFun{asinh}, \axiomFun{acosh}, \axiomFun{atanh}, \axiomFun{acoth}, 
\axiomFun{asech}, \axiomFun{acsch}: \axiom{\$ -> \$}  \newline
\axiomFun{pi}: \axiom{() -> \$}  \newline
\axiomFun{sqrt}: \axiom{\$ -> \$} \newline
\axiomFun{nthRoot}: \axiom{(\$, Integer) -> \$}  \newline
\axiomFunFrom{**}{Float}: \axiom{(\$, Fraction Integer) -> \$} \newline
\axiomFunFrom{**}{Float}: \axiom{(\$,\$) -> \$}  \newline

The handling of roots depends on whether the floating-point type
is real or complex: for the real floating-point types,
\axiomType{DoubleFloat} and \axiomType{Float}, if a real root exists
the one with the same sign as the radicand is returned; for the
complex floating-point types, the principal value is returned.
Also, for real floating-point types the inverse functions
produce errors if the results are not real.
This includes cases such as \axiom{asin(1.2)}, \axiom{log(-3.2)},
\axiom{sqrt(-1.1)}.
%
\xtc{
The default floating-point type is \axiomType{Float} so to evaluate
functions using \axiomType{Float} or \axiomType{Complex Float}, just
use normal decimal notation.
}{
\spadpaste{exp(3.1)}
}
\xtc{
}{
\spadpaste{exp(3.1 + 4.5 * \%i)}
}
\xtc{
To evaluate functions using \axiomType{DoubleFloat}
or \axiomType{Complex DoubleFloat},
a declaration or conversion is required.
}{
\spadpaste{r: DFLOAT := 3.1; t: DFLOAT := 4.5; exp(r + t*\%i)}
}
\xtc{
}{
\spadpaste{exp(3.1::DFLOAT + 4.5::DFLOAT * \%i)}
}

A number of special functions are provided by the package
\axiomType{DoubleFloatSpecialFunctions} for the machine-precision
floating-point types.  The special functions provided are listed
below, where \axiom{F} stands for the types \axiomType{DoubleFloat}
and \axiomType{Complex DoubleFloat}.  The real versions of the
functions yield an error if the result is not real.

\noindent
\axiomFun{Gamma}: \axiom{F -> F}\hfill\newline
\axiom{Gamma(z)} is the Euler gamma function,
   \texht{$\Gamma(z)$}{\axiom{Gamma(z)}},
   defined by
   \texht{
\narrowDisplay{\Gamma(z) = \int_{0}^{\infty} t^{z-1} e^{-t} dt.}%
   }{
\newline
\centerline{{
\axiom{Gamma(z) = integrate(t**(z-1)*exp(-t), t=0..\%infinity).}}}
   }

\noindent
\axiomFun{Beta}: \axiom{F -> F}\hfill\newline
   \axiom{Beta(u, v)} is the Euler Beta function,
   \texht{$B(u,v)$}{\axiom{B(u,v)}}, defined by
   \texht{\narrowDisplay{B(u,v) = \int_{0}^{1} t^{u-1} (1-t)^{v-1} dt.}%
   }{
\newline
\centerline{{      
\axiom{Beta(u,v) = integrate(t**(u-1)*(1-t)**(b-1), t=0..1).}}}
   }
   This is related to \texht{$\Gamma(z)$}{\axiom{Gamma(z)}} by
   \texht{\narrowDisplay{B(u,v) = 
\frac{\Gamma(u) \Gamma(v)}{\Gamma(u + v)}.}%
   }{
\newline
\centerline{{      \axiom{Beta(u,v) = Gamma(u)*Gamma(v)/Gamma(u + v).}}}
   }%

\noindent
\axiomFun{logGamma}: \axiom{F -> F}\hfill\newline
   \axiom{logGamma(z)} is the natural logarithm of
\texht{$\Gamma(z)$}{\axiom{Gamma(z)}}.
   This can often be computed even if 
\texht{$\Gamma(z)$}{\axiom{Gamma(z)}}
cannot.
%

\noindent
\axiomFun{digamma}: \axiom{F -> F}\hfill\newline
   \axiom{digamma(z)}, also called \axiom{psi(z)},
is the function \texht{$\psi(z)$}{\axiom{psi(z)}},
   defined by \texht{\narrowDisplay{\psi(z) = \Gamma'(z)/\Gamma(z).}%
   }{
\newline
\centerline{{      \axiom{psi(z) = Gamma'(z)/Gamma(z).}}}
  }%

\noindent
\axiomFun{polygamma}: 
\axiom{(NonNegativeInteger, F) -> F}\hfill\newline
   \axiom{polygamma(n, z)} is the \eth{\axiom{n}} derivative of
   \texht{$\psi(z)$}{
\axiom{digamma(z)}}\texht{, written $\psi^{(n)}(z)$}{}.

\noindent
\axiomFun{besselJ}: \axiom{(F,F) -> F}\hfill\newline
   \axiom{besselJ(v,z)} is the Bessel function of the first kind,
   \texht{$J_\nu (z)$}{\axiom{J(v,z)}}.
   This function satisfies the differential equation
   \texht{\narrowDisplay{z^2 w''(z) + z w'(z) + (z^2-\nu^2)w(z) = 0.}%
   }{
\newline
\centerline{{      \axiom{z**2*w''(z) + z*w'(z) + (z**2-v**2)*w(z) = 0.}}}
  }%

\noindent
\axiomFun{besselY}: \axiom{(F,F) -> F}\hfill\newline
   \axiom{besselY(v,z)} is the Bessel function of the second kind,
   \texht{$Y_\nu (z)$}{\axiom{Y(v,z)}}.
   This function satisfies the same differential equation as
   \axiomFun{besselJ}.
   The implementation simply uses the relation
   \texht{\narrowDisplay{Y_\nu (z) = 
\frac{J_\nu (z) \cos(\nu \pi) - J_{-\nu} (z)}{\sin(\nu \pi)}.}%
   }{
\newline
\centerline{{      \axiom{Y(v,z) = 
(J(v,z)*cos(v*\%pi) - J(-v,z))/sin(v*\%pi).}}}
   }%

\noindent
\axiomFun{besselI}: \axiom{(F,F) -> F}\hfill\newline
   \axiom{besselI(v,z)} is the modified Bessel function of the first kind,
   \texht{$I_\nu (z)$}{\axiom{I(v,z)}}.
   This function satisfies the differential equation
   \texht{\narrowDisplay{z^2 w''(z) + z w'(z) - (z^2+\nu^2)w(z) = 0.}%
   }{
\newline
\centerline{{      
\axiom{z**2 * w''(z) + z * w'(z) - (z**2+v**2)*w(z) = 0.}}}
   }%

\noindent
\axiomFun{besselK}: \axiom{(F,F) -> F}\hfill\newline
   \axiom{besselK(v,z)} is the modified Bessel 
function of the second kind,
   \texht{$K_\nu (z)$}{\axiom{K(v,z)}}.
   This function satisfies the same differential 
equation as \axiomFun{besselI}.
   The implementation simply uses the relation
   \texht{\narrowDisplay{K_\nu (z) = 
\pi \frac{I_{-\nu} (z) - I_{\nu} (z)}{2 \sin(\nu \pi)}.}%
   }{
\newline
\centerline{{      \axiom{K(v,z) = 
\%pi*(I(v,z) - I(-v,z))/(2*sin(v*\%pi)).}}}
   }

\noindent
\axiomFun{airyAi}: \axiom{F -> F}\hfill\newline
   \axiom{airyAi(z)} is the Airy function \texht{$Ai(z)$}{\axiom{Ai(z)}}.
   This function satisfies the differential equation
   \texht{$w''(z) - z w(z) = 0.$}{\axiom{w''(z) - z * w(z) = 0.}}
   The implementation simply uses the relation
   \texht{\narrowDisplay{Ai(-z) = 
\frac{1}{3}\sqrt{z} ( J_{-1/3} 
(\frac{2}{3}z^{3/2}) + J_{1/3} (\frac{2}{3}z^{3/2}) ).}%
   }{
\newline
\centerline{{      \axiom{Ai(-z) = 
1/3 * sqrt(z) * (J(-1/3, 2/3*z**(3/2)) + J(1/3, 2/3*z**(3/2)) ).}}}
   }%

\noindent
\axiomFun{airyBi}: \axiom{F -> F}\hfill\newline
   \axiom{airyBi(z)} is the Airy function 
\texht{$Bi(z)$}{\axiom{Bi(z)}}.
   This function satisfies the same differential 
equation as \axiomFun{airyAi}.
   The implementation simply uses the relation
   \texht{\narrowDisplay{Bi(-z) = 
\frac{1}{3}\sqrt{3 z} ( J_{-1/3} 
(\frac{2}{3}z^{3/2}) - J_{1/3} (\frac{2}{3}z^{3/2}) ).}%
   }{
\newline
\centerline{{      \axiom{Bi(-z) = 1/3 *sqrt(3*z) *
(J(-1/3, 2/3*z**(3/2)) - J(1/3, 2/3*z**(3/2)) ).}}}
   }

\noindent
\axiomFun{hypergeometric0F1}: \axiom{(F,F) -> F}\hfill\newline
   \axiom{hypergeometric0F1(c,z)} is the hypergeometric function
   \texht{${}_0 F_1 ( ; c; z)$}{\axiom{0F1(; c; z)}}.%

\xtc{
The above special functions are defined only for small floating-point
types.  If you give \axiomType{Float} arguments, they are converted to
\axiomType{DoubleFloat} by Axiom.
}{
\spadpaste{Gamma(0.5)**2}
}
\xtc{
}{
\spadpaste{a := 2.1; b := 1.1; besselI(a + \%i*b, b*a + 1)}
}

A number of additional operations may be used to compute numerical
values.  These are special polynomial functions that can be evaluated
for values in any commutative ring \axiom{R}, and in particular for
values in any floating-point type.  The following operations are
provided by the package \axiomType{OrthogonalPolynomialFunctions}:

\noindent
\axiomFun{chebyshevT}: 
\axiom{(NonNegativeInteger, R) -> R}\hbox{}\hfill\newline
   \axiom{chebyshevT(n,z)} is the \eth{\axiom{n}} 
Chebyshev polynomial of the first
   kind, \texht{$T_n (z)$}{\axiom{T[n](z)}}.  These are defined by
   \texht{\narrowDisplay{\frac{1-t z}{1-2 t z+t^2} = 
\sum_{n=0}^{\infty} T_n (z) t^n.}%
   }{
\newline
\centerline{{   \axiom{(1-t*z)/(1-2*t*z+t**2) = 
sum(T[n](z) *t**n, n = 0..).}}}
   }%

\noindent
\axiomFun{chebyshevU}: \axiom{(NonNegativeInteger, R) -> R}
\hbox{}\hfill\newline
   \axiom{chebyshevU(n,z)} is the \eth{\axiom{n}} 
Chebyshev polynomial of the second
   kind, \texht{$U_n (z)$}{\axiom{U[n](z)}}. These are defined by
   \texht{\narrowDisplay{\frac{1}{1-2 t z+t^2} = 
\sum_{n=0}^{\infty} U_n (z) t^n.}%
   }{
\newline
\centerline{{   \axiom{1/(1-2*t*z+t**2) = sum(U[n](z) *t**n, n = 0..).}}}
   }%

\noindent
\axiomFun{hermiteH}:   \axiom{(NonNegativeInteger, R) -> R}
\hbox{}\hfill\newline
   \axiom{hermiteH(n,z)} is the \eth{\axiom{n}} Hermite polynomial,
   \texht{$H_n (z)$}{\axiom{H[n](z)}}.
   These are defined by
   \texht{\narrowDisplay{e^{2 t z - t^2} = 
\sum_{n=0}^{\infty} H_n (z) \frac{t^n}{n!}.}%
   }{
\newline
\centerline{{   \axiom{exp(2*t*z-t**2) = sum(H[n](z)*t**n/n!, n = 0..).}}}
   }%

\noindent
\axiomFun{laguerreL}:  \axiom{(NonNegativeInteger, R) -> R}
\hbox{}\hfill\newline
   \axiom{laguerreL(n,z)} is the \eth{\axiom{n}} Laguerre polynomial,
   \texht{$L_n (z)$}{\axiom{L[n](z)}}.
   These are defined by
   \texht{\narrowDisplay{\frac{e^{-\frac{t z}{1-t}}}{1-t} = 
\sum_{n=0}^{\infty} L_n (z) \frac{t^n}{n!}.}%
   }{
\newline
\centerline{{   \axiom{exp(-t*z/(1-t))/(1-t) = 
sum(L[n](z)*t**n/n!, n = 0..).}}}
   }%

\noindent
\axiomFun{laguerreL}:  
\axiom{(NonNegativeInteger, NonNegativeInteger, R) -> R}\hbox{}\hfill\newline
   \axiom{laguerreL(m,n,z)} is the associated Laguerre polynomial,
   \texht{$L^m_n (z)$}{\axiom{L<m>[n](z)}}.
   This is the 
\eth{\axiom{m}} derivative of \texht{$L_n (z)$}{\axiom{L[n](z)}}.

\noindent
\axiomFun{legendreP}:  
\axiom{(NonNegativeInteger, R) -> R}\hbox{}\hfill\newline
   \axiom{legendreP(n,z)} is the \eth{\axiom{n}} Legendre polynomial,
   \texht{$P_n (z)$}{\axiom{P[n](z)}}.  These are defined by
   \texht{\narrowDisplay{
\frac{1}{\sqrt{1-2 t z+t^2}} = \sum_{n=0}^{\infty} P_n (z) t^n.}%
   }{
\newline
\centerline{{   \axiom{1/sqrt(1-2*z*t+t**2) = 
sum(P[n](z)*t**n, n = 0..).}}}
   }%

%
\xtc{
These operations require non-negative integers for the indices, 
but otherwise the argument can be given as desired.
}{
\spadpaste{[chebyshevT(i, z) for i in 0..5]}
}
\xtc{
The expression \axiom{chebyshevT(n,z)} evaluates to the 
\eth{\axiom{n}} Chebyshev polynomial of the first kind.
}{
\spadpaste{chebyshevT(3, 5.0 + 6.0*\%i)}
}
\xtc{
}{
\spadpaste{chebyshevT(3, 5.0::DoubleFloat)}
}
\xtc{
The expression \axiom{chebyshevU(n,z)} evaluates to the 
\eth{\axiom{n}} Chebyshev polynomial of the second kind.
}{
\spadpaste{[chebyshevU(i, z) for i in 0..5]}
}
\xtc{
}{
\spadpaste{chebyshevU(3, 0.2)}
}
\xtc{
The expression \axiom{hermiteH(n,z)} evaluates to the 
\eth{\axiom{n}} Hermite polynomial.
}{
\spadpaste{[hermiteH(i, z) for i in 0..5]}
}
\xtc{
}{
\spadpaste{hermiteH(100, 1.0)}
}
\xtc{
The expression \axiom{laguerreL(n,z)} evaluates to the 
\eth{\axiom{n}} Laguerre polynomial.
}{
\spadpaste{[laguerreL(i, z) for i in 0..4]}
}
\xtc{
}{
\spadpaste{laguerreL(4, 1.2)}
}
\xtc{
}{
\spadpaste{[laguerreL(j, 3, z) for j in 0..4]}
}
\xtc{
}{
\spadpaste{laguerreL(1, 3, 2.1)}
}
\xtc{
The expression
\axiom{legendreP(n,z)} evaluates to the 
\eth{\axiom{n}} Legendre polynomial,
}{
\spadpaste{[legendreP(i,z) for i in 0..5]}
}
\xtc{
}{
\spadpaste{legendreP(3, 3.0*\%i)}
}
%

Finally, three number-theoretic polynomial operations may be evaluated.
The following operations are provided by the package
\axiomType{NumberTheoreticPolynomialFunctions}.

\noindent
\axiomFun{bernoulliB}: \axiom{(NonNegativeInteger, R) -> R} 
\hbox{}\hfill\newline
   \axiom{bernoulliB(n,z)} is the \eth{\axiom{n}} Bernoulli polynomial,
   \texht{$B_n (z)$}{\axiom{B[n](z)}}.  These are defined by
   \texht{\narrowDisplay{\frac{t e^{z t}}{e^t - 1} = 
\sum_{n=0}^{\infty} B_n (z) \frac{t^n}{n!}.}
   }{
\newline
\centerline{{   \axiom{t*exp(z*t)/(exp t - 1) = 
sum(B[n](z)*t**n/n! for n - 0..)}}}
   }%

\noindent
\axiomFun{eulerE}: \axiom{(NonNegativeInteger, R) -> R} 
\hbox{}\hfill\newline
   \axiom{eulerE(n,z)} is the \eth{\axiom{n}} Euler polynomial,
   \texht{$E_n (z)$}{\axiom{E[n](z)}}.  These are defined by
   \texht{\narrowDisplay{\frac{2 e^{z t}}{e^t + 1} = 
\sum_{n=0}^{\infty} E_n (z) \frac{t^n}{n!}.}%
   }{
\newline
\centerline{{   \axiom{2*exp(z*t)/(exp t + 1) = 
sum(E[n](z)*t**n/n! for n - 0..)}}}
   }%

\noindent
\axiomFun{cyclotomic}: \axiom{(NonNegativeInteger, R) -> R}
\hbox{}\hfill\newline
   \axiom{cyclotomic(n,z)} is the \eth{\axiom{n}} cyclotomic polynomial
   \texht{$\Phi_n (z)$}{\axiom{phi(n,z)}}.  This is the polynomial whose
   roots are precisely the primitive \eth{\axiom{n}} roots of unity.
   This polynomial has degree given by the Euler totient function
   \texht{$\phi(n)$}{\axiom{phi(n)}}.

\xtc{
The expression \axiom{bernoulliB(n,z)} evaluates to the 
\eth{\axiom{n}} Bernoulli polynomial.
}{
\spadpaste{bernoulliB(3, z)}
}
\xtc{
}{
\spadpaste{bernoulliB(3, 0.7 + 0.4 * \%i)}
}
\xtc{
The expression
\axiom{eulerE(n,z)} evaluates to the \eth{\axiom{n}} Euler polynomial.
}{
\spadpaste{eulerE(3, z)}
}
\xtc{
}{
\spadpaste{eulerE(3, 0.7 + 0.4 * \%i)}
}
\xtc{
The expression
\axiom{cyclotomic(n,z)} evaluates to the 
\eth{\axiom{n}} cyclotomic polynomial.
}{
\spadpaste{cyclotomic(3, z)}
}
\xtc{
}{
\spadpaste{cyclotomic(3, (-1.0 + 0.0 * \%i)**(2/3))}
}

Drawing complex functions in Axiom is presently somewhat
awkward compared to drawing real functions.
It is necessary to use the \axiomFun{draw} operations that operate
on functions rather than expressions.

\psXtc{
This is the complex exponential function\texht{ (rotated
interactively).}{.}  When this is displayed in color, the height is
the value of the real part of the function and the color is the
imaginary part.  Red indicates large negative imaginary values, green
indicates imaginary values near zero and blue/violet indicates large
positive imaginary values.
}{
\graphpaste{draw((x,y)+-> real exp complex(x,y), -2..2, 
-2*\%pi..2*\%pi, colorFunction == 
(x, y) +->  imag exp complex(x,y), 
title=="exp(x+\%i*y)", style=="smooth")}
}{
\epsffile[0 0 295 295]{../ps/compexp.ps}
}

\psXtc{
This is the complex arctangent function.
Again, the height is the real part of the function value but here
the color indicates the function value's phase.
The position of the branch cuts are clearly visible and one can
see that the function is real only for a real argument.
}{
\graphpaste{vp := draw((x,y) +-> real atan complex(x,y), 
-\%pi..\%pi, -\%pi..\%pi, colorFunction==
(x,y) +->argument atan complex(x,y), 
title=="atan(x+\%i*y)", style=="shade"); rotate(vp,-160,-45); vp}
}{
\epsffile[0 0 295 295]{../ps/compatan.ps}
}

\psXtc{
This is the complex Gamma function.
}{
\graphpaste{draw((x,y) +-> max(min(real Gamma complex(x,y),4),-4), 
-\%pi..\%pi, -\%pi..\%pi, style=="shade", colorFunction == 
(x,y) +-> argument Gamma complex(x,y), 
title == "Gamma(x+\%i*y)", var1Steps == 50, var2Steps== 50)}
}{
\epsffile[0 0 295 295]{../ps/compgamm.ps}
}

\psXtc{
This shows the real Beta function near the origin.
}{
\graphpaste{draw(Beta(x,y)/100, x=-1.6..1.7, y = -1.6..1.7, 
style=="shade", title=="Beta(x,y)", var1Steps==40, var2Steps==40)}
}{
\epsffile[0 0 295 295]{../ps/realbeta.ps}
}

\psXtc{
This is the Bessel function \texht{$J_\alpha (x)$}{\axiom{J(alpha,x)}}
for index \texht{$\alpha$}{\axiom{alpha}} in the range \axiom{-6..4} and
argument \texht{$x$}{\axiom{x}} in the range \axiom{2..14}.
}{
\graphpaste{draw((alpha,x) +-> min(max(besselJ(alpha, x+8), -6), 6), 
-6..4, -6..6, title=="besselJ(alpha,x)", style=="shade", 
var1Steps==40, var2Steps==40)}
}{
\epsffile[0 0 295 295]{../ps/bessel.ps}
}

\psXtc{
This is the modified Bessel function
\texht{$I_\alpha (x)$}{\axiom{I(alpha,x)}}
evaluated for various real values of the index 
\texht{$\alpha$}{\axiom{alpha}}
and fixed argument \texht{$x = 5$}{\axiom{x = 5}}.
}{
\graphpaste{draw(besselI(alpha, 5), alpha = -12..12, unit==[5,20])}
}{
\epsffile[0 0 295 295]{../ps/modbess.ps}
}

\psXtc{
This is similar to the last example
except the index \texht{$\alpha$}{\axiom{alpha}}
takes on complex values in a \axiom{6 x 6} rectangle  
centered on the origin.
}{
\graphpaste{draw((x,y) +-> real besselI(complex(x/20, y/20),5), 
-60..60, -60..60, colorFunction == 
(x,y)+-> argument besselI(complex(x/20,y/20),5), 
title=="besselI(x+i*y,5)", style=="shade")}
}{
\epsffile[0 0 295 295]{../ps/modbessc.ps}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugProblemNumericPagePatch1}
\begin{paste}{ugProblemNumericPageFull1}{ugProblemNumericPageEmpty1}
\pastebutton{ugProblemNumericPageFull1}{\hidepaste}
\tab{5}\spadcommand{exp(3.1)}
\indentrel{3}\begin{verbatim}
   (1)  22.1979512814 41633405
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty1}
\begin{paste}{ugProblemNumericPageEmpty1}{ugProblemNumericPagePatch1}
\pastebutton{ugProblemNumericPageEmpty1}{\showpaste}
\tab{5}\spadcommand{exp(3.1)}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch2}
\begin{paste}{ugProblemNumericPageFull2}{ugProblemNumericPageEmpty2}
\pastebutton{ugProblemNumericPageFull2}{\hidepaste}
\tab{5}\spadcommand{exp(3.1 + 4.5 * \%i)}
\indentrel{3}\begin{verbatim}
   (2)
   - 4.6792348860 969899118 - 21.6991659280 71731864 %i
                                    Type: Complex Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty2}
\begin{paste}{ugProblemNumericPageEmpty2}{ugProblemNumericPagePatch2}
\pastebutton{ugProblemNumericPageEmpty2}{\showpaste}
\tab{5}\spadcommand{exp(3.1 + 4.5 * \%i)}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch3}
\begin{paste}{ugProblemNumericPageFull3}{ugProblemNumericPageEmpty3}
\pastebutton{ugProblemNumericPageFull3}{\hidepaste}
\tab{5}\spadcommand{r: DFLOAT := 3.1; t: DFLOAT := 4.5; exp(r + t*\%i)}
\indentrel{3}\begin{verbatim}
   (3)  - 4.6792348860969906 - 21.699165928071732%i
                              Type: Complex DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty3}
\begin{paste}{ugProblemNumericPageEmpty3}{ugProblemNumericPagePatch3}
\pastebutton{ugProblemNumericPageEmpty3}{\showpaste}
\tab{5}\spadcommand{r: DFLOAT := 3.1; t: DFLOAT := 4.5; exp(r + t*\%i)}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch4}
\begin{paste}{ugProblemNumericPageFull4}{ugProblemNumericPageEmpty4}
\pastebutton{ugProblemNumericPageFull4}{\hidepaste}
\tab{5}\spadcommand{exp(3.1::DFLOAT + 4.5::DFLOAT * \%i)}
\indentrel{3}\begin{verbatim}
   (4)  - 4.6792348860969906 - 21.699165928071732%i
                              Type: Complex DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty4}
\begin{paste}{ugProblemNumericPageEmpty4}{ugProblemNumericPagePatch4}
\pastebutton{ugProblemNumericPageEmpty4}{\showpaste}
\tab{5}\spadcommand{exp(3.1::DFLOAT + 4.5::DFLOAT * \%i)}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch5}
\begin{paste}{ugProblemNumericPageFull5}{ugProblemNumericPageEmpty5}
\pastebutton{ugProblemNumericPageFull5}{\hidepaste}
\tab{5}\spadcommand{Gamma(0.5)**2}
\indentrel{3}\begin{verbatim}
   (5)  3.14159265358979
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty5}
\begin{paste}{ugProblemNumericPageEmpty5}{ugProblemNumericPagePatch5}
\pastebutton{ugProblemNumericPageEmpty5}{\showpaste}
\tab{5}\spadcommand{Gamma(0.5)**2}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch6}
\begin{paste}{ugProblemNumericPageFull6}{ugProblemNumericPageEmpty6}
\pastebutton{ugProblemNumericPageFull6}{\hidepaste}
\tab{5}\spadcommand{a := 2.1; b := 1.1; besselI(a + \%i*b, b*a + 1)}
\indentrel{3}\begin{verbatim}
   (6)  2.489482417547372 - 2.3658460381468371%i
                              Type: Complex DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty6}
\begin{paste}{ugProblemNumericPageEmpty6}{ugProblemNumericPagePatch6}
\pastebutton{ugProblemNumericPageEmpty6}{\showpaste}
\tab{5}\spadcommand{a := 2.1; b := 1.1; besselI(a + \%i*b, b*a + 1)}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch7}
\begin{paste}{ugProblemNumericPageFull7}{ugProblemNumericPageEmpty7}
\pastebutton{ugProblemNumericPageFull7}{\hidepaste}
\tab{5}\spadcommand{[chebyshevT(i, z) for i in 0..5]}
\indentrel{3}\begin{verbatim}
   (7)
          2       3        4     2        5      3
   [1,z,2z  - 1,4z  - 3z,8z  - 8z  + 1,16z  - 20z  + 5z]
                          Type: List Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty7}
\begin{paste}{ugProblemNumericPageEmpty7}{ugProblemNumericPagePatch7}
\pastebutton{ugProblemNumericPageEmpty7}{\showpaste}
\tab{5}\spadcommand{[chebyshevT(i, z) for i in 0..5]}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch8}
\begin{paste}{ugProblemNumericPageFull8}{ugProblemNumericPageEmpty8}
\pastebutton{ugProblemNumericPageFull8}{\hidepaste}
\tab{5}\spadcommand{chebyshevT(3, 5.0 + 6.0*\%i)}
\indentrel{3}\begin{verbatim}
   (8)  - 1675.0 + 918.0 %i
                                    Type: Complex Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty8}
\begin{paste}{ugProblemNumericPageEmpty8}{ugProblemNumericPagePatch8}
\pastebutton{ugProblemNumericPageEmpty8}{\showpaste}
\tab{5}\spadcommand{chebyshevT(3, 5.0 + 6.0*\%i)}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch9}
\begin{paste}{ugProblemNumericPageFull9}{ugProblemNumericPageEmpty9}
\pastebutton{ugProblemNumericPageFull9}{\hidepaste}
\tab{5}\spadcommand{chebyshevT(3, 5.0::DoubleFloat)}
\indentrel{3}\begin{verbatim}
   (9)  485.0
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty9}
\begin{paste}{ugProblemNumericPageEmpty9}{ugProblemNumericPagePatch9}
\pastebutton{ugProblemNumericPageEmpty9}{\showpaste}
\tab{5}\spadcommand{chebyshevT(3, 5.0::DoubleFloat)}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch10}
\begin{paste}{ugProblemNumericPageFull10}{ugProblemNumericPageEmpty10}
\pastebutton{ugProblemNumericPageFull10}{\hidepaste}
\tab{5}\spadcommand{[chebyshevU(i, z) for i in 0..5]}
\indentrel{3}\begin{verbatim}
   (10)
             2        3          4      2
   [1, 2z, 4z  - 1, 8z  - 4z, 16z  - 12z  + 1,
       5      3
    32z  - 32z  + 6z]
                          Type: List Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty10}
\begin{paste}{ugProblemNumericPageEmpty10}{ugProblemNumericPagePatch10}
\pastebutton{ugProblemNumericPageEmpty10}{\showpaste}
\tab{5}\spadcommand{[chebyshevU(i, z) for i in 0..5]}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch11}
\begin{paste}{ugProblemNumericPageFull11}{ugProblemNumericPageEmpty11}
\pastebutton{ugProblemNumericPageFull11}{\hidepaste}
\tab{5}\spadcommand{chebyshevU(3, 0.2)}
\indentrel{3}\begin{verbatim}
   (11)  - 0.736
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty11}
\begin{paste}{ugProblemNumericPageEmpty11}{ugProblemNumericPagePatch11}
\pastebutton{ugProblemNumericPageEmpty11}{\showpaste}
\tab{5}\spadcommand{chebyshevU(3, 0.2)}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch12}
\begin{paste}{ugProblemNumericPageFull12}{ugProblemNumericPageEmpty12}
\pastebutton{ugProblemNumericPageFull12}{\hidepaste}
\tab{5}\spadcommand{[hermiteH(i, z) for i in 0..5]}
\indentrel{3}\begin{verbatim}
   (12)
             2        3           4      2
   [1, 2z, 4z  - 2, 8z  - 12z, 16z  - 48z  + 12,
       5       3
    32z  - 160z  + 120z]
                          Type: List Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty12}
\begin{paste}{ugProblemNumericPageEmpty12}{ugProblemNumericPagePatch12}
\pastebutton{ugProblemNumericPageEmpty12}{\showpaste}
\tab{5}\spadcommand{[hermiteH(i, z) for i in 0..5]}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch13}
\begin{paste}{ugProblemNumericPageFull13}{ugProblemNumericPageEmpty13}
\pastebutton{ugProblemNumericPageFull13}{\hidepaste}
\tab{5}\spadcommand{hermiteH(100, 1.0)}
\indentrel{3}\begin{verbatim}
   (13)  - 0.1448706729 337934088 E 93
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty13}
\begin{paste}{ugProblemNumericPageEmpty13}{ugProblemNumericPagePatch13}
\pastebutton{ugProblemNumericPageEmpty13}{\showpaste}
\tab{5}\spadcommand{hermiteH(100, 1.0)}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch14}
\begin{paste}{ugProblemNumericPageFull14}{ugProblemNumericPageEmpty14}
\pastebutton{ugProblemNumericPageFull14}{\hidepaste}
\tab{5}\spadcommand{[laguerreL(i, z) for i in 0..4]}
\indentrel{3}\begin{verbatim}
   (14)
                 2              3     2
   [1, - z + 1, z  - 4z + 2, - z  + 9z  - 18z + 6,
     4      3      2
    z  - 16z  + 72z  - 96z + 24]
                          Type: List Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty14}
\begin{paste}{ugProblemNumericPageEmpty14}{ugProblemNumericPagePatch14}
\pastebutton{ugProblemNumericPageEmpty14}{\showpaste}
\tab{5}\spadcommand{[laguerreL(i, z) for i in 0..4]}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch15}
\begin{paste}{ugProblemNumericPageFull15}{ugProblemNumericPageEmpty15}
\pastebutton{ugProblemNumericPageFull15}{\hidepaste}
\tab{5}\spadcommand{laguerreL(4, 1.2)}
\indentrel{3}\begin{verbatim}
   (15)  - 13.0944
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty15}
\begin{paste}{ugProblemNumericPageEmpty15}{ugProblemNumericPagePatch15}
\pastebutton{ugProblemNumericPageEmpty15}{\showpaste}
\tab{5}\spadcommand{laguerreL(4, 1.2)}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch16}
\begin{paste}{ugProblemNumericPageFull16}{ugProblemNumericPageEmpty16}
\pastebutton{ugProblemNumericPageFull16}{\hidepaste}
\tab{5}\spadcommand{[laguerreL(j, 3, z) for j in 0..4]}
\indentrel{3}\begin{verbatim}
   (16)
       3     2               2
   [- z  + 9z  - 18z + 6,- 3z  + 18z - 18,- 6z + 18,- 6,0]
                          Type: List Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty16}
\begin{paste}{ugProblemNumericPageEmpty16}{ugProblemNumericPagePatch16}
\pastebutton{ugProblemNumericPageEmpty16}{\showpaste}
\tab{5}\spadcommand{[laguerreL(j, 3, z) for j in 0..4]}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch17}
\begin{paste}{ugProblemNumericPageFull17}{ugProblemNumericPageEmpty17}
\pastebutton{ugProblemNumericPageFull17}{\hidepaste}
\tab{5}\spadcommand{laguerreL(1, 3, 2.1)}
\indentrel{3}\begin{verbatim}
   (17)  6.57
                                            Type: Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty17}
\begin{paste}{ugProblemNumericPageEmpty17}{ugProblemNumericPagePatch17}
\pastebutton{ugProblemNumericPageEmpty17}{\showpaste}
\tab{5}\spadcommand{laguerreL(1, 3, 2.1)}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch18}
\begin{paste}{ugProblemNumericPageFull18}{ugProblemNumericPageEmpty18}
\pastebutton{ugProblemNumericPageFull18}{\hidepaste}
\tab{5}\spadcommand{[legendreP(i,z) for i in 0..5]}
\indentrel{3}\begin{verbatim}
   (18)
          3  2   1  5  3   3    35  4   15  2   3
   [1, z, Ä z  - Ä, Ä z  - Ä z, ÄÄ z  - ÄÄ z  + Ä,
          2      2  2      2     8       4      8
    63  5   35  3   15
    ÄÄ z  - ÄÄ z  + ÄÄ z]
     8       4       8
                 Type: List Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty18}
\begin{paste}{ugProblemNumericPageEmpty18}{ugProblemNumericPagePatch18}
\pastebutton{ugProblemNumericPageEmpty18}{\showpaste}
\tab{5}\spadcommand{[legendreP(i,z) for i in 0..5]}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch19}
\begin{paste}{ugProblemNumericPageFull19}{ugProblemNumericPageEmpty19}
\pastebutton{ugProblemNumericPageFull19}{\hidepaste}
\tab{5}\spadcommand{legendreP(3, 3.0*\%i)}
\indentrel{3}\begin{verbatim}
   (19)  - 72.0 %i
                                    Type: Complex Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty19}
\begin{paste}{ugProblemNumericPageEmpty19}{ugProblemNumericPagePatch19}
\pastebutton{ugProblemNumericPageEmpty19}{\showpaste}
\tab{5}\spadcommand{legendreP(3, 3.0*\%i)}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch20}
\begin{paste}{ugProblemNumericPageFull20}{ugProblemNumericPageEmpty20}
\pastebutton{ugProblemNumericPageFull20}{\hidepaste}
\tab{5}\spadcommand{bernoulliB(3, z)}
\indentrel{3}\begin{verbatim}
          3   3  2   1
   (20)  z  - Ä z  + Ä z
              2      2
                      Type: Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty20}
\begin{paste}{ugProblemNumericPageEmpty20}{ugProblemNumericPagePatch20}
\pastebutton{ugProblemNumericPageEmpty20}{\showpaste}
\tab{5}\spadcommand{bernoulliB(3, z)}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch21}
\begin{paste}{ugProblemNumericPageFull21}{ugProblemNumericPageEmpty21}
\pastebutton{ugProblemNumericPageFull21}{\hidepaste}
\tab{5}\spadcommand{bernoulliB(3, 0.7 + 0.4 * \%i)}
\indentrel{3}\begin{verbatim}
   (21)  - 0.138 - 0.116 %i
                                    Type: Complex Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty21}
\begin{paste}{ugProblemNumericPageEmpty21}{ugProblemNumericPagePatch21}
\pastebutton{ugProblemNumericPageEmpty21}{\showpaste}
\tab{5}\spadcommand{bernoulliB(3, 0.7 + 0.4 * \%i)}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch22}
\begin{paste}{ugProblemNumericPageFull22}{ugProblemNumericPageEmpty22}
\pastebutton{ugProblemNumericPageFull22}{\hidepaste}
\tab{5}\spadcommand{eulerE(3, z)}
\indentrel{3}\begin{verbatim}
          3   3  2   1
   (22)  z  - Ä z  + Ä
              2      4
                      Type: Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty22}
\begin{paste}{ugProblemNumericPageEmpty22}{ugProblemNumericPagePatch22}
\pastebutton{ugProblemNumericPageEmpty22}{\showpaste}
\tab{5}\spadcommand{eulerE(3, z)}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch23}
\begin{paste}{ugProblemNumericPageFull23}{ugProblemNumericPageEmpty23}
\pastebutton{ugProblemNumericPageFull23}{\hidepaste}
\tab{5}\spadcommand{eulerE(3, 0.7 + 0.4 * \%i)}
\indentrel{3}\begin{verbatim}
   (23)  - 0.238 - 0.316 %i
                                    Type: Complex Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty23}
\begin{paste}{ugProblemNumericPageEmpty23}{ugProblemNumericPagePatch23}
\pastebutton{ugProblemNumericPageEmpty23}{\showpaste}
\tab{5}\spadcommand{eulerE(3, 0.7 + 0.4 * \%i)}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch24}
\begin{paste}{ugProblemNumericPageFull24}{ugProblemNumericPageEmpty24}
\pastebutton{ugProblemNumericPageFull24}{\hidepaste}
\tab{5}\spadcommand{cyclotomic(3, z)}
\indentrel{3}\begin{verbatim}
          2
   (24)  z  + z + 1
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty24}
\begin{paste}{ugProblemNumericPageEmpty24}{ugProblemNumericPagePatch24}
\pastebutton{ugProblemNumericPageEmpty24}{\showpaste}
\tab{5}\spadcommand{cyclotomic(3, z)}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch25}
\begin{paste}{ugProblemNumericPageFull25}{ugProblemNumericPageEmpty25}
\pastebutton{ugProblemNumericPageFull25}{\hidepaste}
\tab{5}\spadcommand{cyclotomic(3, (-1.0 + 0.0 * \%i)**(2/3))}
\indentrel{3}\begin{verbatim}
   (25)  0.0
                                    Type: Complex Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty25}
\begin{paste}{ugProblemNumericPageEmpty25}{ugProblemNumericPagePatch25}
\pastebutton{ugProblemNumericPageEmpty25}{\showpaste}
\tab{5}\spadcommand{cyclotomic(3, (-1.0 + 0.0 * \%i)**(2/3))}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch26}
\begin{paste}{ugProblemNumericPageFull26}{ugProblemNumericPageEmpty26}
\pastebutton{ugProblemNumericPageFull26}{\hidepaste}
\tab{5}\spadgraph{draw((x,y)+-> real exp complex(x,y), -2..2, -2*\%pi..2*\%pi, colorFunction == (x, y) +-> imag exp complex(x,y), title=="exp(x+\%i*y)", style=="smooth")}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/ugproblemnumericpage26.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/ugproblemnumericpage26}}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty26}
\begin{paste}{ugProblemNumericPageEmpty26}{ugProblemNumericPagePatch26}
\pastebutton{ugProblemNumericPageEmpty26}{\showpaste}
\tab{5}\spadgraph{draw((x,y)+-> real exp complex(x,y), -2..2, -2*\%pi..2*\%pi, colorFunction == (x, y) +-> imag exp complex(x,y), title=="exp(x+\%i*y)", style=="smooth")}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch27}
\begin{paste}{ugProblemNumericPageFull27}{ugProblemNumericPageEmpty27}
\pastebutton{ugProblemNumericPageFull27}{\hidepaste}
\tab{5}\spadgraph{vp := draw((x,y) +-> real atan complex(x,y), -\%pi..\%pi, -\%pi..\%pi, colorFunction==(x,y) +->argument atan complex(x,y), title=="atan(x+\%i*y)", style=="shade"); rotate(vp,-160,-45); vp}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/ugproblemnumericpage27.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/ugproblemnumericpage27}}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty27}
\begin{paste}{ugProblemNumericPageEmpty27}{ugProblemNumericPagePatch27}
\pastebutton{ugProblemNumericPageEmpty27}{\showpaste}
\tab{5}\spadgraph{vp := draw((x,y) +-> real atan complex(x,y), -\%pi..\%pi, -\%pi..\%pi, colorFunction==(x,y) +->argument atan complex(x,y), title=="atan(x+\%i*y)", style=="shade"); rotate(vp,-160,-45); vp}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch28}
\begin{paste}{ugProblemNumericPageFull28}{ugProblemNumericPageEmpty28}
\pastebutton{ugProblemNumericPageFull28}{\hidepaste}
\tab{5}\spadgraph{draw((x,y) +-> max(min(real Gamma complex(x,y),4),-4), -\%pi..\%pi, -\%pi..\%pi, style=="shade", colorFunction == (x,y) +-> argument Gamma complex(x,y), title == "Gamma(x+\%i*y)", var1Steps == 50, var2Steps== 50)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/ugproblemnumericpage28.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/ugproblemnumericpage28}}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty28}
\begin{paste}{ugProblemNumericPageEmpty28}{ugProblemNumericPagePatch28}
\pastebutton{ugProblemNumericPageEmpty28}{\showpaste}
\tab{5}\spadgraph{draw((x,y) +-> max(min(real Gamma complex(x,y),4),-4), -\%pi..\%pi, -\%pi..\%pi, style=="shade", colorFunction == (x,y) +-> argument Gamma complex(x,y), title == "Gamma(x+\%i*y)", var1Steps == 50, var2Steps== 50)}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch29}
\begin{paste}{ugProblemNumericPageFull29}{ugProblemNumericPageEmpty29}
\pastebutton{ugProblemNumericPageFull29}{\hidepaste}
\tab{5}\spadgraph{draw(Beta(x,y)/100, x=-1.6..1.7, y = -1.6..1.7, style=="shade", title=="Beta(x,y)", var1Steps==40, var2Steps==40)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/ugproblemnumericpage29.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/ugproblemnumericpage29}}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty29}
\begin{paste}{ugProblemNumericPageEmpty29}{ugProblemNumericPagePatch29}
\pastebutton{ugProblemNumericPageEmpty29}{\showpaste}
\tab{5}\spadgraph{draw(Beta(x,y)/100, x=-1.6..1.7, y = -1.6..1.7, style=="shade", title=="Beta(x,y)", var1Steps==40, var2Steps==40)}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch30}
\begin{paste}{ugProblemNumericPageFull30}{ugProblemNumericPageEmpty30}
\pastebutton{ugProblemNumericPageFull30}{\hidepaste}
\tab{5}\spadgraph{draw((alpha,x) +-> min(max(besselJ(alpha, x+8), -6), 6), -6..4, -6..6, title=="besselJ(alpha,x)", style=="shade", var1Steps==40, var2Steps==40)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/ugproblemnumericpage30.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/ugproblemnumericpage30}}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty30}
\begin{paste}{ugProblemNumericPageEmpty30}{ugProblemNumericPagePatch30}
\pastebutton{ugProblemNumericPageEmpty30}{\showpaste}
\tab{5}\spadgraph{draw((alpha,x) +-> min(max(besselJ(alpha, x+8), -6), 6), -6..4, -6..6, title=="besselJ(alpha,x)", style=="shade", var1Steps==40, var2Steps==40)}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch31}
\begin{paste}{ugProblemNumericPageFull31}{ugProblemNumericPageEmpty31}
\pastebutton{ugProblemNumericPageFull31}{\hidepaste}
\tab{5}\spadgraph{draw(besselI(alpha, 5), alpha = -12..12, unit==[5,20])}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/ugproblemnumericpage31.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/ugproblemnumericpage31}}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty31}
\begin{paste}{ugProblemNumericPageEmpty31}{ugProblemNumericPagePatch31}
\pastebutton{ugProblemNumericPageEmpty31}{\showpaste}
\tab{5}\spadgraph{draw(besselI(alpha, 5), alpha = -12..12, unit==[5,20])}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch32}
\begin{paste}{ugProblemNumericPageFull32}{ugProblemNumericPageEmpty32}
\pastebutton{ugProblemNumericPageFull32}{\hidepaste}
\tab{5}\spadgraph{draw((x,y) +-> real besselI(complex(x/20, y/20),5), -60..60, -60..60, colorFunction == (x,y)+-> argument besselI(complex(x/20,y/20),5), title=="besselI(x+i*y,5)", style=="shade")}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/ugproblemnumericpage32.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/ugproblemnumericpage32}}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty32}
\begin{paste}{ugProblemNumericPageEmpty32}{ugProblemNumericPagePatch32}
\pastebutton{ugProblemNumericPageEmpty32}{\showpaste}
\tab{5}\spadgraph{draw((x,y) +-> real besselI(complex(x/20, y/20),5), -60..60, -60..60, colorFunction == (x,y)+-> argument besselI(complex(x/20,y/20),5), title=="besselI(x+i*y,5)", style=="shade")}
\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPagePatch33}
\begin{paste}{ugProblemNumericPageFull33}{ugProblemNumericPageEmpty33}
\pastebutton{ugProblemNumericPageFull33}{\hidepaste}
\tab{5}\spadcommand{all}
\indentrel{3}\begin{verbatim}
   (33)  all
                                     Type: Variable all
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemNumericPageEmpty33}
\begin{paste}{ugProblemNumericPageEmpty33}{ugProblemNumericPagePatch33}
\pastebutton{ugProblemNumericPageEmpty33}{\showpaste}
\tab{5}\spadcommand{all}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugProblemFactorPage}{ug08.ht}{Polynomial Factorization}
\pageto{notitle}{ugProblemFactorIntRatPage}
\pageto{notitle}{ugProblemFactorFFPage}
\pageto{notitle}{ugProblemFactorAlgPage}
\pageto{notitle}{ugProblemFactorRatFunPage}
\begin{chunk}{ug08.ht}
\begin{page}{ugProblemFactorPage}{8.2. Polynomial Factorization}
\beginscroll
%
The Axiom polynomial factorization
facilities are available for all polynomial types and a wide variety of
coefficient domains.
Here are some examples.

\beginmenu
    \menudownlink{{8.2.1. Integer and Rational Number Coefficients}}
{ugProblemFactorIntRatPage}
    \menudownlink{{8.2.2. Finite Field Coefficients}}
{ugProblemFactorFFPage}
    \menudownlink{{8.2.3. Simple Algebraic Extension Field Coefficients}}
{ugProblemFactorAlgPage}
    \menudownlink{{8.2.4. Factoring Rational Functions}}
{ugProblemFactorRatFunPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugProblemFactorIntRatPage}{ug08.ht}
{Integer and Rational Number Coefficients}
\begin{chunk}{ug08.ht}
\begin{page}{ugProblemFactorIntRatPage}
{8.2.1. Integer and Rational Number Coefficients}
\beginscroll

\labelSpace{4pc}
\xtc{
Polynomials with integer
coefficients can be be factored.
}{
\spadpaste{v := (4*x**3+2*y**2+1)*(12*x**5-x**3*y+12) \bound{v}}
}
\xtc{
}{
\spadpaste{factor v \free{v}}
}
\xtc{
Also, Axiom can factor polynomials with
rational number coefficients.
}{
\spadpaste{w := (4*x**3+(2/3)*x**2+1)*(12*x**5-(1/2)*x**3+12) \bound{w}}
}
\xtc{
}{
\spadpaste{factor w \free{w}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugProblemFactorIntRatPagePatch1}
\begin{paste}{ugProblemFactorIntRatPageFull1}{ugProblemFactorIntRatPageEmpty1}
\pastebutton{ugProblemFactorIntRatPageFull1}{\hidepaste}
\tab{5}\spadcommand{v := (4*x**3+2*y**2+1)*(12*x**5-x**3*y+12)\bound{v }}
\indentrel{3}\begin{verbatim}
   (1)
         3 3       5       2        6    3        8      5
     - 2x y  + (24x  + 24)y  + (- 4x  - x )y + 48x  + 12x
   + 
        3
     48x  + 12
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemFactorIntRatPageEmpty1}
\begin{paste}{ugProblemFactorIntRatPageEmpty1}{ugProblemFactorIntRatPagePatch1}
\pastebutton{ugProblemFactorIntRatPageEmpty1}{\showpaste}
\tab{5}\spadcommand{v := (4*x**3+2*y**2+1)*(12*x**5-x**3*y+12)\bound{v }}
\end{paste}\end{patch}

\begin{patch}{ugProblemFactorIntRatPagePatch2}
\begin{paste}{ugProblemFactorIntRatPageFull2}{ugProblemFactorIntRatPageEmpty2}
\pastebutton{ugProblemFactorIntRatPageFull2}{\hidepaste}
\tab{5}\spadcommand{factor v\free{v }}
\indentrel{3}\begin{verbatim}
            3       5         2     3
   (2)  - (x y - 12x  - 12)(2y  + 4x  + 1)
                      Type: Factored Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemFactorIntRatPageEmpty2}
\begin{paste}{ugProblemFactorIntRatPageEmpty2}{ugProblemFactorIntRatPagePatch2}
\pastebutton{ugProblemFactorIntRatPageEmpty2}{\showpaste}
\tab{5}\spadcommand{factor v\free{v }}
\end{paste}\end{patch}

\begin{patch}{ugProblemFactorIntRatPagePatch3}
\begin{paste}{ugProblemFactorIntRatPageFull3}{ugProblemFactorIntRatPageEmpty3}
\pastebutton{ugProblemFactorIntRatPageFull3}{\hidepaste}
\tab{5}\spadcommand{w := (4*x**3+(2/3)*x**2+1)*(12*x**5-(1/2)*x**3+12)\bound{w }}
\indentrel{3}\begin{verbatim}
           8     7     6   35  5   95  3     2
   (3)  48x  + 8x  - 2x  + ÄÄ x  + ÄÄ x  + 8x  + 12
                            3       2
                      Type: Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemFactorIntRatPageEmpty3}
\begin{paste}{ugProblemFactorIntRatPageEmpty3}{ugProblemFactorIntRatPagePatch3}
\pastebutton{ugProblemFactorIntRatPageEmpty3}{\showpaste}
\tab{5}\spadcommand{w := (4*x**3+(2/3)*x**2+1)*(12*x**5-(1/2)*x**3+12)\bound{w }}
\end{paste}\end{patch}

\begin{patch}{ugProblemFactorIntRatPagePatch4}
\begin{paste}{ugProblemFactorIntRatPageFull4}{ugProblemFactorIntRatPageEmpty4}
\pastebutton{ugProblemFactorIntRatPageFull4}{\hidepaste}
\tab{5}\spadcommand{factor w\free{w }}
\indentrel{3}\begin{verbatim}
            3   1  2   1   5    1  3
   (4)  48(x  + Ä x  + Ä)(x  - ÄÄ x  + 1)
                6      4       24
             Type: Factored Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemFactorIntRatPageEmpty4}
\begin{paste}{ugProblemFactorIntRatPageEmpty4}{ugProblemFactorIntRatPagePatch4}
\pastebutton{ugProblemFactorIntRatPageEmpty4}{\showpaste}
\tab{5}\spadcommand{factor w\free{w }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugProblemFactorFFPage}{ug08.ht}{Finite Field Coefficients}
\pageto{notitle}{ugProblemFinitePage}
\begin{chunk}{ug08.ht}
\begin{page}{ugProblemFactorFFPage}{8.2.2. Finite Field Coefficients}
\beginscroll

Polynomials with coefficients in a finite field
can be also be factored.

\labelSpace{3pc}
\xtc{
}{
\spadpaste{u : POLY(PF(19)) :=3*x**4+2*x**2+15*x+18 \bound{u}}
}
\xtc{
These include the integers mod \axiom{p}, where \axiom{p} is prime, and
extensions of these fields.
}{
\spadpaste{factor u \free{u}}
}
\xtc{
Convert this to have coefficients in the finite field with
\texht{$19^3$}{\axiom{19**3}} elements.  See
\downlink{``Finite Fields''}{ugProblemFinitePage} in Section
8.11\ignore{ugProblemFinite} for more information
about finite fields.
}{
\spadpaste{factor(u :: POLY FFX(PF 19,3)) \free{u}}
}
%

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugProblemFactorFFPagePatch1}
\begin{paste}{ugProblemFactorFFPageFull1}{ugProblemFactorFFPageEmpty1}
\pastebutton{ugProblemFactorFFPageFull1}{\hidepaste}
\tab{5}\spadcommand{u : POLY(PF(19)) :=3*x**4+2*x**2+15*x+18\bound{u }}
\indentrel{3}\begin{verbatim}
          4     2
   (1)  3x  + 2x  + 15x + 18
                         Type: Polynomial PrimeField 19
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemFactorFFPageEmpty1}
\begin{paste}{ugProblemFactorFFPageEmpty1}{ugProblemFactorFFPagePatch1}
\pastebutton{ugProblemFactorFFPageEmpty1}{\showpaste}
\tab{5}\spadcommand{u : POLY(PF(19)) :=3*x**4+2*x**2+15*x+18\bound{u }}
\end{paste}\end{patch}

\begin{patch}{ugProblemFactorFFPagePatch2}
\begin{paste}{ugProblemFactorFFPageFull2}{ugProblemFactorFFPageEmpty2}
\pastebutton{ugProblemFactorFFPageFull2}{\hidepaste}
\tab{5}\spadcommand{factor u\free{u }}
\indentrel{3}\begin{verbatim}
                   3    2
   (2)  3(x + 18)(x  + x  + 8x + 13)
                Type: Factored Polynomial PrimeField 19
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemFactorFFPageEmpty2}
\begin{paste}{ugProblemFactorFFPageEmpty2}{ugProblemFactorFFPagePatch2}
\pastebutton{ugProblemFactorFFPageEmpty2}{\showpaste}
\tab{5}\spadcommand{factor u\free{u }}
\end{paste}\end{patch}

\begin{patch}{ugProblemFactorFFPagePatch3}
\begin{paste}{ugProblemFactorFFPageFull3}{ugProblemFactorFFPageEmpty3}
\pastebutton{ugProblemFactorFFPageFull3}{\hidepaste}
\tab{5}\spadcommand{factor(u :: POLY FFX(PF 19,3))\free{u }}
\indentrel{3}\begin{verbatim}
   (3)
                       2
     3(x + 18)(x + 5%BC  + 3%BC + 13)
  *
               2                        2
     (x + 16%BC  + 14%BC + 13)(x + 17%BC  + 2%BC + 13)
Type: Factored Polynomial FiniteFieldExtension(PrimeField 19,3)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemFactorFFPageEmpty3}
\begin{paste}{ugProblemFactorFFPageEmpty3}{ugProblemFactorFFPagePatch3}
\pastebutton{ugProblemFactorFFPageEmpty3}{\showpaste}
\tab{5}\spadcommand{factor(u :: POLY FFX(PF 19,3))\free{u }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugProblemFactorAlgPage}{ug08.ht}
{Simple Algebraic Extension Field Coefficients}
\begin{chunk}{ug08.ht}
\begin{page}{ugProblemFactorAlgPage}
{8.2.3. Simple Algebraic Extension Field Coefficients}
\beginscroll

Polynomials with coefficients in simple algebraic extensions
of the rational numbers can be factored.

\labelSpace{2pc}
\xtc{
Here, \axiom{aa} and \axiom{bb} are symbolic roots of polynomials.
}{
\spadpaste{aa := rootOf(aa**2+aa+1) \bound{aa}}
}
\xtc{
}{
\spadpaste{p:=(x**3+aa**2*x+y)*(aa*x**2+aa*x+aa*y**2)**2 
\free{aa}\bound{p}}
}
\xtc{
Note that the second argument to factor can be a list of
algebraic extensions to factor over.
}{
\spadpaste{factor(p,[aa]) \free{p aa}}
}
\xtc{
This factors \axiom{x**2+3} over the integers.
}{
\spadpaste{factor(x**2+3)}
}
\xtc{
Factor the same polynomial over the field obtained by adjoining
\axiom{aa} to the rational numbers.
}{
\spadpaste{factor(x**2+3,[aa]) \free{aa}}
}
\xtc{
Factor \axiom{x**6+108} over the same field.
}{
\spadpaste{factor(x**6+108,[aa]) \free{aa}}
}
\xtc{
}{
\spadpaste{bb:=rootOf(bb**3-2) \bound{bb}}
}
\xtc{
}{
\spadpaste{factor(x**6+108,[bb]) \free{bb}}
}
\xtc{
Factor again over the field obtained by adjoining both \axiom{aa}
and \axiom{bb} to the rational numbers.
}{
\spadpaste{factor(x**6+108,[aa,bb]) \free{aa bb}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugProblemFactorAlgPagePatch1}
\begin{paste}{ugProblemFactorAlgPageFull1}{ugProblemFactorAlgPageEmpty1}
\pastebutton{ugProblemFactorAlgPageFull1}{\hidepaste}
\tab{5}\spadcommand{aa := rootOf(aa**2+aa+1)\bound{aa }}
\indentrel{3}\begin{verbatim}
   (1)  aa
                                  Type: AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemFactorAlgPageEmpty1}
\begin{paste}{ugProblemFactorAlgPageEmpty1}{ugProblemFactorAlgPagePatch1}
\pastebutton{ugProblemFactorAlgPageEmpty1}{\showpaste}
\tab{5}\spadcommand{aa := rootOf(aa**2+aa+1)\bound{aa }}
\end{paste}\end{patch}

\begin{patch}{ugProblemFactorAlgPagePatch2}
\begin{paste}{ugProblemFactorAlgPageFull2}{ugProblemFactorAlgPageEmpty2}
\pastebutton{ugProblemFactorAlgPageFull2}{\hidepaste}
\tab{5}\spadcommand{p:=(x**3+aa**2*x+y)*(aa*x**2+aa*x+aa*y**2)**2\free{aa }\bound{p }}
\indentrel{3}\begin{verbatim}
   (2)
                5               3         4
     (- aa - 1)y  + ((- aa - 1)x  + aa x)y
   + 
                  2                 3
     ((- 2aa - 2)x  + (- 2aa - 2)x)y
   + 
                  5               4        3        2  2
     ((- 2aa - 2)x  + (- 2aa - 2)x  + 2aa x  + 2aa x )y
   + 
                 4               3              2
     ((- aa - 1)x  + (- 2aa - 2)x  + (- aa - 1)x )y
   + 
                7               6    5        4       3
     (- aa - 1)x  + (- 2aa - 2)x  - x  + 2aa x  + aa x
                       Type: Polynomial AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemFactorAlgPageEmpty2}
\begin{paste}{ugProblemFactorAlgPageEmpty2}{ugProblemFactorAlgPagePatch2}
\pastebutton{ugProblemFactorAlgPageEmpty2}{\showpaste}
\tab{5}\spadcommand{p:=(x**3+aa**2*x+y)*(aa*x**2+aa*x+aa*y**2)**2\free{aa }\bound{p }}
\end{paste}\end{patch}

\begin{patch}{ugProblemFactorAlgPagePatch3}
\begin{paste}{ugProblemFactorAlgPageFull3}{ugProblemFactorAlgPageEmpty3}
\pastebutton{ugProblemFactorAlgPageFull3}{\hidepaste}
\tab{5}\spadcommand{factor(p,[aa])\free{p aa }}
\indentrel{3}\begin{verbatim}
                        3                 2    2     2
   (3)  (- aa - 1)(y + x  + (- aa - 1)x)(y  + x  + x)
              Type: Factored Polynomial AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemFactorAlgPageEmpty3}
\begin{paste}{ugProblemFactorAlgPageEmpty3}{ugProblemFactorAlgPagePatch3}
\pastebutton{ugProblemFactorAlgPageEmpty3}{\showpaste}
\tab{5}\spadcommand{factor(p,[aa])\free{p aa }}
\end{paste}\end{patch}

\begin{patch}{ugProblemFactorAlgPagePatch4}
\begin{paste}{ugProblemFactorAlgPageFull4}{ugProblemFactorAlgPageEmpty4}
\pastebutton{ugProblemFactorAlgPageFull4}{\hidepaste}
\tab{5}\spadcommand{factor(x**2+3)}
\indentrel{3}\begin{verbatim}
         2
   (4)  x  + 3
                      Type: Factored Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemFactorAlgPageEmpty4}
\begin{paste}{ugProblemFactorAlgPageEmpty4}{ugProblemFactorAlgPagePatch4}
\pastebutton{ugProblemFactorAlgPageEmpty4}{\showpaste}
\tab{5}\spadcommand{factor(x**2+3)}
\end{paste}\end{patch}

\begin{patch}{ugProblemFactorAlgPagePatch5}
\begin{paste}{ugProblemFactorAlgPageFull5}{ugProblemFactorAlgPageEmpty5}
\pastebutton{ugProblemFactorAlgPageFull5}{\hidepaste}
\tab{5}\spadcommand{factor(x**2+3,[aa])\free{aa }}
\indentrel{3}\begin{verbatim}
   (5)  (x - 2aa - 1)(x + 2aa + 1)
              Type: Factored Polynomial AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemFactorAlgPageEmpty5}
\begin{paste}{ugProblemFactorAlgPageEmpty5}{ugProblemFactorAlgPagePatch5}
\pastebutton{ugProblemFactorAlgPageEmpty5}{\showpaste}
\tab{5}\spadcommand{factor(x**2+3,[aa])\free{aa }}
\end{paste}\end{patch}

\begin{patch}{ugProblemFactorAlgPagePatch6}
\begin{paste}{ugProblemFactorAlgPageFull6}{ugProblemFactorAlgPageEmpty6}
\pastebutton{ugProblemFactorAlgPageFull6}{\hidepaste}
\tab{5}\spadcommand{factor(x**6+108,[aa])\free{aa }}
\indentrel{3}\begin{verbatim}
          3              3
   (6)  (x  - 12aa - 6)(x  + 12aa + 6)
              Type: Factored Polynomial AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemFactorAlgPageEmpty6}
\begin{paste}{ugProblemFactorAlgPageEmpty6}{ugProblemFactorAlgPagePatch6}
\pastebutton{ugProblemFactorAlgPageEmpty6}{\showpaste}
\tab{5}\spadcommand{factor(x**6+108,[aa])\free{aa }}
\end{paste}\end{patch}

\begin{patch}{ugProblemFactorAlgPagePatch7}
\begin{paste}{ugProblemFactorAlgPageFull7}{ugProblemFactorAlgPageEmpty7}
\pastebutton{ugProblemFactorAlgPageFull7}{\hidepaste}
\tab{5}\spadcommand{bb:=rootOf(bb**3-2)\bound{bb }}
\indentrel{3}\begin{verbatim}
   (7)  bb
                                  Type: AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemFactorAlgPageEmpty7}
\begin{paste}{ugProblemFactorAlgPageEmpty7}{ugProblemFactorAlgPagePatch7}
\pastebutton{ugProblemFactorAlgPageEmpty7}{\showpaste}
\tab{5}\spadcommand{bb:=rootOf(bb**3-2)\bound{bb }}
\end{paste}\end{patch}

\begin{patch}{ugProblemFactorAlgPagePatch8}
\begin{paste}{ugProblemFactorAlgPageFull8}{ugProblemFactorAlgPageEmpty8}
\pastebutton{ugProblemFactorAlgPageFull8}{\hidepaste}
\tab{5}\spadcommand{factor(x**6+108,[bb])\free{bb }}
\indentrel{3}\begin{verbatim}
   (8)
     2              2   2      2   2              2
   (x  - 3bb x + 3bb )(x  + 3bb )(x  + 3bb x + 3bb )
              Type: Factored Polynomial AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemFactorAlgPageEmpty8}
\begin{paste}{ugProblemFactorAlgPageEmpty8}{ugProblemFactorAlgPagePatch8}
\pastebutton{ugProblemFactorAlgPageEmpty8}{\showpaste}
\tab{5}\spadcommand{factor(x**6+108,[bb])\free{bb }}
\end{paste}\end{patch}

\begin{patch}{ugProblemFactorAlgPagePatch9}
\begin{paste}{ugProblemFactorAlgPageFull9}{ugProblemFactorAlgPageEmpty9}
\pastebutton{ugProblemFactorAlgPageFull9}{\hidepaste}
\tab{5}\spadcommand{factor(x**6+108,[aa,bb])\free{aa bb }}
\indentrel{3}\begin{verbatim}
   (9)
     (x + (- 2aa - 1)bb)(x + (- aa - 2)bb)
  *
     (x + (- aa + 1)bb)(x + (aa - 1)bb)(x + (aa + 2)bb)
  *
     (x + (2aa + 1)bb)
              Type: Factored Polynomial AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemFactorAlgPageEmpty9}
\begin{paste}{ugProblemFactorAlgPageEmpty9}{ugProblemFactorAlgPagePatch9}
\pastebutton{ugProblemFactorAlgPageEmpty9}{\showpaste}
\tab{5}\spadcommand{factor(x**6+108,[aa,bb])\free{aa bb }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugProblemFactorRatFunPage}{ug08.ht}
{Factoring Rational Functions}
\begin{chunk}{ug08.ht}
\begin{page}{ugProblemFactorRatFunPage}
{8.2.4. Factoring Rational Functions}
\beginscroll

Since fractions of polynomials form a field, every element (other than
zero) divides any other, so there is no useful notion of irreducible
factors.  Thus the \axiomFun{factor} operation is not very useful for
fractions of polynomials.

\xtc{
There is, instead, a specific operation \axiomFun{factorFraction}
that separately factors the numerator and denominator and returns
a fraction of the factored results.
}{
\spadpaste{factorFraction((x**2-4)/(y**2-4))}
}
\xtc{
You can also use \axiomFun{map}. This expression
applies the \axiomFun{factor} operation
to the numerator and denominator.
}{
\spadpaste{map(factor,(x**2-4)/(y**2-4))}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugProblemFactorRatFunPagePatch1}
\begin{paste}{ugProblemFactorRatFunPageFull1}{ugProblemFactorRatFunPageEmpty1}
\pastebutton{ugProblemFactorRatFunPageFull1}{\hidepaste}
\tab{5}\spadcommand{factorFraction((x**2-4)/(y**2-4))}
\indentrel{3}\begin{verbatim}
        (x - 2)(x + 2)
   (1)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
        (y - 2)(y + 2)
             Type: Fraction Factored Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemFactorRatFunPageEmpty1}
\begin{paste}{ugProblemFactorRatFunPageEmpty1}{ugProblemFactorRatFunPagePatch1}
\pastebutton{ugProblemFactorRatFunPageEmpty1}{\showpaste}
\tab{5}\spadcommand{factorFraction((x**2-4)/(y**2-4))}
\end{paste}\end{patch}

\begin{patch}{ugProblemFactorRatFunPagePatch2}
\begin{paste}{ugProblemFactorRatFunPageFull2}{ugProblemFactorRatFunPageEmpty2}
\pastebutton{ugProblemFactorRatFunPageFull2}{\hidepaste}
\tab{5}\spadcommand{map(factor,(x**2-4)/(y**2-4))}
\indentrel{3}\begin{verbatim}
        (x - 2)(x + 2)
   (2)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
        (y - 2)(y + 2)
             Type: Fraction Factored Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemFactorRatFunPageEmpty2}
\begin{paste}{ugProblemFactorRatFunPageEmpty2}{ugProblemFactorRatFunPagePatch2}
\pastebutton{ugProblemFactorRatFunPageEmpty2}{\showpaste}
\tab{5}\spadcommand{map(factor,(x**2-4)/(y**2-4))}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugProblemSymRootPage}{ug08.ht}
{Manipulating Symbolic Roots of a Polynomial}
\pageto{notitle}{ugxProblemOnePolPage}
\pageto{notitle}{ugxProblemPolSysPage}
\pageto{notitle}{ugxProblemSymRootOnePage}
\pageto{notitle}{ugxProblemSymRootAllPage}
\begin{chunk}{ug08.ht}
\begin{page}{ugProblemSymRootPage}
{8.3. Manipulating Symbolic Roots of a Polynomial}
\beginscroll
%
In this section we show you how to work with one root or all roots
of a polynomial.
These roots are represented symbolically (as opposed to being
numeric approximations).
See \downlink{``Solution of a Single Polynomial Equation''}
{ugxProblemOnePolPage} 
in Section 8.5.2\ignore{ugxProblemOnePol} and 
\downlink{``Solution of Systems of Polynomial Equations''}
{ugxProblemPolSysPage} in 
Section 8.5.3\ignore{ugxProblemPolSys} for
information about solving for the roots of one or more
polynomials.

\beginmenu
    \menudownlink{{8.3.1. Using a Single Root of a Polynomial}}
{ugxProblemSymRootOnePage}
    \menudownlink{{8.3.2. Using All Roots of a Polynomial}}
{ugxProblemSymRootAllPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugxProblemSymRootOnePage}{ug08.ht}
{Using a Single Root of a Polynomial}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemSymRootOnePage}
{8.3.1. Using a Single Root of a Polynomial}
\beginscroll

Use \axiomFun{rootOf} to get a symbolic root of a polynomial:
\axiom{rootOf(p, x)} returns a root of \axiom{p(x)}.

\labelSpace{2pc}
\xtc{
This creates an algebraic number \axiom{a}.
}{
\spadpaste{a := rootOf(a**4+1,a) \bound{a}}
}
\xtc{
To find the algebraic relation that defines \axiom{a},
use \axiomFun{definingPolynomial}.
}{
\spadpaste{definingPolynomial a \free{a}}
}
\xtc{
You can use \axiom{a} in any further expression,
including a nested \axiomFun{rootOf}.
}{
\spadpaste{b := rootOf(b**2-a-1,b) \free{a}\bound{b}}
}
\xtc{
Higher powers of the roots are automatically reduced during
calculations.
}{
\spadpaste{a + b \free{a b}\bound{c}}
}
\xtc{
}{
\spadpaste{\% ** 5 \free{c}}
}
\xtc{
The operation \axiomFun{zeroOf} is similar to \axiomFun{rootOf},
except that it may express the root using radicals in some cases.
}{
\spadpaste{rootOf(c**2+c+1,c)}
}
\xtc{
}{
\spadpaste{zeroOf(d**2+d+1,d)}
}
\xtc{
}{
\spadpaste{rootOf(e**5-2,e)}
}
\xtc{
}{
\spadpaste{zeroOf(f**5-2,f)}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxProblemSymRootOnePagePatch1}
\begin{paste}{ugxProblemSymRootOnePageFull1}{ugxProblemSymRootOnePageEmpty1}
\pastebutton{ugxProblemSymRootOnePageFull1}{\hidepaste}
\tab{5}\spadcommand{a := rootOf(a**4+1,a)\bound{a }}
\indentrel{3}\begin{verbatim}
   (1)  a
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootOnePageEmpty1}
\begin{paste}{ugxProblemSymRootOnePageEmpty1}{ugxProblemSymRootOnePagePatch1}
\pastebutton{ugxProblemSymRootOnePageEmpty1}{\showpaste}
\tab{5}\spadcommand{a := rootOf(a**4+1,a)\bound{a }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootOnePagePatch2}
\begin{paste}{ugxProblemSymRootOnePageFull2}{ugxProblemSymRootOnePageEmpty2}
\pastebutton{ugxProblemSymRootOnePageFull2}{\hidepaste}
\tab{5}\spadcommand{definingPolynomial a\free{a }}
\indentrel{3}\begin{verbatim}
         4
   (2)  a  + 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootOnePageEmpty2}
\begin{paste}{ugxProblemSymRootOnePageEmpty2}{ugxProblemSymRootOnePagePatch2}
\pastebutton{ugxProblemSymRootOnePageEmpty2}{\showpaste}
\tab{5}\spadcommand{definingPolynomial a\free{a }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootOnePagePatch3}
\begin{paste}{ugxProblemSymRootOnePageFull3}{ugxProblemSymRootOnePageEmpty3}
\pastebutton{ugxProblemSymRootOnePageFull3}{\hidepaste}
\tab{5}\spadcommand{b := rootOf(b**2-a-1,b)\free{a }\bound{b }}
\indentrel{3}\begin{verbatim}
   (3)  b
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootOnePageEmpty3}
\begin{paste}{ugxProblemSymRootOnePageEmpty3}{ugxProblemSymRootOnePagePatch3}
\pastebutton{ugxProblemSymRootOnePageEmpty3}{\showpaste}
\tab{5}\spadcommand{b := rootOf(b**2-a-1,b)\free{a }\bound{b }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootOnePagePatch4}
\begin{paste}{ugxProblemSymRootOnePageFull4}{ugxProblemSymRootOnePageEmpty4}
\pastebutton{ugxProblemSymRootOnePageFull4}{\hidepaste}
\tab{5}\spadcommand{a + b\free{a b }\bound{c }}
\indentrel{3}\begin{verbatim}
   (4)  b + a
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootOnePageEmpty4}
\begin{paste}{ugxProblemSymRootOnePageEmpty4}{ugxProblemSymRootOnePagePatch4}
\pastebutton{ugxProblemSymRootOnePageEmpty4}{\showpaste}
\tab{5}\spadcommand{a + b\free{a b }\bound{c }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootOnePagePatch5}
\begin{paste}{ugxProblemSymRootOnePageFull5}{ugxProblemSymRootOnePageEmpty5}
\pastebutton{ugxProblemSymRootOnePageFull5}{\hidepaste}
\tab{5}\spadcommand{\% ** 5\free{c }}
\indentrel{3}\begin{verbatim}
            3      2                 3      2
   (5)  (10a  + 11a  + 2a - 4)b + 15a  + 10a  + 4a - 10
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootOnePageEmpty5}
\begin{paste}{ugxProblemSymRootOnePageEmpty5}{ugxProblemSymRootOnePagePatch5}
\pastebutton{ugxProblemSymRootOnePageEmpty5}{\showpaste}
\tab{5}\spadcommand{\% ** 5\free{c }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootOnePagePatch6}
\begin{paste}{ugxProblemSymRootOnePageFull6}{ugxProblemSymRootOnePageEmpty6}
\pastebutton{ugxProblemSymRootOnePageFull6}{\hidepaste}
\tab{5}\spadcommand{rootOf(c**2+c+1,c)}
\indentrel{3}\begin{verbatim}
   (6)  c
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootOnePageEmpty6}
\begin{paste}{ugxProblemSymRootOnePageEmpty6}{ugxProblemSymRootOnePagePatch6}
\pastebutton{ugxProblemSymRootOnePageEmpty6}{\showpaste}
\tab{5}\spadcommand{rootOf(c**2+c+1,c)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootOnePagePatch7}
\begin{paste}{ugxProblemSymRootOnePageFull7}{ugxProblemSymRootOnePageEmpty7}
\pastebutton{ugxProblemSymRootOnePageFull7}{\hidepaste}
\tab{5}\spadcommand{zeroOf(d**2+d+1,d)}
\indentrel{3}\begin{verbatim}
         ÚÄÄÄ¿
        \³- 3  - 1
   (7)  ÄÄÄÄÄÄÄÄÄÄ
             2
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootOnePageEmpty7}
\begin{paste}{ugxProblemSymRootOnePageEmpty7}{ugxProblemSymRootOnePagePatch7}
\pastebutton{ugxProblemSymRootOnePageEmpty7}{\showpaste}
\tab{5}\spadcommand{zeroOf(d**2+d+1,d)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootOnePagePatch8}
\begin{paste}{ugxProblemSymRootOnePageFull8}{ugxProblemSymRootOnePageEmpty8}
\pastebutton{ugxProblemSymRootOnePageFull8}{\hidepaste}
\tab{5}\spadcommand{rootOf(e**5-2,e)}
\indentrel{3}\begin{verbatim}
   (8)  e
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootOnePageEmpty8}
\begin{paste}{ugxProblemSymRootOnePageEmpty8}{ugxProblemSymRootOnePagePatch8}
\pastebutton{ugxProblemSymRootOnePageEmpty8}{\showpaste}
\tab{5}\spadcommand{rootOf(e**5-2,e)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootOnePagePatch9}
\begin{paste}{ugxProblemSymRootOnePageFull9}{ugxProblemSymRootOnePageEmpty9}
\pastebutton{ugxProblemSymRootOnePageFull9}{\hidepaste}
\tab{5}\spadcommand{zeroOf(f**5-2,f)}
\indentrel{3}\begin{verbatim}
        5ÚÄ¿
   (9)  \³2
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootOnePageEmpty9}
\begin{paste}{ugxProblemSymRootOnePageEmpty9}{ugxProblemSymRootOnePagePatch9}
\pastebutton{ugxProblemSymRootOnePageEmpty9}{\showpaste}
\tab{5}\spadcommand{zeroOf(f**5-2,f)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxProblemSymRootAllPage}{ug08.ht}
{Using All Roots of a Polynomial}
\pageto{notitle}{ugxProblemOnePolPage}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemSymRootAllPage}
{8.3.2. Using All Roots of a Polynomial}
\beginscroll

Use \axiomFun{rootsOf} to get all symbolic roots of a polynomial:
\axiom{rootsOf(p, x)} returns a
list of all the roots of \axiom{p(x)}.
If \axiom{p(x)} has a multiple root of order \axiom{n}, then that root
appears \axiom{n} times in the list.
\texht{\typeout{Make sure these variables are x0 etc}}{}

\xtc{
Compute all the roots of \axiom{x**4 + 1}.
}{
\spadpaste{l := rootsOf(x**4+1,x) \bound{l}}
}
\xtc{
As a side effect, the variables \axiom{\%x0, \%x1} and \axiom{\%x2} 
are bound to the first three roots of \axiom{x**4+1}.
}{
\spadpaste{\%x0**5 \free{l}}
}
\xtc{
Although they all satisfy \axiom{x**4 + 1 = 0, \%x0, \%x1,}
and \axiom{\%x2} are different algebraic numbers.
To find the algebraic relation that defines each of them,
use \axiomFun{definingPolynomial}.
}{
\spadpaste{definingPolynomial \%x0 \free{l}}
}
\xtc{
}{
\spadpaste{definingPolynomial \%x1 \free{l}}
}
\xtc{
}{
\spadpaste{definingPolynomial \%x2 \free{l}}
}
\xtc{
We can check that the sum and product of the roots of \axiom{x**4+1} are
its trace and norm.
}{
\spadpaste{x3 := last l \free{l} \bound{x3}}
}
\xtc{
}{
\spadpaste{\%x0 + \%x1 + \%x2 + x3 \free{x3}}
}
\xtc{
}{
\spadpaste{\%x0 * \%x1 * \%x2 * x3 \free{x3}}
}
\xtc{
Corresponding to the pair of operations
\axiomFun{rootOf}/\axiomFun{zeroOf} in
\downlink{``Solution of a Single Polynomial Equation''}
{ugxProblemOnePolPage} in Section
8.5.2\ignore{ugxProblemOnePol}, there is an
operation \axiomFun{zerosOf} that, like \axiomFun{rootsOf}, computes
all the roots of a given polynomial, but which expresses some of them
in terms of radicals.
}{
\spadpaste{zerosOf(y**4+1,y) \bound{z}}
}
\xtc{
As you see, only one implicit algebraic number was created
(\axiom{\%y1}), and its defining equation is this.
The other three roots are expressed in radicals.
}{
\spadpaste{definingPolynomial \%y1 \free{z}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxProblemSymRootAllPagePatch1}
\begin{paste}{ugxProblemSymRootAllPageFull1}{ugxProblemSymRootAllPageEmpty1}
\pastebutton{ugxProblemSymRootAllPageFull1}{\hidepaste}
\tab{5}\spadcommand{l := rootsOf(x**4+1,x)\bound{l }}
\indentrel{3}\begin{verbatim}
   (1)  [%x0,%x0 %x1,- %x0,- %x0 %x1]
                          Type: List Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootAllPageEmpty1}
\begin{paste}{ugxProblemSymRootAllPageEmpty1}{ugxProblemSymRootAllPagePatch1}
\pastebutton{ugxProblemSymRootAllPageEmpty1}{\showpaste}
\tab{5}\spadcommand{l := rootsOf(x**4+1,x)\bound{l }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootAllPagePatch2}
\begin{paste}{ugxProblemSymRootAllPageFull2}{ugxProblemSymRootAllPageEmpty2}
\pastebutton{ugxProblemSymRootAllPageFull2}{\hidepaste}
\tab{5}\spadcommand{\%x0**5\free{l }}
\indentrel{3}\begin{verbatim}
   (2)  - %x0
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootAllPageEmpty2}
\begin{paste}{ugxProblemSymRootAllPageEmpty2}{ugxProblemSymRootAllPagePatch2}
\pastebutton{ugxProblemSymRootAllPageEmpty2}{\showpaste}
\tab{5}\spadcommand{\%x0**5\free{l }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootAllPagePatch3}
\begin{paste}{ugxProblemSymRootAllPageFull3}{ugxProblemSymRootAllPageEmpty3}
\pastebutton{ugxProblemSymRootAllPageFull3}{\hidepaste}
\tab{5}\spadcommand{definingPolynomial \%x0\free{l }}
\indentrel{3}\begin{verbatim}
           4
   (3)  %x0  + 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootAllPageEmpty3}
\begin{paste}{ugxProblemSymRootAllPageEmpty3}{ugxProblemSymRootAllPagePatch3}
\pastebutton{ugxProblemSymRootAllPageEmpty3}{\showpaste}
\tab{5}\spadcommand{definingPolynomial \%x0\free{l }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootAllPagePatch4}
\begin{paste}{ugxProblemSymRootAllPageFull4}{ugxProblemSymRootAllPageEmpty4}
\pastebutton{ugxProblemSymRootAllPageFull4}{\hidepaste}
\tab{5}\spadcommand{definingPolynomial \%x1\free{l }}
\indentrel{3}\begin{verbatim}
           2
   (4)  %x1  + 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootAllPageEmpty4}
\begin{paste}{ugxProblemSymRootAllPageEmpty4}{ugxProblemSymRootAllPagePatch4}
\pastebutton{ugxProblemSymRootAllPageEmpty4}{\showpaste}
\tab{5}\spadcommand{definingPolynomial \%x1\free{l }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootAllPagePatch5}
\begin{paste}{ugxProblemSymRootAllPageFull5}{ugxProblemSymRootAllPageEmpty5}
\pastebutton{ugxProblemSymRootAllPageFull5}{\hidepaste}
\tab{5}\spadcommand{definingPolynomial \%x2\free{l }}
\indentrel{3}\begin{verbatim}
   (5)  - %x2 + %%var
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootAllPageEmpty5}
\begin{paste}{ugxProblemSymRootAllPageEmpty5}{ugxProblemSymRootAllPagePatch5}
\pastebutton{ugxProblemSymRootAllPageEmpty5}{\showpaste}
\tab{5}\spadcommand{definingPolynomial \%x2\free{l }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootAllPagePatch6}
\begin{paste}{ugxProblemSymRootAllPageFull6}{ugxProblemSymRootAllPageEmpty6}
\pastebutton{ugxProblemSymRootAllPageFull6}{\hidepaste}
\tab{5}\spadcommand{x3 := last l\free{l }\bound{x3 }}
\indentrel{3}\begin{verbatim}
   (6)  - %x0 %x1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootAllPageEmpty6}
\begin{paste}{ugxProblemSymRootAllPageEmpty6}{ugxProblemSymRootAllPagePatch6}
\pastebutton{ugxProblemSymRootAllPageEmpty6}{\showpaste}
\tab{5}\spadcommand{x3 := last l\free{l }\bound{x3 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootAllPagePatch7}
\begin{paste}{ugxProblemSymRootAllPageFull7}{ugxProblemSymRootAllPageEmpty7}
\pastebutton{ugxProblemSymRootAllPageFull7}{\hidepaste}
\tab{5}\spadcommand{\%x0 + \%x1 + \%x2 + x3\free{x3 }}
\indentrel{3}\begin{verbatim}
   (7)  (- %x0 + 1)%x1 + %x0 + %x2
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootAllPageEmpty7}
\begin{paste}{ugxProblemSymRootAllPageEmpty7}{ugxProblemSymRootAllPagePatch7}
\pastebutton{ugxProblemSymRootAllPageEmpty7}{\showpaste}
\tab{5}\spadcommand{\%x0 + \%x1 + \%x2 + x3\free{x3 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootAllPagePatch8}
\begin{paste}{ugxProblemSymRootAllPageFull8}{ugxProblemSymRootAllPageEmpty8}
\pastebutton{ugxProblemSymRootAllPageFull8}{\hidepaste}
\tab{5}\spadcommand{\%x0 * \%x1 * \%x2 * x3\free{x3 }}
\indentrel{3}\begin{verbatim}
               2
   (8)  %x2 %x0
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootAllPageEmpty8}
\begin{paste}{ugxProblemSymRootAllPageEmpty8}{ugxProblemSymRootAllPagePatch8}
\pastebutton{ugxProblemSymRootAllPageEmpty8}{\showpaste}
\tab{5}\spadcommand{\%x0 * \%x1 * \%x2 * x3\free{x3 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootAllPagePatch9}
\begin{paste}{ugxProblemSymRootAllPageFull9}{ugxProblemSymRootAllPageEmpty9}
\pastebutton{ugxProblemSymRootAllPageFull9}{\hidepaste}
\tab{5}\spadcommand{zerosOf(y**4+1,y)\bound{z }}
\indentrel{3}\begin{verbatim}
   (9)
     ÚÄÄÄ¿      ÚÄÄÄ¿        ÚÄÄÄ¿        ÚÄÄÄ¿
    \³- 1  + 1 \³- 1  - 1 - \³- 1  - 1 - \³- 1  + 1
   [ÄÄÄÄÄÄÄÄÄÄ,ÄÄÄÄÄÄÄÄÄÄ,ÄÄÄÄÄÄÄÄÄÄÄÄ,ÄÄÄÄÄÄÄÄÄÄÄÄ]
        ÚÄ¿        ÚÄ¿         ÚÄ¿          ÚÄ¿
       \³2        \³2         \³2          \³2
                          Type: List Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootAllPageEmpty9}
\begin{paste}{ugxProblemSymRootAllPageEmpty9}{ugxProblemSymRootAllPagePatch9}
\pastebutton{ugxProblemSymRootAllPageEmpty9}{\showpaste}
\tab{5}\spadcommand{zerosOf(y**4+1,y)\bound{z }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootAllPagePatch10}
\begin{paste}{ugxProblemSymRootAllPageFull10}{ugxProblemSymRootAllPageEmpty10}
\pastebutton{ugxProblemSymRootAllPageFull10}{\hidepaste}
\tab{5}\spadcommand{definingPolynomial \%y1\free{z }}
\indentrel{3}\begin{verbatim}
              2
   (10)  %%var  + 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSymRootAllPageEmpty10}
\begin{paste}{ugxProblemSymRootAllPageEmpty10}{ugxProblemSymRootAllPagePatch10}
\pastebutton{ugxProblemSymRootAllPageEmpty10}{\showpaste}
\tab{5}\spadcommand{definingPolynomial \%y1\free{z }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugProblemEigenPage}{ug08.ht}
{Computation of Eigenvalues and Eigenvectors}
\begin{chunk}{ug08.ht}
\begin{page}{ugProblemEigenPage}
{8.4. Computation of Eigenvalues and Eigenvectors}
\beginscroll
%
In this section we show you
some of Axiom's facilities for computing and
manipulating eigenvalues and eigenvectors, also called
characteristic values and characteristic vectors,
respectively.

\texht{\vskip 4pc}{}

\xtc{
Let's first create a matrix with integer entries.
}{
\spadpaste{m1 := matrix [[1,2,1],[2,1,-2],[1,-2,4]] \bound{m1}}
}
\xtc{
To get a list of the {\it rational} eigenvalues,
use the operation \axiomFun{eigenvalues}.
}{
\spadpaste{leig := eigenvalues(m1) \free{m1} \bound{leig}}
}
\xtc{
Given an explicit eigenvalue, \axiomFun{eigenvector} computes the 
eigenvectors corresponding to it.
}{
\spadpaste{eigenvector(first(leig),m1) \free{m1 leig}}
}

The operation \axiomFun{eigenvectors} returns a list of pairs of values 
and vectors. When an eigenvalue is rational, Axiom gives you
the value explicitly; otherwise, its minimal polynomial is given,
(the polynomial of lowest degree with the eigenvalues as roots),
together with a parametric representation of the eigenvector using the
eigenvalue.
This means that if you ask Axiom to \axiomFun{solve}
the minimal polynomial, then you can substitute these roots
into the parametric form of the corresponding eigenvectors.

\xtc{
You must be aware that unless an exact eigenvalue has been computed,
the eigenvector may be badly in error.
}{
\spadpaste{eigenvectors(m1) \free{m1}}
}
\xtc{
Another possibility is to use the operation
\axiomFun{radicalEigenvectors}
tries to compute explicitly the eigenvectors
in terms of radicals.
}{
\spadpaste{radicalEigenvectors(m1) \free{m1}}
}

Alternatively, Axiom can compute real or complex approximations to the
eigenvectors and eigenvalues using the operations
\axiomFun{realEigenvectors} or \axiomFun{complexEigenvectors}.  They
each take an additional argument \texht{$\epsilon$}{\axiom{epsilon}}
to specify the ``precision'' required.  In the real case, this means
that each approximation will be within \texht{$\pm\epsilon$}{plus or
minus \axiom{epsilon}} of the actual result.  In the complex case,
this means that each approximation will be within
\texht{$\pm\epsilon$}{plus or minus \axiom{epsilon}} of the actual
result in each of the real and imaginary parts.

\xtc{
The precision can be specified as a \axiomType{Float} if the results
are desired in floating-point notation, or as \axiomType{Fraction
Integer} if the results are to be expressed using rational (or complex
rational) numbers.
}{
\spadpaste{realEigenvectors(m1,1/1000) \free{m1}}
}
\xtc{
If an \axiom{n} by \axiom{n} matrix has \axiom{n} distinct eigenvalues
(and therefore \axiom{n} eigenvectors) the operation
\axiomFun{eigenMatrix} gives you a matrix of the eigenvectors.
}{
\spadpaste{eigenMatrix(m1) \free{m1}}
}
\xtc{
}{
\spadpaste{m2 := matrix [[-5,-2],[18,7]] \bound{m2}}
}
\xtc{
}{
\spadpaste{eigenMatrix(m2) \free{m2}}
}
%
%
\xtc{
If a symmetric matrix
has a basis of orthonormal eigenvectors, then
\axiomFun{orthonormalBasis} computes a list of these vectors.
}{
\spadpaste{m3 := matrix [[1,2],[2,1]] \bound{m3}}
}
\xtc{
}{
\spadpaste{orthonormalBasis(m3) \free{m3}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugProblemEigenPagePatch1}
\begin{paste}{ugProblemEigenPageFull1}{ugProblemEigenPageEmpty1}
\pastebutton{ugProblemEigenPageFull1}{\hidepaste}
\tab{5}\spadcommand{m1 := matrix [[1,2,1],[2,1,-2],[1,-2,4]]\bound{m1 }}
\indentrel{3}\begin{verbatim}
        Ú1   2    1 ¿
        ³           ³
   (1)  ³2   1   - 2³
        ³           ³
        À1  - 2   4 Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemEigenPageEmpty1}
\begin{paste}{ugProblemEigenPageEmpty1}{ugProblemEigenPagePatch1}
\pastebutton{ugProblemEigenPageEmpty1}{\showpaste}
\tab{5}\spadcommand{m1 := matrix [[1,2,1],[2,1,-2],[1,-2,4]]\bound{m1 }}
\end{paste}\end{patch}

\begin{patch}{ugProblemEigenPagePatch2}
\begin{paste}{ugProblemEigenPageFull2}{ugProblemEigenPageEmpty2}
\pastebutton{ugProblemEigenPageFull2}{\hidepaste}
\tab{5}\spadcommand{leig := eigenvalues(m1)\free{m1 }\bound{leig }}
\indentrel{3}\begin{verbatim}
                    2
   (2)  [5,%DA | %DA  - %DA - 5]
Type: List Union(Fraction Polynomial Integer,SuchThat(Symbol,Polynomial Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemEigenPageEmpty2}
\begin{paste}{ugProblemEigenPageEmpty2}{ugProblemEigenPagePatch2}
\pastebutton{ugProblemEigenPageEmpty2}{\showpaste}
\tab{5}\spadcommand{leig := eigenvalues(m1)\free{m1 }\bound{leig }}
\end{paste}\end{patch}

\begin{patch}{ugProblemEigenPagePatch3}
\begin{paste}{ugProblemEigenPageFull3}{ugProblemEigenPageEmpty3}
\pastebutton{ugProblemEigenPageFull3}{\hidepaste}
\tab{5}\spadcommand{eigenvector(first(leig),m1)\free{m1 leig }}
\indentrel{3}\begin{verbatim}
         Ú 0 ¿
         ³   ³
         ³  1³
   (3)  [³- Ä³]
         ³  2³
         ³   ³
         À 1 Ù
 Type: List Matrix Fraction Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemEigenPageEmpty3}
\begin{paste}{ugProblemEigenPageEmpty3}{ugProblemEigenPagePatch3}
\pastebutton{ugProblemEigenPageEmpty3}{\showpaste}
\tab{5}\spadcommand{eigenvector(first(leig),m1)\free{m1 leig }}
\end{paste}\end{patch}

\begin{patch}{ugProblemEigenPagePatch4}
\begin{paste}{ugProblemEigenPageFull4}{ugProblemEigenPageEmpty4}
\pastebutton{ugProblemEigenPageFull4}{\hidepaste}
\tab{5}\spadcommand{eigenvectors(m1)\free{m1 }}
\indentrel{3}\begin{verbatim}
   (4)
                                   Ú 0 ¿
                                   ³   ³
                                   ³  1³
   [[eigval= 5,eigmult= 1,eigvec= [³- Ä³]],
                                   ³  2³
                                   ³   ³
                                   À 1 Ù

                        2
     [eigval= (%DB | %DB  - %DB - 5), eigmult= 1,
               Ú%DB¿
               ³   ³
      eigvec= [³ 2 ³]]
               ³   ³
               À 1 Ù
     ]
Type: List Record(eigval: Union(Fraction Polynomial Integer,SuchThat(Symbol,Polynomial Integer)),eigmult: NonNegativeInteger,eigvec: List Matrix Fraction Polynomial Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemEigenPageEmpty4}
\begin{paste}{ugProblemEigenPageEmpty4}{ugProblemEigenPagePatch4}
\pastebutton{ugProblemEigenPageEmpty4}{\showpaste}
\tab{5}\spadcommand{eigenvectors(m1)\free{m1 }}
\end{paste}\end{patch}

\begin{patch}{ugProblemEigenPagePatch5}
\begin{paste}{ugProblemEigenPageFull5}{ugProblemEigenPageEmpty5}
\pastebutton{ugProblemEigenPageFull5}{\hidepaste}
\tab{5}\spadcommand{radicalEigenvectors(m1)\free{m1 }}
\indentrel{3}\begin{verbatim}
   (5)
                                            Ú ÚÄÄ¿    ¿
              ÚÄÄ¿                          ³\³21  + 1³
             \³21  + 1                      ³ÄÄÄÄÄÄÄÄÄ³
   [[radval= ÄÄÄÄÄÄÄÄÄ,radmult= 1,radvect= [³    2    ³]],
                 2                          ³         ³
                                            ³    2    ³
                                            ³         ³
                                            À    1    Ù

                 ÚÄÄ¿
              - \³21  + 1
     [radval= ÄÄÄÄÄÄÄÄÄÄÄ, radmult= 1,
                   2
                Ú   ÚÄÄ¿    ¿
                ³- \³21  + 1³
                ³ÄÄÄÄÄÄÄÄÄÄÄ³
      radvect= [³     2     ³]]
                ³           ³
                ³     2     ³
                ³           ³
                À     1     Ù
     ,
                                    Ú 0 ¿
                                    ³   ³
                                    ³  1³
    [radval= 5,radmult= 1,radvect= [³- Ä³]]]
                                    ³  2³
                                    ³   ³
                                    À 1 Ù
Type: List Record(radval: Expression Integer,radmult: Integer,radvect: List Matrix Expression Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemEigenPageEmpty5}
\begin{paste}{ugProblemEigenPageEmpty5}{ugProblemEigenPagePatch5}
\pastebutton{ugProblemEigenPageEmpty5}{\showpaste}
\tab{5}\spadcommand{radicalEigenvectors(m1)\free{m1 }}
\end{paste}\end{patch}

\begin{patch}{ugProblemEigenPagePatch6}
\begin{paste}{ugProblemEigenPageFull6}{ugProblemEigenPageEmpty6}
\pastebutton{ugProblemEigenPageFull6}{\hidepaste}
\tab{5}\spadcommand{realEigenvectors(m1,1/1000)\free{m1 }}
\indentrel{3}\begin{verbatim}
   (6)
                                    Ú 0 ¿
                                    ³   ³
                                    ³  1³
   [[outval= 5,outmult= 1,outvect= [³- Ä³]],
                                    ³  2³
                                    ³   ³
                                    À 1 Ù
                                       Ú5717¿
                                       ³ÄÄÄÄ³
             5717                      ³2048³
    [outval= ÄÄÄÄ,outmult= 1,outvect= [³    ³]],
             2048                      ³ 2  ³
                                       ³    ³
                                       À 1  Ù
                                         Ú  3669¿
                                         ³- ÄÄÄÄ³
               3669                      ³  2048³
    [outval= - ÄÄÄÄ,outmult= 1,outvect= [³      ³]]]
               2048                      ³  2   ³
                                         ³      ³
                                         À  1   Ù
Type: List Record(outval: Fraction Integer,outmult: Integer,outvect: List Matrix Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemEigenPageEmpty6}
\begin{paste}{ugProblemEigenPageEmpty6}{ugProblemEigenPagePatch6}
\pastebutton{ugProblemEigenPageEmpty6}{\showpaste}
\tab{5}\spadcommand{realEigenvectors(m1,1/1000)\free{m1 }}
\end{paste}\end{patch}

\begin{patch}{ugProblemEigenPagePatch7}
\begin{paste}{ugProblemEigenPageFull7}{ugProblemEigenPageEmpty7}
\pastebutton{ugProblemEigenPageFull7}{\hidepaste}
\tab{5}\spadcommand{eigenMatrix(m1)\free{m1 }}
\indentrel{3}\begin{verbatim}
        Ú ÚÄÄ¿         ÚÄÄ¿         ¿
        ³\³21  + 1  - \³21  + 1     ³
        ³ÄÄÄÄÄÄÄÄÄ  ÄÄÄÄÄÄÄÄÄÄÄ   0 ³
        ³    2           2          ³
   (7)  ³                           ³
        ³                          1³
        ³    2           2       - Ä³
        ³                          2³
        ³                           ³
        À    1           1        1 Ù
             Type: Union(Matrix Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemEigenPageEmpty7}
\begin{paste}{ugProblemEigenPageEmpty7}{ugProblemEigenPagePatch7}
\pastebutton{ugProblemEigenPageEmpty7}{\showpaste}
\tab{5}\spadcommand{eigenMatrix(m1)\free{m1 }}
\end{paste}\end{patch}

\begin{patch}{ugProblemEigenPagePatch8}
\begin{paste}{ugProblemEigenPageFull8}{ugProblemEigenPageEmpty8}
\pastebutton{ugProblemEigenPageFull8}{\hidepaste}
\tab{5}\spadcommand{m2 := matrix [[-5,-2],[18,7]]\bound{m2 }}
\indentrel{3}\begin{verbatim}
        Ú- 5  - 2¿
   (8)  ³        ³
        À18    7 Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemEigenPageEmpty8}
\begin{paste}{ugProblemEigenPageEmpty8}{ugProblemEigenPagePatch8}
\pastebutton{ugProblemEigenPageEmpty8}{\showpaste}
\tab{5}\spadcommand{m2 := matrix [[-5,-2],[18,7]]\bound{m2 }}
\end{paste}\end{patch}

\begin{patch}{ugProblemEigenPagePatch9}
\begin{paste}{ugProblemEigenPageFull9}{ugProblemEigenPageEmpty9}
\pastebutton{ugProblemEigenPageFull9}{\hidepaste}
\tab{5}\spadcommand{eigenMatrix(m2)\free{m2 }}
\indentrel{3}\begin{verbatim}
   (9)  "failed"
                              Type: Union("failed",...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemEigenPageEmpty9}
\begin{paste}{ugProblemEigenPageEmpty9}{ugProblemEigenPagePatch9}
\pastebutton{ugProblemEigenPageEmpty9}{\showpaste}
\tab{5}\spadcommand{eigenMatrix(m2)\free{m2 }}
\end{paste}\end{patch}

\begin{patch}{ugProblemEigenPagePatch10}
\begin{paste}{ugProblemEigenPageFull10}{ugProblemEigenPageEmpty10}
\pastebutton{ugProblemEigenPageFull10}{\hidepaste}
\tab{5}\spadcommand{m3 := matrix [[1,2],[2,1]]\bound{m3 }}
\indentrel{3}\begin{verbatim}
         Ú1  2¿
   (10)  ³    ³
         À2  1Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemEigenPageEmpty10}
\begin{paste}{ugProblemEigenPageEmpty10}{ugProblemEigenPagePatch10}
\pastebutton{ugProblemEigenPageEmpty10}{\showpaste}
\tab{5}\spadcommand{m3 := matrix [[1,2],[2,1]]\bound{m3 }}
\end{paste}\end{patch}

\begin{patch}{ugProblemEigenPagePatch11}
\begin{paste}{ugProblemEigenPageFull11}{ugProblemEigenPageEmpty11}
\pastebutton{ugProblemEigenPageFull11}{\hidepaste}
\tab{5}\spadcommand{orthonormalBasis(m3)\free{m3 }}
\indentrel{3}\begin{verbatim}
          Ú    1 ¿ Ú  1 ¿
          ³- ÄÄÄÄ³ ³ÄÄÄÄ³
          ³   ÚÄ¿³ ³ ÚÄ¿³
          ³  \³2 ³ ³\³2 ³
   (11)  [³      ³,³    ³]
          ³   1  ³ ³  1 ³
          ³ ÄÄÄÄ ³ ³ÄÄÄÄ³
          ³  ÚÄ¿ ³ ³ ÚÄ¿³
          À \³2  Ù À\³2 Ù
                   Type: List Matrix Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemEigenPageEmpty11}
\begin{paste}{ugProblemEigenPageEmpty11}{ugProblemEigenPagePatch11}
\pastebutton{ugProblemEigenPageEmpty11}{\showpaste}
\tab{5}\spadcommand{orthonormalBasis(m3)\free{m3 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugProblemLinPolEqnPage}{ug08.ht}
{Solution of Linear and Polynomial Equations}
\pageto{notitle}{ugProblemDEQPage}
\pageto{notitle}{ugxProblemLinSysPage}
\pageto{notitle}{ugxProblemOnePolPage}
\pageto{notitle}{ugxProblemPolSysPage}
\begin{chunk}{ug08.ht}
\begin{page}{ugProblemLinPolEqnPage}
{8.5. Solution of Linear and Polynomial Equations}
\beginscroll
%
In this section we discuss the Axiom facilities for solving
systems of linear equations, finding the roots of polynomials and
solving systems of polynomial equations.
For a discussion of the solution of differential equations, see
\downlink{``Solution of Differential Equations''}{ugProblemDEQPage} in 
Section 8.10\ignore{ugProblemDEQ}.

\beginmenu
    \menudownlink{{8.5.1. Solution of Systems of Linear Equations}}
{ugxProblemLinSysPage}
    \menudownlink{{8.5.2. Solution of a Single Polynomial Equation}}
{ugxProblemOnePolPage}
    \menudownlink{{8.5.3. Solution of Systems of Polynomial Equations}}
{ugxProblemPolSysPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugxProblemLinSysPage}{ug08.ht}
{Solution of Systems of Linear Equations}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemLinSysPage}
{8.5.1. Solution of Systems of Linear Equations}
\beginscroll

You can use the operation \axiomFun{solve} to solve systems of linear
equations.

The operation \axiomFun{solve} takes two arguments, the list of
equations and the list of the unknowns to be solved for.  A system of
linear equations need not have a unique solution.

\xtc{
To solve the linear system:
\centerline{{\axiom{  x +   y +   z = 8} }}
\centerline{{\axiom{3*x - 2*y +   z = 0} }}
\centerline{{\axiom{  x + 2*y + 2*z = 17}}}
evaluate this expression.
}{
\spadpaste{solve([x+y+z=8,3*x-2*y+z=0,x+2*y+2*z=17],[x,y,z])}
}

Parameters are given as new variables starting with a percent sign and
\spadSyntax{\%} and
the variables are expressed in terms of the parameters.
If the system has no solutions then the empty list is returned.

\xtc{
When you solve the linear system
\centerline{{\axiom{  x + 2*y + 3*z = 2} }}
\centerline{{\axiom{2*x + 3*y + 4*z = 2} }}
\centerline{{\axiom{3*x + 4*y + 5*z = 2}}}
with this expression
you get a solution involving a parameter.
}{
\spadpaste{solve([x+2*y+3*z=2,2*x+3*y+4*z=2,3*x+4*y+5*z=2],[x,y,z])}
}

The system can also be presented as a matrix and a vector.
The matrix contains the coefficients of the linear equations and
the vector contains the numbers appearing on the right-hand sides
of the equations.
You may input the matrix as a list of rows and the vector as a
list of its elements.

\xtc{
To solve the system:
\centerline{{\axiom{  x +   y +   z = 8} }}
\centerline{{\axiom{3*x - 2*y +   z = 0} }}
\centerline{{\axiom{  x + 2*y + 2*z = 17}}}
in matrix form you would evaluate this expression.
}{
\spadpaste{solve([[1,1,1],[3,-2,1],[1,2,2]],[8,0,17])}
}

The solutions are presented as a \pspadtype{Record} with two
components: the component \texht{{\it particular}}{{\tt
particular}} contains a particular solution of the given system or
the item {\tt "failed"} if there are no solutions, the component
\texht{{\it basis}}{{\tt basis}} contains a list of vectors that
are a basis for the space of solutions of the corresponding
homogeneous system.
If the system of linear equations does not have a unique solution,
then the \texht{{\it basis}}{{\tt basis}} component contains
non-trivial vectors.

\xtc{
This happens when you solve the linear system
\centerline{{\axiom{  x + 2*y + 3*z = 2} }}
\centerline{{\axiom{2*x + 3*y + 4*z = 2} }}
\centerline{{\axiom{3*x + 4*y + 5*z = 2}}}
with this command.
}{
\spadpaste{solve([[1,2,3],[2,3,4],[3,4,5]],[2,2,2])}
}

All solutions of this system are obtained by adding the particular
solution with a linear combination of the \texht{{\it basis}}{{\tt
basis}} vectors.

When no solution exists then {\tt "failed"} is returned as the
\texht{{\it particular}}{{\tt particular}} component, as follows:

\xtc{
}{
\spadpaste{solve([[1,2,3],[2,3,4],[3,4,5]],[2,3,2])}
}

When you want to solve a system of homogeneous equations (that is,
a system where the numbers on the right-hand sides of the
equations are all zero) in the matrix form you can omit the second
argument and use the \axiomFun{nullSpace} operation.

\xtc{
This computes the solutions of the following system of equations:
\centerline{{\axiom{  x + 2*y + 3*z = 0} }}
\centerline{{\axiom{2*x + 3*y + 4*z = 0} }}
\centerline{{\axiom{3*x + 4*y + 5*z = 0}}}
The result is given as a list of vectors and
these vectors form a basis for the solution space.
}{
\spadpaste{nullSpace([[1,2,3],[2,3,4],[3,4,5]])}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxProblemLinSysPagePatch1}
\begin{paste}{ugxProblemLinSysPageFull1}{ugxProblemLinSysPageEmpty1}
\pastebutton{ugxProblemLinSysPageFull1}{\hidepaste}
\tab{5}\spadcommand{solve([x+y+z=8,3*x-2*y+z=0,x+2*y+2*z=17],[x,y,z])}
\indentrel{3}\begin{verbatim}
   (1)  [[x= - 1,y= 2,z= 7]]
   Type: List List Equation Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemLinSysPageEmpty1}
\begin{paste}{ugxProblemLinSysPageEmpty1}{ugxProblemLinSysPagePatch1}
\pastebutton{ugxProblemLinSysPageEmpty1}{\showpaste}
\tab{5}\spadcommand{solve([x+y+z=8,3*x-2*y+z=0,x+2*y+2*z=17],[x,y,z])}
\end{paste}\end{patch}

\begin{patch}{ugxProblemLinSysPagePatch2}
\begin{paste}{ugxProblemLinSysPageFull2}{ugxProblemLinSysPageEmpty2}
\pastebutton{ugxProblemLinSysPageFull2}{\hidepaste}
\tab{5}\spadcommand{solve([x+2*y+3*z=2,2*x+3*y+4*z=2,3*x+4*y+5*z=2],[x,y,z])}
\indentrel{3}\begin{verbatim}
   (2)  [[x= %Y - 2,y= - 2%Y + 2,z= %Y]]
   Type: List List Equation Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemLinSysPageEmpty2}
\begin{paste}{ugxProblemLinSysPageEmpty2}{ugxProblemLinSysPagePatch2}
\pastebutton{ugxProblemLinSysPageEmpty2}{\showpaste}
\tab{5}\spadcommand{solve([x+2*y+3*z=2,2*x+3*y+4*z=2,3*x+4*y+5*z=2],[x,y,z])}
\end{paste}\end{patch}

\begin{patch}{ugxProblemLinSysPagePatch3}
\begin{paste}{ugxProblemLinSysPageFull3}{ugxProblemLinSysPageEmpty3}
\pastebutton{ugxProblemLinSysPageFull3}{\hidepaste}
\tab{5}\spadcommand{solve([[1,1,1],[3,-2,1],[1,2,2]],[8,0,17])}
\indentrel{3}\begin{verbatim}
   (3)  [particular= [- 1,2,7],basis= [[0,0,0]]]
Type: Record(particular: Union(Vector Fraction Integer,"failed"),basis: List Vector Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemLinSysPageEmpty3}
\begin{paste}{ugxProblemLinSysPageEmpty3}{ugxProblemLinSysPagePatch3}
\pastebutton{ugxProblemLinSysPageEmpty3}{\showpaste}
\tab{5}\spadcommand{solve([[1,1,1],[3,-2,1],[1,2,2]],[8,0,17])}
\end{paste}\end{patch}

\begin{patch}{ugxProblemLinSysPagePatch4}
\begin{paste}{ugxProblemLinSysPageFull4}{ugxProblemLinSysPageEmpty4}
\pastebutton{ugxProblemLinSysPageFull4}{\hidepaste}
\tab{5}\spadcommand{solve([[1,2,3],[2,3,4],[3,4,5]],[2,2,2])}
\indentrel{3}\begin{verbatim}
   (4)  [particular= [- 2,2,0],basis= [[1,- 2,1]]]
Type: Record(particular: Union(Vector Fraction Integer,"failed"),basis: List Vector Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemLinSysPageEmpty4}
\begin{paste}{ugxProblemLinSysPageEmpty4}{ugxProblemLinSysPagePatch4}
\pastebutton{ugxProblemLinSysPageEmpty4}{\showpaste}
\tab{5}\spadcommand{solve([[1,2,3],[2,3,4],[3,4,5]],[2,2,2])}
\end{paste}\end{patch}

\begin{patch}{ugxProblemLinSysPagePatch5}
\begin{paste}{ugxProblemLinSysPageFull5}{ugxProblemLinSysPageEmpty5}
\pastebutton{ugxProblemLinSysPageFull5}{\hidepaste}
\tab{5}\spadcommand{solve([[1,2,3],[2,3,4],[3,4,5]],[2,3,2])}
\indentrel{3}\begin{verbatim}
   (5)  [particular= "failed",basis= [[1,- 2,1]]]
Type: Record(particular: Union(Vector Fraction Integer,"failed"),basis: List Vector Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemLinSysPageEmpty5}
\begin{paste}{ugxProblemLinSysPageEmpty5}{ugxProblemLinSysPagePatch5}
\pastebutton{ugxProblemLinSysPageEmpty5}{\showpaste}
\tab{5}\spadcommand{solve([[1,2,3],[2,3,4],[3,4,5]],[2,3,2])}
\end{paste}\end{patch}

\begin{patch}{ugxProblemLinSysPagePatch6}
\begin{paste}{ugxProblemLinSysPageFull6}{ugxProblemLinSysPageEmpty6}
\pastebutton{ugxProblemLinSysPageFull6}{\hidepaste}
\tab{5}\spadcommand{nullSpace([[1,2,3],[2,3,4],[3,4,5]])}
\indentrel{3}\begin{verbatim}
   (6)  [[1,- 2,1]]
                              Type: List Vector Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemLinSysPageEmpty6}
\begin{paste}{ugxProblemLinSysPageEmpty6}{ugxProblemLinSysPagePatch6}
\pastebutton{ugxProblemLinSysPageEmpty6}{\showpaste}
\tab{5}\spadcommand{nullSpace([[1,2,3],[2,3,4],[3,4,5]])}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxProblemOnePolPage}{ug08.ht}
{Solution of a Single Polynomial Equation}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemOnePolPage}
{8.5.2. Solution of a Single Polynomial Equation}
\beginscroll

Axiom can solve polynomial equations producing either approximate or
exact solutions.  Exact solutions are either members of the ground
field or can be presented symbolically as roots of irreducible
polynomials.

\xtc{
This returns the one rational root along with an irreducible
polynomial describing the other solutions.
}{
\spadpaste{solve(x**3  = 8,x)}
}
\xtc{
If you want solutions expressed in terms of radicals you would use this
instead.
}{
\spadpaste{radicalSolve(x**3  = 8,x)}
}

The \axiomFun{solve} command always returns a value but
\axiomFun{radicalSolve} returns only the solutions that it is
able to express in terms of radicals.

If the polynomial equation has rational coefficients
you can ask for approximations to its real roots by calling
solve with a second argument that specifies the ``precision''
\texht{$\epsilon$}{\axiom{epsilon}}.
This means that each approximation will be within
\texht{$\pm\epsilon$}{plus or minus \axiom{epsilon}} of the actual
result.

\xtc{
Notice that the type of second argument controls the type of the result.
}{
\spadpaste{solve(x**4 - 10*x**3 + 35*x**2 - 50*x + 25,.0001)}
}
\xtc{
If you give a floating-point precision you get a floating-point result;
if you give the precision as a rational number you get a rational result.
}{
\spadpaste{solve(x**3-2,1/1000)}
}
\xtc{
If you want approximate complex results you should use the
command \axiomFun{complexSolve} that takes the same precision argument
\texht{$\epsilon$}{\axiom{epsilon}}.
}{
\spadpaste{complexSolve(x**3-2,.0001)}
}
\xtc{
Each approximation will be within
\texht{$\pm\epsilon$}{plus or minus \axiom{epsilon}} of the actual result
in each of the real and imaginary parts.
}{
\spadpaste{complexSolve(x**2-2*\%i+1,1/100)}
}

Note that if you omit the \axiomOp{=} from the first argument
Axiom generates an equation by equating the first argument to zero.
Also, when only one variable is present in the equation, you
do not need to specify the variable to be solved for, that is,
you can omit the second argument.

\xtc{
Axiom can also solve equations involving rational functions.
Solutions where the denominator vanishes are discarded.
}{
\spadpaste{radicalSolve(1/x**3 + 1/x**2 + 1/x = 0,x)}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxProblemOnePolPagePatch1}
\begin{paste}{ugxProblemOnePolPageFull1}{ugxProblemOnePolPageEmpty1}
\pastebutton{ugxProblemOnePolPageFull1}{\hidepaste}
\tab{5}\spadcommand{solve(x**3 = 8,x)}
\indentrel{3}\begin{verbatim}
               2
   (1)  [x= 2,x  + 2x + 4= 0]
        Type: List Equation Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemOnePolPageEmpty1}
\begin{paste}{ugxProblemOnePolPageEmpty1}{ugxProblemOnePolPagePatch1}
\pastebutton{ugxProblemOnePolPageEmpty1}{\showpaste}
\tab{5}\spadcommand{solve(x**3 = 8,x)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemOnePolPagePatch2}
\begin{paste}{ugxProblemOnePolPageFull2}{ugxProblemOnePolPageEmpty2}
\pastebutton{ugxProblemOnePolPageFull2}{\hidepaste}
\tab{5}\spadcommand{radicalSolve(x**3 = 8,x)}
\indentrel{3}\begin{verbatim}
               ÚÄÄÄ¿         ÚÄÄÄ¿
   (2)  [x= - \³- 3  - 1,x= \³- 3  - 1,x= 2]
                 Type: List Equation Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemOnePolPageEmpty2}
\begin{paste}{ugxProblemOnePolPageEmpty2}{ugxProblemOnePolPagePatch2}
\pastebutton{ugxProblemOnePolPageEmpty2}{\showpaste}
\tab{5}\spadcommand{radicalSolve(x**3 = 8,x)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemOnePolPagePatch3}
\begin{paste}{ugxProblemOnePolPageFull3}{ugxProblemOnePolPageEmpty3}
\pastebutton{ugxProblemOnePolPageFull3}{\hidepaste}
\tab{5}\spadcommand{solve(x**4 - 10*x**3 + 35*x**2 - 50*x + 25,.0001)}
\indentrel{3}\begin{verbatim}
   (3)  [x= 3.6180114746 09375,x= 1.3819885253 90625]
                   Type: List Equation Polynomial Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemOnePolPageEmpty3}
\begin{paste}{ugxProblemOnePolPageEmpty3}{ugxProblemOnePolPagePatch3}
\pastebutton{ugxProblemOnePolPageEmpty3}{\showpaste}
\tab{5}\spadcommand{solve(x**4 - 10*x**3 + 35*x**2 - 50*x + 25,.0001)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemOnePolPagePatch4}
\begin{paste}{ugxProblemOnePolPageFull4}{ugxProblemOnePolPageEmpty4}
\pastebutton{ugxProblemOnePolPageFull4}{\hidepaste}
\tab{5}\spadcommand{solve(x**3-2,1/1000)}
\indentrel{3}\begin{verbatim}
            2581
   (4)  [x= ÄÄÄÄ]
            2048
        Type: List Equation Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemOnePolPageEmpty4}
\begin{paste}{ugxProblemOnePolPageEmpty4}{ugxProblemOnePolPagePatch4}
\pastebutton{ugxProblemOnePolPageEmpty4}{\showpaste}
\tab{5}\spadcommand{solve(x**3-2,1/1000)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemOnePolPagePatch5}
\begin{paste}{ugxProblemOnePolPageFull5}{ugxProblemOnePolPageEmpty5}
\pastebutton{ugxProblemOnePolPageFull5}{\hidepaste}
\tab{5}\spadcommand{complexSolve(x**3-2,.0001)}
\indentrel{3}\begin{verbatim}
   (5)
   [x= 1.2599182128 90625,
    x= - 0.6298943279 5395613131 - 1.0910949707 03125 %i,
    x= - 0.6298943279 5395613131 + 1.0910949707 03125 %i]
           Type: List Equation Polynomial Complex Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemOnePolPageEmpty5}
\begin{paste}{ugxProblemOnePolPageEmpty5}{ugxProblemOnePolPagePatch5}
\pastebutton{ugxProblemOnePolPageEmpty5}{\showpaste}
\tab{5}\spadcommand{complexSolve(x**3-2,.0001)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemOnePolPagePatch6}
\begin{paste}{ugxProblemOnePolPageFull6}{ugxProblemOnePolPageEmpty6}
\pastebutton{ugxProblemOnePolPageFull6}{\hidepaste}
\tab{5}\spadcommand{complexSolve(x**2-2*\%i+1,1/100)}
\indentrel{3}\begin{verbatim}
              13028925   325       13028925   325
   (6)  [x= - ÄÄÄÄÄÄÄÄ - ÄÄÄ %i,x= ÄÄÄÄÄÄÄÄ + ÄÄÄ %i]
              16777216   256       16777216   256
Type: List Equation Polynomial Complex Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemOnePolPageEmpty6}
\begin{paste}{ugxProblemOnePolPageEmpty6}{ugxProblemOnePolPagePatch6}
\pastebutton{ugxProblemOnePolPageEmpty6}{\showpaste}
\tab{5}\spadcommand{complexSolve(x**2-2*\%i+1,1/100)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemOnePolPagePatch7}
\begin{paste}{ugxProblemOnePolPageFull7}{ugxProblemOnePolPageEmpty7}
\pastebutton{ugxProblemOnePolPageFull7}{\hidepaste}
\tab{5}\spadcommand{radicalSolve(1/x**3 + 1/x**2 + 1/x = 0,x)}
\indentrel{3}\begin{verbatim}
               ÚÄÄÄ¿         ÚÄÄÄ¿
            - \³- 3  - 1    \³- 3  - 1
   (7)  [x= ÄÄÄÄÄÄÄÄÄÄÄÄ,x= ÄÄÄÄÄÄÄÄÄÄ]
                  2              2
                 Type: List Equation Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemOnePolPageEmpty7}
\begin{paste}{ugxProblemOnePolPageEmpty7}{ugxProblemOnePolPagePatch7}
\pastebutton{ugxProblemOnePolPageEmpty7}{\showpaste}
\tab{5}\spadcommand{radicalSolve(1/x**3 + 1/x**2 + 1/x = 0,x)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxProblemPolSysPage}{ug08.ht}
{Solution of Systems of Polynomial Equations}
\pageto{notitle}{ugxProblemOnePolPage}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemPolSysPage}
{8.5.3. Solution of Systems of Polynomial Equations}
\beginscroll

Given a system of equations of rational functions with exact coefficients:
\centerline{{\axiom{p1(x1,...,xn)} }}
\centerline{{\axiom{.}             }}
\centerline{{\axiom{.}             }}
\centerline{{\axiom{.}             }}
\centerline{{\axiom{pm(x1,...,xn)}}}
Axiom can find
numeric or symbolic solutions.
The system is first split into irreducible components, then for
each component, a triangular system of equations is found that reduces
the problem to sequential solution of univariate polynomials resulting
from substitution of partial solutions from the previous stage.
\centerline{{\axiom{q1(x1,...,xn)} }}
\centerline{{\axiom{.} }}
\centerline{{\axiom{.} }}
\centerline{{\axiom{.} }}
\centerline{{\axiom{qm(xn)}}}

Symbolic solutions can be presented using ``implicit'' algebraic numbers
defined as roots of irreducible polynomials or in terms of radicals.
Axiom can also find approximations to the real or complex roots
of a system of polynomial equations to any user-specified accuracy.

The operation \axiomFun{solve} for systems is used in a way similar
to \axiomFun{solve} for single equations.
Instead of a polynomial equation, one has to give a list of
equations and instead of a single variable to solve for, a list of
variables.
For solutions of single equations see 
\downlink{``Solution of a Single Polynomial Equation''}
{ugxProblemOnePolPage} in Section 8.5.2\ignore{ugxProblemOnePol}.

%
\xtc{
Use the operation \axiomFun{solve} if you want implicitly presented
solutions.
}{
\spadpaste{solve([3*x**3 + y + 1,y**2 -4],[x,y])}
}
\xtc{
}{
\spadpaste{solve([x = y**2-19,y = z**2+x+3,z = 3*x],[x,y,z])}
}
\xtc{
Use \axiomFun{radicalSolve} if you want your solutions expressed
in terms of radicals.
}{
\spadpaste{radicalSolve([3*x**3 + y + 1,y**2 -4],[x,y])}
}

To get numeric solutions you only need to give the list of
equations and the precision desired.
The list of variables would be redundant information since there
can be no parameters for the numerical solver.

\xtc{
If the precision is expressed as a floating-point number you get
results expressed as floats.
}{
\spadpaste{solve([x**2*y - 1,x*y**2 - 2],.01)}
}
\xtc{
To get complex numeric solutions, use the operation \axiomFun{complexSolve},
which takes the same arguments as in the real case.
}{
\spadpaste{complexSolve([x**2*y - 1,x*y**2 - 2],1/1000)}
}
\xtc{
It is also possible to solve systems of equations in rational functions
over the rational numbers.
Note that \axiom{[x = 0.0, a = 0.0]} is not returned as a solution since
the denominator vanishes there.
}{
\spadpaste{solve([x**2/a = a,a = a*x],.001)}
}
\xtc{
When solving equations with
denominators, all solutions where the denominator vanishes are
discarded.
}{
\spadpaste{radicalSolve([x**2/a + a + y**3 - 1,a*y + a + 1],[x,y])}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxProblemPolSysPagePatch1}
\begin{paste}{ugxProblemPolSysPageFull1}{ugxProblemPolSysPageEmpty1}
\pastebutton{ugxProblemPolSysPageFull1}{\hidepaste}
\tab{5}\spadcommand{solve([3*x**3 + y + 1,y**2 -4],[x,y])}
\indentrel{3}\begin{verbatim}
   (1)
                     2
   [[x= - 1,y= 2], [x  - x + 1= 0,y= 2],
       3
    [3x  - 1= 0,y= - 2]]
   Type: List List Equation Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemPolSysPageEmpty1}
\begin{paste}{ugxProblemPolSysPageEmpty1}{ugxProblemPolSysPagePatch1}
\pastebutton{ugxProblemPolSysPageEmpty1}{\showpaste}
\tab{5}\spadcommand{solve([3*x**3 + y + 1,y**2 -4],[x,y])}
\end{paste}\end{patch}

\begin{patch}{ugxProblemPolSysPagePatch2}
\begin{paste}{ugxProblemPolSysPageFull2}{ugxProblemPolSysPageEmpty2}
\pastebutton{ugxProblemPolSysPageFull2}{\hidepaste}
\tab{5}\spadcommand{solve([x = y**2-19,y = z**2+x+3,z = 3*x],[x,y,z])}
\indentrel{3}\begin{verbatim}
   (2)
               2
        z    3z  + z + 9   4     3      2
   [[x= Ä,y= ÄÄÄÄÄÄÄÄÄÄÄ,9z  + 6z  + 55z  + 15z - 90= 0]]
        3         3
   Type: List List Equation Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemPolSysPageEmpty2}
\begin{paste}{ugxProblemPolSysPageEmpty2}{ugxProblemPolSysPagePatch2}
\pastebutton{ugxProblemPolSysPageEmpty2}{\showpaste}
\tab{5}\spadcommand{solve([x = y**2-19,y = z**2+x+3,z = 3*x],[x,y,z])}
\end{paste}\end{patch}

\begin{patch}{ugxProblemPolSysPagePatch3}
\begin{paste}{ugxProblemPolSysPageFull3}{ugxProblemPolSysPageEmpty3}
\pastebutton{ugxProblemPolSysPageFull3}{\hidepaste}
\tab{5}\spadcommand{radicalSolve([3*x**3 + y + 1,y**2 -4],[x,y])}
\indentrel{3}\begin{verbatim}
   (3)
         ÚÄÄÄ¿                   ÚÄÄÄ¿
        \³- 3  + 1            - \³- 3  + 1
   [[x= ÄÄÄÄÄÄÄÄÄÄ,y= 2], [x= ÄÄÄÄÄÄÄÄÄÄÄÄ,y= 2],
             2                      2
           ÚÄÄÄ¿ ÚÄ¿
        - \³- 1 \³3  - 1
    [x= ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ,y= - 2],
               3ÚÄ¿
              2\³3
         ÚÄÄÄ¿ ÚÄ¿
        \³- 1 \³3  - 1                1
    [x= ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ,y= - 2], [x= ÄÄÄÄ,y= - 2],
              3ÚÄ¿                  3ÚÄ¿
             2\³3                   \³3
    [x= - 1,y= 2]]
            Type: List List Equation Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemPolSysPageEmpty3}
\begin{paste}{ugxProblemPolSysPageEmpty3}{ugxProblemPolSysPagePatch3}
\pastebutton{ugxProblemPolSysPageEmpty3}{\showpaste}
\tab{5}\spadcommand{radicalSolve([3*x**3 + y + 1,y**2 -4],[x,y])}
\end{paste}\end{patch}

\begin{patch}{ugxProblemPolSysPagePatch4}
\begin{paste}{ugxProblemPolSysPageFull4}{ugxProblemPolSysPageEmpty4}
\pastebutton{ugxProblemPolSysPageFull4}{\hidepaste}
\tab{5}\spadcommand{solve([x**2*y - 1,x*y**2 - 2],.01)}
\indentrel{3}\begin{verbatim}
   (4)  [[y= 1.5859375,x= 0.79296875]]
              Type: List List Equation Polynomial Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemPolSysPageEmpty4}
\begin{paste}{ugxProblemPolSysPageEmpty4}{ugxProblemPolSysPagePatch4}
\pastebutton{ugxProblemPolSysPageEmpty4}{\showpaste}
\tab{5}\spadcommand{solve([x**2*y - 1,x*y**2 - 2],.01)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemPolSysPagePatch5}
\begin{paste}{ugxProblemPolSysPageFull5}{ugxProblemPolSysPageEmpty5}
\pastebutton{ugxProblemPolSysPageFull5}{\hidepaste}
\tab{5}\spadcommand{complexSolve([x**2*y - 1,x*y**2 - 2],1/1000)}
\indentrel{3}\begin{verbatim}
   (5)
        1625    1625
   [[y= ÄÄÄÄ,x= ÄÄÄÄ],
        1024    2048

           435445573689   1407
     [y= - ÄÄÄÄÄÄÄÄÄÄÄÄ - ÄÄÄÄ %i,
           549755813888   1024
            435445573689   1407
      x= - ÄÄÄÄÄÄÄÄÄÄÄÄÄ - ÄÄÄÄ %i]
           1099511627776   2048
     ,

           435445573689   1407
     [y= - ÄÄÄÄÄÄÄÄÄÄÄÄ + ÄÄÄÄ %i,
           549755813888   1024
            435445573689   1407
      x= - ÄÄÄÄÄÄÄÄÄÄÄÄÄ + ÄÄÄÄ %i]
           1099511627776   2048
     ]
Type: List List Equation Polynomial Complex Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemPolSysPageEmpty5}
\begin{paste}{ugxProblemPolSysPageEmpty5}{ugxProblemPolSysPagePatch5}
\pastebutton{ugxProblemPolSysPageEmpty5}{\showpaste}
\tab{5}\spadcommand{complexSolve([x**2*y - 1,x*y**2 - 2],1/1000)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemPolSysPagePatch6}
\begin{paste}{ugxProblemPolSysPageFull6}{ugxProblemPolSysPageEmpty6}
\pastebutton{ugxProblemPolSysPageFull6}{\hidepaste}
\tab{5}\spadcommand{solve([x**2/a = a,a = a*x],.001)}
\indentrel{3}\begin{verbatim}
   (6)  [[x= 1.0,a= - 1.0],[x= 1.0,a= 1.0]]
              Type: List List Equation Polynomial Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemPolSysPageEmpty6}
\begin{paste}{ugxProblemPolSysPageEmpty6}{ugxProblemPolSysPagePatch6}
\pastebutton{ugxProblemPolSysPageEmpty6}{\showpaste}
\tab{5}\spadcommand{solve([x**2/a = a,a = a*x],.001)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemPolSysPagePatch7}
\begin{paste}{ugxProblemPolSysPageFull7}{ugxProblemPolSysPageEmpty7}
\pastebutton{ugxProblemPolSysPageFull7}{\hidepaste}
\tab{5}\spadcommand{radicalSolve([x**2/a + a + y**3 - 1,a*y + a + 1],[x,y])}
\indentrel{3}\begin{verbatim}
   (7)
           ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
           ³   4     3     2
           ³- a  + 2a  + 3a  + 3a + 1     - a - 1
   [[x= -  ³ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ,y= ÄÄÄÄÄÄÄ],
           ³             2                   a
          \³            a
         ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
         ³   4     3     2
         ³- a  + 2a  + 3a  + 3a + 1     - a - 1
    [x=  ³ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ,y= ÄÄÄÄÄÄÄ]]
         ³             2                   a
        \³            a
            Type: List List Equation Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemPolSysPageEmpty7}
\begin{paste}{ugxProblemPolSysPageEmpty7}{ugxProblemPolSysPagePatch7}
\pastebutton{ugxProblemPolSysPageEmpty7}{\showpaste}
\tab{5}\spadcommand{radicalSolve([x**2/a + a + y**3 - 1,a*y + a + 1],[x,y])}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugProblemLimitsPage}{ug08.ht}{Limits}
\begin{chunk}{ug08.ht}
\begin{page}{ugProblemLimitsPage}{8.6. Limits}
\beginscroll
%
To compute a limit, you must specify a functional expression,
a variable, and a limiting value for that variable.
If you do not specify a direction, Axiom attempts to
compute a two-sided limit.

\xtc{
Issue this to compute the limit
\texht{$$\lim_{x \rightarrow 1}{{\displaystyle x^2 - 3x +
2}\over{\displaystyle x^2 - 1}}.$$}{
of \axiom{(x**2 - 3*x + 2)/(x**2 - 1)} as \axiom{x} approaches \axiom{1}.}
}{
\spadpaste{limit((x**2 - 3*x + 2)/(x**2 - 1),x = 1)}
}

Sometimes the limit when approached from the left is different from
the limit from the right and, in this case, you may wish to ask for a
one-sided limit.  Also, if you have a function that is only defined on
one side of a particular value, you can compute a one-sided limit.

\xtc{
The function \axiom{log(x)} is only defined to the right of zero,
that is, for \axiom{x > 0}.
Thus, when computing limits of functions involving \axiom{log(x)},
you probably want a ``right-hand'' limit.
}{
\spadpaste{limit(x * log(x),x = 0,"right")}
}
\xtc{
When you do not specify \axiom{"right"} or \axiom{"left"} as the
optional fourth argument, \axiomFun{limit} tries to compute a
two-sided limit.
Here the limit from the left does not exist, as Axiom
indicates when you try to take a two-sided limit.
}{
\spadpaste{limit(x * log(x),x = 0)}
}

A function can be defined on both sides of a particular value, but
tend to different limits as its variable approaches that value from the
left and from the right.
We can construct an example of this as follows:
Since
\texht{$\sqrt{y^2}$}{\axiom{sqrt(y**2)}}
is simply the absolute value of \axiom{y},
the function
\texht{$\sqrt{y^2} / y$}{\axiom{sqrt(y**2) / y}}
is simply the sign (\axiom{+1} or \axiom{-1}) of the nonzero
real number \axiom{y}.
Therefore,
\texht{$\sqrt{y^2} / y = -1$}{\axiom{sqrt(y**2) / y = -1}}
for \axiom{y < 0} and
\texht{$\sqrt{y^2} / y = +1$}{\axiom{sqrt(y**2) / y = +1}}
for \axiom{y > 0}.
\xtc{
This is what happens when we take the limit at \axiom{y = 0}.
The answer returned by Axiom gives both a
``left-hand'' and a ``right-hand'' limit.
}{
\spadpaste{limit(sqrt(y**2)/y,y = 0)}
}
\xtc{
Here is another example, this time using a more complicated function.
}{
\spadpaste{limit(sqrt(1 - cos(t))/t,t = 0)}
}

You can compute limits at infinity by passing either
\texht{$+\infty$ or $-\infty$}{``plus infinity'' or ``minus infinity''}
as the third argument of \axiomFun{limit}.
\xtc{
To do this, use the constants 
\axiom{\%plusInfinity} and \axiom{\%minusInfinity}.
}{
\spadpaste{limit(sqrt(3*x**2 + 1)/(5*x),x = \%plusInfinity)}
}
\xtc{
}{
\spadpaste{limit(sqrt(3*x**2 + 1)/(5*x),x = \%minusInfinity)}
}

\xtc{
You can take limits of functions with parameters.
As you can see, the limit is expressed in terms of the parameters.
}{
\spadpaste{limit(sinh(a*x)/tan(b*x),x = 0)}
}

When you use \axiomFun{limit}, you are taking the limit of a real
function of a real variable.
\xtc{
When you compute this, Axiom returns \axiom{0} because, as a function
of a real variable, \axiom{sin(1/z)} is always between \axiom{-1} and
\axiom{1}, so \axiom{z * sin(1/z)} tends to \axiom{0} as \axiom{z}
tends to \axiom{0}.
}{
\spadpaste{limit(z * sin(1/z),z = 0)}
}
However, as a function of a {\it complex} variable, \axiom{sin(1/z)}
is badly behaved near \axiom{0} (one says that \axiom{sin(1/z)} has an
{\it essential singularity} at \axiom{z = 0}).
\xtc{
When viewed as a function of a complex variable, \axiom{z * sin(1/z)}
does not approach any limit as \axiom{z} tends to \axiom{0} in the
complex plane.  Axiom indicates this when we call
\axiomFun{complexLimit}.
}{
\spadpaste{complexLimit(z * sin(1/z),z = 0)}
}

You can also take complex limits at infinity, that is, limits of a
function of \axiom{z} as \axiom{z} approaches infinity on the Riemann
sphere.  Use the symbol \axiom{\%infinity} to denote ``complex
infinity.''
\xtc{
As above, to compute complex limits rather than real limits, use
\axiomFun{complexLimit}.
}{
\spadpaste{complexLimit((2 + z)/(1 - z),z = \%infinity)}
}
\xtc{
In many cases, a limit of a real function of a real variable
exists when the corresponding complex limit does not.
This limit exists.
}{
\spadpaste{limit(sin(x)/x,x = \%plusInfinity)}
}
\xtc{
But this limit does not.
}{
\spadpaste{complexLimit(sin(x)/x,x = \%infinity)}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugProblemLimitsPagePatch1}
\begin{paste}{ugProblemLimitsPageFull1}{ugProblemLimitsPageEmpty1}
\pastebutton{ugProblemLimitsPageFull1}{\hidepaste}
\tab{5}\spadcommand{limit((x**2 - 3*x + 2)/(x**2 - 1),x = 1)}
\indentrel{3}\begin{verbatim}
          1
   (1)  - Ä
          2
Type: Union(OrderedCompletion Fraction Polynomial Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPageEmpty1}
\begin{paste}{ugProblemLimitsPageEmpty1}{ugProblemLimitsPagePatch1}
\pastebutton{ugProblemLimitsPageEmpty1}{\showpaste}
\tab{5}\spadcommand{limit((x**2 - 3*x + 2)/(x**2 - 1),x = 1)}
\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPagePatch2}
\begin{paste}{ugProblemLimitsPageFull2}{ugProblemLimitsPageEmpty2}
\pastebutton{ugProblemLimitsPageFull2}{\hidepaste}
\tab{5}\spadcommand{limit(x * log(x),x = 0,"right")}
\indentrel{3}\begin{verbatim}
   (2)  0
  Type: Union(OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPageEmpty2}
\begin{paste}{ugProblemLimitsPageEmpty2}{ugProblemLimitsPagePatch2}
\pastebutton{ugProblemLimitsPageEmpty2}{\showpaste}
\tab{5}\spadcommand{limit(x * log(x),x = 0,"right")}
\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPagePatch3}
\begin{paste}{ugProblemLimitsPageFull3}{ugProblemLimitsPageEmpty3}
\pastebutton{ugProblemLimitsPageFull3}{\hidepaste}
\tab{5}\spadcommand{limit(x * log(x),x = 0)}
\indentrel{3}\begin{verbatim}
   (3)  [leftHandLimit= "failed",rightHandLimit= 0]
Type: Union(Record(leftHandLimit: Union(OrderedCompletion Expression Integer,"failed"),rightHandLimit: Union(OrderedCompletion Expression Integer,"failed")),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPageEmpty3}
\begin{paste}{ugProblemLimitsPageEmpty3}{ugProblemLimitsPagePatch3}
\pastebutton{ugProblemLimitsPageEmpty3}{\showpaste}
\tab{5}\spadcommand{limit(x * log(x),x = 0)}
\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPagePatch4}
\begin{paste}{ugProblemLimitsPageFull4}{ugProblemLimitsPageEmpty4}
\pastebutton{ugProblemLimitsPageFull4}{\hidepaste}
\tab{5}\spadcommand{limit(sqrt(y**2)/y,y = 0)}
\indentrel{3}\begin{verbatim}
   (4)  [leftHandLimit= - 1,rightHandLimit= 1]
Type: Union(Record(leftHandLimit: Union(OrderedCompletion Expression Integer,"failed"),rightHandLimit: Union(OrderedCompletion Expression Integer,"failed")),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPageEmpty4}
\begin{paste}{ugProblemLimitsPageEmpty4}{ugProblemLimitsPagePatch4}
\pastebutton{ugProblemLimitsPageEmpty4}{\showpaste}
\tab{5}\spadcommand{limit(sqrt(y**2)/y,y = 0)}
\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPagePatch5}
\begin{paste}{ugProblemLimitsPageFull5}{ugProblemLimitsPageEmpty5}
\pastebutton{ugProblemLimitsPageFull5}{\hidepaste}
\tab{5}\spadcommand{limit(sqrt(1 - cos(t))/t,t = 0)}
\indentrel{3}\begin{verbatim}
                            1                    1
   (5)  [leftHandLimit= - ÄÄÄÄ,rightHandLimit= ÄÄÄÄ]
                           ÚÄ¿                  ÚÄ¿
                          \³2                  \³2
Type: Union(Record(leftHandLimit: Union(OrderedCompletion Expression Integer,"failed"),rightHandLimit: Union(OrderedCompletion Expression Integer,"failed")),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPageEmpty5}
\begin{paste}{ugProblemLimitsPageEmpty5}{ugProblemLimitsPagePatch5}
\pastebutton{ugProblemLimitsPageEmpty5}{\showpaste}
\tab{5}\spadcommand{limit(sqrt(1 - cos(t))/t,t = 0)}
\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPagePatch6}
\begin{paste}{ugProblemLimitsPageFull6}{ugProblemLimitsPageEmpty6}
\pastebutton{ugProblemLimitsPageFull6}{\hidepaste}
\tab{5}\spadcommand{limit(sqrt(3*x**2 + 1)/(5*x),x = \%plusInfinity)}
\indentrel{3}\begin{verbatim}
         ÚÄ¿
        \³3
   (6)  ÄÄÄÄ
          5
  Type: Union(OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPageEmpty6}
\begin{paste}{ugProblemLimitsPageEmpty6}{ugProblemLimitsPagePatch6}
\pastebutton{ugProblemLimitsPageEmpty6}{\showpaste}
\tab{5}\spadcommand{limit(sqrt(3*x**2 + 1)/(5*x),x = \%plusInfinity)}
\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPagePatch7}
\begin{paste}{ugProblemLimitsPageFull7}{ugProblemLimitsPageEmpty7}
\pastebutton{ugProblemLimitsPageFull7}{\hidepaste}
\tab{5}\spadcommand{limit(sqrt(3*x**2 + 1)/(5*x),x = \%minusInfinity)}
\indentrel{3}\begin{verbatim}
           ÚÄ¿
          \³3
   (7)  - ÄÄÄÄ
            5
  Type: Union(OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPageEmpty7}
\begin{paste}{ugProblemLimitsPageEmpty7}{ugProblemLimitsPagePatch7}
\pastebutton{ugProblemLimitsPageEmpty7}{\showpaste}
\tab{5}\spadcommand{limit(sqrt(3*x**2 + 1)/(5*x),x = \%minusInfinity)}
\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPagePatch8}
\begin{paste}{ugProblemLimitsPageFull8}{ugProblemLimitsPageEmpty8}
\pastebutton{ugProblemLimitsPageFull8}{\hidepaste}
\tab{5}\spadcommand{limit(sinh(a*x)/tan(b*x),x = 0)}
\indentrel{3}\begin{verbatim}
        a
   (8)  Ä
        b
  Type: Union(OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPageEmpty8}
\begin{paste}{ugProblemLimitsPageEmpty8}{ugProblemLimitsPagePatch8}
\pastebutton{ugProblemLimitsPageEmpty8}{\showpaste}
\tab{5}\spadcommand{limit(sinh(a*x)/tan(b*x),x = 0)}
\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPagePatch9}
\begin{paste}{ugProblemLimitsPageFull9}{ugProblemLimitsPageEmpty9}
\pastebutton{ugProblemLimitsPageFull9}{\hidepaste}
\tab{5}\spadcommand{limit(z * sin(1/z),z = 0)}
\indentrel{3}\begin{verbatim}
   (9)  0
  Type: Union(OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPageEmpty9}
\begin{paste}{ugProblemLimitsPageEmpty9}{ugProblemLimitsPagePatch9}
\pastebutton{ugProblemLimitsPageEmpty9}{\showpaste}
\tab{5}\spadcommand{limit(z * sin(1/z),z = 0)}
\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPagePatch10}
\begin{paste}{ugProblemLimitsPageFull10}{ugProblemLimitsPageEmpty10}
\pastebutton{ugProblemLimitsPageFull10}{\hidepaste}
\tab{5}\spadcommand{complexLimit(z * sin(1/z),z = 0)}
\indentrel{3}\begin{verbatim}
   (10)  "failed"
                              Type: Union("failed",...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPageEmpty10}
\begin{paste}{ugProblemLimitsPageEmpty10}{ugProblemLimitsPagePatch10}
\pastebutton{ugProblemLimitsPageEmpty10}{\showpaste}
\tab{5}\spadcommand{complexLimit(z * sin(1/z),z = 0)}
\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPagePatch11}
\begin{paste}{ugProblemLimitsPageFull11}{ugProblemLimitsPageEmpty11}
\pastebutton{ugProblemLimitsPageFull11}{\hidepaste}
\tab{5}\spadcommand{complexLimit((2 + z)/(1 - z),z = \%infinity)}
\indentrel{3}\begin{verbatim}
   (11)  - 1
   Type: OnePointCompletion Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPageEmpty11}
\begin{paste}{ugProblemLimitsPageEmpty11}{ugProblemLimitsPagePatch11}
\pastebutton{ugProblemLimitsPageEmpty11}{\showpaste}
\tab{5}\spadcommand{complexLimit((2 + z)/(1 - z),z = \%infinity)}
\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPagePatch12}
\begin{paste}{ugProblemLimitsPageFull12}{ugProblemLimitsPageEmpty12}
\pastebutton{ugProblemLimitsPageFull12}{\hidepaste}
\tab{5}\spadcommand{limit(sin(x)/x,x = \%plusInfinity)}
\indentrel{3}\begin{verbatim}
   (12)  0
  Type: Union(OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPageEmpty12}
\begin{paste}{ugProblemLimitsPageEmpty12}{ugProblemLimitsPagePatch12}
\pastebutton{ugProblemLimitsPageEmpty12}{\showpaste}
\tab{5}\spadcommand{limit(sin(x)/x,x = \%plusInfinity)}
\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPagePatch13}
\begin{paste}{ugProblemLimitsPageFull13}{ugProblemLimitsPageEmpty13}
\pastebutton{ugProblemLimitsPageFull13}{\hidepaste}
\tab{5}\spadcommand{complexLimit(sin(x)/x,x = \%infinity)}
\indentrel{3}\begin{verbatim}
   (13)  "failed"
                              Type: Union("failed",...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemLimitsPageEmpty13}
\begin{paste}{ugProblemLimitsPageEmpty13}{ugProblemLimitsPagePatch13}
\pastebutton{ugProblemLimitsPageEmpty13}{\showpaste}
\tab{5}\spadcommand{complexLimit(sin(x)/x,x = \%infinity)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugProblemLaplacePage}{ug08.ht}{Laplace Transforms}
\begin{chunk}{ug08.ht}
\begin{page}{ugProblemLaplacePage}{8.7. Laplace Transforms}
\beginscroll
%
Axiom can compute some forward Laplace transforms, mostly
of elementary
functions
not involving logarithms, although some cases of
special functions are handled.
\xtc{
To compute the forward Laplace transform of \axiom{F(t)} with respect to
\axiom{t} and express the result as \axiom{f(s)}, issue the command
\axiom{laplace(F(t), t, s)}.
}{
\spadpaste{laplace(sin(a*t)*cosh(a*t)-cos(a*t)*sinh(a*t), t, s)}
}
\xtc{
Here are some other non-trivial examples.
}{
\spadpaste{laplace((exp(a*t) - exp(b*t))/t, t, s)}
}
\xtc{
}{
\spadpaste{laplace(2/t * (1 - cos(a*t)), t, s)}
}
\xtc{
}{
\spadpaste{laplace(exp(-a*t) * sin(b*t) / b**2, t, s)}
}
\xtc{
}{
\spadpaste{laplace((cos(a*t) - cos(b*t))/t, t, s)}
}
\xtc{
Axiom also knows about a few special functions.
}{
\spadpaste{laplace(exp(a*t+b)*Ei(c*t), t, s)}
}
\xtc{
}{
\spadpaste{laplace(a*Ci(b*t) + c*Si(d*t), t, s)}
}
\xtc{
When Axiom does not know about a particular transform,
it keeps it as a formal transform in the answer.
}{
\spadpaste{laplace(sin(a*t) - a*t*cos(a*t) + exp(t**2), t, s)}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugProblemLaplacePagePatch1}
\begin{paste}{ugProblemLaplacePageFull1}{ugProblemLaplacePageEmpty1}
\pastebutton{ugProblemLaplacePageFull1}{\hidepaste}
\tab{5}\spadcommand{laplace(sin(a*t)*cosh(a*t)-cos(a*t)*sinh(a*t), t, s)}
\indentrel{3}\begin{verbatim}
             3
           4a
   (1)  ÄÄÄÄÄÄÄÄ
         4     4
        s  + 4a
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemLaplacePageEmpty1}
\begin{paste}{ugProblemLaplacePageEmpty1}{ugProblemLaplacePagePatch1}
\pastebutton{ugProblemLaplacePageEmpty1}{\showpaste}
\tab{5}\spadcommand{laplace(sin(a*t)*cosh(a*t)-cos(a*t)*sinh(a*t), t, s)}
\end{paste}\end{patch}

\begin{patch}{ugProblemLaplacePagePatch2}
\begin{paste}{ugProblemLaplacePageFull2}{ugProblemLaplacePageEmpty2}
\pastebutton{ugProblemLaplacePageFull2}{\hidepaste}
\tab{5}\spadcommand{laplace((exp(a*t) - exp(b*t))/t, t, s)}
\indentrel{3}\begin{verbatim}
   (2)  - log(s - a) + log(s - b)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemLaplacePageEmpty2}
\begin{paste}{ugProblemLaplacePageEmpty2}{ugProblemLaplacePagePatch2}
\pastebutton{ugProblemLaplacePageEmpty2}{\showpaste}
\tab{5}\spadcommand{laplace((exp(a*t) - exp(b*t))/t, t, s)}
\end{paste}\end{patch}

\begin{patch}{ugProblemLaplacePagePatch3}
\begin{paste}{ugProblemLaplacePageFull3}{ugProblemLaplacePageEmpty3}
\pastebutton{ugProblemLaplacePageFull3}{\hidepaste}
\tab{5}\spadcommand{laplace(2/t * (1 - cos(a*t)), t, s)}
\indentrel{3}\begin{verbatim}
             2    2
   (3)  log(s  + a ) - 2log(s)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemLaplacePageEmpty3}
\begin{paste}{ugProblemLaplacePageEmpty3}{ugProblemLaplacePagePatch3}
\pastebutton{ugProblemLaplacePageEmpty3}{\showpaste}
\tab{5}\spadcommand{laplace(2/t * (1 - cos(a*t)), t, s)}
\end{paste}\end{patch}

\begin{patch}{ugProblemLaplacePagePatch4}
\begin{paste}{ugProblemLaplacePageFull4}{ugProblemLaplacePageEmpty4}
\pastebutton{ugProblemLaplacePageFull4}{\hidepaste}
\tab{5}\spadcommand{laplace(exp(-a*t) * sin(b*t) / b**2, t, s)}
\indentrel{3}\begin{verbatim}
                    1
   (4)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
           2             3    2
        b s  + 2a b s + b  + a b
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemLaplacePageEmpty4}
\begin{paste}{ugProblemLaplacePageEmpty4}{ugProblemLaplacePagePatch4}
\pastebutton{ugProblemLaplacePageEmpty4}{\showpaste}
\tab{5}\spadcommand{laplace(exp(-a*t) * sin(b*t) / b**2, t, s)}
\end{paste}\end{patch}

\begin{patch}{ugProblemLaplacePagePatch5}
\begin{paste}{ugProblemLaplacePageFull5}{ugProblemLaplacePageEmpty5}
\pastebutton{ugProblemLaplacePageFull5}{\hidepaste}
\tab{5}\spadcommand{laplace((cos(a*t) - cos(b*t))/t, t, s)}
\indentrel{3}\begin{verbatim}
             2    2         2    2
        log(s  + b ) - log(s  + a )
   (5)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                     2
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemLaplacePageEmpty5}
\begin{paste}{ugProblemLaplacePageEmpty5}{ugProblemLaplacePagePatch5}
\pastebutton{ugProblemLaplacePageEmpty5}{\showpaste}
\tab{5}\spadcommand{laplace((cos(a*t) - cos(b*t))/t, t, s)}
\end{paste}\end{patch}

\begin{patch}{ugProblemLaplacePagePatch6}
\begin{paste}{ugProblemLaplacePageFull6}{ugProblemLaplacePageEmpty6}
\pastebutton{ugProblemLaplacePageFull6}{\hidepaste}
\tab{5}\spadcommand{laplace(exp(a*t+b)*Ei(c*t), t, s)}
\indentrel{3}\begin{verbatim}
          b    s + c - a
        %e log(ÄÄÄÄÄÄÄÄÄ)
                   c
   (6)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
              s - a
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemLaplacePageEmpty6}
\begin{paste}{ugProblemLaplacePageEmpty6}{ugProblemLaplacePagePatch6}
\pastebutton{ugProblemLaplacePageEmpty6}{\showpaste}
\tab{5}\spadcommand{laplace(exp(a*t+b)*Ei(c*t), t, s)}
\end{paste}\end{patch}

\begin{patch}{ugProblemLaplacePagePatch7}
\begin{paste}{ugProblemLaplacePageFull7}{ugProblemLaplacePageEmpty7}
\pastebutton{ugProblemLaplacePageFull7}{\hidepaste}
\tab{5}\spadcommand{laplace(a*Ci(b*t) + c*Si(d*t), t, s)}
\indentrel{3}\begin{verbatim}
               2    2
              s  + b             d
        a log(ÄÄÄÄÄÄÄ) + 2c atan(Ä)
                  2              s
                 b
   (7)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                     2s
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemLaplacePageEmpty7}
\begin{paste}{ugProblemLaplacePageEmpty7}{ugProblemLaplacePagePatch7}
\pastebutton{ugProblemLaplacePageEmpty7}{\showpaste}
\tab{5}\spadcommand{laplace(a*Ci(b*t) + c*Si(d*t), t, s)}
\end{paste}\end{patch}

\begin{patch}{ugProblemLaplacePagePatch8}
\begin{paste}{ugProblemLaplacePageFull8}{ugProblemLaplacePageEmpty8}
\pastebutton{ugProblemLaplacePageFull8}{\hidepaste}
\tab{5}\spadcommand{laplace(sin(a*t) - a*t*cos(a*t) + exp(t**2), t, s)}
\indentrel{3}\begin{verbatim}
                                    2
          4     2 2    4           t           3
        (s  + 2a s  + a )laplace(%e  ,t,s) + 2a
   (8)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                      4     2 2    4
                     s  + 2a s  + a
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemLaplacePageEmpty8}
\begin{paste}{ugProblemLaplacePageEmpty8}{ugProblemLaplacePagePatch8}
\pastebutton{ugProblemLaplacePageEmpty8}{\showpaste}
\tab{5}\spadcommand{laplace(sin(a*t) - a*t*cos(a*t) + exp(t**2), t, s)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugProblemIntegrationPage}{ug08.ht}{Integration}
\pageto{notitle}{ugxProblemSymRootAllPage}
\begin{chunk}{ug08.ht}
\begin{page}{ugProblemIntegrationPage}{8.8. Integration}
\beginscroll
%
Integration is the reverse process of differentiation, that is,
an {\it integral} of a function \axiom{f} with respect to a variable
\axiom{x} is any function \axiom{g} such that \axiom{D(g,x)}
is equal to \axiom{f}.
\xtc{
The package \axiomType{FunctionSpaceIntegration} provides the top-level
integration operation, \axiomFunFrom{integrate}{FunctionSpaceIntegration},
for integrating real-valued elementary functions.
}{
\spadpaste{integrate(cosh(a*x)*sinh(a*x), x)}
}
\xtc{
Unfortunately, antiderivatives of most functions cannot be expressed in
terms of elementary functions.
}{
\spadpaste{integrate(log(1 + sqrt(a * x + b)) / x, x)}
}
Given an elementary function to integrate, Axiom returns a formal
integral as above only when it can prove that the integral is not
elementary and not when it cannot determine the integral.
In this rare case it prints a message that it cannot
determine if an elementary integral exists.
%
\xtc{
Similar functions may have antiderivatives
that look quite different because the form of the antiderivative
depends on the sign of a constant that appears in the function.
}{
\spadpaste{integrate(1/(x**2 - 2),x)}
}
\xtc{
}{
\spadpaste{integrate(1/(x**2 + 2),x)}
}
%
If the integrand contains parameters, then there may be several possible
antiderivatives, depending on the signs of expressions of the parameters.
\xtc{
In this case Axiom returns a list of answers that cover all
the possible cases.
Here you
use the answer involving the square root of \axiom{a} when \axiom{a > 0} and
the answer involving the square root of \axiom{-a} when \axiom{a < 0}.
}{
\spadpaste{integrate(x**2 / (x**4 - a**2), x)}
}

If the parameters and the variables of integration can be complex
numbers rather than real, then the notion of sign is not defined.
In this case all the possible answers can be expressed as one
complex function.
To get that function, rather than a list of real functions, use
\axiomFunFrom{complexIntegrate}{FunctionSpaceComplexIntegration},
which is provided by the package
\axiomType{FunctionSpaceComplexIntegration}.

\xtc{
This operation is used for
integrating complex-valued elementary functions.
}{
\spadpaste{complexIntegrate(x**2 / (x**4 - a**2), x)}
}
\xtc{
As with the real case,
antiderivatives for most complex-valued functions cannot be expressed
in terms of elementary functions.
}{
\spadpaste{complexIntegrate(log(1 + sqrt(a * x + b)) / x, x)}
}

Sometimes \axiomFun{integrate} can involve symbolic algebraic numbers
such as those returned by \axiomFunFrom{rootOf}{Expression}.
To see how to work with these strange generated symbols (such as
\axiom{\%\%a0}), see 
\downlink{``Using All Roots of a Polynomial''}{ugxProblemSymRootAllPage} 
in Section 8.3.2\ignore{ugxProblemSymRootAll}.

Definite integration is the process of computing the area between the
\axiom{x}-axis and the curve of a function \axiom{f(x)}.  The
fundamental theorem of calculus states that if \axiom{f} is continuous
on an interval \axiom{a..b} and if there exists a function \axiom{g}
that is differentiable on \axiom{a..b} and such that \axiom{D(g, x)}
is equal to \axiom{f}, then the definite integral of \axiom{f} for
\axiom{x} in the interval \axiom{a..b} is equal to \axiom{g(b) -
g(a)}.

\xtc{
The package \axiomType{RationalFunctionDefiniteIntegration} provides
the top-level definite integration operation,
\axiomFunFrom{integrate}{RationalFunctionDefiniteIntegration},
for integrating real-valued rational functions.
}{
\spadpaste{integrate((x**4 - 3*x**2 + 6)/(x**6-5*x**4+5*x**2+4), x = 1..2)}
}
Axiom checks beforehand that the function you are integrating is
defined on the interval \axiom{a..b}, and prints an error message if it
finds that this is not case, as in the following example:
\begin{verbatim}
integrate(1/(x**2-2), x = 1..2)

    >> Error detected within library code:
       Pole in path of integration
       You are being returned to the top level
       of the interpreter.
\end{verbatim}
When parameters are present in the function, the function may or may not be
defined on the interval of integration.

\xtc{
If this is the case, Axiom issues a warning that a pole might
lie in the path of integration, and does not compute the integral.
}{
\spadpaste{integrate(1/(x**2-a), x = 1..2)}
}

If you know that you are using values of the parameter for which
the function has no pole in the interval of integration, use the
string {\tt "noPole"} as a third argument to
\axiomFunFrom{integrate}{RationalFunctionDefiniteIntegration}:

%
\xtc{
The value here is, of course, incorrect if \axiom{sqrt(a)} is between
\axiom{1} and \axiom{2.}
}{
\spadpaste{integrate(1/(x**2-a), x = 1..2, "noPole")}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugProblemIntegrationPagePatch1}
\begin{paste}{ugProblemIntegrationPageFull1}{ugProblemIntegrationPageEmpty1}
\pastebutton{ugProblemIntegrationPageFull1}{\hidepaste}
\tab{5}\spadcommand{integrate(cosh(a*x)*sinh(a*x), x)}
\indentrel{3}\begin{verbatim}
                 2            2
        sinh(a x)  + cosh(a x)
   (1)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                   4a
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIntegrationPageEmpty1}
\begin{paste}{ugProblemIntegrationPageEmpty1}{ugProblemIntegrationPagePatch1}
\pastebutton{ugProblemIntegrationPageEmpty1}{\showpaste}
\tab{5}\spadcommand{integrate(cosh(a*x)*sinh(a*x), x)}
\end{paste}\end{patch}

\begin{patch}{ugProblemIntegrationPagePatch2}
\begin{paste}{ugProblemIntegrationPageFull2}{ugProblemIntegrationPageEmpty2}
\pastebutton{ugProblemIntegrationPageFull2}{\hidepaste}
\tab{5}\spadcommand{integrate(log(1 + sqrt(a * x + b)) / x, x)}
\indentrel{3}\begin{verbatim}
           x      ÚÄÄÄÄÄÄÄÄ¿
         Ú¿  log(\³b + %E a  + 1)
   (2)   ³   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ d%E
        ÀÙ            %E
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIntegrationPageEmpty2}
\begin{paste}{ugProblemIntegrationPageEmpty2}{ugProblemIntegrationPagePatch2}
\pastebutton{ugProblemIntegrationPageEmpty2}{\showpaste}
\tab{5}\spadcommand{integrate(log(1 + sqrt(a * x + b)) / x, x)}
\end{paste}\end{patch}

\begin{patch}{ugProblemIntegrationPagePatch3}
\begin{paste}{ugProblemIntegrationPageFull3}{ugProblemIntegrationPageEmpty3}
\pastebutton{ugProblemIntegrationPageFull3}{\hidepaste}
\tab{5}\spadcommand{integrate(1/(x**2 - 2),x)}
\indentrel{3}\begin{verbatim}
              2      ÚÄ¿
            (x  + 2)\³2  - 4x
        log(ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ)
                   2
                  x  - 2
   (3)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                   ÚÄ¿
                 2\³2
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIntegrationPageEmpty3}
\begin{paste}{ugProblemIntegrationPageEmpty3}{ugProblemIntegrationPagePatch3}
\pastebutton{ugProblemIntegrationPageEmpty3}{\showpaste}
\tab{5}\spadcommand{integrate(1/(x**2 - 2),x)}
\end{paste}\end{patch}

\begin{patch}{ugProblemIntegrationPagePatch4}
\begin{paste}{ugProblemIntegrationPageFull4}{ugProblemIntegrationPageEmpty4}
\pastebutton{ugProblemIntegrationPageFull4}{\hidepaste}
\tab{5}\spadcommand{integrate(1/(x**2 + 2),x)}
\indentrel{3}\begin{verbatim}
               ÚÄ¿
             x\³2
        atan(ÄÄÄÄÄ)
               2
   (4)  ÄÄÄÄÄÄÄÄÄÄÄ
             ÚÄ¿
            \³2
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIntegrationPageEmpty4}
\begin{paste}{ugProblemIntegrationPageEmpty4}{ugProblemIntegrationPagePatch4}
\pastebutton{ugProblemIntegrationPageEmpty4}{\showpaste}
\tab{5}\spadcommand{integrate(1/(x**2 + 2),x)}
\end{paste}\end{patch}

\begin{patch}{ugProblemIntegrationPagePatch5}
\begin{paste}{ugProblemIntegrationPageFull5}{ugProblemIntegrationPageEmpty5}
\pastebutton{ugProblemIntegrationPageFull5}{\hidepaste}
\tab{5}\spadcommand{integrate(x**2 / (x**4 - a**2), x)}
\indentrel{3}\begin{verbatim}
   (5)
          2      ÚÄ¿                   ÚÄ¿
        (x  + a)\³a  - 2a x          x\³a
    log(ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ) + 2atan(ÄÄÄÄÄ)
                2                      a
               x  - a
   [ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ,
                       ÚÄ¿
                     4\³a
          2      ÚÄÄÄ¿                   ÚÄÄÄ¿
        (x  - a)\³- a  + 2a x          x\³- a
    log(ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ) - 2atan(ÄÄÄÄÄÄÄ)
                 2                        a
                x  + a
    ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ]
                        ÚÄÄÄ¿
                      4\³- a
               Type: Union(List Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIntegrationPageEmpty5}
\begin{paste}{ugProblemIntegrationPageEmpty5}{ugProblemIntegrationPagePatch5}
\pastebutton{ugProblemIntegrationPageEmpty5}{\showpaste}
\tab{5}\spadcommand{integrate(x**2 / (x**4 - a**2), x)}
\end{paste}\end{patch}

\begin{patch}{ugProblemIntegrationPagePatch6}
\begin{paste}{ugProblemIntegrationPageFull6}{ugProblemIntegrationPageEmpty6}
\pastebutton{ugProblemIntegrationPageFull6}{\hidepaste}
\tab{5}\spadcommand{complexIntegrate(x**2 / (x**4 - a**2), x)}
\indentrel{3}\begin{verbatim}
   (6)
                  ÚÄÄÄÄ¿                      ÚÄÄ¿
        ÚÄÄ¿    x\³- 4a  + 2a     ÚÄÄÄÄ¿    x\³4a  + 2a
       \³4a log(ÄÄÄÄÄÄÄÄÄÄÄÄÄ) - \³- 4a log(ÄÄÄÄÄÄÄÄÄÄÄ)
                    ÚÄÄÄÄ¿                      ÚÄÄ¿
                   \³- 4a                      \³4a
     + 
                    ÚÄÄ¿                    ÚÄÄÄÄ¿
        ÚÄÄÄÄ¿    x\³4a  - 2a     ÚÄÄ¿    x\³- 4a  - 2a
       \³- 4a log(ÄÄÄÄÄÄÄÄÄÄÄ) - \³4a log(ÄÄÄÄÄÄÄÄÄÄÄÄÄ)
                      ÚÄÄ¿                    ÚÄÄÄÄ¿
                     \³4a                    \³- 4a
  /
       ÚÄÄÄÄ¿ ÚÄÄ¿
     2\³- 4a \³4a
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIntegrationPageEmpty6}
\begin{paste}{ugProblemIntegrationPageEmpty6}{ugProblemIntegrationPagePatch6}
\pastebutton{ugProblemIntegrationPageEmpty6}{\showpaste}
\tab{5}\spadcommand{complexIntegrate(x**2 / (x**4 - a**2), x)}
\end{paste}\end{patch}

\begin{patch}{ugProblemIntegrationPagePatch7}
\begin{paste}{ugProblemIntegrationPageFull7}{ugProblemIntegrationPageEmpty7}
\pastebutton{ugProblemIntegrationPageFull7}{\hidepaste}
\tab{5}\spadcommand{complexIntegrate(log(1 + sqrt(a * x + b)) / x, x)}
\indentrel{3}\begin{verbatim}
           x      ÚÄÄÄÄÄÄÄÄ¿
         Ú¿  log(\³b + %E a  + 1)
   (7)   ³   ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ d%E
        ÀÙ            %E
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIntegrationPageEmpty7}
\begin{paste}{ugProblemIntegrationPageEmpty7}{ugProblemIntegrationPagePatch7}
\pastebutton{ugProblemIntegrationPageEmpty7}{\showpaste}
\tab{5}\spadcommand{complexIntegrate(log(1 + sqrt(a * x + b)) / x, x)}
\end{paste}\end{patch}

\begin{patch}{ugProblemIntegrationPagePatch8}
\begin{paste}{ugProblemIntegrationPageFull8}{ugProblemIntegrationPageEmpty8}
\pastebutton{ugProblemIntegrationPageFull8}{\hidepaste}
\tab{5}\spadcommand{integrate((x**4 - 3*x**2 + 6)/(x**6-5*x**4+5*x**2+4), x = 1..2)}
\indentrel{3}\begin{verbatim}
                                               1
        2atan(8) + 2atan(5) + 2atan(2) + 2atan(Ä) - %pi
                                               2
   (8)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                               2
Type: Union(f1: OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIntegrationPageEmpty8}
\begin{paste}{ugProblemIntegrationPageEmpty8}{ugProblemIntegrationPagePatch8}
\pastebutton{ugProblemIntegrationPageEmpty8}{\showpaste}
\tab{5}\spadcommand{integrate((x**4 - 3*x**2 + 6)/(x**6-5*x**4+5*x**2+4), x = 1..2)}
\end{paste}\end{patch}

\begin{patch}{ugProblemIntegrationPagePatch9}
\begin{paste}{ugProblemIntegrationPageFull9}{ugProblemIntegrationPageEmpty9}
\pastebutton{ugProblemIntegrationPageFull9}{\hidepaste}
\tab{5}\spadcommand{integrate(1/(x**2-a), x = 1..2)}
\indentrel{3}\begin{verbatim}
   (9)  potentialPole
                   Type: Union(pole: potentialPole,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIntegrationPageEmpty9}
\begin{paste}{ugProblemIntegrationPageEmpty9}{ugProblemIntegrationPagePatch9}
\pastebutton{ugProblemIntegrationPageEmpty9}{\showpaste}
\tab{5}\spadcommand{integrate(1/(x**2-a), x = 1..2)}
\end{paste}\end{patch}

\begin{patch}{ugProblemIntegrationPagePatch10}
\begin{paste}{ugProblemIntegrationPageFull10}{ugProblemIntegrationPageEmpty10}
\pastebutton{ugProblemIntegrationPageFull10}{\hidepaste}
\tab{5}\spadcommand{integrate(1/(x**2-a), x = 1..2, "noPole")}
\indentrel{3}\begin{verbatim}
   (10)
   [
                    2       ÚÄ¿    3     2
               (- 4a  - 4a)\³a  + a  + 6a  + a
         - log(ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ)
                          2
                         a  - 2a + 1
       + 
                  2        ÚÄ¿    3      2
             (- 8a  - 32a)\³a  + a  + 24a  + 16a
         log(ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ)
                          2
                         a  - 8a + 16
    /
         ÚÄ¿
       4\³a
     ,
             ÚÄÄÄ¿          ÚÄÄÄ¿
           2\³- a          \³- a
    - atan(ÄÄÄÄÄÄÄ) + atan(ÄÄÄÄÄÄ)
              a               a
    ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ]
                 ÚÄÄÄ¿
                \³- a
Type: Union(f2: List OrderedCompletion Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIntegrationPageEmpty10}
\begin{paste}{ugProblemIntegrationPageEmpty10}{ugProblemIntegrationPagePatch10}
\pastebutton{ugProblemIntegrationPageEmpty10}{\showpaste}
\tab{5}\spadcommand{integrate(1/(x**2-a), x = 1..2, "noPole")}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugProblemSeriesPage}{ug08.ht}{Working with Power Series}
\pageto{notitle}{ugxProblemDEQSeriesPage}
\pageto{notitle}{ugxProblemSeriesCreatePage}
\pageto{notitle}{ugxProblemSeriesCoefficientsPage}
\pageto{notitle}{ugxProblemSeriesArithmeticPage}
\pageto{notitle}{ugxProblemSeriesFunctionsPage}
\pageto{notitle}{ugxProblemSeriesConversionsPage}
\pageto{notitle}{ugxProblemSeriesFormulaPage}
\pageto{notitle}{ugxProblemSeriesSubstitutePage}
\pageto{notitle}{ugxProblemSeriesBernoulliPage}
\begin{chunk}{ug08.ht}
\begin{page}{ugProblemSeriesPage}{8.9. Working with Power Series}
\beginscroll
%
Axiom has very sophisticated facilities for working with power
series.
Infinite series are represented by a list of the
coefficients that have already been determined, together with a
function for computing the additional coefficients if needed.
%
The system command that determines how many terms of a series is displayed
is \spadcmd{)set streams calculate}.
For the purposes of this book, we have used this system command to display
fewer than ten terms.
Series can be created from expressions, from functions for the
series coefficients, and from applications of operations on
existing series.
The most general function for creating a series is called
\axiomFun{series}, although you can also use \axiomFun{taylor},
\axiomFun{laurent} and \axiomFun{puiseux} in situations where you
know what kind of exponents are involved.

For information about solving differential equations in terms of
power series, see 
\downlink{``Power Series Solutions of Differential Equations''}
{ugxProblemDEQSeriesPage} in 
Section 8.10.3\ignore{ugxProblemDEQSeries}.

\beginmenu
  \menudownlink{{8.9.1. Creation of Power Series}}
{ugxProblemSeriesCreatePage}
  \menudownlink{{8.9.2. Coefficients of Power Series}}
{ugxProblemSeriesCoefficientsPage}
  \menudownlink{{8.9.3. Power Series Arithmetic}}
{ugxProblemSeriesArithmeticPage}
  \menudownlink{{8.9.4. Functions on Power Series}}
{ugxProblemSeriesFunctionsPage}
  \menudownlink{{8.9.5. Converting to Power Series}}
{ugxProblemSeriesConversionsPage}
  \menudownlink{{8.9.6. Power Series from Formulas}}
{ugxProblemSeriesFormulaPage}
  \menudownlink{{8.9.7. Substituting Numerical Values in Power Series}}
{ugxProblemSeriesSubstitutePage}
  \menudownlink{{8.9.8. Example: Bernoulli Polynomials and Sums of Powers}}
{ugxProblemSeriesBernoulliPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugxProblemSeriesCreatePage}{ug08.ht}{Creation of Power Series}
\pageto{notitle}{ugxProblemSeriesConversionsPage}
\pageto{notitle}{ugTypesDeclarePage}
\pageto{notitle}{ugxProblemSeriesFunctionsPage}
\pageto{notitle}{ugxProblemSeriesFormulaPage}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemSeriesCreatePage}{8.9.1. Creation of Power Series}
\beginscroll

\labelSpace{4pc}
\xtc{
This is the easiest way to create a power series.
This tells Axiom that \axiom{x} is to be treated as a power series,
so functions of \axiom{x} are again power series.
}{
\spadpaste{x := series 'x \bound{x}}
}
%
We didn't say anything about the coefficients of the power
series, so the coefficients are general expressions over the integers.
This allows us to introduce denominators, symbolic constants, and other
variables as needed.
\xtc{
Here the coefficients are integers (note that the coefficients
are the Fibonacci
numbers).
}{
\spadpaste{1/(1 - x - x**2) \free{x}}
}
\xtc{
This series has coefficients that are rational numbers.
}{
\spadpaste{sin(x) \free{x}}
}
\xtc{
When you enter this expression
you introduce the symbolic constants \axiom{sin(1)} and \axiom{cos(1).}
}{
\spadpaste{sin(1 + x) \free{x}}
}
\xtc{
When you enter the expression
the variable \axiom{a} appears in the resulting series expansion.
}{
\spadpaste{sin(a * x) \free{x}}
}

\xtc{
You can also convert an expression into a series expansion.
This expression creates the series expansion of \axiom{1/log(y)}
about \axiom{y = 1}.
For details and more examples, see
\downlink{``Converting to Power Series''}
{ugxProblemSeriesConversionsPage} in Section 
8.9.5\ignore{ugxProblemSeriesConversions}.
}{
\spadpaste{series(1/log(y),y = 1)}
}

You can create power series with more general coefficients.
You normally accomplish this via a type declaration (see
\downlink{``Declarations''}{ugTypesDeclarePage} in Section 
2.3\ignore{ugTypesDeclare}).
See 
\downlink{``Functions on Power Series''}
{ugxProblemSeriesFunctionsPage}
in Section 8.9.4\ignore{ugxProblemSeriesFunctions} 
for some warnings about working with declared series.

\xtc{
We declare that \axiom{y} is a one-variable Taylor series
(\axiomType{UTS} is the abbreviation for 
\axiomType{UnivariateTaylorSeries})
in the variable \axiom{z} with \axiomType{FLOAT}
(that is, floating-point) coefficients, centered about \axiom{0.}
Then, by assignment, we obtain the Taylor expansion of
\axiom{exp(z)} with floating-point coefficients.
}{
\spadpaste{y : UTS(FLOAT,'z,0) := exp(z) \bound{y}}
}

You can also create a power series by giving an explicit formula
for its \eth{\axiom{n}} coefficient.
For details and more examples, see
\downlink{``Power Series from Formulas''}{ugxProblemSeriesFormulaPage} 
in Section 8.9.6\ignore{ugxProblemSeriesFormula}.

\xtc{
To create a series about
\axiom{w = 0} whose \eth{\axiom{n}} Taylor coefficient
is \axiom{1/n!}, you can evaluate this expression.
This is the Taylor expansion of \axiom{exp(w)} at \axiom{w = 0}.
}{
\spadpaste{series(1/factorial(n),n,w = 0)}
}
%

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxProblemSeriesCreatePagePatch1}
\begin{paste}{ugxProblemSeriesCreatePageFull1}{ugxProblemSeriesCreatePageEmpty1}
\pastebutton{ugxProblemSeriesCreatePageFull1}{\hidepaste}
\tab{5}\spadcommand{x := series 'x\bound{x }}
\indentrel{3}\begin{verbatim}
   (1)  x
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCreatePageEmpty1}
\begin{paste}{ugxProblemSeriesCreatePageEmpty1}{ugxProblemSeriesCreatePagePatch1}
\pastebutton{ugxProblemSeriesCreatePageEmpty1}{\showpaste}
\tab{5}\spadcommand{x := series 'x\bound{x }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCreatePagePatch2}
\begin{paste}{ugxProblemSeriesCreatePageFull2}{ugxProblemSeriesCreatePageEmpty2}
\pastebutton{ugxProblemSeriesCreatePageFull2}{\hidepaste}
\tab{5}\spadcommand{1/(1 - x - x**2)\free{x }}
\indentrel{3}\begin{verbatim}
   (2)
               2     3     4     5      6      7      8
     1 + x + 2x  + 3x  + 5x  + 8x  + 13x  + 21x  + 34x
   + 
        9      10      11
     55x  + 89x   + O(x  )
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCreatePageEmpty2}
\begin{paste}{ugxProblemSeriesCreatePageEmpty2}{ugxProblemSeriesCreatePagePatch2}
\pastebutton{ugxProblemSeriesCreatePageEmpty2}{\showpaste}
\tab{5}\spadcommand{1/(1 - x - x**2)\free{x }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCreatePagePatch3}
\begin{paste}{ugxProblemSeriesCreatePageFull3}{ugxProblemSeriesCreatePageEmpty3}
\pastebutton{ugxProblemSeriesCreatePageFull3}{\hidepaste}
\tab{5}\spadcommand{sin(x)\free{x }}
\indentrel{3}\begin{verbatim}
   (3)
         1  3    1   5     1   7      1    9
     x - Ä x  + ÄÄÄ x  - ÄÄÄÄ x  + ÄÄÄÄÄÄ x
         6      120      5040      362880
   + 
           1     11      12
     - ÄÄÄÄÄÄÄÄ x   + O(x  )
       39916800
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCreatePageEmpty3}
\begin{paste}{ugxProblemSeriesCreatePageEmpty3}{ugxProblemSeriesCreatePagePatch3}
\pastebutton{ugxProblemSeriesCreatePageEmpty3}{\showpaste}
\tab{5}\spadcommand{sin(x)\free{x }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCreatePagePatch4}
\begin{paste}{ugxProblemSeriesCreatePageFull4}{ugxProblemSeriesCreatePageEmpty4}
\pastebutton{ugxProblemSeriesCreatePageFull4}{\hidepaste}
\tab{5}\spadcommand{sin(1 + x)\free{x }}
\indentrel{3}\begin{verbatim}
   (4)
                        sin(1)  2   cos(1)  3   sin(1)  4
     sin(1) + cos(1)x - ÄÄÄÄÄÄ x  - ÄÄÄÄÄÄ x  + ÄÄÄÄÄÄ x
                           2           6          24
   + 
     cos(1)  5   sin(1)  6   cos(1)  7   sin(1)  8
     ÄÄÄÄÄÄ x  - ÄÄÄÄÄÄ x  - ÄÄÄÄÄÄ x  + ÄÄÄÄÄÄ x
       120         720        5040        40320
   + 
     cos(1)  9    sin(1)  10      11
     ÄÄÄÄÄÄ x  - ÄÄÄÄÄÄÄ x   + O(x  )
     362880      3628800
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCreatePageEmpty4}
\begin{paste}{ugxProblemSeriesCreatePageEmpty4}{ugxProblemSeriesCreatePagePatch4}
\pastebutton{ugxProblemSeriesCreatePageEmpty4}{\showpaste}
\tab{5}\spadcommand{sin(1 + x)\free{x }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCreatePagePatch5}
\begin{paste}{ugxProblemSeriesCreatePageFull5}{ugxProblemSeriesCreatePageEmpty5}
\pastebutton{ugxProblemSeriesCreatePageFull5}{\hidepaste}
\tab{5}\spadcommand{sin(a * x)\free{x }}
\indentrel{3}\begin{verbatim}
   (5)
            3        5        7          9
           a   3    a   5    a    7     a     9
     a x - ÄÄ x  + ÄÄÄ x  - ÄÄÄÄ x  + ÄÄÄÄÄÄ x
            6      120      5040      362880
   + 
           11
          a      11      12
     - ÄÄÄÄÄÄÄÄ x   + O(x  )
       39916800
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCreatePageEmpty5}
\begin{paste}{ugxProblemSeriesCreatePageEmpty5}{ugxProblemSeriesCreatePagePatch5}
\pastebutton{ugxProblemSeriesCreatePageEmpty5}{\showpaste}
\tab{5}\spadcommand{sin(a * x)\free{x }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCreatePagePatch6}
\begin{paste}{ugxProblemSeriesCreatePageFull6}{ugxProblemSeriesCreatePageEmpty6}
\pastebutton{ugxProblemSeriesCreatePageFull6}{\hidepaste}
\tab{5}\spadcommand{series(1/log(y),y = 1)}
\indentrel{3}\begin{verbatim}
   (6)
            - 1   1    1            1        2
     (y - 1)    + Ä - ÄÄ (y - 1) + ÄÄ (y - 1)
                  2   12           24
   + 
        19        3    3         4    863         5
     - ÄÄÄ (y - 1)  + ÄÄÄ (y - 1)  - ÄÄÄÄÄ (y - 1)
       720            160            60480
   + 
      275         6    33953         7     8183         8
     ÄÄÄÄÄ (y - 1)  - ÄÄÄÄÄÄÄ (y - 1)  + ÄÄÄÄÄÄÄ (y - 1)
     24192            3628800            1036800
   + 
        3250433         9            10
     - ÄÄÄÄÄÄÄÄÄ (y - 1)  + O((y - 1)  )
       479001600
  Type: UnivariatePuiseuxSeries(Expression Integer,y,1)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCreatePageEmpty6}
\begin{paste}{ugxProblemSeriesCreatePageEmpty6}{ugxProblemSeriesCreatePagePatch6}
\pastebutton{ugxProblemSeriesCreatePageEmpty6}{\showpaste}
\tab{5}\spadcommand{series(1/log(y),y = 1)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCreatePagePatch7}
\begin{paste}{ugxProblemSeriesCreatePageFull7}{ugxProblemSeriesCreatePageEmpty7}
\pastebutton{ugxProblemSeriesCreatePageFull7}{\hidepaste}
\tab{5}\spadcommand{y : UTS(FLOAT,'z,0) := exp(z)\bound{y }}
\indentrel{3}\begin{verbatim}
   (7)
                    2                            3
     1.0 + z + 0.5 z  + 0.1666666666 6666666667 z
   + 
                                4
     0.0416666666 6666666666 7 z
   + 
                                 5
     0.0083333333 3333333333 34 z
   + 
                                 6
     0.0013888888 8888888888 89 z
   + 
                                 7
     0.0001984126 9841269841 27 z
   + 
                                   8
     0.0000248015 8730158730 1587 z
   + 
                                    9
     0.0000027557 3192239858 90653 z
   + 
                                   10      11
     0.2755731922 3985890653 E -6 z   + O(z  )
              Type: UnivariateTaylorSeries(Float,z,0.0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCreatePageEmpty7}
\begin{paste}{ugxProblemSeriesCreatePageEmpty7}{ugxProblemSeriesCreatePagePatch7}
\pastebutton{ugxProblemSeriesCreatePageEmpty7}{\showpaste}
\tab{5}\spadcommand{y : UTS(FLOAT,'z,0) := exp(z)\bound{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCreatePagePatch8}
\begin{paste}{ugxProblemSeriesCreatePageFull8}{ugxProblemSeriesCreatePageEmpty8}
\pastebutton{ugxProblemSeriesCreatePageFull8}{\hidepaste}
\tab{5}\spadcommand{series(1/factorial(n),n,w = 0)}
\indentrel{3}\begin{verbatim}
   (8)
             1  2   1  3    1  4    1   5    1   6
     1 + w + Ä w  + Ä w  + ÄÄ w  + ÄÄÄ w  + ÄÄÄ w
             2      6      24      120      720
   + 
     1   7     1    8      1    9      1     10      11
   ÄÄÄÄ w  + ÄÄÄÄÄ w  + ÄÄÄÄÄÄ w  + ÄÄÄÄÄÄÄ w   + O(w  )
   5040      40320      362880      3628800
  Type: UnivariatePuiseuxSeries(Expression Integer,w,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCreatePageEmpty8}
\begin{paste}{ugxProblemSeriesCreatePageEmpty8}{ugxProblemSeriesCreatePagePatch8}
\pastebutton{ugxProblemSeriesCreatePageEmpty8}{\showpaste}
\tab{5}\spadcommand{series(1/factorial(n),n,w = 0)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxProblemSeriesCoefficientsPage}{ug08.ht}
{Coefficients of Power Series}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemSeriesCoefficientsPage}
{8.9.2. Coefficients of Power Series}
\beginscroll

You can extract any coefficient from a power series---even one
that hasn't been computed yet.
This is possible because in Axiom, infinite series are
represented by a list of the coefficients that have already been
determined, together with a function for computing the additional
coefficients.
(This is known as {\it lazy evaluation}.) When you ask for a
coefficient that hasn't yet been computed, Axiom computes
whatever additional coefficients it needs and then stores them in
the representation of the power series.

\xtc{
Here's an example of how to extract the coefficients of a power series.
}{
\spadpaste{x := series(x) \bound{x}}
}
\xtc{
}{
\spadpaste{y := exp(x) * sin(x) \free{x} \bound{y}}
}
\xtc{
This coefficient is readily available.
}{
\spadpaste{coefficient(y,6) \free{y}}
}
\xtc{
But let's get the fifteenth coefficient of \axiom{y}.
}{
\spadpaste{coefficient(y,15) \free{y} \bound{y15}}
}
\xtc{
If you look at \axiom{y}
then you see that the coefficients up to order \axiom{15}
have all been computed.
}{
\spadpaste{y \free{y15}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxProblemSeriesCoefficientsPagePatch1}
\begin{paste}{ugxProblemSeriesCoefficientsPageFull1}{ugxProblemSeriesCoefficientsPageEmpty1}
\pastebutton{ugxProblemSeriesCoefficientsPageFull1}{\hidepaste}
\tab{5}\spadcommand{x := series(x)\bound{x }}
\indentrel{3}\begin{verbatim}
   (1)  x
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCoefficientsPageEmpty1}
\begin{paste}{ugxProblemSeriesCoefficientsPageEmpty1}{ugxProblemSeriesCoefficientsPagePatch1}
\pastebutton{ugxProblemSeriesCoefficientsPageEmpty1}{\showpaste}
\tab{5}\spadcommand{x := series(x)\bound{x }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCoefficientsPagePatch2}
\begin{paste}{ugxProblemSeriesCoefficientsPageFull2}{ugxProblemSeriesCoefficientsPageEmpty2}
\pastebutton{ugxProblemSeriesCoefficientsPageFull2}{\hidepaste}
\tab{5}\spadcommand{y := exp(x) * sin(x)\free{x }\bound{y }}
\indentrel{3}\begin{verbatim}
   (2)
          2   1  3    1  5    1  6    1   7     1    9
     x + x  + Ä x  - ÄÄ x  - ÄÄ x  - ÄÄÄ x  + ÄÄÄÄÄ x
              3      30      90      630      22680
   + 
        1    10      1     11      12
     ÄÄÄÄÄÄ x   + ÄÄÄÄÄÄÄ x   + O(x  )
     113400       1247400
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCoefficientsPageEmpty2}
\begin{paste}{ugxProblemSeriesCoefficientsPageEmpty2}{ugxProblemSeriesCoefficientsPagePatch2}
\pastebutton{ugxProblemSeriesCoefficientsPageEmpty2}{\showpaste}
\tab{5}\spadcommand{y := exp(x) * sin(x)\free{x }\bound{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCoefficientsPagePatch3}
\begin{paste}{ugxProblemSeriesCoefficientsPageFull3}{ugxProblemSeriesCoefficientsPageEmpty3}
\pastebutton{ugxProblemSeriesCoefficientsPageFull3}{\hidepaste}
\tab{5}\spadcommand{coefficient(y,6)\free{y }}
\indentrel{3}\begin{verbatim}
           1
   (3)  - ÄÄ
          90
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCoefficientsPageEmpty3}
\begin{paste}{ugxProblemSeriesCoefficientsPageEmpty3}{ugxProblemSeriesCoefficientsPagePatch3}
\pastebutton{ugxProblemSeriesCoefficientsPageEmpty3}{\showpaste}
\tab{5}\spadcommand{coefficient(y,6)\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCoefficientsPagePatch4}
\begin{paste}{ugxProblemSeriesCoefficientsPageFull4}{ugxProblemSeriesCoefficientsPageEmpty4}
\pastebutton{ugxProblemSeriesCoefficientsPageFull4}{\hidepaste}
\tab{5}\spadcommand{coefficient(y,15)\free{y }\bound{y15 }}
\indentrel{3}\begin{verbatim}
               1
   (4)  - ÄÄÄÄÄÄÄÄÄÄÄ
          10216206000
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCoefficientsPageEmpty4}
\begin{paste}{ugxProblemSeriesCoefficientsPageEmpty4}{ugxProblemSeriesCoefficientsPagePatch4}
\pastebutton{ugxProblemSeriesCoefficientsPageEmpty4}{\showpaste}
\tab{5}\spadcommand{coefficient(y,15)\free{y }\bound{y15 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCoefficientsPagePatch5}
\begin{paste}{ugxProblemSeriesCoefficientsPageFull5}{ugxProblemSeriesCoefficientsPageEmpty5}
\pastebutton{ugxProblemSeriesCoefficientsPageFull5}{\hidepaste}
\tab{5}\spadcommand{y\free{y15 }}
\indentrel{3}\begin{verbatim}
   (5)
          2   1  3    1  5    1  6    1   7     1    9
     x + x  + Ä x  - ÄÄ x  - ÄÄ x  - ÄÄÄ x  + ÄÄÄÄÄ x
              3      30      90      630      22680
   + 
        1    10      1     11       1     13
     ÄÄÄÄÄÄ x   + ÄÄÄÄÄÄÄ x   - ÄÄÄÄÄÄÄÄ x
     113400       1247400       97297200
   + 
           1      14        1       15      16
     - ÄÄÄÄÄÄÄÄÄ x   - ÄÄÄÄÄÄÄÄÄÄÄ x   + O(x  )
       681080400       10216206000
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesCoefficientsPageEmpty5}
\begin{paste}{ugxProblemSeriesCoefficientsPageEmpty5}{ugxProblemSeriesCoefficientsPagePatch5}
\pastebutton{ugxProblemSeriesCoefficientsPageEmpty5}{\showpaste}
\tab{5}\spadcommand{y\free{y15 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxProblemSeriesArithmeticPage}{ug08.ht}
{Power Series Arithmetic}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemSeriesArithmeticPage}
{8.9.3. Power Series Arithmetic}
\beginscroll

You can manipulate power series using the usual arithmetic operations
\axiomOpFrom{+}{UnivariatePuiseuxSeries},
\axiomOpFrom{-}{UnivariatePuiseuxSeries},
\axiomOpFrom{*}{UnivariatePuiseuxSeries}, and
\axiomOpFrom{/}{UnivariatePuiseuxSeries}.
%

\labelSpace{1pc}
\xtc{
The results of these operations are also power series.
}{
\spadpaste{x := series x \bound{x}}
}
\xtc{
}{
\spadpaste{(3 + x) / (1 + 7*x)}
}
\xtc{
You can also compute \axiom{f(x) ** g(x)}, where 
\axiom{f(x)} and \axiom{g(x)}
are two power series.
}{
\spadpaste{base := 1 / (1 - x) \free{x} \bound{base}}
}
%
\xtc{
}{
\spadpaste{expon := x * base \free{x base} \bound{expon}}
}
%
\xtc{
}{
\spadpaste{base ** expon \free{base expon}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxProblemSeriesArithmeticPagePatch1}
\begin{paste}{ugxProblemSeriesArithmeticPageFull1}{ugxProblemSeriesArithmeticPageEmpty1}
\pastebutton{ugxProblemSeriesArithmeticPageFull1}{\hidepaste}
\tab{5}\spadcommand{x := series x\bound{x }}
\indentrel{3}\begin{verbatim}
   (1)  x
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesArithmeticPageEmpty1}
\begin{paste}{ugxProblemSeriesArithmeticPageEmpty1}{ugxProblemSeriesArithmeticPagePatch1}
\pastebutton{ugxProblemSeriesArithmeticPageEmpty1}{\showpaste}
\tab{5}\spadcommand{x := series x\bound{x }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesArithmeticPagePatch2}
\begin{paste}{ugxProblemSeriesArithmeticPageFull2}{ugxProblemSeriesArithmeticPageEmpty2}
\pastebutton{ugxProblemSeriesArithmeticPageFull2}{\hidepaste}
\tab{5}\spadcommand{(3 + x) / (1 + 7*x)}
\indentrel{3}\begin{verbatim}
   (2)
                   2       3        4         5          6
     3 - 20x + 140x  - 980x  + 6860x  - 48020x  + 336140x
   + 
               7            8             9             10
     - 2352980x  + 16470860x  - 115296020x  + 807072140x
   + 
        11
     O(x  )
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesArithmeticPageEmpty2}
\begin{paste}{ugxProblemSeriesArithmeticPageEmpty2}{ugxProblemSeriesArithmeticPagePatch2}
\pastebutton{ugxProblemSeriesArithmeticPageEmpty2}{\showpaste}
\tab{5}\spadcommand{(3 + x) / (1 + 7*x)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesArithmeticPagePatch3}
\begin{paste}{ugxProblemSeriesArithmeticPageFull3}{ugxProblemSeriesArithmeticPageEmpty3}
\pastebutton{ugxProblemSeriesArithmeticPageFull3}{\hidepaste}
\tab{5}\spadcommand{base := 1 / (1 - x)\free{x }\bound{base }}
\indentrel{3}\begin{verbatim}
   (3)
              2    3    4    5    6    7    8    9    10
     1 + x + x  + x  + x  + x  + x  + x  + x  + x  + x
   + 
        11
     O(x  )
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesArithmeticPageEmpty3}
\begin{paste}{ugxProblemSeriesArithmeticPageEmpty3}{ugxProblemSeriesArithmeticPagePatch3}
\pastebutton{ugxProblemSeriesArithmeticPageEmpty3}{\showpaste}
\tab{5}\spadcommand{base := 1 / (1 - x)\free{x }\bound{base }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesArithmeticPagePatch4}
\begin{paste}{ugxProblemSeriesArithmeticPageFull4}{ugxProblemSeriesArithmeticPageEmpty4}
\pastebutton{ugxProblemSeriesArithmeticPageFull4}{\hidepaste}
\tab{5}\spadcommand{expon := x * base\free{x base }\bound{expon }}
\indentrel{3}\begin{verbatim}
   (4)
          2    3    4    5    6    7    8    9    10    11
     x + x  + x  + x  + x  + x  + x  + x  + x  + x   + x
   + 
        12
     O(x  )
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesArithmeticPageEmpty4}
\begin{paste}{ugxProblemSeriesArithmeticPageEmpty4}{ugxProblemSeriesArithmeticPagePatch4}
\pastebutton{ugxProblemSeriesArithmeticPageEmpty4}{\showpaste}
\tab{5}\spadcommand{expon := x * base\free{x base }\bound{expon }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesArithmeticPagePatch5}
\begin{paste}{ugxProblemSeriesArithmeticPageFull5}{ugxProblemSeriesArithmeticPageEmpty5}
\pastebutton{ugxProblemSeriesArithmeticPageFull5}{\hidepaste}
\tab{5}\spadcommand{base ** expon\free{base expon }}
\indentrel{3}\begin{verbatim}
   (5)
          2   3  3   7  4   43  5   649  6   241  7
     1 + x  + Ä x  + Ä x  + ÄÄ x  + ÄÄÄ x  + ÄÄÄ x
              2      3      12      120       30
   + 
     3706  8   85763  9   245339  10      11
     ÄÄÄÄ x  + ÄÄÄÄÄ x  + ÄÄÄÄÄÄ x   + O(x  )
      315       5040       10080
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesArithmeticPageEmpty5}
\begin{paste}{ugxProblemSeriesArithmeticPageEmpty5}{ugxProblemSeriesArithmeticPagePatch5}
\pastebutton{ugxProblemSeriesArithmeticPageEmpty5}{\showpaste}
\tab{5}\spadcommand{base ** expon\free{base expon }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxProblemSeriesFunctionsPage}{ug08.ht}
{Functions on Power Series}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemSeriesFunctionsPage}
{8.9.4. Functions on Power Series}
\beginscroll

Once you have created a power series, you can apply transcendental
functions
(for example, \axiomFun{exp}, \axiomFun{log}, 
\axiomFun{sin}, \axiomFun{tan},
\axiomFun{cosh}, etc.) to it.

\labelSpace{1pc}
%
\xtc{
To demonstrate this, we first create the power series
expansion of the rational function
\texht{
${\displaystyle x^2} \over {\displaystyle 1 - 6x + x^2}$
}{
\axiom{x**2/(1 - 6*x + x**2)}
}
about \axiom{x = 0}.
}{
\spadpaste{x := series 'x \bound{x}}
}
%
\xtc{
}{
\spadpaste{rat := x**2 / (1 - 6*x + x**2) \free{x} \bound{rat}}
}
%
%
\xtc{
If you want to compute the series expansion of
\texht{
$\sin\left({\displaystyle x^2} \over {\displaystyle 1 - 6x + x^2}\right)$
}{
\axiom{sin(x**2/(1 - 6*x + x**2))}
}
you simply compute the sine of \axiom{rat}.
}{
\spadpaste{sin(rat) \free{rat}}
}
%

\beginImportant
\noindent {\bf Warning:}
the type of the coefficients of a power series may
affect the kind of computations that you can do with that series.
This can only happen when you have made a declaration to
specify a series domain with a certain type of coefficient.
\endImportant

\xtc{
If you evaluate
then you have declared that \axiom{y} is a one variable Taylor series
(\axiomType{UTS} is the abbreviation for \axiomType{UnivariateTaylorSeries})
in the variable \axiom{y} with \axiomType{FRAC INT}
(that is, fractions of integer) coefficients, centered about \axiom{0}.
}{
\spadpaste{y : UTS(FRAC INT,y,0) := y \bound{y}}
}
%
\xtc{
You can now compute certain power series in \axiom{y},
{\it provided} that these series have rational coefficients.
}{
\spadpaste{exp(y) \free{y}}
}
%
\xtc{
You can get examples of such series
by applying transcendental functions to
series in \axiom{y} that have no constant terms.
}{
\spadpaste{tan(y**2) \free{y}}
}
%
\xtc{
}{
\spadpaste{cos(y + y**5) \free{y}}
}
%
%
\xtc{
Similarly, you can compute the logarithm of a power series with rational
coefficients if the constant coefficient is \axiom{1.}
}{
\spadpaste{log(1 + sin(y)) \free{y}}
}
%
If you wanted to apply, say, the operation \axiomFun{exp} to a power
series with a nonzero constant coefficient \texht{$a_0$}{\axiom{a0}},
then the constant coefficient of the result would be
\texht{$e^{a_0}$}{\axiom{exp(a0)}}, which is {\it not} a rational number.
Therefore, evaluating \axiom{exp(2 + tan(y))} would generate an error
message.

If you want to compute the Taylor expansion of \axiom{exp(2 +
tan(y))}, you must ensure that the coefficient domain has an operation
\axiomFun{exp} defined for it.  An example of such a domain is
\axiomType{Expression Integer}, the type of formal functional
expressions over the integers.

\xtc{
When working with coefficients of this type,
}{
\spadpaste{z : UTS(EXPR INT,z,0) := z \bound{z}}
}
\xtc{
this presents no problems.
}{
\spadpaste{exp(2 + tan(z)) \free{z}}
}
%
Another way to create Taylor series whose coefficients are expressions over
the integers is to use \axiomFun{taylor} which works similarly to
\axiomFun{series}.
%
\xtc{
This is equivalent to the previous computation, except that now we
are using the variable \axiom{w} instead of \axiom{z}.
}{
\spadpaste{w := taylor 'w \bound{w}}
}
\xtc{
}{
\spadpaste{exp(2 + tan(w)) \free{w}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxProblemSeriesFunctionsPagePatch1}
\begin{paste}{ugxProblemSeriesFunctionsPageFull1}{ugxProblemSeriesFunctionsPageEmpty1}
\pastebutton{ugxProblemSeriesFunctionsPageFull1}{\hidepaste}
\tab{5}\spadcommand{x := series 'x\bound{x }}
\indentrel{3}\begin{verbatim}
   (1)  x
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPageEmpty1}
\begin{paste}{ugxProblemSeriesFunctionsPageEmpty1}{ugxProblemSeriesFunctionsPagePatch1}
\pastebutton{ugxProblemSeriesFunctionsPageEmpty1}{\showpaste}
\tab{5}\spadcommand{x := series 'x\bound{x }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPagePatch2}
\begin{paste}{ugxProblemSeriesFunctionsPageFull2}{ugxProblemSeriesFunctionsPageEmpty2}
\pastebutton{ugxProblemSeriesFunctionsPageFull2}{\hidepaste}
\tab{5}\spadcommand{rat := x**2 / (1 - 6*x + x**2)\free{x }\bound{rat }}
\indentrel{3}\begin{verbatim}
   (2)
      2     3      4       5        6        7         8
     x  + 6x  + 35x  + 204x  + 1189x  + 6930x  + 40391x
   + 
            9           10           11            12
     235416x  + 1372105x   + 7997214x   + 46611179x
   + 
        13
     O(x  )
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPageEmpty2}
\begin{paste}{ugxProblemSeriesFunctionsPageEmpty2}{ugxProblemSeriesFunctionsPagePatch2}
\pastebutton{ugxProblemSeriesFunctionsPageEmpty2}{\showpaste}
\tab{5}\spadcommand{rat := x**2 / (1 - 6*x + x**2)\free{x }\bound{rat }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPagePatch3}
\begin{paste}{ugxProblemSeriesFunctionsPageFull3}{ugxProblemSeriesFunctionsPageEmpty3}
\pastebutton{ugxProblemSeriesFunctionsPageFull3}{\hidepaste}
\tab{5}\spadcommand{sin(rat)\free{rat }}
\indentrel{3}\begin{verbatim}
   (3)
      2     3      4       5   7133  6        7   80711  8
     x  + 6x  + 35x  + 204x  + ÄÄÄÄ x  + 6927x  + ÄÄÄÄÄ x
                                 6                  2
   + 
            9   164285281  10   31888513  11
     235068x  + ÄÄÄÄÄÄÄÄÄ x   + ÄÄÄÄÄÄÄÄ x
                   120              4
   + 
     371324777  12      13
     ÄÄÄÄÄÄÄÄÄ x   + O(x  )
         8
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPageEmpty3}
\begin{paste}{ugxProblemSeriesFunctionsPageEmpty3}{ugxProblemSeriesFunctionsPagePatch3}
\pastebutton{ugxProblemSeriesFunctionsPageEmpty3}{\showpaste}
\tab{5}\spadcommand{sin(rat)\free{rat }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPagePatch4}
\begin{paste}{ugxProblemSeriesFunctionsPageFull4}{ugxProblemSeriesFunctionsPageEmpty4}
\pastebutton{ugxProblemSeriesFunctionsPageFull4}{\hidepaste}
\tab{5}\spadcommand{y : UTS(FRAC INT,y,0) := y\bound{y }}
\indentrel{3}\begin{verbatim}
   (4)  y
     Type: UnivariateTaylorSeries(Fraction Integer,y,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPageEmpty4}
\begin{paste}{ugxProblemSeriesFunctionsPageEmpty4}{ugxProblemSeriesFunctionsPagePatch4}
\pastebutton{ugxProblemSeriesFunctionsPageEmpty4}{\showpaste}
\tab{5}\spadcommand{y : UTS(FRAC INT,y,0) := y\bound{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPagePatch5}
\begin{paste}{ugxProblemSeriesFunctionsPageFull5}{ugxProblemSeriesFunctionsPageEmpty5}
\pastebutton{ugxProblemSeriesFunctionsPageFull5}{\hidepaste}
\tab{5}\spadcommand{exp(y)\free{y }}
\indentrel{3}\begin{verbatim}
   (5)
             1  2   1  3    1  4    1   5    1   6
     1 + y + Ä y  + Ä y  + ÄÄ y  + ÄÄÄ y  + ÄÄÄ y
             2      6      24      120      720
   + 
     1   7     1    8      1    9      1     10      11
   ÄÄÄÄ y  + ÄÄÄÄÄ y  + ÄÄÄÄÄÄ y  + ÄÄÄÄÄÄÄ y   + O(y  )
   5040      40320      362880      3628800
     Type: UnivariateTaylorSeries(Fraction Integer,y,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPageEmpty5}
\begin{paste}{ugxProblemSeriesFunctionsPageEmpty5}{ugxProblemSeriesFunctionsPagePatch5}
\pastebutton{ugxProblemSeriesFunctionsPageEmpty5}{\showpaste}
\tab{5}\spadcommand{exp(y)\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPagePatch6}
\begin{paste}{ugxProblemSeriesFunctionsPageFull6}{ugxProblemSeriesFunctionsPageEmpty6}
\pastebutton{ugxProblemSeriesFunctionsPageFull6}{\hidepaste}
\tab{5}\spadcommand{tan(y**2)\free{y }}
\indentrel{3}\begin{verbatim}
         2   1  6    2  10      11
   (6)  y  + Ä y  + ÄÄ y   + O(y  )
             3      15
     Type: UnivariateTaylorSeries(Fraction Integer,y,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPageEmpty6}
\begin{paste}{ugxProblemSeriesFunctionsPageEmpty6}{ugxProblemSeriesFunctionsPagePatch6}
\pastebutton{ugxProblemSeriesFunctionsPageEmpty6}{\showpaste}
\tab{5}\spadcommand{tan(y**2)\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPagePatch7}
\begin{paste}{ugxProblemSeriesFunctionsPageFull7}{ugxProblemSeriesFunctionsPageEmpty7}
\pastebutton{ugxProblemSeriesFunctionsPageFull7}{\hidepaste}
\tab{5}\spadcommand{cos(y + y**5)\free{y }}
\indentrel{3}\begin{verbatim}
   (7)
         1  2    1  4   721  6    6721  8   1844641  10
     1 - Ä y  + ÄÄ y  - ÄÄÄ y  + ÄÄÄÄÄ y  - ÄÄÄÄÄÄÄ y
         2      24      720      40320      3628800
   + 
        11
     O(y  )
     Type: UnivariateTaylorSeries(Fraction Integer,y,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPageEmpty7}
\begin{paste}{ugxProblemSeriesFunctionsPageEmpty7}{ugxProblemSeriesFunctionsPagePatch7}
\pastebutton{ugxProblemSeriesFunctionsPageEmpty7}{\showpaste}
\tab{5}\spadcommand{cos(y + y**5)\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPagePatch8}
\begin{paste}{ugxProblemSeriesFunctionsPageFull8}{ugxProblemSeriesFunctionsPageEmpty8}
\pastebutton{ugxProblemSeriesFunctionsPageFull8}{\hidepaste}
\tab{5}\spadcommand{log(1 + sin(y))\free{y }}
\indentrel{3}\begin{verbatim}
   (8)
         1  2   1  3    1  4    1  5    1  6    61   7
     y - Ä y  + Ä y  - ÄÄ y  + ÄÄ y  - ÄÄ y  + ÄÄÄÄ y
         2      6      12      24      45      5040
   + 
        17   8    277   9     31   10      11
     - ÄÄÄÄ y  + ÄÄÄÄÄ y  - ÄÄÄÄÄ y   + O(y  )
       2520      72576      14175
     Type: UnivariateTaylorSeries(Fraction Integer,y,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPageEmpty8}
\begin{paste}{ugxProblemSeriesFunctionsPageEmpty8}{ugxProblemSeriesFunctionsPagePatch8}
\pastebutton{ugxProblemSeriesFunctionsPageEmpty8}{\showpaste}
\tab{5}\spadcommand{log(1 + sin(y))\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPagePatch9}
\begin{paste}{ugxProblemSeriesFunctionsPageFull9}{ugxProblemSeriesFunctionsPageEmpty9}
\pastebutton{ugxProblemSeriesFunctionsPageFull9}{\hidepaste}
\tab{5}\spadcommand{z : UTS(EXPR INT,z,0) := z\bound{z }}
\indentrel{3}\begin{verbatim}
   (9)  z
   Type: UnivariateTaylorSeries(Expression Integer,z,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPageEmpty9}
\begin{paste}{ugxProblemSeriesFunctionsPageEmpty9}{ugxProblemSeriesFunctionsPagePatch9}
\pastebutton{ugxProblemSeriesFunctionsPageEmpty9}{\showpaste}
\tab{5}\spadcommand{z : UTS(EXPR INT,z,0) := z\bound{z }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPagePatch10}
\begin{paste}{ugxProblemSeriesFunctionsPageFull10}{ugxProblemSeriesFunctionsPageEmpty10}
\pastebutton{ugxProblemSeriesFunctionsPageFull10}{\hidepaste}
\tab{5}\spadcommand{exp(2 + tan(z))\free{z }}
\indentrel{3}\begin{verbatim}
   (10)
                    2        2         2          2
       2     2    %e   2   %e   3   3%e   4   37%e   5
     %e  + %e z + ÄÄÄ z  + ÄÄÄ z  + ÄÄÄÄ z  + ÄÄÄÄÄ z
                   2        2         8        120
   + 
         2           2           2             2
     59%e   6   137%e   7   871%e   8   41641%e   9
     ÄÄÄÄÄ z  + ÄÄÄÄÄÄ z  + ÄÄÄÄÄÄ z  + ÄÄÄÄÄÄÄÄ z
      240         720        5760        362880
   + 
             2
     325249%e   10      11
     ÄÄÄÄÄÄÄÄÄ z   + O(z  )
      3628800
   Type: UnivariateTaylorSeries(Expression Integer,z,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPageEmpty10}
\begin{paste}{ugxProblemSeriesFunctionsPageEmpty10}{ugxProblemSeriesFunctionsPagePatch10}
\pastebutton{ugxProblemSeriesFunctionsPageEmpty10}{\showpaste}
\tab{5}\spadcommand{exp(2 + tan(z))\free{z }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPagePatch11}
\begin{paste}{ugxProblemSeriesFunctionsPageFull11}{ugxProblemSeriesFunctionsPageEmpty11}
\pastebutton{ugxProblemSeriesFunctionsPageFull11}{\hidepaste}
\tab{5}\spadcommand{w := taylor 'w\bound{w }}
\indentrel{3}\begin{verbatim}
   (11)  w
   Type: UnivariateTaylorSeries(Expression Integer,w,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPageEmpty11}
\begin{paste}{ugxProblemSeriesFunctionsPageEmpty11}{ugxProblemSeriesFunctionsPagePatch11}
\pastebutton{ugxProblemSeriesFunctionsPageEmpty11}{\showpaste}
\tab{5}\spadcommand{w := taylor 'w\bound{w }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPagePatch12}
\begin{paste}{ugxProblemSeriesFunctionsPageFull12}{ugxProblemSeriesFunctionsPageEmpty12}
\pastebutton{ugxProblemSeriesFunctionsPageFull12}{\hidepaste}
\tab{5}\spadcommand{exp(2 + tan(w))\free{w }}
\indentrel{3}\begin{verbatim}
   (12)
                    2        2         2          2
       2     2    %e   2   %e   3   3%e   4   37%e   5
     %e  + %e w + ÄÄÄ w  + ÄÄÄ w  + ÄÄÄÄ w  + ÄÄÄÄÄ w
                   2        2         8        120
   + 
         2           2           2             2
     59%e   6   137%e   7   871%e   8   41641%e   9
     ÄÄÄÄÄ w  + ÄÄÄÄÄÄ w  + ÄÄÄÄÄÄ w  + ÄÄÄÄÄÄÄÄ w
      240         720        5760        362880
   + 
             2
     325249%e   10      11
     ÄÄÄÄÄÄÄÄÄ w   + O(w  )
      3628800
   Type: UnivariateTaylorSeries(Expression Integer,w,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFunctionsPageEmpty12}
\begin{paste}{ugxProblemSeriesFunctionsPageEmpty12}{ugxProblemSeriesFunctionsPagePatch12}
\pastebutton{ugxProblemSeriesFunctionsPageEmpty12}{\showpaste}
\tab{5}\spadcommand{exp(2 + tan(w))\free{w }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxProblemSeriesConversionsPage}{ug08.ht}
{Converting to Power Series}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemSeriesConversionsPage}
{8.9.5. Converting to Power Series}
\beginscroll

The \axiomType{ExpressionToUnivariatePowerSeries} package provides
operations for computing series expansions of functions.

\labelSpace{1pc}
\xtc{
Evaluate this
to compute the Taylor expansion of \axiom{sin x} about
\axiom{x = 0}.
The first argument, \axiom{sin(x)}, specifies the function whose series
expansion is to be computed and the second argument, \axiom{x = 0},
specifies that the series is to be expanded in power of \axiom{(x - 0)},
that is, in power of \axiom{x}.
}{
\spadpaste{taylor(sin(x),x = 0)}
}
\xtc{
Here is the Taylor expansion of \axiom{sin x} about
\texht{$x = \frac{\pi}{6}$}{\axiom{x = \%pi/6}}:
}{
\spadpaste{taylor(sin(x),x = \%pi/6)}
}

The function to be expanded into a series may have variables other than
the series variable.
%
\xtc{
For example, we may expand \axiom{tan(x*y)} as a Taylor series in
\axiom{x}
}{
\spadpaste{taylor(tan(x*y),x = 0)}
}
%
\xtc{
or as a Taylor series in \axiom{y}.
}{
\spadpaste{taylor(tan(x*y),y = 0)}
}
\xtc{
A more interesting function is
\texht{${\displaystyle t e^{x t}} \over 
{\displaystyle e^t - 1}$}{(t * \%e**(x*t))/(\%e**t - 1)}.
When we expand this function as a Taylor series in \axiom{t}
the \eth{\axiom{n}} order coefficient is the \eth{\axiom{n}} Bernoulli
polynomial
divided by \axiom{n!}.
}{
\spadpaste{bern := taylor(t*exp(x*t)/(exp(t) - 1),t = 0) \bound{bern}}
}
\xtc{
Therefore, this and the next expression
produce the same result.
}{
\spadpaste{factorial(6) * coefficient(bern,6) \free{bern}}
}
\xtc{
}{
\spadpaste{bernoulliB(6,x)}
}

Technically, a series with terms of negative degree is not considered to
be a Taylor series, but, rather, a
{\it Laurent series}.
If you try to compute a Taylor series expansion of
\texht{$\frac{x}{\log x}$}{x/log(x)}
at \axiom{x = 1} via \axiom{taylor(x/log(x),x = 1)}
you get an error message.
The reason is that the function has a {\it pole} at \axiom{x =
1}, meaning that
its series expansion about this point has terms of negative degree.
A series with finitely many terms of negative degree is called a Laurent
series.
\xtc{
You get the desired series expansion by issuing this.
}{
\spadpaste{laurent(x/log(x),x = 1)}
}

Similarly, a series with terms of fractional degree is neither a
Taylor series nor a Laurent series.  Such a series is called a {\it
Puiseux series}.  The expression \axiom{laurent(sqrt(sec(x)),x = 3 *
\%pi/2)} results in an error message because the series expansion
about this point has terms of fractional degree.

\xtc{
However, this command produces what you want.
}{
\spadpaste{puiseux(sqrt(sec(x)),x = 3 * \%pi/2)}
}

Finally, consider the case of functions that do not have Puiseux
expansions about certain points.  An example of this is
\texht{$x^x$}{\axiom{x^x}} about \axiom{x = 0}.
\axiom{puiseux(x**x,x=0)} produces an error message because of the
type of singularity of the function at \axiom{x = 0}.

\xtc{
The general function \axiomFun{series} can be used in this case.
Notice that the series returned is not, strictly speaking, a power series
because of the \axiom{log(x)} in the expansion.
}{
\spadpaste{series(x**x,x=0)}
}

\beginImportant
The operation \axiomFun{series} returns the most general type of
infinite series.
The user who is not interested in distinguishing
between various types of infinite series may wish to use this operation
exclusively.
\endImportant

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxProblemSeriesConversionsPagePatch1}
\begin{paste}{ugxProblemSeriesConversionsPageFull1}{ugxProblemSeriesConversionsPageEmpty1}
\pastebutton{ugxProblemSeriesConversionsPageFull1}{\hidepaste}
\tab{5}\spadcommand{taylor(sin(x),x = 0)}
\indentrel{3}\begin{verbatim}
            1  3    1   5     1   7      1    9      11
   (1)  x - Ä x  + ÄÄÄ x  - ÄÄÄÄ x  + ÄÄÄÄÄÄ x  + O(x  )
            6      120      5040      362880
   Type: UnivariateTaylorSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesConversionsPageEmpty1}
\begin{paste}{ugxProblemSeriesConversionsPageEmpty1}{ugxProblemSeriesConversionsPagePatch1}
\pastebutton{ugxProblemSeriesConversionsPageEmpty1}{\showpaste}
\tab{5}\spadcommand{taylor(sin(x),x = 0)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesConversionsPagePatch2}
\begin{paste}{ugxProblemSeriesConversionsPageFull2}{ugxProblemSeriesConversionsPageEmpty2}
\pastebutton{ugxProblemSeriesConversionsPageFull2}{\hidepaste}
\tab{5}\spadcommand{taylor(sin(x),x = \%pi/6)}
\indentrel{3}\begin{verbatim}
   (2)
          ÚÄ¿                             ÚÄ¿
     1   \³3       %pi    1      %pi 2   \³3       %pi 3
     Ä + ÄÄÄÄ (x - ÄÄÄ) - Ä (x - ÄÄÄ)  - ÄÄÄÄ (x - ÄÄÄ)
     2     2        6     4       6       12        6
   + 
                      ÚÄ¿
      1      %pi 4   \³3       %pi 5     1       %pi 6
     ÄÄ (x - ÄÄÄ)  + ÄÄÄÄ (x - ÄÄÄ)  - ÄÄÄÄ (x - ÄÄÄ)
     48       6       240       6      1440       6
   + 
         ÚÄ¿
        \³3       %pi 7     1        %pi 8
     - ÄÄÄÄÄ (x - ÄÄÄ)  + ÄÄÄÄÄ (x - ÄÄÄ)
       10080       6      80640       6
   + 
       ÚÄ¿
      \³3        %pi 9      1         %pi 10
     ÄÄÄÄÄÄ (x - ÄÄÄ)  - ÄÄÄÄÄÄÄ (x - ÄÄÄ)
     725760       6      7257600       6
   + 
            %pi 11
     O((x - ÄÄÄ)  )
             6
Type: UnivariateTaylorSeries(Expression Integer,x,pi/6)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesConversionsPageEmpty2}
\begin{paste}{ugxProblemSeriesConversionsPageEmpty2}{ugxProblemSeriesConversionsPagePatch2}
\pastebutton{ugxProblemSeriesConversionsPageEmpty2}{\showpaste}
\tab{5}\spadcommand{taylor(sin(x),x = \%pi/6)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesConversionsPagePatch3}
\begin{paste}{ugxProblemSeriesConversionsPageFull3}{ugxProblemSeriesConversionsPageEmpty3}
\pastebutton{ugxProblemSeriesConversionsPageFull3}{\hidepaste}
\tab{5}\spadcommand{taylor(tan(x*y),x = 0)}
\indentrel{3}\begin{verbatim}
   (3)
          3        5         7         9
         y   3   2y   5   17y   7   62y   9      11
   y x + ÄÄ x  + ÄÄÄ x  + ÄÄÄÄ x  + ÄÄÄÄ x  + O(x  )
          3       15       315      2835
   Type: UnivariateTaylorSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesConversionsPageEmpty3}
\begin{paste}{ugxProblemSeriesConversionsPageEmpty3}{ugxProblemSeriesConversionsPagePatch3}
\pastebutton{ugxProblemSeriesConversionsPageEmpty3}{\showpaste}
\tab{5}\spadcommand{taylor(tan(x*y),x = 0)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesConversionsPagePatch4}
\begin{paste}{ugxProblemSeriesConversionsPageFull4}{ugxProblemSeriesConversionsPageEmpty4}
\pastebutton{ugxProblemSeriesConversionsPageFull4}{\hidepaste}
\tab{5}\spadcommand{taylor(tan(x*y),y = 0)}
\indentrel{3}\begin{verbatim}
   (4)
          3        5         7         9
         x   3   2x   5   17x   7   62x   9      11
   x y + ÄÄ y  + ÄÄÄ y  + ÄÄÄÄ y  + ÄÄÄÄ y  + O(y  )
          3       15       315      2835
   Type: UnivariateTaylorSeries(Expression Integer,y,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesConversionsPageEmpty4}
\begin{paste}{ugxProblemSeriesConversionsPageEmpty4}{ugxProblemSeriesConversionsPagePatch4}
\pastebutton{ugxProblemSeriesConversionsPageEmpty4}{\showpaste}
\tab{5}\spadcommand{taylor(tan(x*y),y = 0)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesConversionsPagePatch5}
\begin{paste}{ugxProblemSeriesConversionsPageFull5}{ugxProblemSeriesConversionsPageEmpty5}
\pastebutton{ugxProblemSeriesConversionsPageFull5}{\hidepaste}
\tab{5}\spadcommand{bern := taylor(t*exp(x*t)/(exp(t) - 1),t = 0)\bound{bern }}
\indentrel{3}\begin{verbatim}
   (5)
                      2                 3     2
         2x - 1     6x  - 6x + 1  2   2x  - 3x  + x  3
     1 + ÄÄÄÄÄÄ t + ÄÄÄÄÄÄÄÄÄÄÄÄ t  + ÄÄÄÄÄÄÄÄÄÄÄÄÄ t
            2            12                 12
   + 
        4      3      2            5      4      3
     30x  - 60x  + 30x  - 1  4   6x  - 15x  + 10x  - x  5
     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ t  + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ t
               720                        720
   + 
        6       5       4      2
     42x  - 126x  + 105x  - 21x  + 1  6
     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ t
                  30240
   + 
       7      6      5     3
     6x  - 21x  + 21x  - 7x  + x  7
     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ t
                30240
   + 
        8       7       6      4      2
     30x  - 120x  + 140x  - 70x  + 20x  - 1  8
     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ t
                     1209600
   + 
        9      8      7      5      3
     10x  - 45x  + 60x  - 42x  + 20x  - 3x  9
     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ t
                    3628800
   + 
        10       9       8       6       4      2
     66x   - 330x  + 495x  - 462x  + 330x  - 99x  + 5  10
     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ t
                         239500800
   + 
        11
     O(t  )
   Type: UnivariateTaylorSeries(Expression Integer,t,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesConversionsPageEmpty5}
\begin{paste}{ugxProblemSeriesConversionsPageEmpty5}{ugxProblemSeriesConversionsPagePatch5}
\pastebutton{ugxProblemSeriesConversionsPageEmpty5}{\showpaste}
\tab{5}\spadcommand{bern := taylor(t*exp(x*t)/(exp(t) - 1),t = 0)\bound{bern }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesConversionsPagePatch6}
\begin{paste}{ugxProblemSeriesConversionsPageFull6}{ugxProblemSeriesConversionsPageEmpty6}
\pastebutton{ugxProblemSeriesConversionsPageFull6}{\hidepaste}
\tab{5}\spadcommand{factorial(6) * coefficient(bern,6)\free{bern }}
\indentrel{3}\begin{verbatim}
           6       5       4      2
        42x  - 126x  + 105x  - 21x  + 1
   (6)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                       42
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesConversionsPageEmpty6}
\begin{paste}{ugxProblemSeriesConversionsPageEmpty6}{ugxProblemSeriesConversionsPagePatch6}
\pastebutton{ugxProblemSeriesConversionsPageEmpty6}{\showpaste}
\tab{5}\spadcommand{factorial(6) * coefficient(bern,6)\free{bern }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesConversionsPagePatch7}
\begin{paste}{ugxProblemSeriesConversionsPageFull7}{ugxProblemSeriesConversionsPageEmpty7}
\pastebutton{ugxProblemSeriesConversionsPageFull7}{\hidepaste}
\tab{5}\spadcommand{bernoulliB(6,x)}
\indentrel{3}\begin{verbatim}
         6     5   5  4   1  2    1
   (7)  x  - 3x  + Ä x  - Ä x  + ÄÄ
                   2      2      42
                      Type: Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesConversionsPageEmpty7}
\begin{paste}{ugxProblemSeriesConversionsPageEmpty7}{ugxProblemSeriesConversionsPagePatch7}
\pastebutton{ugxProblemSeriesConversionsPageEmpty7}{\showpaste}
\tab{5}\spadcommand{bernoulliB(6,x)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesConversionsPagePatch8}
\begin{paste}{ugxProblemSeriesConversionsPageFull8}{ugxProblemSeriesConversionsPageEmpty8}
\pastebutton{ugxProblemSeriesConversionsPageFull8}{\hidepaste}
\tab{5}\spadcommand{laurent(x/log(x),x = 1)}
\indentrel{3}\begin{verbatim}
   (8)
            - 1   3    5            1        2
     (x - 1)    + Ä + ÄÄ (x - 1) - ÄÄ (x - 1)
                  2   12           24
   + 
      11        3    11         4    271         5
     ÄÄÄ (x - 1)  - ÄÄÄÄ (x - 1)  + ÄÄÄÄÄ (x - 1)
     720            1440            60480
   + 
        13         6     7297         7     425         8
     - ÄÄÄÄ (x - 1)  + ÄÄÄÄÄÄÄ (x - 1)  - ÄÄÄÄÄÄ (x - 1)
       4480            3628800            290304
   + 
       530113         9            10
     ÄÄÄÄÄÄÄÄÄ (x - 1)  + O((x - 1)  )
     479001600
  Type: UnivariateLaurentSeries(Expression Integer,x,1)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesConversionsPageEmpty8}
\begin{paste}{ugxProblemSeriesConversionsPageEmpty8}{ugxProblemSeriesConversionsPagePatch8}
\pastebutton{ugxProblemSeriesConversionsPageEmpty8}{\showpaste}
\tab{5}\spadcommand{laurent(x/log(x),x = 1)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesConversionsPagePatch9}
\begin{paste}{ugxProblemSeriesConversionsPageFull9}{ugxProblemSeriesConversionsPageEmpty9}
\pastebutton{ugxProblemSeriesConversionsPageFull9}{\hidepaste}
\tab{5}\spadcommand{puiseux(sqrt(sec(x)),x = 3 * \%pi/2)}
\indentrel{3}\begin{verbatim}
   (9)
                 1                3                 7
               - Ä                Ä                 Ä
          3%pi   2    1      3%pi 2    1       3%pi 2
     (x - ÄÄÄÄ)    + ÄÄ (x - ÄÄÄÄ)  + ÄÄÄ (x - ÄÄÄÄ)
            2        12        2      160        2
   + 
            3%pi 5
     O((x - ÄÄÄÄ) )
              2
Type: UnivariatePuiseuxSeries(Expression Integer,x,(3*pi)/2)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesConversionsPageEmpty9}
\begin{paste}{ugxProblemSeriesConversionsPageEmpty9}{ugxProblemSeriesConversionsPagePatch9}
\pastebutton{ugxProblemSeriesConversionsPageEmpty9}{\showpaste}
\tab{5}\spadcommand{puiseux(sqrt(sec(x)),x = 3 * \%pi/2)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesConversionsPagePatch10}
\begin{paste}{ugxProblemSeriesConversionsPageFull10}{ugxProblemSeriesConversionsPageEmpty10}
\pastebutton{ugxProblemSeriesConversionsPageFull10}{\hidepaste}
\tab{5}\spadcommand{series(x**x,x=0)}
\indentrel{3}\begin{verbatim}
   (10)
                         2            3            4
                   log(x)   2   log(x)   3   log(x)   4
     1 + log(x)x + ÄÄÄÄÄÄÄ x  + ÄÄÄÄÄÄÄ x  + ÄÄÄÄÄÄÄ x
                      2            6            24
   + 
           5            6            7            8
     log(x)   5   log(x)   6   log(x)   7   log(x)   8
     ÄÄÄÄÄÄÄ x  + ÄÄÄÄÄÄÄ x  + ÄÄÄÄÄÄÄ x  + ÄÄÄÄÄÄÄ x
       120          720          5040        40320
   + 
           9            10
     log(x)   9   log(x)    10      11
     ÄÄÄÄÄÄÄ x  + ÄÄÄÄÄÄÄÄ x   + O(x  )
      362880       3628800
Type: GeneralUnivariatePowerSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesConversionsPageEmpty10}
\begin{paste}{ugxProblemSeriesConversionsPageEmpty10}{ugxProblemSeriesConversionsPagePatch10}
\pastebutton{ugxProblemSeriesConversionsPageEmpty10}{\showpaste}
\tab{5}\spadcommand{series(x**x,x=0)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxProblemSeriesFormulaPage}{ug08.ht}
{Power Series from Formulas}
\pageto{notitle}{ugxProblemSeriesConversionsPage}
\pageto{notitle}{ugUserAnonPage}
\pageto{notitle}{ugxProblemSeriesConversionsPage}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemSeriesFormulaPage}
{8.9.6. Power Series from Formulas}
\beginscroll

The \axiomType{GenerateUnivariatePowerSeries} package enables you to
create power series from explicit formulas for their \eth{\axiom{n}}
coefficients.  In what follows, we construct series expansions for
certain transcendental functions by giving formulas for their
coefficients.  You can also compute such series expansions directly
simply by specifying the function and the point about which the series
is to be expanded.  See
\downlink{``Converting to Power Series''}
{ugxProblemSeriesConversionsPage} in Section
8.9.5\ignore{ugxProblemSeriesConversions}
for more information.

Consider the Taylor expansion of \texht{$e^x$}{\axiom{\%e**x}}
about \axiom{x = 0}:
\texht{\narrowDisplay{%
\begin{array}{ccl}
e^x &=& \displaystyle 1 + x + \frac{x^2}{2} + \frac{x^3}{6} + \cdots \\ \\
    &=& \displaystyle\sum_{n=0}^\infty \frac{x^n}{n!}
\end{array}}%
}{
\begin{verbatim}
%e**x = 1 + x + x**2/2 + x**3/6 + ...
      = sum from n=0 to n=%infty of x**n / n!
\end{verbatim}
}
The \eth{\axiom{n}} Taylor coefficient is \axiom{1/n!}.
%
\xtc{
This is how you create this series in Axiom.
}{
\spadpaste{series(n +-> 1/factorial(n),x = 0)}
}

The first argument specifies a formula for the \eth{\axiom{n}}
coefficient by giving a function that maps \axiom{n} to \axiom{1/n!}.
The second argument specifies that the series is to be expanded in
powers of \axiom{(x - 0)}, that is, in powers of \axiom{x}.  Since we
did not specify an initial degree, the first term in the series was
the term of degree 0 (the constant term).  Note that the formula was
given as an anonymous function.  These are discussed in
\downlink{``Anonymous Functions''}{ugUserAnonPage} in Section
6.17\ignore{ugUserAnon}.

Consider the Taylor expansion of \axiom{log x} about \axiom{x = 1}:
\texht{\narrowDisplay{%
\begin{array}{ccl}
\log(x) &=& \displaystyle (x - 1) - \frac{(x - 1)^2}{2} + 
\frac{(x - 1)^3}{3} - \cdots \\ \\
        &=& \displaystyle\sum_{n = 1}^\infty (-1)^{n-1} \frac{(x - 1)^n}{n}
\end{array}}%
}{
\begin{verbatim}
log x = (x - 1) - \(x - 1)^2/2 + (x - 1)^3/3 - ...
      = sum from n=1 to n=%infty of (-1)**(n-1) (x - 1)**n / n
\end{verbatim}
}
If you were to evaluate the expression
\axiom{series(n +-> (-1)**(n-1) / n, x = 1)}
you would get an error message because Axiom would try to
calculate a term of degree \axiom{0} and therefore divide by \axiom{0.}

\xtc{
Instead, evaluate this.
The third argument, \axiom{1..}, indicates that only terms of degree
\axiom{n = 1, ...} are to be computed.
}{
\spadpaste{series(n +-> (-1)**(n-1)/n,x = 1,1..)}
}
%

Next consider the Taylor expansion of an odd function, say,
\axiom{sin(x)}:
\begin{verbatim}
sin x = x - x**3/3! + x**5/5! - ...
\end{verbatim}
Here every other coefficient is zero and we would like to give an
explicit formula only for the odd Taylor coefficients.
%
\xtc{
This is one way to do it.  The third argument, \axiom{1..}, specifies
that the first term to be computed is the term of degree 1.  The
fourth argument, \axiom{2}, specifies that we increment by \axiom{2}
to find the degrees of subsequent terms, that is, the next term is of
degree \axiom{1 + 2}, the next of degree \axiom{1 + 2 + 2}, etc.
}{
\spadpaste{series(n +-> (-1)**((n-1)/2)/factorial(n),x = 0,1..,2)}
}
%

\xtc{
The initial degree and the increment do not have to be integers.
For example, this expression produces a series expansion of
\texht{$\sin(x^{\frac{1}{3}})$}{\axiom{sin(x**(1/3))}}.
}{
\spadpaste{series(n +-> (-1)**((3*n-1)/2)/factorial(3*n),x = 0,1/3..,2/3)}
}
\xtc{
While the increment must be positive, the initial degree may be negative.
This yields the Laurent expansion of \axiom{csc(x)} at
\axiom{x = 0}.
%
}{
\spadpaste{cscx := 
series(n +-> (-1)**((n-1)/2) * 2 * (2**n-1) * bernoulli(numer(n+1)) 
/ factorial(n+1), x=0, -1..,2) \bound{cscx}}
}
\xtc{
Of course, the reciprocal of this power series is the Taylor expansion
of \axiom{sin(x)}.
}{
\spadpaste{1/cscx \free{cscx}}
}
%
\xtc{
As a final example,
here is the Taylor expansion of \axiom{asin(x)} about \axiom{x = 0}.
}{
\spadpaste{asinx := series(n +-> binomial(n-1,(n-1)/2)/(n*2**(n-1)),
x=0,1..,2) \bound{asinx}}
}
\xtc{
When we compute the \axiom{sin} of this series, we get \axiom{x}
(in the sense that all higher terms computed so far are zero).
}{
\spadpaste{sin(asinx) \free{asinx}}
}

As we discussed in 
\downlink{``Converting to Power Series''}
{ugxProblemSeriesConversionsPage} in Section 
8.9.5\ignore{ugxProblemSeriesConversions},
you can also use the operations \axiomFun{taylor}, \axiomFun{laurent} and
\axiomFun{puiseux} instead of \axiomFun{series} if you know ahead of time
what kind of exponents a series has.
You can't go wrong using \axiomFun{series}, though.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxProblemSeriesFormulaPagePatch1}
\begin{paste}{ugxProblemSeriesFormulaPageFull1}{ugxProblemSeriesFormulaPageEmpty1}
\pastebutton{ugxProblemSeriesFormulaPageFull1}{\hidepaste}
\tab{5}\spadcommand{series(n +-> 1/factorial(n),x = 0)}
\indentrel{3}\begin{verbatim}
   (1)
             1  2   1  3    1  4    1   5    1   6
     1 + x + Ä x  + Ä x  + ÄÄ x  + ÄÄÄ x  + ÄÄÄ x
             2      6      24      120      720
   + 
     1   7     1    8      1    9      1     10      11
   ÄÄÄÄ x  + ÄÄÄÄÄ x  + ÄÄÄÄÄÄ x  + ÄÄÄÄÄÄÄ x   + O(x  )
   5040      40320      362880      3628800
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFormulaPageEmpty1}
\begin{paste}{ugxProblemSeriesFormulaPageEmpty1}{ugxProblemSeriesFormulaPagePatch1}
\pastebutton{ugxProblemSeriesFormulaPageEmpty1}{\showpaste}
\tab{5}\spadcommand{series(n +-> 1/factorial(n),x = 0)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFormulaPagePatch2}
\begin{paste}{ugxProblemSeriesFormulaPageFull2}{ugxProblemSeriesFormulaPageEmpty2}
\pastebutton{ugxProblemSeriesFormulaPageFull2}{\hidepaste}
\tab{5}\spadcommand{series(n +-> (-1)**(n-1)/n,x = 1,1..)}
\indentrel{3}\begin{verbatim}
   (2)
               1        2   1        3   1        4
     (x - 1) - Ä (x - 1)  + Ä (x - 1)  - Ä (x - 1)
               2            3            4
   + 
     1        5   1        6   1        7   1        8
     Ä (x - 1)  - Ä (x - 1)  + Ä (x - 1)  - Ä (x - 1)
     5            6            7            8
   + 
   1        9    1        10    1        11            12
   Ä (x - 1)  - ÄÄ (x - 1)   + ÄÄ (x - 1)   + O((x - 1)  )
   9            10             11
  Type: UnivariatePuiseuxSeries(Expression Integer,x,1)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFormulaPageEmpty2}
\begin{paste}{ugxProblemSeriesFormulaPageEmpty2}{ugxProblemSeriesFormulaPagePatch2}
\pastebutton{ugxProblemSeriesFormulaPageEmpty2}{\showpaste}
\tab{5}\spadcommand{series(n +-> (-1)**(n-1)/n,x = 1,1..)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFormulaPagePatch3}
\begin{paste}{ugxProblemSeriesFormulaPageFull3}{ugxProblemSeriesFormulaPageEmpty3}
\pastebutton{ugxProblemSeriesFormulaPageFull3}{\hidepaste}
\tab{5}\spadcommand{series(n +-> (-1)**((n-1)/2)/factorial(n),x = 0,1..,2)}
\indentrel{3}\begin{verbatim}
   (3)
         1  3    1   5     1   7      1    9
     x - Ä x  + ÄÄÄ x  - ÄÄÄÄ x  + ÄÄÄÄÄÄ x
         6      120      5040      362880
   + 
           1     11      12
     - ÄÄÄÄÄÄÄÄ x   + O(x  )
       39916800
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFormulaPageEmpty3}
\begin{paste}{ugxProblemSeriesFormulaPageEmpty3}{ugxProblemSeriesFormulaPagePatch3}
\pastebutton{ugxProblemSeriesFormulaPageEmpty3}{\showpaste}
\tab{5}\spadcommand{series(n +-> (-1)**((n-1)/2)/factorial(n),x = 0,1..,2)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFormulaPagePatch4}
\begin{paste}{ugxProblemSeriesFormulaPageFull4}{ugxProblemSeriesFormulaPageEmpty4}
\pastebutton{ugxProblemSeriesFormulaPageFull4}{\hidepaste}
\tab{5}\spadcommand{series(n +-> (-1)**((3*n-1)/2)/factorial(3*n),x = 0,1/3..,2/3)}
\indentrel{3}\begin{verbatim}
   (4)
      1              5         7
      Ä              Ä         Ä
      3   1      1   3     1   3      1    3
     x  - Ä x + ÄÄÄ x  - ÄÄÄÄ x  + ÄÄÄÄÄÄ x
          6     120      5040      362880
   + 
                 11
                 ÄÄ
           1      3      4
     - ÄÄÄÄÄÄÄÄ x   + O(x )
       39916800
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFormulaPageEmpty4}
\begin{paste}{ugxProblemSeriesFormulaPageEmpty4}{ugxProblemSeriesFormulaPagePatch4}
\pastebutton{ugxProblemSeriesFormulaPageEmpty4}{\showpaste}
\tab{5}\spadcommand{series(n +-> (-1)**((3*n-1)/2)/factorial(3*n),x = 0,1/3..,2/3)}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFormulaPagePatch5}
\begin{paste}{ugxProblemSeriesFormulaPageFull5}{ugxProblemSeriesFormulaPageEmpty5}
\pastebutton{ugxProblemSeriesFormulaPageFull5}{\hidepaste}
\tab{5}\spadcommand{cscx := series(n +-> (-1)**((n-1)/2) * 2 * (2**n-1) * bernoulli(numer(n+1)) / factorial(n+1), x=0, -1..,2)\bound{cscx }}
\indentrel{3}\begin{verbatim}
   (5)
      - 1   1      7   3     31   5     127   7
     x    + Ä x + ÄÄÄ x  + ÄÄÄÄÄ x  + ÄÄÄÄÄÄ x
            6     360      15120      604800
   + 
        73    9      10
     ÄÄÄÄÄÄÄ x  + O(x  )
     3421440
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFormulaPageEmpty5}
\begin{paste}{ugxProblemSeriesFormulaPageEmpty5}{ugxProblemSeriesFormulaPagePatch5}
\pastebutton{ugxProblemSeriesFormulaPageEmpty5}{\showpaste}
\tab{5}\spadcommand{cscx := series(n +-> (-1)**((n-1)/2) * 2 * (2**n-1) * bernoulli(numer(n+1)) / factorial(n+1), x=0, -1..,2)\bound{cscx }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFormulaPagePatch6}
\begin{paste}{ugxProblemSeriesFormulaPageFull6}{ugxProblemSeriesFormulaPageEmpty6}
\pastebutton{ugxProblemSeriesFormulaPageFull6}{\hidepaste}
\tab{5}\spadcommand{1/cscx\free{cscx }}
\indentrel{3}\begin{verbatim}
   (6)
         1  3    1   5     1   7      1    9
     x - Ä x  + ÄÄÄ x  - ÄÄÄÄ x  + ÄÄÄÄÄÄ x
         6      120      5040      362880
   + 
           1     11      12
     - ÄÄÄÄÄÄÄÄ x   + O(x  )
       39916800
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFormulaPageEmpty6}
\begin{paste}{ugxProblemSeriesFormulaPageEmpty6}{ugxProblemSeriesFormulaPagePatch6}
\pastebutton{ugxProblemSeriesFormulaPageEmpty6}{\showpaste}
\tab{5}\spadcommand{1/cscx\free{cscx }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFormulaPagePatch7}
\begin{paste}{ugxProblemSeriesFormulaPageFull7}{ugxProblemSeriesFormulaPageEmpty7}
\pastebutton{ugxProblemSeriesFormulaPageFull7}{\hidepaste}
\tab{5}\spadcommand{asinx := series(n +-> binomial(n-1,(n-1)/2)/(n*2**(n-1)),x=0,1..,2)\bound{asinx }}
\indentrel{3}\begin{verbatim}
   (7)
       1  3    3  5    5   7    35   9    63   11      12
   x + Ä x  + ÄÄ x  + ÄÄÄ x  + ÄÄÄÄ x  + ÄÄÄÄ x   + O(x  )
       6      40      112      1152      2816
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFormulaPageEmpty7}
\begin{paste}{ugxProblemSeriesFormulaPageEmpty7}{ugxProblemSeriesFormulaPagePatch7}
\pastebutton{ugxProblemSeriesFormulaPageEmpty7}{\showpaste}
\tab{5}\spadcommand{asinx := series(n +-> binomial(n-1,(n-1)/2)/(n*2**(n-1)),x=0,1..,2)\bound{asinx }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFormulaPagePatch8}
\begin{paste}{ugxProblemSeriesFormulaPageFull8}{ugxProblemSeriesFormulaPageEmpty8}
\pastebutton{ugxProblemSeriesFormulaPageFull8}{\hidepaste}
\tab{5}\spadcommand{sin(asinx)\free{asinx }}
\indentrel{3}\begin{verbatim}
               12
   (8)  x + O(x  )
  Type: UnivariatePuiseuxSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesFormulaPageEmpty8}
\begin{paste}{ugxProblemSeriesFormulaPageEmpty8}{ugxProblemSeriesFormulaPagePatch8}
\pastebutton{ugxProblemSeriesFormulaPageEmpty8}{\showpaste}
\tab{5}\spadcommand{sin(asinx)\free{asinx }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxProblemSeriesSubstitutePage}{ug08.ht}
{Substituting Numerical Values in Power Series}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemSeriesSubstitutePage}
{8.9.7. Substituting Numerical Values in Power Series}
\beginscroll

Use \axiomFunFrom{eval}{UnivariatePowerSeriesCategory}
to substitute a numerical value for a variable in
a power series.
For example, here's a way to obtain numerical approximations of
\axiom{\%e} from the Taylor series
expansion of \axiom{exp(x)}.

\labelSpace{1pc}
\xtc{
First you create the desired Taylor expansion.
}{
\spadpaste{f := taylor(exp(x)) \bound{f}}
}
\xtc{
Then you evaluate the series at the value \axiom{1.0}.
The result is a sequence of the partial sums.
}{
\spadpaste{eval(f,1.0)}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxProblemSeriesSubstitutePagePatch1}
\begin{paste}{ugxProblemSeriesSubstitutePageFull1}{ugxProblemSeriesSubstitutePageEmpty1}
\pastebutton{ugxProblemSeriesSubstitutePageFull1}{\hidepaste}
\tab{5}\spadcommand{f := taylor(exp(x))\bound{f }}
\indentrel{3}\begin{verbatim}
   (1)
             1  2   1  3    1  4    1   5    1   6
     1 + x + Ä x  + Ä x  + ÄÄ x  + ÄÄÄ x  + ÄÄÄ x
             2      6      24      120      720
   + 
     1   7     1    8      1    9      1     10      11
   ÄÄÄÄ x  + ÄÄÄÄÄ x  + ÄÄÄÄÄÄ x  + ÄÄÄÄÄÄÄ x   + O(x  )
   5040      40320      362880      3628800
   Type: UnivariateTaylorSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesSubstitutePageEmpty1}
\begin{paste}{ugxProblemSeriesSubstitutePageEmpty1}{ugxProblemSeriesSubstitutePagePatch1}
\pastebutton{ugxProblemSeriesSubstitutePageEmpty1}{\showpaste}
\tab{5}\spadcommand{f := taylor(exp(x))\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesSubstitutePagePatch2}
\begin{paste}{ugxProblemSeriesSubstitutePageFull2}{ugxProblemSeriesSubstitutePageEmpty2}
\pastebutton{ugxProblemSeriesSubstitutePageFull2}{\hidepaste}
\tab{5}\spadcommand{eval(f,1.0)}
\indentrel{3}\begin{verbatim}
   (2)
   [1.0, 2.0, 2.5, 2.6666666666 666666667,
    2.7083333333 333333333, 2.7166666666 666666667,
    2.7180555555 555555556, 2.7182539682 53968254,
    2.7182787698 412698413, 2.7182815255 731922399, ...]
                          Type: Stream Expression Float
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesSubstitutePageEmpty2}
\begin{paste}{ugxProblemSeriesSubstitutePageEmpty2}{ugxProblemSeriesSubstitutePagePatch2}
\pastebutton{ugxProblemSeriesSubstitutePageEmpty2}{\showpaste}
\tab{5}\spadcommand{eval(f,1.0)}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxProblemSeriesBernoulliPage}{ug08.ht}
{Example: Bernoulli Polynomials and Sums of Powers}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemSeriesBernoulliPage}
{8.9.8. Example: Bernoulli Polynomials and Sums of Powers}
\beginscroll

Axiom provides operations for computing definite and
indefinite sums.

\labelSpace{3pc}
\xtc{
You can compute the sum of the first
ten fourth powers by evaluating this.
This creates a list whose entries are
\texht{$m^4$}{\axiom{m**4}} as \texht{$m$}{\axiom{m}} ranges from 1
to 10, and then computes the sum of the entries of that list.
}{
\spadpaste{reduce(+,[m**4 for m in 1..10])}
}
\xtc{
You can also compute a formula for the sum of the first
\texht{$k$}{\axiom{k}} fourth powers, where \texht{$k$}{\axiom{k}} is an
unspecified positive integer.
}{
\spadpaste{sum4 := sum(m**4, m = 1..k) \bound{sum4}}
}
\xtc{
This formula is valid for any positive integer \texht{$k$}{\axiom{k}}.
For instance, if we replace \texht{$k$}{\axiom{k}} by 10,
we obtain the number we computed earlier.
}{
\spadpaste{eval(sum4, k = 10) \free{sum4}}
}

You can compute a formula for the sum of the first
\texht{$k$}{\axiom{k}} \eth{\axiom{n}} powers in a similar fashion.
Just replace the \axiom{4} in the definition of \userfun{sum4} by
any expression not involving \texht{$k$}{\axiom{k}}.
Axiom computes these formulas using Bernoulli polynomials;
we
use the rest of this section to describe this method.

%
\xtc{
First consider this function of \axiom{t} and \axiom{x}.
}{
\spadpaste{f := t*exp(x*t) / (exp(t) - 1) \bound{f}}
}
\noOutputXtc{
Since the expressions involved get quite large, we tell
Axiom to show us only terms of degree up to \axiom{5.}
}{
\spadpaste{)set streams calculate 5 \bound{set}}
}
%
%
\xtc{
If we look at the Taylor expansion of \axiom{f(x, t)} about \axiom{t = 0,}
we see that the coefficients of the powers of \axiom{t} are polynomials
in \axiom{x}.
}{
\spadpaste{ff := taylor(f,t = 0) \free{f set} \bound{ff}}
}

In fact, the \eth{\axiom{n}} coefficient in this series is essentially
the \eth{\axiom{n}} Bernoulli polynomial: the \eth{\axiom{n}}
coefficient of the series is 
\texht{${1 \over {n!}} B_n(x)$}{\axiom{1/n! * Bn(x)}}, 
where \texht{$B_n(x)$}{\axiom{Bn(x)}}
is the \eth{\axiom{n}} Bernoulli polynomial.  Thus, to obtain the
\eth{\axiom{n}} Bernoulli polynomial, we multiply the \eth{\axiom{n}}
coefficient of the series \axiom{ff} by \axiom{n!}.

\xtc{
For example, the sixth Bernoulli polynomial is this.
}{
\spadpaste{factorial(6) * coefficient(ff,6) \free{ff}}
}
%
\xtc{
We derive some properties of the function \axiom{f(x,t)}.
First we compute \axiom{f(x + 1,t) - f(x,t)}.
}{
\spadpaste{g := eval(f, x = x + 1) - f \bound{g} \free{f}}
}
%
\xtc{
If we normalize \axiom{g}, we see that it has a particularly simple form.
}{
\spadpaste{normalize(g) \free{g}}
}
%
From this it follows that the \eth{\axiom{n}}
coefficient in the Taylor expansion of
\axiom{g(x,t)} at \axiom{t = 0} is
\texht{${1\over{(n-1)\:!}}\:x^{n-1}$}{\axiom{1/(n-1)! * x**(n-1)}}.
\xtc{
If you want to check this, evaluate the next expression.
}{
\spadpaste{taylor(g,t = 0) \free{g}}
}
%
However, since \axiom{g(x,t) = f(x+1,t)-f(x,t)}, it follows that the
\eth{\axiom{n}} coefficient is
\texht{${1 \over {n!}}\:(B_n(x+1)-B_n(x))$}{\axiom{1/n! * (Bn(x + 1) -
Bn(x))}}.
Equating coefficients, we see that
\texht{${1\over{(n-1)\:!}}\:x^{n-1} = {1\over{n!}}\:(B_n(x + 1) -
B_n(x))$}{\axiom{1/(n-1)! * x**(n-1) = 1/n! * (Bn(x + 1) - Bn(x))}}
and, therefore,
\texht{$x^{n-1} = {1\over{n}}\:(B_n(x + 1) -
B_n(x))$}{\axiom{x**(n-1) = 1/n * (Bn(x + 1) - Bn(x))}}.
%
Let's apply this formula repeatedly, letting \axiom{x} vary between two
integers \axiom{a} and \axiom{b}, with \axiom{a < b}:
%
\begin{verbatim}
  a**(n-1)       = 1/n * (Bn(a + 1) - Bn(a))
  (a + 1)**(n-1) = 1/n * (Bn(a + 2) - Bn(a + 1))
  (a + 2)**(n-1) = 1/n * (Bn(a + 3) - Bn(a + 2))
     .
     .
     .
  (b - 1)**(n-1) = 1/n * (Bn(b) - Bn(b - 1))
  b**(n-1)       = 1/n * (Bn(b + 1) - Bn(b))
\end{verbatim}

When we add these equations we find that
the sum of the left-hand sides is
\texht{$\sum_{m=a}^{b} m^{n-1},$}{\axiom{sum(m = a..b,m ** (n-1))},}%
the sum of the
\texht{$(n-1)^{\hbox{\small\rm st}}$}{\axiom{(n-1)}-st}
powers from \axiom{a} to \axiom{b}.
The sum of the right-hand sides is a ``telescoping series.''
After cancellation, the sum is simply
\texht{${1\over{n}}\:(B_n(b + 1) -
B_n(a))$}{\axiom{1/n * (Bn(b + 1) - Bn(a))}}.

Replacing \axiom{n} by \axiom{n + 1}, we have shown that
\centerline{{\axiom{sum(m = a..b,m ** n) = 1/(n + 1) * 
(B<n+1>(b + 1) - B<n+1>(a))}.}}

Let's use this to obtain the formula for the sum of fourth powers.
\xtc{
First we obtain the Bernoulli polynomial \texht{$B_5$}{\axiom{B5}}.
}{
\spadpaste{B5 := factorial(5) * coefficient(ff,5) \free{ff} \bound{B5}}
}
%
\xtc{
To find the sum of the first \texht{$k$}{\axiom{k}} 4th powers,
we multiply \axiom{1/5} by
\texht{$B_5(k+1) - B_5(1)$}{\axiom{B5(k + 1) - B5(1)}}.
}{
\spadpaste{1/5 * (eval(B5, x = k + 1) - eval(B5, x = 1)) \free{B5}}
}
%
\xtc{
This is the same formula that we obtained via \axiom{sum(m**4, m = 1..k)}.
}{
\spadpaste{sum4 \free{sum4}}
}

At this point you may want to do the same computation, but with an
exponent other than \axiom{4.}
For example, you might try to find a formula for the sum of the
first \texht{$k$}{\axiom{k}} 20th powers.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxProblemSeriesBernoulliPagePatch1}
\begin{paste}{ugxProblemSeriesBernoulliPageFull1}{ugxProblemSeriesBernoulliPageEmpty1}
\pastebutton{ugxProblemSeriesBernoulliPageFull1}{\hidepaste}
\tab{5}\spadcommand{reduce(+,[m**4 for m in 1..10])}
\indentrel{3}\begin{verbatim}
   (1)  25333
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPageEmpty1}
\begin{paste}{ugxProblemSeriesBernoulliPageEmpty1}{ugxProblemSeriesBernoulliPagePatch1}
\pastebutton{ugxProblemSeriesBernoulliPageEmpty1}{\showpaste}
\tab{5}\spadcommand{reduce(+,[m**4 for m in 1..10])}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPagePatch2}
\begin{paste}{ugxProblemSeriesBernoulliPageFull2}{ugxProblemSeriesBernoulliPageEmpty2}
\pastebutton{ugxProblemSeriesBernoulliPageFull2}{\hidepaste}
\tab{5}\spadcommand{sum4 := sum(m**4, m = 1..k)\bound{sum4 }}
\indentrel{3}\begin{verbatim}
          5      4      3
        6k  + 15k  + 10k  - k
   (2)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                  30
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPageEmpty2}
\begin{paste}{ugxProblemSeriesBernoulliPageEmpty2}{ugxProblemSeriesBernoulliPagePatch2}
\pastebutton{ugxProblemSeriesBernoulliPageEmpty2}{\showpaste}
\tab{5}\spadcommand{sum4 := sum(m**4, m = 1..k)\bound{sum4 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPagePatch3}
\begin{paste}{ugxProblemSeriesBernoulliPageFull3}{ugxProblemSeriesBernoulliPageEmpty3}
\pastebutton{ugxProblemSeriesBernoulliPageFull3}{\hidepaste}
\tab{5}\spadcommand{eval(sum4, k = 10)\free{sum4 }}
\indentrel{3}\begin{verbatim}
   (3)  25333
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPageEmpty3}
\begin{paste}{ugxProblemSeriesBernoulliPageEmpty3}{ugxProblemSeriesBernoulliPagePatch3}
\pastebutton{ugxProblemSeriesBernoulliPageEmpty3}{\showpaste}
\tab{5}\spadcommand{eval(sum4, k = 10)\free{sum4 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPagePatch4}
\begin{paste}{ugxProblemSeriesBernoulliPageFull4}{ugxProblemSeriesBernoulliPageEmpty4}
\pastebutton{ugxProblemSeriesBernoulliPageFull4}{\hidepaste}
\tab{5}\spadcommand{f := t*exp(x*t) / (exp(t) - 1)\bound{f }}
\indentrel{3}\begin{verbatim}
            t x
        t %e
   (4)  ÄÄÄÄÄÄÄ
          t
        %e  - 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPageEmpty4}
\begin{paste}{ugxProblemSeriesBernoulliPageEmpty4}{ugxProblemSeriesBernoulliPagePatch4}
\pastebutton{ugxProblemSeriesBernoulliPageEmpty4}{\showpaste}
\tab{5}\spadcommand{f := t*exp(x*t) / (exp(t) - 1)\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPagePatch5}
\begin{paste}{ugxProblemSeriesBernoulliPageFull5}{ugxProblemSeriesBernoulliPageEmpty5}
\pastebutton{ugxProblemSeriesBernoulliPageFull5}{\hidepaste}
\tab{5}\spadcommand{)set streams calculate 5\bound{set }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPageEmpty5}
\begin{paste}{ugxProblemSeriesBernoulliPageEmpty5}{ugxProblemSeriesBernoulliPagePatch5}
\pastebutton{ugxProblemSeriesBernoulliPageEmpty5}{\showpaste}
\tab{5}\spadcommand{)set streams calculate 5\bound{set }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPagePatch6}
\begin{paste}{ugxProblemSeriesBernoulliPageFull6}{ugxProblemSeriesBernoulliPageEmpty6}
\pastebutton{ugxProblemSeriesBernoulliPageFull6}{\hidepaste}
\tab{5}\spadcommand{ff := taylor(f,t = 0)\free{f set }\bound{ff }}
\indentrel{3}\begin{verbatim}
   (5)
                      2                 3     2
         2x - 1     6x  - 6x + 1  2   2x  - 3x  + x  3
     1 + ÄÄÄÄÄÄ t + ÄÄÄÄÄÄÄÄÄÄÄÄ t  + ÄÄÄÄÄÄÄÄÄÄÄÄÄ t
            2            12                 12
   + 
        4      3      2            5      4      3
     30x  - 60x  + 30x  - 1  4   6x  - 15x  + 10x  - x  5
     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ t  + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ t
               720                        720
   + 
        6
     O(t )
   Type: UnivariateTaylorSeries(Expression Integer,t,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPageEmpty6}
\begin{paste}{ugxProblemSeriesBernoulliPageEmpty6}{ugxProblemSeriesBernoulliPagePatch6}
\pastebutton{ugxProblemSeriesBernoulliPageEmpty6}{\showpaste}
\tab{5}\spadcommand{ff := taylor(f,t = 0)\free{f set }\bound{ff }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPagePatch7}
\begin{paste}{ugxProblemSeriesBernoulliPageFull7}{ugxProblemSeriesBernoulliPageEmpty7}
\pastebutton{ugxProblemSeriesBernoulliPageFull7}{\hidepaste}
\tab{5}\spadcommand{factorial(6) * coefficient(ff,6)\free{ff }}
\indentrel{3}\begin{verbatim}
           6       5       4      2
        42x  - 126x  + 105x  - 21x  + 1
   (6)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                       42
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPageEmpty7}
\begin{paste}{ugxProblemSeriesBernoulliPageEmpty7}{ugxProblemSeriesBernoulliPagePatch7}
\pastebutton{ugxProblemSeriesBernoulliPageEmpty7}{\showpaste}
\tab{5}\spadcommand{factorial(6) * coefficient(ff,6)\free{ff }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPagePatch8}
\begin{paste}{ugxProblemSeriesBernoulliPageFull8}{ugxProblemSeriesBernoulliPageEmpty8}
\pastebutton{ugxProblemSeriesBernoulliPageFull8}{\hidepaste}
\tab{5}\spadcommand{g := eval(f, x = x + 1) - f\bound{g }\free{f }}
\indentrel{3}\begin{verbatim}
            t x + t       t x
        t %e        - t %e
   (7)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                 t
               %e  - 1
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPageEmpty8}
\begin{paste}{ugxProblemSeriesBernoulliPageEmpty8}{ugxProblemSeriesBernoulliPagePatch8}
\pastebutton{ugxProblemSeriesBernoulliPageEmpty8}{\showpaste}
\tab{5}\spadcommand{g := eval(f, x = x + 1) - f\bound{g }\free{f }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPagePatch9}
\begin{paste}{ugxProblemSeriesBernoulliPageFull9}{ugxProblemSeriesBernoulliPageEmpty9}
\pastebutton{ugxProblemSeriesBernoulliPageFull9}{\hidepaste}
\tab{5}\spadcommand{normalize(g)\free{g }}
\indentrel{3}\begin{verbatim}
            t x
   (8)  t %e
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPageEmpty9}
\begin{paste}{ugxProblemSeriesBernoulliPageEmpty9}{ugxProblemSeriesBernoulliPagePatch9}
\pastebutton{ugxProblemSeriesBernoulliPageEmpty9}{\showpaste}
\tab{5}\spadcommand{normalize(g)\free{g }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPagePatch10}
\begin{paste}{ugxProblemSeriesBernoulliPageFull10}{ugxProblemSeriesBernoulliPageEmpty10}
\pastebutton{ugxProblemSeriesBernoulliPageFull10}{\hidepaste}
\tab{5}\spadcommand{taylor(g,t = 0)\free{g }}
\indentrel{3}\begin{verbatim}
                    2       3       4
               2   x   3   x   4   x   5      6
   (9)  t + x t  + ÄÄ t  + ÄÄ t  + ÄÄ t  + O(t )
                    2       6      24
   Type: UnivariateTaylorSeries(Expression Integer,t,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPageEmpty10}
\begin{paste}{ugxProblemSeriesBernoulliPageEmpty10}{ugxProblemSeriesBernoulliPagePatch10}
\pastebutton{ugxProblemSeriesBernoulliPageEmpty10}{\showpaste}
\tab{5}\spadcommand{taylor(g,t = 0)\free{g }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPagePatch11}
\begin{paste}{ugxProblemSeriesBernoulliPageFull11}{ugxProblemSeriesBernoulliPageEmpty11}
\pastebutton{ugxProblemSeriesBernoulliPageFull11}{\hidepaste}
\tab{5}\spadcommand{B5 := factorial(5) * coefficient(ff,5)\free{ff }\bound{B5 }}
\indentrel{3}\begin{verbatim}
           5      4      3
         6x  - 15x  + 10x  - x
   (10)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                   6
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPageEmpty11}
\begin{paste}{ugxProblemSeriesBernoulliPageEmpty11}{ugxProblemSeriesBernoulliPagePatch11}
\pastebutton{ugxProblemSeriesBernoulliPageEmpty11}{\showpaste}
\tab{5}\spadcommand{B5 := factorial(5) * coefficient(ff,5)\free{ff }\bound{B5 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPagePatch12}
\begin{paste}{ugxProblemSeriesBernoulliPageFull12}{ugxProblemSeriesBernoulliPageEmpty12}
\pastebutton{ugxProblemSeriesBernoulliPageFull12}{\hidepaste}
\tab{5}\spadcommand{1/5 * (eval(B5, x = k + 1) - eval(B5, x = 1))\free{B5 }}
\indentrel{3}\begin{verbatim}
           5      4      3
         6k  + 15k  + 10k  - k
   (11)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                   30
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPageEmpty12}
\begin{paste}{ugxProblemSeriesBernoulliPageEmpty12}{ugxProblemSeriesBernoulliPagePatch12}
\pastebutton{ugxProblemSeriesBernoulliPageEmpty12}{\showpaste}
\tab{5}\spadcommand{1/5 * (eval(B5, x = k + 1) - eval(B5, x = 1))\free{B5 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPagePatch13}
\begin{paste}{ugxProblemSeriesBernoulliPageFull13}{ugxProblemSeriesBernoulliPageEmpty13}
\pastebutton{ugxProblemSeriesBernoulliPageFull13}{\hidepaste}
\tab{5}\spadcommand{sum4\free{sum4 }}
\indentrel{3}\begin{verbatim}
           5      4      3
         6k  + 15k  + 10k  - k
   (12)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                   30
                      Type: Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemSeriesBernoulliPageEmpty13}
\begin{paste}{ugxProblemSeriesBernoulliPageEmpty13}{ugxProblemSeriesBernoulliPagePatch13}
\pastebutton{ugxProblemSeriesBernoulliPageEmpty13}{\showpaste}
\tab{5}\spadcommand{sum4\free{sum4 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugProblemDEQPage}{ug08.ht}{Solution of Differential Equations}
\pageto{notitle}{ugProblemLinPolEqnPage}
\pageto{notitle}{ugxProblemLDEQClosedPage}
\pageto{notitle}{ugxProblemNLDEQClosedPage}
\pageto{notitle}{ugxProblemDEQSeriesPage}
\begin{chunk}{ug08.ht}
\begin{page}{ugProblemDEQPage}{8.10. Solution of Differential Equations}
\beginscroll
%
In this section we discuss Axiom's facilities for
solving
differential equations in closed-form and in series.

Axiom provides facilities for closed-form solution of
single differential equations of the following kinds:
\indent{4}
\beginitems
\item[-] linear ordinary differential equations, and
\item[-] non-linear first order ordinary differential equations
when integrating factors can be found just by integration.
\enditems
\indent{0}

For a discussion of the solution of systems of linear and polynomial
equations, see
\downlink{``Solution of Linear and Polynomial Equations''}
{ugProblemLinPolEqnPage} in Section 8.5\ignore{ugProblemLinPolEqn}.

\beginmenu
    \menudownlink{
{8.10.1. Closed-Form Solutions of Linear Differential Equations}}
{ugxProblemLDEQClosedPage}
    \menudownlink{
{8.10.2. Closed-Form Solutions of Non-Linear Differential Equations}}
{ugxProblemNLDEQClosedPage}
    \menudownlink{
{8.10.3. Power Series Solutions of Differential Equations}}
{ugxProblemDEQSeriesPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugxProblemLDEQClosedPage}{ug08.ht}
{Closed-Form Solutions of Linear Differential Equations}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemLDEQClosedPage}
{8.10.1. Closed-Form Solutions of Linear Differential Equations}
\beginscroll

A {\it differential equation} is an equation involving an unknown 
{\it function} and one or more of its derivatives.  The equation is 
called {\it ordinary} if derivatives with respect to only one dependent
variable appear in the equation (it is called {\it partial}
otherwise).  The package \axiomType{ElementaryFunctionODESolver}
provides the top-level operation \spadfun {solve} for finding
closed-form solutions of ordinary differential equations.

To solve a differential equation, you must first create an operator for
the unknown function.
%
\xtc{
We let \axiom{y} be the unknown function in terms of \axiom{x}.
}{
\spadpaste{y := operator 'y \bound{y}}
}
%
You then type the equation using \axiomFun{D} to create the
derivatives of the unknown function \axiom{y(x)} where \axiom{x} is any
symbol you choose (the so-called {\it dependent variable}).
%
\xtc{
This is how you enter
the equation \axiom{y'' + y' + y = 0}.
}{
\spadpaste{deq := D(y x, x, 2) + D(y x, x) + y x = 0\bound{e1}\free{y}}
}
%
The simplest way to invoke the \axiomFun{solve} command is with three
arguments.
\begin{items}
\item the differential equation,
\item the operator representing the unknown function,
\item the dependent variable.
\end{items}
%
\xtc{
So, to solve the above equation, we enter this.
}{
\spadpaste{solve(deq, y, x) \free{e1}\free{y}}
}
%
Since linear ordinary differential equations have infinitely many
solutions, \axiomFun{solve} returns a {\it particular solution}
\texht{$f_p$}{\axiom{f_p}}
and a basis
\texht{$f_1,\dots,f_n$}{\axiom{f1,...,fn}}
for the solutions of the corresponding homogenuous equation.
Any expression of the form
\texht{$f_p + c_1 f_1 + \dots c_n f_n$}{\axiom{fp + c1 f1 + ... + cn fn}}
where the \texht{$c_i$}{\axiom{ci}} do not involve
the dependent variable is also a solution.
This is similar to what you get when you solve systems of linear
algebraic equations.

A way to select a unique solution is to specify {\it initial
conditions}: choose a value \axiom{a} for the dependent variable
and specify the values of the unknown function and its derivatives
at \axiom{a}.
If the number of initial conditions is equal to the order of the
equation, then the solution is unique (if it exists in closed
form!) and \axiomFun{solve} tries to find it.
To specify initial conditions to \axiomFun{solve}, use an
\axiomType{Equation} of the form \axiom{x = a} for the third
parameter instead of the dependent variable, and add a fourth
parameter consisting of the list of values \axiom{y(a), y'(a), ...}.

\xtc{
To find the solution of \axiom{y'' + y = 0} satisfying \axiom{y(0) =
y'(0) = 1}, do this.
}{
\spadpaste{deq := D(y x, x, 2) + y x \bound{e2}\free{y}}
}
\xtc{
You can omit the \axiom{= 0} when you enter the equation to be solved.
}{
\spadpaste{solve(deq, y, x = 0, [1, 1]) \free{e2}\free{y}}
}
%

Axiom is not limited to linear differential equations with constant
coefficients.  It can also find solutions when the coefficients are
rational or algebraic functions of the dependent variable.
Furthermore, Axiom is not limited by the order of the equation.

\xtc{
Axiom can solve the following third order equations with
polynomial coefficients.
}{
\spadpaste{deq := x**3 * D(y x, x, 3) + x**2 * D(y x, x, 2) - 2 * 
x * D(y x, x) + 2 * y x = 2 * x**4 \bound{e3}\free{y}}
}
\xtc{
}{
\spadpaste{solve(deq, y, x) \free{e3}\free{y}}
}
%
%
\xtc{
Here we are solving a homogeneous equation.
}{
\spadpaste{deq := (x**9+x**3) * D(y x, x, 3) + 18 * x**8 * 
D(y x, x, 2) - 90 * x * D(y x, x) - 30 * (11 * x**6 - 3) * y x 
\bound{e4}\free{y}}
}
\xtc{
}{
\spadpaste{solve(deq, y, x) \free{e4}\free{y}}
}

On the other hand, and in contrast with the operation
\axiomFun{integrate}, it can happen that Axiom finds no solution and
that some closed-form solution still exists.  While it is
mathematically complicated to describe exactly when the solutions are
guaranteed to be found, the following statements are correct and form
good guidelines for linear ordinary differential equations:

\begin{items}
\item If the coefficients are constants, Axiom finds a complete basis
of solutions (i,e, all solutions).
\item If the coefficients are rational functions in the dependent variable,
Axiom at least finds all solutions that do not involve algebraic
functions.
\end{items}
%
Note that this last statement does not mean that Axiom does not find
the solutions that are algebraic functions.
It means that it is not
guaranteed that the algebraic function solutions will be found.
%
\xtc{
This is an example where all the algebraic solutions are found.
}{
\spadpaste{deq := (x**2 + 1) * D(y x, x, 2) + 3 * x * 
D(y x, x) + y x = 0 \bound{e5}\free{y}}
}
\xtc{
}{
\spadpaste{solve(deq, y, x) \free{e5}\free{y}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxProblemLDEQClosedPagePatch1}
\begin{paste}{ugxProblemLDEQClosedPageFull1}{ugxProblemLDEQClosedPageEmpty1}
\pastebutton{ugxProblemLDEQClosedPageFull1}{\hidepaste}
\tab{5}\spadcommand{y := operator 'y\bound{y }}
\indentrel{3}\begin{verbatim}
   (1)  y
                                    Type: BasicOperator
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemLDEQClosedPageEmpty1}
\begin{paste}{ugxProblemLDEQClosedPageEmpty1}{ugxProblemLDEQClosedPagePatch1}
\pastebutton{ugxProblemLDEQClosedPageEmpty1}{\showpaste}
\tab{5}\spadcommand{y := operator 'y\bound{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemLDEQClosedPagePatch2}
\begin{paste}{ugxProblemLDEQClosedPageFull2}{ugxProblemLDEQClosedPageEmpty2}
\pastebutton{ugxProblemLDEQClosedPageFull2}{\hidepaste}
\tab{5}\spadcommand{deq := D(y x, x, 2) + D(y x, x) + y x = 0\bound{e1 }\free{y }}
\indentrel{3}\begin{verbatim}
         ,,       ,
   (2)  y  (x) + y (x) + y(x)= 0

                      Type: Equation Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemLDEQClosedPageEmpty2}
\begin{paste}{ugxProblemLDEQClosedPageEmpty2}{ugxProblemLDEQClosedPagePatch2}
\pastebutton{ugxProblemLDEQClosedPageEmpty2}{\showpaste}
\tab{5}\spadcommand{deq := D(y x, x, 2) + D(y x, x) + y x = 0\bound{e1 }\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemLDEQClosedPagePatch3}
\begin{paste}{ugxProblemLDEQClosedPageFull3}{ugxProblemLDEQClosedPageEmpty3}
\pastebutton{ugxProblemLDEQClosedPageFull3}{\hidepaste}
\tab{5}\spadcommand{solve(deq, y, x)\free{e1 }\free{y }}
\indentrel{3}\begin{verbatim}
   (3)
   [particular= 0,
                          x     x
                  ÚÄ¿   - Ä   - Ä      ÚÄ¿
                x\³3      2     2    x\³3
    basis= [cos(ÄÄÄÄÄ)%e   ,%e   sin(ÄÄÄÄÄ)]]
                  2                    2
Type: Union(Record(particular: Expression Integer,basis: List Expression Integer),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemLDEQClosedPageEmpty3}
\begin{paste}{ugxProblemLDEQClosedPageEmpty3}{ugxProblemLDEQClosedPagePatch3}
\pastebutton{ugxProblemLDEQClosedPageEmpty3}{\showpaste}
\tab{5}\spadcommand{solve(deq, y, x)\free{e1 }\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemLDEQClosedPagePatch4}
\begin{paste}{ugxProblemLDEQClosedPageFull4}{ugxProblemLDEQClosedPageEmpty4}
\pastebutton{ugxProblemLDEQClosedPageFull4}{\hidepaste}
\tab{5}\spadcommand{deq := D(y x, x, 2) + y x\bound{e2 }\free{y }}
\indentrel{3}\begin{verbatim}
         ,,
   (4)  y  (x) + y(x)

                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemLDEQClosedPageEmpty4}
\begin{paste}{ugxProblemLDEQClosedPageEmpty4}{ugxProblemLDEQClosedPagePatch4}
\pastebutton{ugxProblemLDEQClosedPageEmpty4}{\showpaste}
\tab{5}\spadcommand{deq := D(y x, x, 2) + y x\bound{e2 }\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemLDEQClosedPagePatch5}
\begin{paste}{ugxProblemLDEQClosedPageFull5}{ugxProblemLDEQClosedPageEmpty5}
\pastebutton{ugxProblemLDEQClosedPageFull5}{\hidepaste}
\tab{5}\spadcommand{solve(deq, y, x = 0, [1, 1])\free{e2 }\free{y }}
\indentrel{3}\begin{verbatim}
   (5)  sin(x) + cos(x)
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemLDEQClosedPageEmpty5}
\begin{paste}{ugxProblemLDEQClosedPageEmpty5}{ugxProblemLDEQClosedPagePatch5}
\pastebutton{ugxProblemLDEQClosedPageEmpty5}{\showpaste}
\tab{5}\spadcommand{solve(deq, y, x = 0, [1, 1])\free{e2 }\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemLDEQClosedPagePatch6}
\begin{paste}{ugxProblemLDEQClosedPageFull6}{ugxProblemLDEQClosedPageEmpty6}
\pastebutton{ugxProblemLDEQClosedPageFull6}{\hidepaste}
\tab{5}\spadcommand{deq := x**3 * D(y x, x, 3) + x**2 * D(y x, x, 2) - 2 * x * D(y x, x) + 2 * y x = 2 * x**4\bound{e3 }\free{y }}
\indentrel{3}\begin{verbatim}
         3 ,,,       2 ,,         ,               4
   (6)  x y   (x) + x y  (x) - 2xy (x) + 2y(x)= 2x

                      Type: Equation Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemLDEQClosedPageEmpty6}
\begin{paste}{ugxProblemLDEQClosedPageEmpty6}{ugxProblemLDEQClosedPagePatch6}
\pastebutton{ugxProblemLDEQClosedPageEmpty6}{\showpaste}
\tab{5}\spadcommand{deq := x**3 * D(y x, x, 3) + x**2 * D(y x, x, 2) - 2 * x * D(y x, x) + 2 * y x = 2 * x**4\bound{e3 }\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemLDEQClosedPagePatch7}
\begin{paste}{ugxProblemLDEQClosedPageFull7}{ugxProblemLDEQClosedPageEmpty7}
\pastebutton{ugxProblemLDEQClosedPageFull7}{\hidepaste}
\tab{5}\spadcommand{solve(deq, y, x)\free{e3 }\free{y }}
\indentrel{3}\begin{verbatim}
   (7)
                 5      3      2
                x  - 10x  + 20x  + 4
   [particular= ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ,
                         15x
              3     2      3      3     2
            2x  - 3x  + 1 x  - 1 x  - 3x  - 1
    basis= [ÄÄÄÄÄÄÄÄÄÄÄÄÄ,ÄÄÄÄÄÄ,ÄÄÄÄÄÄÄÄÄÄÄÄ]]
                  x          x         x
Type: Union(Record(particular: Expression Integer,basis: List Expression Integer),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemLDEQClosedPageEmpty7}
\begin{paste}{ugxProblemLDEQClosedPageEmpty7}{ugxProblemLDEQClosedPagePatch7}
\pastebutton{ugxProblemLDEQClosedPageEmpty7}{\showpaste}
\tab{5}\spadcommand{solve(deq, y, x)\free{e3 }\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemLDEQClosedPagePatch8}
\begin{paste}{ugxProblemLDEQClosedPageFull8}{ugxProblemLDEQClosedPageEmpty8}
\pastebutton{ugxProblemLDEQClosedPageFull8}{\hidepaste}
\tab{5}\spadcommand{deq := (x**9+x**3) * D(y x, x, 3) + 18 * x**8 * D(y x, x, 2) - 90 * x * D(y x, x) - 30 * (11 * x**6 - 3) * y x\bound{e4 }\free{y }}
\indentrel{3}\begin{verbatim}
   (8)
       9    3  ,,,         8 ,,          ,
     (x  + x )y   (x) + 18x y  (x) - 90xy (x)

   + 
            6
     (- 330x  + 90)y(x)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemLDEQClosedPageEmpty8}
\begin{paste}{ugxProblemLDEQClosedPageEmpty8}{ugxProblemLDEQClosedPagePatch8}
\pastebutton{ugxProblemLDEQClosedPageEmpty8}{\showpaste}
\tab{5}\spadcommand{deq := (x**9+x**3) * D(y x, x, 3) + 18 * x**8 * D(y x, x, 2) - 90 * x * D(y x, x) - 30 * (11 * x**6 - 3) * y x\bound{e4 }\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemLDEQClosedPagePatch9}
\begin{paste}{ugxProblemLDEQClosedPageFull9}{ugxProblemLDEQClosedPageEmpty9}
\pastebutton{ugxProblemLDEQClosedPageFull9}{\hidepaste}
\tab{5}\spadcommand{solve(deq, y, x)\free{e4 }\free{y }}
\indentrel{3}\begin{verbatim}
   (9)
   [particular= 0,
                          ÚÄÄ¿            ÚÄÄ¿
                       - \³91 log(x)     \³91 log(x)
               x   x %e              x %e
    basis= [ÄÄÄÄÄÄ,ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ,ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ]]
             6            6                6
            x  + 1       x  + 1           x  + 1
Type: Union(Record(particular: Expression Integer,basis: List Expression Integer),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemLDEQClosedPageEmpty9}
\begin{paste}{ugxProblemLDEQClosedPageEmpty9}{ugxProblemLDEQClosedPagePatch9}
\pastebutton{ugxProblemLDEQClosedPageEmpty9}{\showpaste}
\tab{5}\spadcommand{solve(deq, y, x)\free{e4 }\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemLDEQClosedPagePatch10}
\begin{paste}{ugxProblemLDEQClosedPageFull10}{ugxProblemLDEQClosedPageEmpty10}
\pastebutton{ugxProblemLDEQClosedPageFull10}{\hidepaste}
\tab{5}\spadcommand{deq := (x**2 + 1) * D(y x, x, 2) + 3 * x * D(y x, x) + y x = 0\bound{e5 }\free{y }}
\indentrel{3}\begin{verbatim}
           2      ,,         ,
   (10)  (x  + 1)y  (x) + 3xy (x) + y(x)= 0

                      Type: Equation Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemLDEQClosedPageEmpty10}
\begin{paste}{ugxProblemLDEQClosedPageEmpty10}{ugxProblemLDEQClosedPagePatch10}
\pastebutton{ugxProblemLDEQClosedPageEmpty10}{\showpaste}
\tab{5}\spadcommand{deq := (x**2 + 1) * D(y x, x, 2) + 3 * x * D(y x, x) + y x = 0\bound{e5 }\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemLDEQClosedPagePatch11}
\begin{paste}{ugxProblemLDEQClosedPageFull11}{ugxProblemLDEQClosedPageEmpty11}
\pastebutton{ugxProblemLDEQClosedPageFull11}{\hidepaste}
\tab{5}\spadcommand{solve(deq, y, x)\free{e5 }\free{y }}
\indentrel{3}\begin{verbatim}
   (11)
                                         ÚÄÄÄÄÄÄ¿
                                         ³ 2
                              1     log(\³x  + 1  - x)
   [particular= 0,basis= [ÄÄÄÄÄÄÄÄÄ,ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ]]
                           ÚÄÄÄÄÄÄ¿       ÚÄÄÄÄÄÄ¿
                           ³ 2            ³ 2
                          \³x  + 1       \³x  + 1
Type: Union(Record(particular: Expression Integer,basis: List Expression Integer),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemLDEQClosedPageEmpty11}
\begin{paste}{ugxProblemLDEQClosedPageEmpty11}{ugxProblemLDEQClosedPagePatch11}
\pastebutton{ugxProblemLDEQClosedPageEmpty11}{\showpaste}
\tab{5}\spadcommand{solve(deq, y, x)\free{e5 }\free{y }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxProblemNLDEQClosedPage}{ug08.ht}
{Closed-Form Solutions of Non-Linear DEs}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemNLDEQClosedPage}
{8.10.2. Closed-Form Solutions of Non-Linear DEs}
\beginscroll

This is an example that shows how to solve a non-linear
first order ordinary differential equation manually when an integrating
factor can be found just by integration.
At the end, we show you how to solve it directly.

Let's solve the differential equation \axiom{y' = y / (x + y log y)}.
%
\xtc{
Using the notation
\axiom{m(x, y) + n(x, y) y' = 0},
we have \axiom{m = -y} and \axiom{n = x + y log y}.
}{
\spadpaste{m := -y \bound{m}}
}
\xtc{
}{
\spadpaste{n := x + y * log y \bound{n}}
}
%
\xtc{
We first check for exactness, that is, does \axiom{dm/dy = dn/dx}?
}{
\spadpaste{D(m, y) - D(n, x) \free{m n}}
}
%
This is not zero, so the equation is not exact.
Therefore we must look for
an integrating factor: a function \axiom{mu(x,y)} such that
\axiom{d(mu m)/dy = d(mu n)/dx}.
Normally, we first search for \axiom{mu(x,y)} depending only on
\axiom{x} or only on \axiom{y}.
%
\xtc{
Let's search for such a \axiom{mu(x)} first.
}{
\spadpaste{mu := operator 'mu \bound{mu}}
}
\xtc{
}{
\spadpaste{a := D(mu(x) * m, y) - D(mu(x) * n, x) \bound{a}\free{m n mu}}
}
%
%
\xtc{
If the above is zero for a function
\axiom{mu} that does {\it not} depend on \axiom{y}, then
\axiom{mu(x)} is an integrating factor.
}{
\spadpaste{solve(a = 0, mu, x) \free{mu a}}
}
%
The solution depends on \axiom{y}, so there is no integrating
factor that depends on \axiom{x} only.
%
\xtc{
Let's look for one that depends on \axiom{y} only.
}{
\spadpaste{b := D(mu(y) * m, y) - D(mu(y) * n, x) \bound{b}\free{mu m}}
}
\xtc{
}{
\spadpaste{sb := solve(b = 0, mu, y) \free{mu b}\bound{sb}}
}
\noindent
We've found one!
%
\xtc{
The above \axiom{mu(y)} is an integrating factor.
We must multiply our initial equation
(that is, \axiom{m} and \axiom{n}) by the integrating factor.
}{
\spadpaste{intFactor := sb.basis.1 \bound{intFactor}\free{sb}}
}
\xtc{
}{
\spadpaste{m := intFactor * m \bound{m1}\free{m intFactor}}
}
\xtc{
}{
\spadpaste{n := intFactor * n \bound{n1}\free{n intFactor}}
}
%
\xtc{
Let's check for exactness.
}{
\spadpaste{D(m, y) - D(n, x) \free{m1 n1}}
}
%
We must solve the exact equation, that is, find a function
\axiom{s(x,y)} such that
\axiom{ds/dx = m}  and \axiom{ds/dy = n}.
%
\xtc{
We start by writing \axiom{s(x, y) = h(y) + integrate(m, x)}
where \axiom{h(y)} is an unknown function of \axiom{y}.
This guarantees that \axiom{ds/dx = m}.
}{
\spadpaste{h := operator 'h \bound{h}}
}
\xtc{
}{
\spadpaste{sol := h y + integrate(m, x) \bound{sol}\free{h m1}}
}
%
%
\xtc{
All we want is to find \axiom{h(y)} such that
\axiom{ds/dy = n}.
}{
\spadpaste{dsol := D(sol, y) \free{sol}\bound{dsol}}
}
\xtc{
}{
\spadpaste{nsol := solve(dsol = n, h, y) \free{dsol n1 h}\bound{nsol}}
}
%
\xtc{
The above particular solution is the \axiom{h(y)} we want, so we just
replace \axiom{h(y)} by it in the implicit solution.
}{
\spadpaste{eval(sol, h y = nsol.particular) \free{sol h nsol}}
}
%
A first integral of the initial equation is obtained by setting
this result equal to an arbitrary constant.

Now that we've seen how to solve the equation ``by hand,''
we show you how to do it with the \axiomFun{solve} operation.
\xtc{
First define \axiom{y} to be an operator.
}{
\spadpaste{y := operator 'y \bound{y}}
}
\xtc{
Next we create the differential equation.
}{
\spadpaste{deq := D(y x, x) = y(x) / (x + y(x) * log y x) 
\bound{deqi}\free{y}}
}
\xtc{
Finally, we solve it.
}{
\spadpaste{solve(deq, y, x) \free{deqi y}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxProblemNLDEQClosedPagePatch1}
\begin{paste}{ugxProblemNLDEQClosedPageFull1}{ugxProblemNLDEQClosedPageEmpty1}
\pastebutton{ugxProblemNLDEQClosedPageFull1}{\hidepaste}
\tab{5}\spadcommand{m := -y\bound{m }}
\indentrel{3}\begin{verbatim}
   (1)  - y
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPageEmpty1}
\begin{paste}{ugxProblemNLDEQClosedPageEmpty1}{ugxProblemNLDEQClosedPagePatch1}
\pastebutton{ugxProblemNLDEQClosedPageEmpty1}{\showpaste}
\tab{5}\spadcommand{m := -y\bound{m }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPagePatch2}
\begin{paste}{ugxProblemNLDEQClosedPageFull2}{ugxProblemNLDEQClosedPageEmpty2}
\pastebutton{ugxProblemNLDEQClosedPageFull2}{\hidepaste}
\tab{5}\spadcommand{n := x + y * log y\bound{n }}
\indentrel{3}\begin{verbatim}
   (2)  y log(y) + x
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPageEmpty2}
\begin{paste}{ugxProblemNLDEQClosedPageEmpty2}{ugxProblemNLDEQClosedPagePatch2}
\pastebutton{ugxProblemNLDEQClosedPageEmpty2}{\showpaste}
\tab{5}\spadcommand{n := x + y * log y\bound{n }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPagePatch3}
\begin{paste}{ugxProblemNLDEQClosedPageFull3}{ugxProblemNLDEQClosedPageEmpty3}
\pastebutton{ugxProblemNLDEQClosedPageFull3}{\hidepaste}
\tab{5}\spadcommand{D(m, y) - D(n, x)\free{m n }}
\indentrel{3}\begin{verbatim}
   (3)  - 2
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPageEmpty3}
\begin{paste}{ugxProblemNLDEQClosedPageEmpty3}{ugxProblemNLDEQClosedPagePatch3}
\pastebutton{ugxProblemNLDEQClosedPageEmpty3}{\showpaste}
\tab{5}\spadcommand{D(m, y) - D(n, x)\free{m n }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPagePatch4}
\begin{paste}{ugxProblemNLDEQClosedPageFull4}{ugxProblemNLDEQClosedPageEmpty4}
\pastebutton{ugxProblemNLDEQClosedPageFull4}{\hidepaste}
\tab{5}\spadcommand{mu := operator 'mu\bound{mu }}
\indentrel{3}\begin{verbatim}
   (4)  mu
                                    Type: BasicOperator
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPageEmpty4}
\begin{paste}{ugxProblemNLDEQClosedPageEmpty4}{ugxProblemNLDEQClosedPagePatch4}
\pastebutton{ugxProblemNLDEQClosedPageEmpty4}{\showpaste}
\tab{5}\spadcommand{mu := operator 'mu\bound{mu }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPagePatch5}
\begin{paste}{ugxProblemNLDEQClosedPageFull5}{ugxProblemNLDEQClosedPageEmpty5}
\pastebutton{ugxProblemNLDEQClosedPageFull5}{\hidepaste}
\tab{5}\spadcommand{a := D(mu(x) * m, y) - D(mu(x) * n, x)\bound{a }\free{m n mu }}
\indentrel{3}\begin{verbatim}
                          ,
   (5)  (- y log(y) - x)mu (x) - 2mu(x)

                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPageEmpty5}
\begin{paste}{ugxProblemNLDEQClosedPageEmpty5}{ugxProblemNLDEQClosedPagePatch5}
\pastebutton{ugxProblemNLDEQClosedPageEmpty5}{\showpaste}
\tab{5}\spadcommand{a := D(mu(x) * m, y) - D(mu(x) * n, x)\bound{a }\free{m n mu }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPagePatch6}
\begin{paste}{ugxProblemNLDEQClosedPageFull6}{ugxProblemNLDEQClosedPageEmpty6}
\pastebutton{ugxProblemNLDEQClosedPageFull6}{\hidepaste}
\tab{5}\spadcommand{solve(a = 0, mu, x)\free{mu a }}
\indentrel{3}\begin{verbatim}
   (6)
                                        1
   [particular= 0,basis= [ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ]]
                           2      2                  2
                          y log(y)  + 2x y log(y) + x
Type: Union(Record(particular: Expression Integer,basis: List Expression Integer),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPageEmpty6}
\begin{paste}{ugxProblemNLDEQClosedPageEmpty6}{ugxProblemNLDEQClosedPagePatch6}
\pastebutton{ugxProblemNLDEQClosedPageEmpty6}{\showpaste}
\tab{5}\spadcommand{solve(a = 0, mu, x)\free{mu a }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPagePatch7}
\begin{paste}{ugxProblemNLDEQClosedPageFull7}{ugxProblemNLDEQClosedPageEmpty7}
\pastebutton{ugxProblemNLDEQClosedPageFull7}{\hidepaste}
\tab{5}\spadcommand{b := D(mu(y) * m, y) - D(mu(y) * n, x)\bound{b }\free{mu m }}
\indentrel{3}\begin{verbatim}
             ,
   (7)  - ymu (y) - 2mu(y)

                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPageEmpty7}
\begin{paste}{ugxProblemNLDEQClosedPageEmpty7}{ugxProblemNLDEQClosedPagePatch7}
\pastebutton{ugxProblemNLDEQClosedPageEmpty7}{\showpaste}
\tab{5}\spadcommand{b := D(mu(y) * m, y) - D(mu(y) * n, x)\bound{b }\free{mu m }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPagePatch8}
\begin{paste}{ugxProblemNLDEQClosedPageFull8}{ugxProblemNLDEQClosedPageEmpty8}
\pastebutton{ugxProblemNLDEQClosedPageFull8}{\hidepaste}
\tab{5}\spadcommand{sb := solve(b = 0, mu, y)\free{mu b }\bound{sb }}
\indentrel{3}\begin{verbatim}
                                1
   (8)  [particular= 0,basis= [ÄÄ]]
                                2
                               y
Type: Union(Record(particular: Expression Integer,basis: List Expression Integer),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPageEmpty8}
\begin{paste}{ugxProblemNLDEQClosedPageEmpty8}{ugxProblemNLDEQClosedPagePatch8}
\pastebutton{ugxProblemNLDEQClosedPageEmpty8}{\showpaste}
\tab{5}\spadcommand{sb := solve(b = 0, mu, y)\free{mu b }\bound{sb }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPagePatch9}
\begin{paste}{ugxProblemNLDEQClosedPageFull9}{ugxProblemNLDEQClosedPageEmpty9}
\pastebutton{ugxProblemNLDEQClosedPageFull9}{\hidepaste}
\tab{5}\spadcommand{intFactor := sb.basis.1\bound{intFactor }\free{sb }}
\indentrel{3}\begin{verbatim}
         1
   (9)  ÄÄ
         2
        y
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPageEmpty9}
\begin{paste}{ugxProblemNLDEQClosedPageEmpty9}{ugxProblemNLDEQClosedPagePatch9}
\pastebutton{ugxProblemNLDEQClosedPageEmpty9}{\showpaste}
\tab{5}\spadcommand{intFactor := sb.basis.1\bound{intFactor }\free{sb }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPagePatch10}
\begin{paste}{ugxProblemNLDEQClosedPageFull10}{ugxProblemNLDEQClosedPageEmpty10}
\pastebutton{ugxProblemNLDEQClosedPageFull10}{\hidepaste}
\tab{5}\spadcommand{m := intFactor * m\bound{m1 }\free{m intFactor }}
\indentrel{3}\begin{verbatim}
           1
   (10)  - Ä
           y
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPageEmpty10}
\begin{paste}{ugxProblemNLDEQClosedPageEmpty10}{ugxProblemNLDEQClosedPagePatch10}
\pastebutton{ugxProblemNLDEQClosedPageEmpty10}{\showpaste}
\tab{5}\spadcommand{m := intFactor * m\bound{m1 }\free{m intFactor }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPagePatch11}
\begin{paste}{ugxProblemNLDEQClosedPageFull11}{ugxProblemNLDEQClosedPageEmpty11}
\pastebutton{ugxProblemNLDEQClosedPageFull11}{\hidepaste}
\tab{5}\spadcommand{n := intFactor * n\bound{n1 }\free{n intFactor }}
\indentrel{3}\begin{verbatim}
         y log(y) + x
   (11)  ÄÄÄÄÄÄÄÄÄÄÄÄ
               2
              y
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPageEmpty11}
\begin{paste}{ugxProblemNLDEQClosedPageEmpty11}{ugxProblemNLDEQClosedPagePatch11}
\pastebutton{ugxProblemNLDEQClosedPageEmpty11}{\showpaste}
\tab{5}\spadcommand{n := intFactor * n\bound{n1 }\free{n intFactor }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPagePatch12}
\begin{paste}{ugxProblemNLDEQClosedPageFull12}{ugxProblemNLDEQClosedPageEmpty12}
\pastebutton{ugxProblemNLDEQClosedPageFull12}{\hidepaste}
\tab{5}\spadcommand{D(m, y) - D(n, x)\free{m1 n1 }}
\indentrel{3}\begin{verbatim}
   (12)  0
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPageEmpty12}
\begin{paste}{ugxProblemNLDEQClosedPageEmpty12}{ugxProblemNLDEQClosedPagePatch12}
\pastebutton{ugxProblemNLDEQClosedPageEmpty12}{\showpaste}
\tab{5}\spadcommand{D(m, y) - D(n, x)\free{m1 n1 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPagePatch13}
\begin{paste}{ugxProblemNLDEQClosedPageFull13}{ugxProblemNLDEQClosedPageEmpty13}
\pastebutton{ugxProblemNLDEQClosedPageFull13}{\hidepaste}
\tab{5}\spadcommand{h := operator 'h\bound{h }}
\indentrel{3}\begin{verbatim}
   (13)  h
                                    Type: BasicOperator
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPageEmpty13}
\begin{paste}{ugxProblemNLDEQClosedPageEmpty13}{ugxProblemNLDEQClosedPagePatch13}
\pastebutton{ugxProblemNLDEQClosedPageEmpty13}{\showpaste}
\tab{5}\spadcommand{h := operator 'h\bound{h }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPagePatch14}
\begin{paste}{ugxProblemNLDEQClosedPageFull14}{ugxProblemNLDEQClosedPageEmpty14}
\pastebutton{ugxProblemNLDEQClosedPageFull14}{\hidepaste}
\tab{5}\spadcommand{sol := h y + integrate(m, x)\bound{sol }\free{h m1 }}
\indentrel{3}\begin{verbatim}
         y h(y) - x
   (14)  ÄÄÄÄÄÄÄÄÄÄ
              y
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPageEmpty14}
\begin{paste}{ugxProblemNLDEQClosedPageEmpty14}{ugxProblemNLDEQClosedPagePatch14}
\pastebutton{ugxProblemNLDEQClosedPageEmpty14}{\showpaste}
\tab{5}\spadcommand{sol := h y + integrate(m, x)\bound{sol }\free{h m1 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPagePatch15}
\begin{paste}{ugxProblemNLDEQClosedPageFull15}{ugxProblemNLDEQClosedPageEmpty15}
\pastebutton{ugxProblemNLDEQClosedPageFull15}{\hidepaste}
\tab{5}\spadcommand{dsol := D(sol, y)\free{sol }\bound{dsol }}
\indentrel{3}\begin{verbatim}
          2 ,
         y h (y) + x

   (15)  ÄÄÄÄÄÄÄÄÄÄÄ
               2
              y
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPageEmpty15}
\begin{paste}{ugxProblemNLDEQClosedPageEmpty15}{ugxProblemNLDEQClosedPagePatch15}
\pastebutton{ugxProblemNLDEQClosedPageEmpty15}{\showpaste}
\tab{5}\spadcommand{dsol := D(sol, y)\free{sol }\bound{dsol }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPagePatch16}
\begin{paste}{ugxProblemNLDEQClosedPageFull16}{ugxProblemNLDEQClosedPageEmpty16}
\pastebutton{ugxProblemNLDEQClosedPageFull16}{\hidepaste}
\tab{5}\spadcommand{nsol := solve(dsol = n, h, y)\free{dsol n1 h }\bound{nsol }}
\indentrel{3}\begin{verbatim}
                            2
                      log(y)
   (16)  [particular= ÄÄÄÄÄÄÄ,basis= [1]]
                         2
Type: Union(Record(particular: Expression Integer,basis: List Expression Integer),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPageEmpty16}
\begin{paste}{ugxProblemNLDEQClosedPageEmpty16}{ugxProblemNLDEQClosedPagePatch16}
\pastebutton{ugxProblemNLDEQClosedPageEmpty16}{\showpaste}
\tab{5}\spadcommand{nsol := solve(dsol = n, h, y)\free{dsol n1 h }\bound{nsol }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPagePatch17}
\begin{paste}{ugxProblemNLDEQClosedPageFull17}{ugxProblemNLDEQClosedPageEmpty17}
\pastebutton{ugxProblemNLDEQClosedPageFull17}{\hidepaste}
\tab{5}\spadcommand{eval(sol, h y = nsol.particular)\free{sol h nsol }}
\indentrel{3}\begin{verbatim}
                 2
         y log(y)  - 2x
   (17)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
               2y
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPageEmpty17}
\begin{paste}{ugxProblemNLDEQClosedPageEmpty17}{ugxProblemNLDEQClosedPagePatch17}
\pastebutton{ugxProblemNLDEQClosedPageEmpty17}{\showpaste}
\tab{5}\spadcommand{eval(sol, h y = nsol.particular)\free{sol h nsol }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPagePatch18}
\begin{paste}{ugxProblemNLDEQClosedPageFull18}{ugxProblemNLDEQClosedPageEmpty18}
\pastebutton{ugxProblemNLDEQClosedPageFull18}{\hidepaste}
\tab{5}\spadcommand{y := operator 'y\bound{y }}
\indentrel{3}\begin{verbatim}
   (18)  y
                                    Type: BasicOperator
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPageEmpty18}
\begin{paste}{ugxProblemNLDEQClosedPageEmpty18}{ugxProblemNLDEQClosedPagePatch18}
\pastebutton{ugxProblemNLDEQClosedPageEmpty18}{\showpaste}
\tab{5}\spadcommand{y := operator 'y\bound{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPagePatch19}
\begin{paste}{ugxProblemNLDEQClosedPageFull19}{ugxProblemNLDEQClosedPageEmpty19}
\pastebutton{ugxProblemNLDEQClosedPageFull19}{\hidepaste}
\tab{5}\spadcommand{deq := D(y x, x) = y(x) / (x + y(x) * log y x)\bound{deqi }\free{y }}
\indentrel{3}\begin{verbatim}
          ,            y(x)
   (19)  y (x)= ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                y(x)log(y(x)) + x
                      Type: Equation Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPageEmpty19}
\begin{paste}{ugxProblemNLDEQClosedPageEmpty19}{ugxProblemNLDEQClosedPagePatch19}
\pastebutton{ugxProblemNLDEQClosedPageEmpty19}{\showpaste}
\tab{5}\spadcommand{deq := D(y x, x) = y(x) / (x + y(x) * log y x)\bound{deqi }\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPagePatch20}
\begin{paste}{ugxProblemNLDEQClosedPageFull20}{ugxProblemNLDEQClosedPageEmpty20}
\pastebutton{ugxProblemNLDEQClosedPageFull20}{\hidepaste}
\tab{5}\spadcommand{solve(deq, y, x)\free{deqi y }}
\indentrel{3}\begin{verbatim}
                      2
         y(x)log(y(x))  - 2x
   (20)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                2y(x)
                    Type: Union(Expression Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemNLDEQClosedPageEmpty20}
\begin{paste}{ugxProblemNLDEQClosedPageEmpty20}{ugxProblemNLDEQClosedPagePatch20}
\pastebutton{ugxProblemNLDEQClosedPageEmpty20}{\showpaste}
\tab{5}\spadcommand{solve(deq, y, x)\free{deqi y }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxProblemDEQSeriesPage}{ug08.ht}
{Power Series Solutions of Differential Equations}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemDEQSeriesPage}
{8.10.3. Power Series Solutions of Differential Equations}
\beginscroll

The command to solve differential equations in power
series
around
a particular initial point with specific initial conditions is called
\axiomFun{seriesSolve}.
It can take a variety of parameters, so we illustrate
its use with some examples.

\labelSpace{1pc}
\noOutputXtc{
Since the coefficients of some solutions
are quite large, we reset the default to compute only seven terms.
}{
\spadpaste{)set streams calculate 7 \bound{c7}}
}

You can solve a single nonlinear equation of any order. For example,
we solve  \axiom{y''' = sin(y'') * exp(y) + cos(x)}
subject to \axiom{y(0) = 1, y'(0) = 0, y''(0) = 0}.

\xtc{
We first tell Axiom
that the symbol \axiom{'y} denotes a new operator.
}{
\spadpaste{y := operator 'y \bound{y}}
}
\xtc{
Enter the differential equation using \axiom{y} like any system
function.
}{
\spadpaste{eq := D(y(x), x, 3) - sin(D(y(x), x, 2))*exp(y(x)) = 
cos(x)\bound{eq}\free{y}}
}
%
\xtc{
Solve it around \axiom{x = 0} with the initial conditions
\axiom{y(0) = 1, y'(0) = y''(0) = 0}.
}{
\spadpaste{seriesSolve(eq, y, x = 0, [1, 0, 0])\free{y}\free{eq}\free{c7}}
}

You can also solve a system of nonlinear first order equations.
For example, we solve a system that has \axiom{tan(t)} and
\axiom{sec(t)} as solutions.

\xtc{
We tell Axiom that \axiom{x} is also an operator.
}{
\spadpaste{x := operator 'x\bound{x}}
}
\xtc{
Enter the two equations forming our system.
}{
\spadpaste{eq1 := D(x(t), t) = 1 + x(t)**2\free{x}\free{y}\bound{eq1}}
}
%
\xtc{
}{
\spadpaste{eq2 := D(y(t), t) = x(t) * y(t)\free{x}\free{y}\bound{eq2}}
}
%
\xtc{
Solve the system around \axiom{t = 0} with the initial conditions
\axiom{x(0) = 0} and \axiom{y(0) = 1}.
Notice that since we give the unknowns in the
order \axiom{[x, y]}, the answer is a list of two series in the order
\axiom{[series for x(t), series for y(t)]}.
}{
\spadpaste{seriesSolve([eq2, eq1], [x, y], t = 0, 
[y(0) = 1, x(0) = 0])\free{x}\free{y}\free{eq1}\free{eq2}\free{c7}}
}
\noindent
The order in which we give the
equations and the initial conditions has no effect on the order of
the solution.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxProblemDEQSeriesPagePatch1}
\begin{paste}{ugxProblemDEQSeriesPageFull1}{ugxProblemDEQSeriesPageEmpty1}
\pastebutton{ugxProblemDEQSeriesPageFull1}{\hidepaste}
\tab{5}\spadcommand{)set streams calculate 7\bound{c7 }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemDEQSeriesPageEmpty1}
\begin{paste}{ugxProblemDEQSeriesPageEmpty1}{ugxProblemDEQSeriesPagePatch1}
\pastebutton{ugxProblemDEQSeriesPageEmpty1}{\showpaste}
\tab{5}\spadcommand{)set streams calculate 7\bound{c7 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemDEQSeriesPagePatch2}
\begin{paste}{ugxProblemDEQSeriesPageFull2}{ugxProblemDEQSeriesPageEmpty2}
\pastebutton{ugxProblemDEQSeriesPageFull2}{\hidepaste}
\tab{5}\spadcommand{y := operator 'y\bound{y }}
\indentrel{3}\begin{verbatim}
   (1)  y
                                    Type: BasicOperator
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemDEQSeriesPageEmpty2}
\begin{paste}{ugxProblemDEQSeriesPageEmpty2}{ugxProblemDEQSeriesPagePatch2}
\pastebutton{ugxProblemDEQSeriesPageEmpty2}{\showpaste}
\tab{5}\spadcommand{y := operator 'y\bound{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemDEQSeriesPagePatch3}
\begin{paste}{ugxProblemDEQSeriesPageFull3}{ugxProblemDEQSeriesPageEmpty3}
\pastebutton{ugxProblemDEQSeriesPageFull3}{\hidepaste}
\tab{5}\spadcommand{eq := D(y(x), x, 3) - sin(D(y(x), x, 2))*exp(y(x)) = cos(x)\bound{eq }\free{y }}
\indentrel{3}\begin{verbatim}
         ,,,        y(x)     ,,
   (2)  y   (x) - %e    sin(y  (x))= cos(x)

                      Type: Equation Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemDEQSeriesPageEmpty3}
\begin{paste}{ugxProblemDEQSeriesPageEmpty3}{ugxProblemDEQSeriesPagePatch3}
\pastebutton{ugxProblemDEQSeriesPageEmpty3}{\showpaste}
\tab{5}\spadcommand{eq := D(y(x), x, 3) - sin(D(y(x), x, 2))*exp(y(x)) = cos(x)\bound{eq }\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemDEQSeriesPagePatch4}
\begin{paste}{ugxProblemDEQSeriesPageFull4}{ugxProblemDEQSeriesPageEmpty4}
\pastebutton{ugxProblemDEQSeriesPageFull4}{\hidepaste}
\tab{5}\spadcommand{seriesSolve(eq, y, x = 0, [1, 0, 0])\free{y }\free{eq }\free{c7 }}
\indentrel{3}\begin{verbatim}
   (3)
                          2            3
         1  3   %e  4   %e  - 1  5   %e  - 2%e  6
     1 + Ä x  + ÄÄ x  + ÄÄÄÄÄÄÄ x  + ÄÄÄÄÄÄÄÄÄ x
         6      24        120           720
   + 
       4      2
     %e  - 8%e  + 4%e + 1  7      8
     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ x  + O(x )
             5040
   Type: UnivariateTaylorSeries(Expression Integer,x,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemDEQSeriesPageEmpty4}
\begin{paste}{ugxProblemDEQSeriesPageEmpty4}{ugxProblemDEQSeriesPagePatch4}
\pastebutton{ugxProblemDEQSeriesPageEmpty4}{\showpaste}
\tab{5}\spadcommand{seriesSolve(eq, y, x = 0, [1, 0, 0])\free{y }\free{eq }\free{c7 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemDEQSeriesPagePatch5}
\begin{paste}{ugxProblemDEQSeriesPageFull5}{ugxProblemDEQSeriesPageEmpty5}
\pastebutton{ugxProblemDEQSeriesPageFull5}{\hidepaste}
\tab{5}\spadcommand{x := operator 'x\bound{x }}
\indentrel{3}\begin{verbatim}
   (4)  x
                                    Type: BasicOperator
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemDEQSeriesPageEmpty5}
\begin{paste}{ugxProblemDEQSeriesPageEmpty5}{ugxProblemDEQSeriesPagePatch5}
\pastebutton{ugxProblemDEQSeriesPageEmpty5}{\showpaste}
\tab{5}\spadcommand{x := operator 'x\bound{x }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemDEQSeriesPagePatch6}
\begin{paste}{ugxProblemDEQSeriesPageFull6}{ugxProblemDEQSeriesPageEmpty6}
\pastebutton{ugxProblemDEQSeriesPageFull6}{\hidepaste}
\tab{5}\spadcommand{eq1 := D(x(t), t) = 1 + x(t)**2\free{x }\free{y }\bound{eq1 }}
\indentrel{3}\begin{verbatim}
         ,         2
   (5)  x (t)= x(t)  + 1

                      Type: Equation Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemDEQSeriesPageEmpty6}
\begin{paste}{ugxProblemDEQSeriesPageEmpty6}{ugxProblemDEQSeriesPagePatch6}
\pastebutton{ugxProblemDEQSeriesPageEmpty6}{\showpaste}
\tab{5}\spadcommand{eq1 := D(x(t), t) = 1 + x(t)**2\free{x }\free{y }\bound{eq1 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemDEQSeriesPagePatch7}
\begin{paste}{ugxProblemDEQSeriesPageFull7}{ugxProblemDEQSeriesPageEmpty7}
\pastebutton{ugxProblemDEQSeriesPageFull7}{\hidepaste}
\tab{5}\spadcommand{eq2 := D(y(t), t) = x(t) * y(t)\free{x }\free{y }\bound{eq2 }}
\indentrel{3}\begin{verbatim}
         ,
   (6)  y (t)= x(t)y(t)

                      Type: Equation Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemDEQSeriesPageEmpty7}
\begin{paste}{ugxProblemDEQSeriesPageEmpty7}{ugxProblemDEQSeriesPagePatch7}
\pastebutton{ugxProblemDEQSeriesPageEmpty7}{\showpaste}
\tab{5}\spadcommand{eq2 := D(y(t), t) = x(t) * y(t)\free{x }\free{y }\bound{eq2 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemDEQSeriesPagePatch8}
\begin{paste}{ugxProblemDEQSeriesPageFull8}{ugxProblemDEQSeriesPageEmpty8}
\pastebutton{ugxProblemDEQSeriesPageFull8}{\hidepaste}
\tab{5}\spadcommand{seriesSolve([eq2, eq1], [x, y], t = 0, [y(0) = 1, x(0) = 0])\free{x }\free{y }\free{eq1 }\free{eq2 }\free{c7 }}
\indentrel{3}\begin{verbatim}
   (7)
        1  3    2  5    17  7      8
   [t + Ä t  + ÄÄ t  + ÄÄÄ t  + O(t ),
        3      15      315
        1  2    5  4    61  6      8
    1 + Ä t  + ÄÄ t  + ÄÄÄ t  + O(t )]
        2      24      720
Type: List UnivariateTaylorSeries(Expression Integer,t,0)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemDEQSeriesPageEmpty8}
\begin{paste}{ugxProblemDEQSeriesPageEmpty8}{ugxProblemDEQSeriesPagePatch8}
\pastebutton{ugxProblemDEQSeriesPageEmpty8}{\showpaste}
\tab{5}\spadcommand{seriesSolve([eq2, eq1], [x, y], t = 0, [y(0) = 1, x(0) = 0])\free{x }\free{y }\free{eq1 }\free{eq2 }\free{c7 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugProblemFinitePage}{ug08.ht}{Finite Fields}
\pagepic{ps/v71ugproblemfinitepage.eps}{ugProblemFinitePage}{0.50}
\pagefrom{Axiom Number Types}{NumberPage}
\pageto{Modular Arithmetic and Prime Fields}{ugxProblemFinitePrimePage}
\pageto{Extensions of Finite Fields}{ugxProblemFiniteExtensionFinitePage}
\pageto{Irreducible Modulus Polynomial Representations}
{ugxProblemFiniteModulusPage}
\pageto{Cyclic Group Representations}{ugxProblemFiniteCyclicPage}
\pageto{Normal Basis Representations}{ugxProblemFiniteNormalPage}
\pageto{Conversion Operations for Finite Fields}
{ugxProblemFiniteConversionPage}
\pageto{Utility Operations for Finite Fields}
{ugxProblemFiniteUtilityPage}
\begin{chunk}{ug08.ht}
\begin{page}{ugProblemFinitePage}{8.11. Finite Fields}
\beginscroll
A {\it finite field} (also called a {\it Galois field}) is a
finite algebraic structure where one can add, multiply and divide
under the same laws (for example, commutativity, associativity or
distributivity) as apply to the rational, real or complex numbers.
Unlike those three fields, for any finite field there exists a
positive prime integer \smath{p}, called the
\axiomFun{characteristic}, such that 
\texht{$p \: x = 0$}{\axiom{p * x = 0}} 
for any element \smath{x} in the finite field.
In fact, the number of elements in a finite field is a power of
the characteristic and for each prime \smath{p} and positive
integer \smath{n} there exists exactly one finite field with
\texht{$p^n$}{\axiom{p**n}} elements, up to
isomorphism.\footnote{For more information about the algebraic
structure and properties of finite fields, see, for example, S.
Lang, {\it Algebra}, Second Edition, New York: Addison-Wesley
Publishing Company, Inc., 1984, ISBN 0 201 05487 6; or R.
Lidl, H.
Niederreiter, {\it Finite Fields}, Encyclopedia of Mathematics and
Its Applications, Vol.
20, Cambridge: Cambridge Univ.
Press, 1983, ISBN 0 521 30240 4.}

When \axiom{n = 1,} the field has \smath{p} elements and is
called a {\it prime field}, discussed in \texht{the next
section}{
\downlink{``Modular Arithmetic and Prime Fields''}
{ugxProblemFinitePrimePage} 
in Section 8.11.1\ignore{ugxProblemFinitePrime}}.
There are several ways of implementing extensions of finite
fields, and Axiom provides quite a bit of freedom to allow
you to choose the one that is best for your application.
Moreover, we provide operations for converting among the different
representations of extensions and different extensions of a single
field.
Finally, note that you usually need to package-call operations
from finite fields if the operations do not take as an argument an
object of the field.
See \downlink{``Package Calling and Target Types''}
{ugTypesPkgCallPage} in Section 2.9\ignore{ugTypesPkgCall} for more 
information on package-calling.

\beginmenu
\menudownlink{{8.11.1. Modular Arithmetic and Prime Fields}}
{ugxProblemFinitePrimePage}
\menudownlink{{8.11.2. Extensions of Finite Fields}}
{ugxProblemFiniteExtensionFinitePage}
\menudownlink{{8.11.3. Irreducible Modulus Polynomial Representations}}
{ugxProblemFiniteModulusPage}
\menudownlink{{8.11.4. Cyclic Group Representations}}
{ugxProblemFiniteCyclicPage}
\menudownlink{{8.11.5. Normal Basis Representations}}
{ugxProblemFiniteNormalPage}
\menudownlink{{8.11.6. Conversion Operations for Finite Fields}}
{ugxProblemFiniteConversionPage}
\menudownlink{{8.11.7. Utility Operations for Finite Fields}}
{ugxProblemFiniteUtilityPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugxProblemFinitePrimePage}{ug08.ht}
{Modular Arithmetic and Prime Fields}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemFinitePrimePage}
{8.11.1. Modular Arithmetic and Prime Fields}
\beginscroll

Let \smath{n} be a positive integer.
It is well known that you can get the same result if you perform
addition, subtraction or multiplication of integers and then take
the remainder on dividing by \smath{n} as if
you had first done such remaindering on the operands, performed the
arithmetic and then (if necessary) done remaindering again.
This allows us to speak of arithmetic
{\it modulo} \smath{n} or, more simply
{\it mod} \smath{n}.
\xtc{
In Axiom, you use \axiomType{IntegerMod} to do such arithmetic.
}{
\spadpaste{(a,b) : IntegerMod 12 \bound{abdec}}
}
\xtc{
}{
\spadpaste{(a, b) := (16, 7) \free{abdec}\bound{a b}}
}
\xtc{
}{
\spadpaste{[a - b, a * b] \free{a b}}
}
\xtc{
If \smath{n} is not prime, there is only a limited notion of
reciprocals and division.
}{
\spadpaste{a / b \free{a b}}
}
\xtc{
}{
\spadpaste{recip a \free{a}}
}
\xtc{
Here \axiom{7} and \axiom{12} are relatively prime, so \axiom{7}
has a multiplicative inverse modulo \axiom{12}.
}{
\spadpaste{recip b \free{b}}
}

If we take \smath{n} to be a prime number \smath{p},
then taking inverses and, therefore, division are generally defined.
\xtc{
Use \axiomType{PrimeField} instead of \axiomType{IntegerMod}
for \smath{n} prime.
}{
\spadpaste{c : PrimeField 11 := 8 \bound{c}}
}
\xtc{
}{
\spadpaste{inv c \free{c}}
}
\xtc{
You can also use \axiom{1/c} and \axiom{c**(-1)} for the inverse of
\smath{c}.
}{
\spadpaste{9/c \free{c}}
}

\axiomType{PrimeField} (abbreviation \axiomType{PF}) checks if its
argument is prime when you try to use an operation from it.
If you know the argument is prime (particularly if it is large),
\axiomType{InnerPrimeField} (abbreviation \axiomType{IPF}) assumes
the argument has already been verified to be prime.
If you do use a number that is not prime, you will eventually get
an error message, most likely a division by zero message.
For computer science applications, the most important finite fields
are \axiomType{PrimeField 2} and its extensions.

\xtc{
In the following examples, we work with the finite field with
\smath{p = 101} elements.
}{
\spadpaste{GF101 := PF 101 \bound{GF101} }
}
\xtc{
Like many domains in Axiom, finite fields provide an operation
for returning a random element of the domain.
}{
\spadpaste{x := random()\$GF101 \bound{x}\free{GF101}}
}
\xtc{
}{
\spadpaste{y : GF101 := 37 \bound{y}\free{GF101}}
}
\xtc{
}{
\spadpaste{z := x/y \bound{z}\free{x y}}
}
\xtc{
}{
\spadpaste{z * y - x \free{x y z}}
}
%
\xtc{
The element \axiom{2} is a {\it primitive element} of this field,
}{
\spadpaste{pe := primitiveElement()\$GF101 \bound{pe}\free{GF101}}
}
%
\xtc{
in the sense that its powers enumerate all nonzero elements.
}{
\spadpaste{[pe**i for i in 0..99] \free{pe}}
}
%
%
\xtc{
If every nonzero element is a power of a primitive element, how do you
determine what the exponent is?
Use
\axiomFun{discreteLog}.
}{
\spadpaste{ex := discreteLog(y) \bound{ex}\free{y}}
}
\xtc{
}{
\spadpaste{pe ** ex \free{ex pe}}
}
%
\xtc{
The \axiomFun{order} of a nonzero element \smath{x} is the
smallest positive integer \smath{t} such
\texht{$x^t = 1$}{\axiom{x**t = 1}}.
}{
\spadpaste{order y \free{y}}
}
\xtc{
The order of a primitive element is the defining \smath{p-1}.
}{
\spadpaste{order pe \free{pe}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxProblemFinitePrimePagePatch1}
\begin{paste}{ugxProblemFinitePrimePageFull1}{ugxProblemFinitePrimePageEmpty1}
\pastebutton{ugxProblemFinitePrimePageFull1}{\hidepaste}
\tab{5}\spadcommand{(a,b) : IntegerMod 12\bound{abdec }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePageEmpty1}
\begin{paste}{ugxProblemFinitePrimePageEmpty1}{ugxProblemFinitePrimePagePatch1}
\pastebutton{ugxProblemFinitePrimePageEmpty1}{\showpaste}
\tab{5}\spadcommand{(a,b) : IntegerMod 12\bound{abdec }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePagePatch2}
\begin{paste}{ugxProblemFinitePrimePageFull2}{ugxProblemFinitePrimePageEmpty2}
\pastebutton{ugxProblemFinitePrimePageFull2}{\hidepaste}
\tab{5}\spadcommand{(a, b) := (16, 7)\free{abdec }\bound{a b }}
\indentrel{3}\begin{verbatim}
   (2)  7
                                    Type: IntegerMod 12
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePageEmpty2}
\begin{paste}{ugxProblemFinitePrimePageEmpty2}{ugxProblemFinitePrimePagePatch2}
\pastebutton{ugxProblemFinitePrimePageEmpty2}{\showpaste}
\tab{5}\spadcommand{(a, b) := (16, 7)\free{abdec }\bound{a b }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePagePatch3}
\begin{paste}{ugxProblemFinitePrimePageFull3}{ugxProblemFinitePrimePageEmpty3}
\pastebutton{ugxProblemFinitePrimePageFull3}{\hidepaste}
\tab{5}\spadcommand{[a - b, a * b]\free{a b }}
\indentrel{3}\begin{verbatim}
   (3)  [9,4]
                               Type: List IntegerMod 12
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePageEmpty3}
\begin{paste}{ugxProblemFinitePrimePageEmpty3}{ugxProblemFinitePrimePagePatch3}
\pastebutton{ugxProblemFinitePrimePageEmpty3}{\showpaste}
\tab{5}\spadcommand{[a - b, a * b]\free{a b }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePagePatch4}
\begin{paste}{ugxProblemFinitePrimePageFull4}{ugxProblemFinitePrimePageEmpty4}
\pastebutton{ugxProblemFinitePrimePageFull4}{\hidepaste}
\tab{5}\spadcommand{a / b\free{a b }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePageEmpty4}
\begin{paste}{ugxProblemFinitePrimePageEmpty4}{ugxProblemFinitePrimePagePatch4}
\pastebutton{ugxProblemFinitePrimePageEmpty4}{\showpaste}
\tab{5}\spadcommand{a / b\free{a b }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePagePatch5}
\begin{paste}{ugxProblemFinitePrimePageFull5}{ugxProblemFinitePrimePageEmpty5}
\pastebutton{ugxProblemFinitePrimePageFull5}{\hidepaste}
\tab{5}\spadcommand{recip a\free{a }}
\indentrel{3}\begin{verbatim}
   (4)  "failed"
                              Type: Union("failed",...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePageEmpty5}
\begin{paste}{ugxProblemFinitePrimePageEmpty5}{ugxProblemFinitePrimePagePatch5}
\pastebutton{ugxProblemFinitePrimePageEmpty5}{\showpaste}
\tab{5}\spadcommand{recip a\free{a }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePagePatch6}
\begin{paste}{ugxProblemFinitePrimePageFull6}{ugxProblemFinitePrimePageEmpty6}
\pastebutton{ugxProblemFinitePrimePageFull6}{\hidepaste}
\tab{5}\spadcommand{recip b\free{b }}
\indentrel{3}\begin{verbatim}
   (5)  7
                         Type: Union(IntegerMod 12,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePageEmpty6}
\begin{paste}{ugxProblemFinitePrimePageEmpty6}{ugxProblemFinitePrimePagePatch6}
\pastebutton{ugxProblemFinitePrimePageEmpty6}{\showpaste}
\tab{5}\spadcommand{recip b\free{b }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePagePatch7}
\begin{paste}{ugxProblemFinitePrimePageFull7}{ugxProblemFinitePrimePageEmpty7}
\pastebutton{ugxProblemFinitePrimePageFull7}{\hidepaste}
\tab{5}\spadcommand{c : PrimeField 11 := 8\bound{c }}
\indentrel{3}\begin{verbatim}
   (6)  8
                                    Type: PrimeField 11
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePageEmpty7}
\begin{paste}{ugxProblemFinitePrimePageEmpty7}{ugxProblemFinitePrimePagePatch7}
\pastebutton{ugxProblemFinitePrimePageEmpty7}{\showpaste}
\tab{5}\spadcommand{c : PrimeField 11 := 8\bound{c }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePagePatch8}
\begin{paste}{ugxProblemFinitePrimePageFull8}{ugxProblemFinitePrimePageEmpty8}
\pastebutton{ugxProblemFinitePrimePageFull8}{\hidepaste}
\tab{5}\spadcommand{inv c\free{c }}
\indentrel{3}\begin{verbatim}
   (7)  7
                                    Type: PrimeField 11
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePageEmpty8}
\begin{paste}{ugxProblemFinitePrimePageEmpty8}{ugxProblemFinitePrimePagePatch8}
\pastebutton{ugxProblemFinitePrimePageEmpty8}{\showpaste}
\tab{5}\spadcommand{inv c\free{c }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePagePatch9}
\begin{paste}{ugxProblemFinitePrimePageFull9}{ugxProblemFinitePrimePageEmpty9}
\pastebutton{ugxProblemFinitePrimePageFull9}{\hidepaste}
\tab{5}\spadcommand{9/c\free{c }}
\indentrel{3}\begin{verbatim}
   (8)  8
                                    Type: PrimeField 11
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePageEmpty9}
\begin{paste}{ugxProblemFinitePrimePageEmpty9}{ugxProblemFinitePrimePagePatch9}
\pastebutton{ugxProblemFinitePrimePageEmpty9}{\showpaste}
\tab{5}\spadcommand{9/c\free{c }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePagePatch10}
\begin{paste}{ugxProblemFinitePrimePageFull10}{ugxProblemFinitePrimePageEmpty10}
\pastebutton{ugxProblemFinitePrimePageFull10}{\hidepaste}
\tab{5}\spadcommand{GF101 := PF 101\bound{GF101 }}
\indentrel{3}\begin{verbatim}
   (9)  PrimeField 101
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePageEmpty10}
\begin{paste}{ugxProblemFinitePrimePageEmpty10}{ugxProblemFinitePrimePagePatch10}
\pastebutton{ugxProblemFinitePrimePageEmpty10}{\showpaste}
\tab{5}\spadcommand{GF101 := PF 101\bound{GF101 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePagePatch11}
\begin{paste}{ugxProblemFinitePrimePageFull11}{ugxProblemFinitePrimePageEmpty11}
\pastebutton{ugxProblemFinitePrimePageFull11}{\hidepaste}
\tab{5}\spadcommand{x := random()$GF101\bound{x }\free{GF101 }}
\indentrel{3}\begin{verbatim}
   (10)  78
                                   Type: PrimeField 101
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePageEmpty11}
\begin{paste}{ugxProblemFinitePrimePageEmpty11}{ugxProblemFinitePrimePagePatch11}
\pastebutton{ugxProblemFinitePrimePageEmpty11}{\showpaste}
\tab{5}\spadcommand{x := random()$GF101\bound{x }\free{GF101 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePagePatch12}
\begin{paste}{ugxProblemFinitePrimePageFull12}{ugxProblemFinitePrimePageEmpty12}
\pastebutton{ugxProblemFinitePrimePageFull12}{\hidepaste}
\tab{5}\spadcommand{y : GF101 := 37\bound{y }\free{GF101 }}
\indentrel{3}\begin{verbatim}
   (11)  37
                                   Type: PrimeField 101
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePageEmpty12}
\begin{paste}{ugxProblemFinitePrimePageEmpty12}{ugxProblemFinitePrimePagePatch12}
\pastebutton{ugxProblemFinitePrimePageEmpty12}{\showpaste}
\tab{5}\spadcommand{y : GF101 := 37\bound{y }\free{GF101 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePagePatch13}
\begin{paste}{ugxProblemFinitePrimePageFull13}{ugxProblemFinitePrimePageEmpty13}
\pastebutton{ugxProblemFinitePrimePageFull13}{\hidepaste}
\tab{5}\spadcommand{z := x/y\bound{z }\free{x y }}
\indentrel{3}\begin{verbatim}
   (12)  84
                                   Type: PrimeField 101
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePageEmpty13}
\begin{paste}{ugxProblemFinitePrimePageEmpty13}{ugxProblemFinitePrimePagePatch13}
\pastebutton{ugxProblemFinitePrimePageEmpty13}{\showpaste}
\tab{5}\spadcommand{z := x/y\bound{z }\free{x y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePagePatch14}
\begin{paste}{ugxProblemFinitePrimePageFull14}{ugxProblemFinitePrimePageEmpty14}
\pastebutton{ugxProblemFinitePrimePageFull14}{\hidepaste}
\tab{5}\spadcommand{z * y - x\free{x y z }}
\indentrel{3}\begin{verbatim}
   (13)  0
                                   Type: PrimeField 101
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePageEmpty14}
\begin{paste}{ugxProblemFinitePrimePageEmpty14}{ugxProblemFinitePrimePagePatch14}
\pastebutton{ugxProblemFinitePrimePageEmpty14}{\showpaste}
\tab{5}\spadcommand{z * y - x\free{x y z }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePagePatch15}
\begin{paste}{ugxProblemFinitePrimePageFull15}{ugxProblemFinitePrimePageEmpty15}
\pastebutton{ugxProblemFinitePrimePageFull15}{\hidepaste}
\tab{5}\spadcommand{pe := primitiveElement()$GF101\bound{pe }\free{GF101 }}
\indentrel{3}\begin{verbatim}
   (14)  2
                                   Type: PrimeField 101
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePageEmpty15}
\begin{paste}{ugxProblemFinitePrimePageEmpty15}{ugxProblemFinitePrimePagePatch15}
\pastebutton{ugxProblemFinitePrimePageEmpty15}{\showpaste}
\tab{5}\spadcommand{pe := primitiveElement()$GF101\bound{pe }\free{GF101 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePagePatch16}
\begin{paste}{ugxProblemFinitePrimePageFull16}{ugxProblemFinitePrimePageEmpty16}
\pastebutton{ugxProblemFinitePrimePageFull16}{\hidepaste}
\tab{5}\spadcommand{[pe**i for i in 0..99]\free{pe }}
\indentrel{3}\begin{verbatim}
   (15)
   [1, 2, 4, 8, 16, 32, 64, 27, 54, 7, 14, 28, 56, 11,
    22, 44, 88, 75, 49, 98, 95, 89, 77, 53, 5, 10, 20,
    40, 80, 59, 17, 34, 68, 35, 70, 39, 78, 55, 9, 18,
    36, 72, 43, 86, 71, 41, 82, 63, 25, 50, 100, 99, 97,
    93, 85, 69, 37, 74, 47, 94, 87, 73, 45, 90, 79, 57,
    13, 26, 52, 3, 6, 12, 24, 48, 96, 91, 81, 61, 21, 42,
    84, 67, 33, 66, 31, 62, 23, 46, 92, 83, 65, 29, 58,
    15, 30, 60, 19, 38, 76, 51]
                              Type: List PrimeField 101
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePageEmpty16}
\begin{paste}{ugxProblemFinitePrimePageEmpty16}{ugxProblemFinitePrimePagePatch16}
\pastebutton{ugxProblemFinitePrimePageEmpty16}{\showpaste}
\tab{5}\spadcommand{[pe**i for i in 0..99]\free{pe }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePagePatch17}
\begin{paste}{ugxProblemFinitePrimePageFull17}{ugxProblemFinitePrimePageEmpty17}
\pastebutton{ugxProblemFinitePrimePageFull17}{\hidepaste}
\tab{5}\spadcommand{ex := discreteLog(y)\bound{ex }\free{y }}
\indentrel{3}\begin{verbatim}
   (16)  56
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePageEmpty17}
\begin{paste}{ugxProblemFinitePrimePageEmpty17}{ugxProblemFinitePrimePagePatch17}
\pastebutton{ugxProblemFinitePrimePageEmpty17}{\showpaste}
\tab{5}\spadcommand{ex := discreteLog(y)\bound{ex }\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePagePatch18}
\begin{paste}{ugxProblemFinitePrimePageFull18}{ugxProblemFinitePrimePageEmpty18}
\pastebutton{ugxProblemFinitePrimePageFull18}{\hidepaste}
\tab{5}\spadcommand{pe ** ex\free{ex pe }}
\indentrel{3}\begin{verbatim}
   (17)  37
                                   Type: PrimeField 101
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePageEmpty18}
\begin{paste}{ugxProblemFinitePrimePageEmpty18}{ugxProblemFinitePrimePagePatch18}
\pastebutton{ugxProblemFinitePrimePageEmpty18}{\showpaste}
\tab{5}\spadcommand{pe ** ex\free{ex pe }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePagePatch19}
\begin{paste}{ugxProblemFinitePrimePageFull19}{ugxProblemFinitePrimePageEmpty19}
\pastebutton{ugxProblemFinitePrimePageFull19}{\hidepaste}
\tab{5}\spadcommand{order y\free{y }}
\indentrel{3}\begin{verbatim}
   (18)  25
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePageEmpty19}
\begin{paste}{ugxProblemFinitePrimePageEmpty19}{ugxProblemFinitePrimePagePatch19}
\pastebutton{ugxProblemFinitePrimePageEmpty19}{\showpaste}
\tab{5}\spadcommand{order y\free{y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePagePatch20}
\begin{paste}{ugxProblemFinitePrimePageFull20}{ugxProblemFinitePrimePageEmpty20}
\pastebutton{ugxProblemFinitePrimePageFull20}{\hidepaste}
\tab{5}\spadcommand{order pe\free{pe }}
\indentrel{3}\begin{verbatim}
   (19)  100
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFinitePrimePageEmpty20}
\begin{paste}{ugxProblemFinitePrimePageEmpty20}{ugxProblemFinitePrimePagePatch20}
\pastebutton{ugxProblemFinitePrimePageEmpty20}{\showpaste}
\tab{5}\spadcommand{order pe\free{pe }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxProblemFiniteExtensionFinitePage}{ug08.ht}
{Extensions of Finite Fields}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemFiniteExtensionFinitePage}
{8.11.2. Extensions of Finite Fields}
\beginscroll

When you want to work with an extension of a finite field in Axiom,
you have three choices to make:
\indent{4}
\beginitems
\item[1. ] Do you want to generate an extension of the prime field
(for example, \axiomType{PrimeField 2}) or an extension of a given field?
%
\item[2. ] Do you want to use a representation that is particularly
efficient for multiplication, exponentiation and addition but
uses a lot of computer memory (a representation that models the cyclic
group structure of the multiplicative group of the field extension
and uses a Zech logarithm table),  one that
uses a normal basis for the vector space structure of the field
extension, or one that performs arithmetic modulo an irreducible
polynomial?
The cyclic group representation is only usable up to ``medium''
(relative to your machine's performance)
sized fields.
If the field is large and the normal basis is relatively simple,
the normal basis representation is more efficient for exponentiation than
the irreducible polynomial representation.
%
\item[3. ] Do you want to provide a polynomial explicitly, a root of which
``generates'' the extension in one of the three senses in (2),
or do you wish to have the polynomial generated for you?
\enditems
\indent{0}

This illustrates one of the most important features of Axiom:
you can choose exactly the right data-type and representation to
suit your application best.

We first tell you what domain constructors to use for each case
above, and then give some examples.

\texht{\hangafter=1\hangindent=2pc}{\noindent}
Constructors that automatically generate extensions of the prime field:
\newline
\axiomType{FiniteField} \newline
\axiomType{FiniteFieldCyclicGroup} \newline
\axiomType{FiniteFieldNormalBasis}

\texht{\hangafter=1\hangindent=2pc}{\noindent}
Constructors that generate extensions of an arbitrary field:
\newline
\axiomType{FiniteFieldExtension} \newline
\axiomType{FiniteFieldExtensionByPolynomial} \newline
\axiomType{FiniteFieldCyclicGroupExtension} \newline
\axiomType{FiniteFieldCyclicGroupExtensionByPolynomial} \newline
\axiomType{FiniteFieldNormalBasisExtension} \newline
\axiomType{FiniteFieldNormalBasisExtensionByPolynomial}

\texht{\hangafter=1\hangindent=2pc}{\noindent}
Constructors that use a cyclic group representation:
\newline
\axiomType{FiniteFieldCyclicGroup} \newline
\axiomType{FiniteFieldCyclicGroupExtension} \newline
\axiomType{FiniteFieldCyclicGroupExtensionByPolynomial}

\texht{\hangafter=1\hangindent=2pc}{\noindent}
Constructors that use a normal basis representation:
\newline
\axiomType{FiniteFieldNormalBasis} \newline
\axiomType{FiniteFieldNormalBasisExtension} \newline
\axiomType{FiniteFieldNormalBasisExtensionByPolynomial}

\texht{\hangafter=1\hangindent=2pc}{\noindent}
Constructors that use an irreducible modulus polynomial representation:
\newline
\axiomType{FiniteField} \newline
\axiomType{FiniteFieldExtension} \newline
\axiomType{FiniteFieldExtensionByPolynomial}

\texht{\hangafter=1\hangindent=2pc}{\noindent}
Constructors that generate a polynomial for you:
\newline
\axiomType{FiniteField} \newline
\axiomType{FiniteFieldExtension} \newline
\axiomType{FiniteFieldCyclicGroup} \newline
\axiomType{FiniteFieldCyclicGroupExtension} \newline
\axiomType{FiniteFieldNormalBasis} \newline
\axiomType{FiniteFieldNormalBasisExtension}

\texht{\hangafter=1\hangindent=2pc}{\noindent}
Constructors for which you provide a polynomial:
\newline
\axiomType{FiniteFieldExtensionByPolynomial} \newline
\axiomType{FiniteFieldCyclicGroupExtensionByPolynomial} \newline
\axiomType{FiniteFieldNormalBasisExtensionByPolynomial}

These constructors are discussed in the following sections where
we collect together descriptions of extension fields that have the
same underlying representation.\footnote{For
more information on the implementation aspects of finite
fields, see
J. Grabmeier, A. Scheerhorn, {\it Finite Fields in AXIOM,}
Technical Report, IBM Heidelberg Scientific Center, 1992.}

If you don't really care about all this detail, just use
\axiomType{FiniteField}.
As your knowledge of your application and its Axiom implementation
grows, you can come back and choose an alternative constructor that
may improve the efficiency of your code.
Note that the exported operations are almost the same for all constructors
of finite field extensions and include the operations exported by
\axiomType{PrimeField}.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugxProblemFiniteModulusPage}{ug08.ht}
{Irreducible Mod Polynomial Representations}
\pageto{notitle}{ugxProblemFiniteExtensionFinitePage}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemFiniteModulusPage}
{8.11.3. Irreducible Mod Polynomial Representations}
\beginscroll

All finite field extension constructors discussed in this
section
use a representation that performs arithmetic with univariate
(one-variable) polynomials modulo an irreducible polynomial.
This polynomial may be given explicitly by you or automatically
generated.
The ground field may be the prime field or one you specify.
See 
\downlink{``Extensions of Finite Fields''}
{ugxProblemFiniteExtensionFinitePage} in Section 8.11.2
\ignore{ugxProblemFiniteExtensionFinite}
for general information about finite field extensions.

For \axiomType{FiniteField} (abbreviation \axiomType{FF}) you provide a
prime number \smath{p} and an extension degree \smath{n}.
This degree can be 1.
%
\xtc{
Axiom uses the prime field \axiomType{PrimeField(p)},
here \axiomType{PrimeField 2},
and it chooses an irreducible polynomial of degree \smath{n},
here 12, over the ground field.
}{
\spadpaste{GF4096 := FF(2,12); \bound{GF4096}}
}
%

The objects in the generated field extension are polynomials
of degree at most \smath{n-1} with coefficients in the
prime field.
The polynomial indeterminate is automatically chosen by Axiom and
is typically something like \axiom{\%A} or \axiom{\%D}.
These (strange) variables are {\it only} for output display;
there are several ways to construct elements of this field.

The operation \axiomFun{index} enumerates the elements of the field
extension and accepts as argument the integers from 1 to
\smath{p \texht{^}{**} n}.
%
\xtc{
The expression
\axiom{index(p)} always gives the indeterminate.
}{
\spadpaste{a := index(2)\$GF4096 \bound{a}\free{GF4096}}
}
%
%
\xtc{
You can build polynomials in \smath{a} and calculate in
\axiom{GF4096}.
}{
\spadpaste{b := a**12 - a**5 + a \bound{b}\free{a}}
}
\xtc{
}{
\spadpaste{b ** 1000 \free{b}}
}
\xtc{
}{
\spadpaste{c := a/b \free{a b}\bound{c}}
}
%
\xtc{
Among the available operations are \axiomFun{norm} and \axiomFun{trace}.
}{
\spadpaste{norm c \free{c}}
}
\xtc{
}{
\spadpaste{trace c \free{c}}
}
%
%

Since any nonzero element is a power of a primitive element, how
do we discover what the exponent is?
%
\xtc{
The operation \axiomFun{discreteLog} calculates
the exponent and,
if it is called with only one argument, always refers to the primitive
element returned by \axiomFun{primitiveElement}.
}{
\spadpaste{dL := discreteLog a \free{a}\bound{dL}}
}
\xtc{
}{
\spadpaste{g ** dL \free{dL g}}
}

\axiomType{FiniteFieldExtension} (abbreviation \axiomType{FFX}) is
similar to \axiomType{FiniteField} except that the
ground-field for \axiomType{FiniteFieldExtension} is arbitrary and
chosen by you.
%
\xtc{
In case you select the prime field as ground field, there is
essentially no difference between the constructed two finite field
extensions.
}{
\spadpaste{GF16 := FF(2,4); \bound{GF16}}
}
\xtc{
}{
\spadpaste{GF4096 := FFX(GF16,3); \bound{GF4096x}\free{GF16}}
}
\xtc{
}{
\spadpaste{r := (random()\$GF4096) ** 20 \free{GF4096x}\bound{r}}
}
\xtc{
}{
\spadpaste{norm(r) \free{r}}
}
%

\axiomType{FiniteFieldExtensionByPolynomial} (abbreviation \axiomType{FFP})
is similar to \axiomType{FiniteField} and \axiomType{FiniteFieldExtension}
but is more general.
%
\xtc{
}{
\spadpaste{GF4 := FF(2,2); \bound{GF4}}
}
\xtc{
}{
\spadpaste{f := nextIrreduciblePoly(random(6)\$FFPOLY(GF4))\$FFPOLY(GF4) 
\free{GF4}\bound{f}}
}
\xtc{
For \axiomType{FFP} you choose both the
ground field and the irreducible polynomial used in the representation.
The degree of the extension is the degree of the polynomial.
}{
\spadpaste{GF4096 := FFP(GF4,f); \bound{GF4096y}\free{f GF4}}
}
\xtc{
}{
\spadpaste{discreteLog random()\$GF4096 \free{GF4096y}}
}
%

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxProblemFiniteModulusPagePatch1}
\begin{paste}{ugxProblemFiniteModulusPageFull1}{ugxProblemFiniteModulusPageEmpty1}
\pastebutton{ugxProblemFiniteModulusPageFull1}{\hidepaste}
\tab{5}\spadcommand{GF4096 := FF(2,12);\bound{GF4096 }}
\indentrel{3}\begin{verbatim}
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPageEmpty1}
\begin{paste}{ugxProblemFiniteModulusPageEmpty1}{ugxProblemFiniteModulusPagePatch1}
\pastebutton{ugxProblemFiniteModulusPageEmpty1}{\showpaste}
\tab{5}\spadcommand{GF4096 := FF(2,12);\bound{GF4096 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPagePatch2}
\begin{paste}{ugxProblemFiniteModulusPageFull2}{ugxProblemFiniteModulusPageEmpty2}
\pastebutton{ugxProblemFiniteModulusPageFull2}{\hidepaste}
\tab{5}\spadcommand{a := index(2)$GF4096\bound{a }\free{GF4096 }}
\indentrel{3}\begin{verbatim}
   (2)  %CS
                                Type: FiniteField(2,12)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPageEmpty2}
\begin{paste}{ugxProblemFiniteModulusPageEmpty2}{ugxProblemFiniteModulusPagePatch2}
\pastebutton{ugxProblemFiniteModulusPageEmpty2}{\showpaste}
\tab{5}\spadcommand{a := index(2)$GF4096\bound{a }\free{GF4096 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPagePatch3}
\begin{paste}{ugxProblemFiniteModulusPageFull3}{ugxProblemFiniteModulusPageEmpty3}
\pastebutton{ugxProblemFiniteModulusPageFull3}{\hidepaste}
\tab{5}\spadcommand{b := a**12 - a**5 + a\bound{b }\free{a }}
\indentrel{3}\begin{verbatim}
           5      3
   (3)  %CS  + %CS  + %CS + 1
                                Type: FiniteField(2,12)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPageEmpty3}
\begin{paste}{ugxProblemFiniteModulusPageEmpty3}{ugxProblemFiniteModulusPagePatch3}
\pastebutton{ugxProblemFiniteModulusPageEmpty3}{\showpaste}
\tab{5}\spadcommand{b := a**12 - a**5 + a\bound{b }\free{a }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPagePatch4}
\begin{paste}{ugxProblemFiniteModulusPageFull4}{ugxProblemFiniteModulusPageEmpty4}
\pastebutton{ugxProblemFiniteModulusPageFull4}{\hidepaste}
\tab{5}\spadcommand{b ** 1000\free{b }}
\indentrel{3}\begin{verbatim}
           10      9      7      5      4      3
   (4)  %CS   + %CS  + %CS  + %CS  + %CS  + %CS  + %CS
                                Type: FiniteField(2,12)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPageEmpty4}
\begin{paste}{ugxProblemFiniteModulusPageEmpty4}{ugxProblemFiniteModulusPagePatch4}
\pastebutton{ugxProblemFiniteModulusPageEmpty4}{\showpaste}
\tab{5}\spadcommand{b ** 1000\free{b }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPagePatch5}
\begin{paste}{ugxProblemFiniteModulusPageFull5}{ugxProblemFiniteModulusPageEmpty5}
\pastebutton{ugxProblemFiniteModulusPageFull5}{\hidepaste}
\tab{5}\spadcommand{c := a/b\free{a b }\bound{c }}
\indentrel{3}\begin{verbatim}
           11      8      7      5      4      3      2
   (5)  %CS   + %CS  + %CS  + %CS  + %CS  + %CS  + %CS
                                Type: FiniteField(2,12)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPageEmpty5}
\begin{paste}{ugxProblemFiniteModulusPageEmpty5}{ugxProblemFiniteModulusPagePatch5}
\pastebutton{ugxProblemFiniteModulusPageEmpty5}{\showpaste}
\tab{5}\spadcommand{c := a/b\free{a b }\bound{c }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPagePatch6}
\begin{paste}{ugxProblemFiniteModulusPageFull6}{ugxProblemFiniteModulusPageEmpty6}
\pastebutton{ugxProblemFiniteModulusPageFull6}{\hidepaste}
\tab{5}\spadcommand{norm c\free{c }}
\indentrel{3}\begin{verbatim}
   (6)  1
                                     Type: PrimeField 2
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPageEmpty6}
\begin{paste}{ugxProblemFiniteModulusPageEmpty6}{ugxProblemFiniteModulusPagePatch6}
\pastebutton{ugxProblemFiniteModulusPageEmpty6}{\showpaste}
\tab{5}\spadcommand{norm c\free{c }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPagePatch7}
\begin{paste}{ugxProblemFiniteModulusPageFull7}{ugxProblemFiniteModulusPageEmpty7}
\pastebutton{ugxProblemFiniteModulusPageFull7}{\hidepaste}
\tab{5}\spadcommand{trace c\free{c }}
\indentrel{3}\begin{verbatim}
   (7)  0
                                     Type: PrimeField 2
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPageEmpty7}
\begin{paste}{ugxProblemFiniteModulusPageEmpty7}{ugxProblemFiniteModulusPagePatch7}
\pastebutton{ugxProblemFiniteModulusPageEmpty7}{\showpaste}
\tab{5}\spadcommand{trace c\free{c }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPagePatch8}
\begin{paste}{ugxProblemFiniteModulusPageFull8}{ugxProblemFiniteModulusPageEmpty8}
\pastebutton{ugxProblemFiniteModulusPageFull8}{\hidepaste}
\tab{5}\spadcommand{dL := discreteLog a\free{a }\bound{dL }}
\indentrel{3}\begin{verbatim}
   (8)  1729
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPageEmpty8}
\begin{paste}{ugxProblemFiniteModulusPageEmpty8}{ugxProblemFiniteModulusPagePatch8}
\pastebutton{ugxProblemFiniteModulusPageEmpty8}{\showpaste}
\tab{5}\spadcommand{dL := discreteLog a\free{a }\bound{dL }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPagePatch9}
\begin{paste}{ugxProblemFiniteModulusPageFull9}{ugxProblemFiniteModulusPageEmpty9}
\pastebutton{ugxProblemFiniteModulusPageFull9}{\hidepaste}
\tab{5}\spadcommand{g ** dL\free{dL g }}
\indentrel{3}\begin{verbatim}
         1729
   (9)  g
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPageEmpty9}
\begin{paste}{ugxProblemFiniteModulusPageEmpty9}{ugxProblemFiniteModulusPagePatch9}
\pastebutton{ugxProblemFiniteModulusPageEmpty9}{\showpaste}
\tab{5}\spadcommand{g ** dL\free{dL g }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPagePatch10}
\begin{paste}{ugxProblemFiniteModulusPageFull10}{ugxProblemFiniteModulusPageEmpty10}
\pastebutton{ugxProblemFiniteModulusPageFull10}{\hidepaste}
\tab{5}\spadcommand{GF16 := FF(2,4);\bound{GF16 }}
\indentrel{3}\begin{verbatim}
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPageEmpty10}
\begin{paste}{ugxProblemFiniteModulusPageEmpty10}{ugxProblemFiniteModulusPagePatch10}
\pastebutton{ugxProblemFiniteModulusPageEmpty10}{\showpaste}
\tab{5}\spadcommand{GF16 := FF(2,4);\bound{GF16 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPagePatch11}
\begin{paste}{ugxProblemFiniteModulusPageFull11}{ugxProblemFiniteModulusPageEmpty11}
\pastebutton{ugxProblemFiniteModulusPageFull11}{\hidepaste}
\tab{5}\spadcommand{GF4096 := FFX(GF16,3);\bound{GF4096x }\free{GF16 }}
\indentrel{3}\begin{verbatim}
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPageEmpty11}
\begin{paste}{ugxProblemFiniteModulusPageEmpty11}{ugxProblemFiniteModulusPagePatch11}
\pastebutton{ugxProblemFiniteModulusPageEmpty11}{\showpaste}
\tab{5}\spadcommand{GF4096 := FFX(GF16,3);\bound{GF4096x }\free{GF16 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPagePatch12}
\begin{paste}{ugxProblemFiniteModulusPageFull12}{ugxProblemFiniteModulusPageEmpty12}
\pastebutton{ugxProblemFiniteModulusPageFull12}{\hidepaste}
\tab{5}\spadcommand{r := (random()$GF4096) ** 20\free{GF4096x }\bound{r }}
\indentrel{3}\begin{verbatim}
             3              2
   (12)  (%CT  + %CT + 1)%CU  + %CT %CU
         Type: FiniteFieldExtension(FiniteField(2,4),3)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPageEmpty12}
\begin{paste}{ugxProblemFiniteModulusPageEmpty12}{ugxProblemFiniteModulusPagePatch12}
\pastebutton{ugxProblemFiniteModulusPageEmpty12}{\showpaste}
\tab{5}\spadcommand{r := (random()$GF4096) ** 20\free{GF4096x }\bound{r }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPagePatch13}
\begin{paste}{ugxProblemFiniteModulusPageFull13}{ugxProblemFiniteModulusPageEmpty13}
\pastebutton{ugxProblemFiniteModulusPageFull13}{\hidepaste}
\tab{5}\spadcommand{norm(r)\free{r }}
\indentrel{3}\begin{verbatim}
            2
   (13)  %CT  + %CT
                                 Type: FiniteField(2,4)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPageEmpty13}
\begin{paste}{ugxProblemFiniteModulusPageEmpty13}{ugxProblemFiniteModulusPagePatch13}
\pastebutton{ugxProblemFiniteModulusPageEmpty13}{\showpaste}
\tab{5}\spadcommand{norm(r)\free{r }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPagePatch14}
\begin{paste}{ugxProblemFiniteModulusPageFull14}{ugxProblemFiniteModulusPageEmpty14}
\pastebutton{ugxProblemFiniteModulusPageFull14}{\hidepaste}
\tab{5}\spadcommand{GF4 := FF(2,2);\bound{GF4 }}
\indentrel{3}\begin{verbatim}
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPageEmpty14}
\begin{paste}{ugxProblemFiniteModulusPageEmpty14}{ugxProblemFiniteModulusPagePatch14}
\pastebutton{ugxProblemFiniteModulusPageEmpty14}{\showpaste}
\tab{5}\spadcommand{GF4 := FF(2,2);\bound{GF4 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPagePatch15}
\begin{paste}{ugxProblemFiniteModulusPageFull15}{ugxProblemFiniteModulusPageEmpty15}
\pastebutton{ugxProblemFiniteModulusPageFull15}{\hidepaste}
\tab{5}\spadcommand{f := nextIrreduciblePoly(random(6)$FFPOLY(GF4))$FFPOLY(GF4)\free{GF4 }\bound{f }}
\indentrel{3}\begin{verbatim}
          6    5             4             2
   (15)  ?  + ?  + (%CV + 1)?  + (%CV + 1)?  + ? + %CV
Type: Union(SparseUnivariatePolynomial FiniteField(2,2),...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPageEmpty15}
\begin{paste}{ugxProblemFiniteModulusPageEmpty15}{ugxProblemFiniteModulusPagePatch15}
\pastebutton{ugxProblemFiniteModulusPageEmpty15}{\showpaste}
\tab{5}\spadcommand{f := nextIrreduciblePoly(random(6)$FFPOLY(GF4))$FFPOLY(GF4)\free{GF4 }\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPagePatch16}
\begin{paste}{ugxProblemFiniteModulusPageFull16}{ugxProblemFiniteModulusPageEmpty16}
\pastebutton{ugxProblemFiniteModulusPageFull16}{\hidepaste}
\tab{5}\spadcommand{GF4096 := FFP(GF4,f);\bound{GF4096y }\free{f GF4 }}
\indentrel{3}\begin{verbatim}
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPageEmpty16}
\begin{paste}{ugxProblemFiniteModulusPageEmpty16}{ugxProblemFiniteModulusPagePatch16}
\pastebutton{ugxProblemFiniteModulusPageEmpty16}{\showpaste}
\tab{5}\spadcommand{GF4096 := FFP(GF4,f);\bound{GF4096y }\free{f GF4 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPagePatch17}
\begin{paste}{ugxProblemFiniteModulusPageFull17}{ugxProblemFiniteModulusPageEmpty17}
\pastebutton{ugxProblemFiniteModulusPageFull17}{\hidepaste}
\tab{5}\spadcommand{discreteLog random()$GF4096\free{GF4096y }}
\indentrel{3}\begin{verbatim}
   (17)  3370
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteModulusPageEmpty17}
\begin{paste}{ugxProblemFiniteModulusPageEmpty17}{ugxProblemFiniteModulusPagePatch17}
\pastebutton{ugxProblemFiniteModulusPageEmpty17}{\showpaste}
\tab{5}\spadcommand{discreteLog random()$GF4096\free{GF4096y }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxProblemFiniteCyclicPage}{ug08.ht}
{Cyclic Group Representations}
\pageto{notitle}{ugxProblemFiniteUtilityPage}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemFiniteCyclicPage}
{8.11.4. Cyclic Group Representations}
\beginscroll

In every finite field there exist elements whose powers are all the
nonzero elements of the field.
Such an element is called a {\it primitive element}.

In \axiomType{FiniteFieldCyclicGroup} (abbreviation \axiomType{FFCG})
the nonzero elements are represented by the powers of a fixed
primitive element of the field (that is, a generator of its cyclic
multiplicative group).  Multiplication (and hence exponentiation)
using this representation is easy.  To do addition, we consider our
primitive element as the root of a primitive polynomial (an
irreducible polynomial whose roots are all primitive).  See
\downlink{``Utility Operations for Finite Fields''}
{ugxProblemFiniteUtilityPage} in Section
8.11.7\ignore{ugxProblemFiniteUtility} for
examples of how to compute such a polynomial.

%
\xtc{
To use \axiomType{FiniteFieldCyclicGroup} you provide a prime number and an
extension degree.
}{
\spadpaste{GF81 := FFCG(3,4); \bound{GF81}}
}
%
%
\xtc{
Axiom uses the prime field, here \axiomType{PrimeField 3}, as the
ground field and it chooses a primitive polynomial of degree
\smath{n}, here 4, over the prime field.
}{
\spadpaste{a := primitiveElement()\$GF81 \bound{a}\free{GF81}}
}
%
%
\xtc{
You can calculate in \axiom{GF81}.
}{
\spadpaste{b  := a**12 - a**5 + a \bound{b}\free{a}}
}
%
\xtc{
In this representation of finite fields the discrete logarithm
of an element can be seen directly in its output form.
}{
\spadpaste{b \free{b}}
}
\xtc{
}{
\spadpaste{discreteLog b \free{b}}
}
%

\axiomType{FiniteFieldCyclicGroupExtension} (abbreviation
\axiomType{FFCGX}) is similar to \axiomType{FiniteFieldCyclicGroup}
except that the ground field for
\axiomType{FiniteFieldCyclicGroupExtension} is arbitrary and chosen
by you.
In case you select the prime field as ground field, there is
essentially no difference between the constructed two finite field
extensions.
%
\xtc{
}{
\spadpaste{GF9 := FF(3,2); \bound{GF9}}
}
\xtc{
}{
\spadpaste{GF729 := FFCGX(GF9,3); \bound{GF729}\free{GF9}}
}
\xtc{
}{
\spadpaste{r := (random()\$GF729) ** 20 \free{GF729}\bound{r}}
}
\xtc{
}{
\spadpaste{trace(r) \free{r}}
}
%

\axiomType{FiniteFieldCyclicGroupExtensionByPolynomial} (abbreviation
\axiomType{FFCGP}) is similar to \axiomType{FiniteFieldCyclicGroup}
and \axiomType{FiniteFieldCyclicGroupExtension} but is more general.
For \axiomType{FiniteFieldCyclicGroupExtensionByPolynomial} you choose
both the ground field and the irreducible polynomial used in the
representation.  The degree of the extension is the degree of the
polynomial.

\xtc{
}{
\spadpaste{GF3  := PrimeField 3; \bound{GF3}}
}
\xtc{
We use a utility operation to generate an irreducible primitive
polynomial (see 
\downlink{``Utility Operations for Finite Fields''}
{ugxProblemFiniteUtilityPage} 
in Section 8.11.7\ignore{ugxProblemFiniteUtility}).
The polynomial has one variable that is ``anonymous'': it displays
as a question mark.
}{
\spadpaste{f := createPrimitivePoly(4)\$FFPOLY(GF3) \bound{f}\free{GF3}}
}
\xtc{
}{
\spadpaste{GF81 := FFCGP(GF3,f); \bound{GF81x}\free{f GF3}}
}
\xtc{
Let's look at a random element from this field.
}{
\spadpaste{random()\$GF81 \free{GF81x}}
}
%

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxProblemFiniteCyclicPagePatch1}
\begin{paste}{ugxProblemFiniteCyclicPageFull1}{ugxProblemFiniteCyclicPageEmpty1}
\pastebutton{ugxProblemFiniteCyclicPageFull1}{\hidepaste}
\tab{5}\spadcommand{GF81 := FFCG(3,4);\bound{GF81 }}
\indentrel{3}\begin{verbatim}
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPageEmpty1}
\begin{paste}{ugxProblemFiniteCyclicPageEmpty1}{ugxProblemFiniteCyclicPagePatch1}
\pastebutton{ugxProblemFiniteCyclicPageEmpty1}{\showpaste}
\tab{5}\spadcommand{GF81 := FFCG(3,4);\bound{GF81 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPagePatch2}
\begin{paste}{ugxProblemFiniteCyclicPageFull2}{ugxProblemFiniteCyclicPageEmpty2}
\pastebutton{ugxProblemFiniteCyclicPageFull2}{\hidepaste}
\tab{5}\spadcommand{a := primitiveElement()$GF81\bound{a }\free{GF81 }}
\indentrel{3}\begin{verbatim}
           1
   (2)  %BF
                      Type: FiniteFieldCyclicGroup(3,4)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPageEmpty2}
\begin{paste}{ugxProblemFiniteCyclicPageEmpty2}{ugxProblemFiniteCyclicPagePatch2}
\pastebutton{ugxProblemFiniteCyclicPageEmpty2}{\showpaste}
\tab{5}\spadcommand{a := primitiveElement()$GF81\bound{a }\free{GF81 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPagePatch3}
\begin{paste}{ugxProblemFiniteCyclicPageFull3}{ugxProblemFiniteCyclicPageEmpty3}
\pastebutton{ugxProblemFiniteCyclicPageFull3}{\hidepaste}
\tab{5}\spadcommand{b := a**12 - a**5 + a\bound{b }\free{a }}
\indentrel{3}\begin{verbatim}
           72
   (3)  %BF
                      Type: FiniteFieldCyclicGroup(3,4)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPageEmpty3}
\begin{paste}{ugxProblemFiniteCyclicPageEmpty3}{ugxProblemFiniteCyclicPagePatch3}
\pastebutton{ugxProblemFiniteCyclicPageEmpty3}{\showpaste}
\tab{5}\spadcommand{b := a**12 - a**5 + a\bound{b }\free{a }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPagePatch4}
\begin{paste}{ugxProblemFiniteCyclicPageFull4}{ugxProblemFiniteCyclicPageEmpty4}
\pastebutton{ugxProblemFiniteCyclicPageFull4}{\hidepaste}
\tab{5}\spadcommand{b\free{b }}
\indentrel{3}\begin{verbatim}
           72
   (4)  %BF
                      Type: FiniteFieldCyclicGroup(3,4)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPageEmpty4}
\begin{paste}{ugxProblemFiniteCyclicPageEmpty4}{ugxProblemFiniteCyclicPagePatch4}
\pastebutton{ugxProblemFiniteCyclicPageEmpty4}{\showpaste}
\tab{5}\spadcommand{b\free{b }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPagePatch5}
\begin{paste}{ugxProblemFiniteCyclicPageFull5}{ugxProblemFiniteCyclicPageEmpty5}
\pastebutton{ugxProblemFiniteCyclicPageFull5}{\hidepaste}
\tab{5}\spadcommand{discreteLog b\free{b }}
\indentrel{3}\begin{verbatim}
   (5)  72
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPageEmpty5}
\begin{paste}{ugxProblemFiniteCyclicPageEmpty5}{ugxProblemFiniteCyclicPagePatch5}
\pastebutton{ugxProblemFiniteCyclicPageEmpty5}{\showpaste}
\tab{5}\spadcommand{discreteLog b\free{b }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPagePatch6}
\begin{paste}{ugxProblemFiniteCyclicPageFull6}{ugxProblemFiniteCyclicPageEmpty6}
\pastebutton{ugxProblemFiniteCyclicPageFull6}{\hidepaste}
\tab{5}\spadcommand{GF9 := FF(3,2);\bound{GF9 }}
\indentrel{3}\begin{verbatim}
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPageEmpty6}
\begin{paste}{ugxProblemFiniteCyclicPageEmpty6}{ugxProblemFiniteCyclicPagePatch6}
\pastebutton{ugxProblemFiniteCyclicPageEmpty6}{\showpaste}
\tab{5}\spadcommand{GF9 := FF(3,2);\bound{GF9 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPagePatch7}
\begin{paste}{ugxProblemFiniteCyclicPageFull7}{ugxProblemFiniteCyclicPageEmpty7}
\pastebutton{ugxProblemFiniteCyclicPageFull7}{\hidepaste}
\tab{5}\spadcommand{GF729 := FFCGX(GF9,3);\bound{GF729 }\free{GF9 }}
\indentrel{3}\begin{verbatim}
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPageEmpty7}
\begin{paste}{ugxProblemFiniteCyclicPageEmpty7}{ugxProblemFiniteCyclicPagePatch7}
\pastebutton{ugxProblemFiniteCyclicPageEmpty7}{\showpaste}
\tab{5}\spadcommand{GF729 := FFCGX(GF9,3);\bound{GF729 }\free{GF9 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPagePatch8}
\begin{paste}{ugxProblemFiniteCyclicPageFull8}{ugxProblemFiniteCyclicPageEmpty8}
\pastebutton{ugxProblemFiniteCyclicPageFull8}{\hidepaste}
\tab{5}\spadcommand{r := (random()$GF729) ** 20\free{GF729 }\bound{r }}
\indentrel{3}\begin{verbatim}
           68
   (8)  %CN
Type: FiniteFieldCyclicGroupExtension(FiniteField(3,2),3)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPageEmpty8}
\begin{paste}{ugxProblemFiniteCyclicPageEmpty8}{ugxProblemFiniteCyclicPagePatch8}
\pastebutton{ugxProblemFiniteCyclicPageEmpty8}{\showpaste}
\tab{5}\spadcommand{r := (random()$GF729) ** 20\free{GF729 }\bound{r }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPagePatch9}
\begin{paste}{ugxProblemFiniteCyclicPageFull9}{ugxProblemFiniteCyclicPageEmpty9}
\pastebutton{ugxProblemFiniteCyclicPageFull9}{\hidepaste}
\tab{5}\spadcommand{trace(r)\free{r }}
\indentrel{3}\begin{verbatim}
   (9)  2
                                 Type: FiniteField(3,2)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPageEmpty9}
\begin{paste}{ugxProblemFiniteCyclicPageEmpty9}{ugxProblemFiniteCyclicPagePatch9}
\pastebutton{ugxProblemFiniteCyclicPageEmpty9}{\showpaste}
\tab{5}\spadcommand{trace(r)\free{r }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPagePatch10}
\begin{paste}{ugxProblemFiniteCyclicPageFull10}{ugxProblemFiniteCyclicPageEmpty10}
\pastebutton{ugxProblemFiniteCyclicPageFull10}{\hidepaste}
\tab{5}\spadcommand{GF3 := PrimeField 3;\bound{GF3 }}
\indentrel{3}\begin{verbatim}
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPageEmpty10}
\begin{paste}{ugxProblemFiniteCyclicPageEmpty10}{ugxProblemFiniteCyclicPagePatch10}
\pastebutton{ugxProblemFiniteCyclicPageEmpty10}{\showpaste}
\tab{5}\spadcommand{GF3 := PrimeField 3;\bound{GF3 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPagePatch11}
\begin{paste}{ugxProblemFiniteCyclicPageFull11}{ugxProblemFiniteCyclicPageEmpty11}
\pastebutton{ugxProblemFiniteCyclicPageFull11}{\hidepaste}
\tab{5}\spadcommand{f := createPrimitivePoly(4)$FFPOLY(GF3)\bound{f }\free{GF3 }}
\indentrel{3}\begin{verbatim}
          4
   (11)  ?  + ? + 2
          Type: SparseUnivariatePolynomial PrimeField 3
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPageEmpty11}
\begin{paste}{ugxProblemFiniteCyclicPageEmpty11}{ugxProblemFiniteCyclicPagePatch11}
\pastebutton{ugxProblemFiniteCyclicPageEmpty11}{\showpaste}
\tab{5}\spadcommand{f := createPrimitivePoly(4)$FFPOLY(GF3)\bound{f }\free{GF3 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPagePatch12}
\begin{paste}{ugxProblemFiniteCyclicPageFull12}{ugxProblemFiniteCyclicPageEmpty12}
\pastebutton{ugxProblemFiniteCyclicPageFull12}{\hidepaste}
\tab{5}\spadcommand{GF81 := FFCGP(GF3,f);\bound{GF81x }\free{f GF3 }}
\indentrel{3}\begin{verbatim}
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPageEmpty12}
\begin{paste}{ugxProblemFiniteCyclicPageEmpty12}{ugxProblemFiniteCyclicPagePatch12}
\pastebutton{ugxProblemFiniteCyclicPageEmpty12}{\showpaste}
\tab{5}\spadcommand{GF81 := FFCGP(GF3,f);\bound{GF81x }\free{f GF3 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPagePatch13}
\begin{paste}{ugxProblemFiniteCyclicPageFull13}{ugxProblemFiniteCyclicPageEmpty13}
\pastebutton{ugxProblemFiniteCyclicPageFull13}{\hidepaste}
\tab{5}\spadcommand{random()$GF81\free{GF81x }}
\indentrel{3}\begin{verbatim}
            8
   (13)  %BF
Type: FiniteFieldCyclicGroupExtensionByPolynomial(PrimeField 3,?**4+?+2)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteCyclicPageEmpty13}
\begin{paste}{ugxProblemFiniteCyclicPageEmpty13}{ugxProblemFiniteCyclicPagePatch13}
\pastebutton{ugxProblemFiniteCyclicPageEmpty13}{\showpaste}
\tab{5}\spadcommand{random()$GF81\free{GF81x }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxProblemFiniteNormalPage}{ug08.ht}
{Normal Basis Representations}
\pageto{notitle}{ugxProblemFiniteUtilityPage}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemFiniteNormalPage}
{8.11.5. Normal Basis Representations}
\beginscroll

Let \smath{K} be a finite extension of degree \smath{n} of the
finite field \smath{F} and let \smath{F} have \smath{q}
elements.
An element \smath{x} of \smath{K} is said to be
{\it normal} over \smath{F} if the elements
\centerline{{\axiom{1, x**q, x**(q**2), ..., x**(q**(n-1))}}}
form a basis of \smath{K} as a vector space over \smath{F}.
Such a basis is called a {\it normal basis}.\footnote{This
agrees with the general definition of a normal basis because the
\smath{n} distinct powers of the automorphism
\texht{$x \mapsto x^q$}{\axiom{x +-> x**q}}
constitute the Galois group of \smath{K/F}.}

If \smath{x} is normal over \smath{F}, its minimal
polynomial is also said to be {\it normal} over \smath{F}.
There exist normal bases for all finite extensions of arbitrary
finite fields.

In \axiomType{FiniteFieldNormalBasis} (abbreviation
\axiomType{FFNB}), the elements of the finite field are represented
by coordinate vectors with respect to a normal basis.

\xtc{
You provide a prime \smath{p} and an extension degree
\smath{n}.
}{
\spadpaste{K := FFNB(3,8) \bound{K}}
}

Axiom uses the prime field \axiomType{PrimeField(p)}, here
\axiomType{PrimeField 3}, and it chooses a normal polynomial of degree
\smath{n}, here 8, over the ground field.  The remainder class of the
indeterminate is used as the normal element.  The polynomial
indeterminate is automatically chosen by Axiom and is typically
something like \axiom{\%A} or \axiom{\%D}.  These (strange) variables
are only for output display; there are several ways to construct
elements of this field.  The output of the basis elements is something
like
\texht{$\%A^{q^i}.$}{
\begin{verbatim}
   i
  q
%A  .
\end{verbatim}
}
%
\xtc{
}{
\spadpaste{a := normalElement()\$K \bound{a}\free{K}}
}
%
%
\xtc{
You can calculate in \smath{K} using \smath{a}.
}{
\spadpaste{b  := a**12 - a**5 + a \bound{b}\free{a}}
}

\axiomType{FiniteFieldNormalBasisExtension} 
(abbreviation \axiomType{FFNBX}) is similar to 
\axiomType{FiniteFieldNormalBasis}
except that the groundfield for
\axiomType{FiniteFieldNormalBasisExtension} is arbitrary and chosen 
by you.  In case you select the prime field as ground field, there 
is essentially no difference between the constructed two finite field
extensions.

\xtc{
}{
\spadpaste{GF9 := FFNB(3,2); \bound{GF9}}
}
\xtc{
}{
\spadpaste{GF729 := FFNBX(GF9,3); \bound{GF729}\free{GF9}}
}
\xtc{
}{
\spadpaste{r := random()\$GF729 \bound{r}\free{GF729}}
}
\xtc{
}{
\spadpaste{r + r**3 + r**9 + r**27 \free{r}}
}

\axiomType{FiniteFieldNormalBasisExtensionByPolynomial}
(abbreviation \axiomType{FFNBP}) is similar to
\axiomType{FiniteFieldNormalBasis} and
\axiomType{FiniteFieldNormalBasisExtension} but is more general.
For \axiomType{FiniteFieldNormalBasisExtensionByPolynomial} you
choose both the ground field and the irreducible polynomial used
in the representation.
The degree of the extension is the degree of the polynomial.

%
\xtc{
}{
\spadpaste{GF3 := PrimeField 3; \bound{GF3}}
}
\xtc{
We use a utility operation to generate an irreducible normal
polynomial (see 
\downlink{``Utility Operations for Finite Fields''}
{ugxProblemFiniteUtilityPage} 
in Section 8.11.7\ignore{ugxProblemFiniteUtility}).
The polynomial has one variable that is ``anonymous'': it displays
as a question mark.
}{
\spadpaste{f := createNormalPoly(4)\$FFPOLY(GF3) \free{GF3}\bound{f}}
}
\xtc{
}{
\spadpaste{GF81 := FFNBP(GF3,f); \bound{GF81}\free{f GF3}}
}
\xtc{
Let's look at a random element from this field.
}{
\spadpaste{r := random()\$GF81 \free{GF81}\bound{r1}}
}
\xtc{
}{
\spadpaste{r * r**3 * r**9 * r**27 \free{r1}}
}
\xtc{
}{
\spadpaste{norm r \free{r1}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxProblemFiniteNormalPagePatch1}
\begin{paste}{ugxProblemFiniteNormalPageFull1}{ugxProblemFiniteNormalPageEmpty1}
\pastebutton{ugxProblemFiniteNormalPageFull1}{\hidepaste}
\tab{5}\spadcommand{K := FFNB(3,8)\bound{K }}
\indentrel{3}\begin{verbatim}
   (1)  FiniteFieldNormalBasis(3,8)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPageEmpty1}
\begin{paste}{ugxProblemFiniteNormalPageEmpty1}{ugxProblemFiniteNormalPagePatch1}
\pastebutton{ugxProblemFiniteNormalPageEmpty1}{\showpaste}
\tab{5}\spadcommand{K := FFNB(3,8)\bound{K }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPagePatch2}
\begin{paste}{ugxProblemFiniteNormalPageFull2}{ugxProblemFiniteNormalPageEmpty2}
\pastebutton{ugxProblemFiniteNormalPageFull2}{\hidepaste}
\tab{5}\spadcommand{a := normalElement()$K\bound{a }\free{K }}
\indentrel{3}\begin{verbatim}
   (2)  %CO
                      Type: FiniteFieldNormalBasis(3,8)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPageEmpty2}
\begin{paste}{ugxProblemFiniteNormalPageEmpty2}{ugxProblemFiniteNormalPagePatch2}
\pastebutton{ugxProblemFiniteNormalPageEmpty2}{\showpaste}
\tab{5}\spadcommand{a := normalElement()$K\bound{a }\free{K }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPagePatch3}
\begin{paste}{ugxProblemFiniteNormalPageFull3}{ugxProblemFiniteNormalPageEmpty3}
\pastebutton{ugxProblemFiniteNormalPageFull3}{\hidepaste}
\tab{5}\spadcommand{b := a**12 - a**5 + a\bound{b }\free{a }}
\indentrel{3}\begin{verbatim}
             7       5
            q       q       q
   (3)  2%CO   + %CO   + %CO
                      Type: FiniteFieldNormalBasis(3,8)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPageEmpty3}
\begin{paste}{ugxProblemFiniteNormalPageEmpty3}{ugxProblemFiniteNormalPagePatch3}
\pastebutton{ugxProblemFiniteNormalPageEmpty3}{\showpaste}
\tab{5}\spadcommand{b := a**12 - a**5 + a\bound{b }\free{a }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPagePatch4}
\begin{paste}{ugxProblemFiniteNormalPageFull4}{ugxProblemFiniteNormalPageEmpty4}
\pastebutton{ugxProblemFiniteNormalPageFull4}{\hidepaste}
\tab{5}\spadcommand{GF9 := FFNB(3,2);\bound{GF9 }}
\indentrel{3}\begin{verbatim}
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPageEmpty4}
\begin{paste}{ugxProblemFiniteNormalPageEmpty4}{ugxProblemFiniteNormalPagePatch4}
\pastebutton{ugxProblemFiniteNormalPageEmpty4}{\showpaste}
\tab{5}\spadcommand{GF9 := FFNB(3,2);\bound{GF9 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPagePatch5}
\begin{paste}{ugxProblemFiniteNormalPageFull5}{ugxProblemFiniteNormalPageEmpty5}
\pastebutton{ugxProblemFiniteNormalPageFull5}{\hidepaste}
\tab{5}\spadcommand{GF729 := FFNBX(GF9,3);\bound{GF729 }\free{GF9 }}
\indentrel{3}\begin{verbatim}
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPageEmpty5}
\begin{paste}{ugxProblemFiniteNormalPageEmpty5}{ugxProblemFiniteNormalPagePatch5}
\pastebutton{ugxProblemFiniteNormalPageEmpty5}{\showpaste}
\tab{5}\spadcommand{GF729 := FFNBX(GF9,3);\bound{GF729 }\free{GF9 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPagePatch6}
\begin{paste}{ugxProblemFiniteNormalPageFull6}{ugxProblemFiniteNormalPageEmpty6}
\pastebutton{ugxProblemFiniteNormalPageFull6}{\hidepaste}
\tab{5}\spadcommand{r := random()$GF729\bound{r }\free{GF729 }}
\indentrel{3}\begin{verbatim}
                 2
            q   q
   (6)  2%CP %CQ
Type: FiniteFieldNormalBasisExtension(FiniteFieldNormalBasis(3,2),3)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPageEmpty6}
\begin{paste}{ugxProblemFiniteNormalPageEmpty6}{ugxProblemFiniteNormalPagePatch6}
\pastebutton{ugxProblemFiniteNormalPageEmpty6}{\showpaste}
\tab{5}\spadcommand{r := random()$GF729\bound{r }\free{GF729 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPagePatch7}
\begin{paste}{ugxProblemFiniteNormalPageFull7}{ugxProblemFiniteNormalPageEmpty7}
\pastebutton{ugxProblemFiniteNormalPageFull7}{\hidepaste}
\tab{5}\spadcommand{r + r**3 + r**9 + r**27\free{r }}
\indentrel{3}\begin{verbatim}
                          2
             q           q            q       q
   (7)  (2%CP  + 2%CP)%CQ   + 2%CP %CQ  + 2%CP %CQ
Type: FiniteFieldNormalBasisExtension(FiniteFieldNormalBasis(3,2),3)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPageEmpty7}
\begin{paste}{ugxProblemFiniteNormalPageEmpty7}{ugxProblemFiniteNormalPagePatch7}
\pastebutton{ugxProblemFiniteNormalPageEmpty7}{\showpaste}
\tab{5}\spadcommand{r + r**3 + r**9 + r**27\free{r }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPagePatch8}
\begin{paste}{ugxProblemFiniteNormalPageFull8}{ugxProblemFiniteNormalPageEmpty8}
\pastebutton{ugxProblemFiniteNormalPageFull8}{\hidepaste}
\tab{5}\spadcommand{GF3 := PrimeField 3;\bound{GF3 }}
\indentrel{3}\begin{verbatim}
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPageEmpty8}
\begin{paste}{ugxProblemFiniteNormalPageEmpty8}{ugxProblemFiniteNormalPagePatch8}
\pastebutton{ugxProblemFiniteNormalPageEmpty8}{\showpaste}
\tab{5}\spadcommand{GF3 := PrimeField 3;\bound{GF3 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPagePatch9}
\begin{paste}{ugxProblemFiniteNormalPageFull9}{ugxProblemFiniteNormalPageEmpty9}
\pastebutton{ugxProblemFiniteNormalPageFull9}{\hidepaste}
\tab{5}\spadcommand{f := createNormalPoly(4)$FFPOLY(GF3)\free{GF3 }\bound{f }}
\indentrel{3}\begin{verbatim}
         4     3
   (9)  ?  + 2?  + 2
          Type: SparseUnivariatePolynomial PrimeField 3
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPageEmpty9}
\begin{paste}{ugxProblemFiniteNormalPageEmpty9}{ugxProblemFiniteNormalPagePatch9}
\pastebutton{ugxProblemFiniteNormalPageEmpty9}{\showpaste}
\tab{5}\spadcommand{f := createNormalPoly(4)$FFPOLY(GF3)\free{GF3 }\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPagePatch10}
\begin{paste}{ugxProblemFiniteNormalPageFull10}{ugxProblemFiniteNormalPageEmpty10}
\pastebutton{ugxProblemFiniteNormalPageFull10}{\hidepaste}
\tab{5}\spadcommand{GF81 := FFNBP(GF3,f);\bound{GF81 }\free{f GF3 }}
\indentrel{3}\begin{verbatim}
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPageEmpty10}
\begin{paste}{ugxProblemFiniteNormalPageEmpty10}{ugxProblemFiniteNormalPagePatch10}
\pastebutton{ugxProblemFiniteNormalPageEmpty10}{\showpaste}
\tab{5}\spadcommand{GF81 := FFNBP(GF3,f);\bound{GF81 }\free{f GF3 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPagePatch11}
\begin{paste}{ugxProblemFiniteNormalPageFull11}{ugxProblemFiniteNormalPageEmpty11}
\pastebutton{ugxProblemFiniteNormalPageFull11}{\hidepaste}
\tab{5}\spadcommand{r := random()$GF81\free{GF81 }\bound{r1 }}
\indentrel{3}\begin{verbatim}
             3       2
            q       q       q
   (11)  %CR   + %CR   + %CR
Type: FiniteFieldNormalBasisExtensionByPolynomial(PrimeField 3,?**4+2*?**3+2)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPageEmpty11}
\begin{paste}{ugxProblemFiniteNormalPageEmpty11}{ugxProblemFiniteNormalPagePatch11}
\pastebutton{ugxProblemFiniteNormalPageEmpty11}{\showpaste}
\tab{5}\spadcommand{r := random()$GF81\free{GF81 }\bound{r1 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPagePatch12}
\begin{paste}{ugxProblemFiniteNormalPageFull12}{ugxProblemFiniteNormalPageEmpty12}
\pastebutton{ugxProblemFiniteNormalPageFull12}{\hidepaste}
\tab{5}\spadcommand{r * r**3 * r**9 * r**27\free{r1 }}
\indentrel{3}\begin{verbatim}
              3        2
             q        q        q
   (12)  2%CR   + 2%CR   + 2%CR  + 2%CR
Type: FiniteFieldNormalBasisExtensionByPolynomial(PrimeField 3,?**4+2*?**3+2)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPageEmpty12}
\begin{paste}{ugxProblemFiniteNormalPageEmpty12}{ugxProblemFiniteNormalPagePatch12}
\pastebutton{ugxProblemFiniteNormalPageEmpty12}{\showpaste}
\tab{5}\spadcommand{r * r**3 * r**9 * r**27\free{r1 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPagePatch13}
\begin{paste}{ugxProblemFiniteNormalPageFull13}{ugxProblemFiniteNormalPageEmpty13}
\pastebutton{ugxProblemFiniteNormalPageFull13}{\hidepaste}
\tab{5}\spadcommand{norm r\free{r1 }}
\indentrel{3}\begin{verbatim}
   (13)  2
                                     Type: PrimeField 3
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteNormalPageEmpty13}
\begin{paste}{ugxProblemFiniteNormalPageEmpty13}{ugxProblemFiniteNormalPagePatch13}
\pastebutton{ugxProblemFiniteNormalPageEmpty13}{\showpaste}
\tab{5}\spadcommand{norm r\free{r1 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxProblemFiniteConversionPage}{ug08.ht}
{Conversion Operations for Finite Fields}
\pageto{notitle}{ugxProblemFiniteExtensionFinitePage}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemFiniteConversionPage}
{8.11.6. Conversion Operations for Finite Fields}
\beginscroll

\labelSpace{5pc}
%
\xtc{
Let \texht{$K$}{\axiom{K}} be a finite field.
}{
\spadpaste{K := PrimeField 3 \bound{K}}
}
%
An extension field \texht{$K_m$}{\axiom{Km}} of degree
\smath{m} over \texht{$K$}{\axiom{K}} is a subfield of an
extension field \texht{$K_n$}{\axiom{Kn}} of degree \smath{n}
over \texht{$K$}{\axiom{K}} if and only if \smath{m} divides
\smath{n}.
\texht{
\centerline{{\begin{tabular}{ccc}}}
\centerline{{$K_n$ }}
\centerline{{$|$ }}
\centerline{{$K_m$ & $\Longleftrightarrow$ & $m | n$ }}
\centerline{{$|$ }}
\centerline{{K}}
\centerline{{\end{tabular}}}
}{
\begin{verbatim}
Kn
|
Km   <==>  m | n
|
K
\end{verbatim}
}
\axiomType{FiniteFieldHomomorphisms} provides conversion operations
between different extensions of one
fixed finite ground field and between different representations of
these finite fields.
\xtc{
Let's choose \smath{m} and \smath{n},
}{
\spadpaste{(m,n) := (4,8) \bound{m n}}
}
\xtc{
build the field extensions,
}{
\spadpaste{Km := FiniteFieldExtension(K,m) \bound{Km}\free{K m}}
}
\xtc{
and pick two random elements from the smaller field.
}{
\spadpaste{Kn := FiniteFieldExtension(K,n) \bound{Kn}\free{K n}}
}
\xtc{
}{
\spadpaste{a1 := random()\$Km \bound{a1}\free{Km}}
}
\xtc{
}{
\spadpaste{b1 := random()\$Km \bound{b1}\free{Km}}
}
%
\xtc{
Since \smath{m} divides \smath{n},
\texht{$K_m$}{\axiom{Km}} is a subfield of \texht{$K_n$}{\axiom{Kn}}.
}{
\spadpaste{a2 := a1 :: Kn \bound{a2}\free{a1 Kn}}
}
\xtc{
Therefore we can convert the elements of \texht{$K_m$}{\axiom{Km}}
into elements of \texht{$K_n$}{\axiom{Kn}}.
}{
\spadpaste{b2 := b1 :: Kn \bound{b2}\free{b1 Kn}}
}
%
%
\xtc{
To check this, let's do some arithmetic.
}{
\spadpaste{a1+b1 - ((a2+b2) :: Km) \free{a1 a2 b1 b2 Km Kn}}
}
\xtc{
}{
\spadpaste{a1*b1 - ((a2*b2) :: Km) \free{a1 a2 b1 b2 Km Kn}}
}
%
There are also conversions available for the
situation, when \texht{$K_m$}{\axiom{Km}} and \texht{$K_n$}{\axiom{Kn}}
are represented in different ways (see
\downlink{``Extensions of Finite Fields''}
{ugxProblemFiniteExtensionFinitePage} in Section 8.11.2
\ignore{ugxProblemFiniteExtensionFinite}).
For example let's choose \texht{$K_m$}{\axiom{Km}} where the
representation is 0 plus the cyclic multiplicative group and
\texht{$K_n$}{\axiom{Kn}} with a normal basis representation.
\xtc{
}{
\spadpaste{Km := FFCGX(K,m) \bound{Km2}\free{K m}}
}
\xtc{
}{
\spadpaste{Kn := FFNBX(K,n) \bound{Kn2}\free{K n}}
}
\xtc{
}{
\spadpaste{(a1,b1) := (random()\$Km,random()\$Km) 
\bound{a12 b12}\free{Km2}}
}
\xtc{
}{
\spadpaste{a2 := a1 :: Kn \bound{a22}\free{a12 Kn2}}
}
\xtc{
}{
\spadpaste{b2 := b1 :: Kn \bound{b22}\free{b12 Kn2}}
}
%
\xtc{
Check the arithmetic again.
}{
\spadpaste{a1+b1 - ((a2+b2) :: Km) \free{a12 a22 b12 b22 Km2}}
}
\xtc{
}{
\spadpaste{a1*b1 - ((a2*b2) :: Km) \free{a12 a22 b12 b22 Km2}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxProblemFiniteConversionPagePatch1}
\begin{paste}{ugxProblemFiniteConversionPageFull1}{ugxProblemFiniteConversionPageEmpty1}
\pastebutton{ugxProblemFiniteConversionPageFull1}{\hidepaste}
\tab{5}\spadcommand{K := PrimeField 3\bound{K }}
\indentrel{3}\begin{verbatim}
   (1)  PrimeField 3
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPageEmpty1}
\begin{paste}{ugxProblemFiniteConversionPageEmpty1}{ugxProblemFiniteConversionPagePatch1}
\pastebutton{ugxProblemFiniteConversionPageEmpty1}{\showpaste}
\tab{5}\spadcommand{K := PrimeField 3\bound{K }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPagePatch2}
\begin{paste}{ugxProblemFiniteConversionPageFull2}{ugxProblemFiniteConversionPageEmpty2}
\pastebutton{ugxProblemFiniteConversionPageFull2}{\hidepaste}
\tab{5}\spadcommand{(m,n) := (4,8)\bound{m n }}
\indentrel{3}\begin{verbatim}
   (2)  8
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPageEmpty2}
\begin{paste}{ugxProblemFiniteConversionPageEmpty2}{ugxProblemFiniteConversionPagePatch2}
\pastebutton{ugxProblemFiniteConversionPageEmpty2}{\showpaste}
\tab{5}\spadcommand{(m,n) := (4,8)\bound{m n }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPagePatch3}
\begin{paste}{ugxProblemFiniteConversionPageFull3}{ugxProblemFiniteConversionPageEmpty3}
\pastebutton{ugxProblemFiniteConversionPageFull3}{\hidepaste}
\tab{5}\spadcommand{Km := FiniteFieldExtension(K,m)\bound{Km }\free{K m }}
\indentrel{3}\begin{verbatim}
   (3)  FiniteFieldExtension(PrimeField 3,4)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPageEmpty3}
\begin{paste}{ugxProblemFiniteConversionPageEmpty3}{ugxProblemFiniteConversionPagePatch3}
\pastebutton{ugxProblemFiniteConversionPageEmpty3}{\showpaste}
\tab{5}\spadcommand{Km := FiniteFieldExtension(K,m)\bound{Km }\free{K m }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPagePatch4}
\begin{paste}{ugxProblemFiniteConversionPageFull4}{ugxProblemFiniteConversionPageEmpty4}
\pastebutton{ugxProblemFiniteConversionPageFull4}{\hidepaste}
\tab{5}\spadcommand{Kn := FiniteFieldExtension(K,n)\bound{Kn }\free{K n }}
\indentrel{3}\begin{verbatim}
   (4)  FiniteFieldExtension(PrimeField 3,8)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPageEmpty4}
\begin{paste}{ugxProblemFiniteConversionPageEmpty4}{ugxProblemFiniteConversionPagePatch4}
\pastebutton{ugxProblemFiniteConversionPageEmpty4}{\showpaste}
\tab{5}\spadcommand{Kn := FiniteFieldExtension(K,n)\bound{Kn }\free{K n }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPagePatch5}
\begin{paste}{ugxProblemFiniteConversionPageFull5}{ugxProblemFiniteConversionPageEmpty5}
\pastebutton{ugxProblemFiniteConversionPageFull5}{\hidepaste}
\tab{5}\spadcommand{a1 := random()$Km\bound{a1 }\free{Km }}
\indentrel{3}\begin{verbatim}
            3       2
   (5)  2%BD  + 2%BD  + 2%BD + 1
             Type: FiniteFieldExtension(PrimeField 3,4)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPageEmpty5}
\begin{paste}{ugxProblemFiniteConversionPageEmpty5}{ugxProblemFiniteConversionPagePatch5}
\pastebutton{ugxProblemFiniteConversionPageEmpty5}{\showpaste}
\tab{5}\spadcommand{a1 := random()$Km\bound{a1 }\free{Km }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPagePatch6}
\begin{paste}{ugxProblemFiniteConversionPageFull6}{ugxProblemFiniteConversionPageEmpty6}
\pastebutton{ugxProblemFiniteConversionPageFull6}{\hidepaste}
\tab{5}\spadcommand{b1 := random()$Km\bound{b1 }\free{Km }}
\indentrel{3}\begin{verbatim}
           3      2
   (6)  %BD  + %BD  + 2%BD + 2
             Type: FiniteFieldExtension(PrimeField 3,4)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPageEmpty6}
\begin{paste}{ugxProblemFiniteConversionPageEmpty6}{ugxProblemFiniteConversionPagePatch6}
\pastebutton{ugxProblemFiniteConversionPageEmpty6}{\showpaste}
\tab{5}\spadcommand{b1 := random()$Km\bound{b1 }\free{Km }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPagePatch7}
\begin{paste}{ugxProblemFiniteConversionPageFull7}{ugxProblemFiniteConversionPageEmpty7}
\pastebutton{ugxProblemFiniteConversionPageFull7}{\hidepaste}
\tab{5}\spadcommand{a2 := a1 :: Kn\bound{a2 }\free{a1 Kn }}
\indentrel{3}\begin{verbatim}
            6
   (7)  2%BE  + 1
             Type: FiniteFieldExtension(PrimeField 3,8)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPageEmpty7}
\begin{paste}{ugxProblemFiniteConversionPageEmpty7}{ugxProblemFiniteConversionPagePatch7}
\pastebutton{ugxProblemFiniteConversionPageEmpty7}{\showpaste}
\tab{5}\spadcommand{a2 := a1 :: Kn\bound{a2 }\free{a1 Kn }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPagePatch8}
\begin{paste}{ugxProblemFiniteConversionPageFull8}{ugxProblemFiniteConversionPageEmpty8}
\pastebutton{ugxProblemFiniteConversionPageFull8}{\hidepaste}
\tab{5}\spadcommand{b2 := b1 :: Kn\bound{b2 }\free{b1 Kn }}
\indentrel{3}\begin{verbatim}
            6       4      2
   (8)  2%BE  + 2%BE  + %BE  + 2
             Type: FiniteFieldExtension(PrimeField 3,8)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPageEmpty8}
\begin{paste}{ugxProblemFiniteConversionPageEmpty8}{ugxProblemFiniteConversionPagePatch8}
\pastebutton{ugxProblemFiniteConversionPageEmpty8}{\showpaste}
\tab{5}\spadcommand{b2 := b1 :: Kn\bound{b2 }\free{b1 Kn }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPagePatch9}
\begin{paste}{ugxProblemFiniteConversionPageFull9}{ugxProblemFiniteConversionPageEmpty9}
\pastebutton{ugxProblemFiniteConversionPageFull9}{\hidepaste}
\tab{5}\spadcommand{a1+b1 - ((a2+b2) :: Km)\free{a1 a2 b1 b2 Km Kn }}
\indentrel{3}\begin{verbatim}
   (9)  0
             Type: FiniteFieldExtension(PrimeField 3,4)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPageEmpty9}
\begin{paste}{ugxProblemFiniteConversionPageEmpty9}{ugxProblemFiniteConversionPagePatch9}
\pastebutton{ugxProblemFiniteConversionPageEmpty9}{\showpaste}
\tab{5}\spadcommand{a1+b1 - ((a2+b2) :: Km)\free{a1 a2 b1 b2 Km Kn }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPagePatch10}
\begin{paste}{ugxProblemFiniteConversionPageFull10}{ugxProblemFiniteConversionPageEmpty10}
\pastebutton{ugxProblemFiniteConversionPageFull10}{\hidepaste}
\tab{5}\spadcommand{a1*b1 - ((a2*b2) :: Km)\free{a1 a2 b1 b2 Km Kn }}
\indentrel{3}\begin{verbatim}
   (10)  0
             Type: FiniteFieldExtension(PrimeField 3,4)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPageEmpty10}
\begin{paste}{ugxProblemFiniteConversionPageEmpty10}{ugxProblemFiniteConversionPagePatch10}
\pastebutton{ugxProblemFiniteConversionPageEmpty10}{\showpaste}
\tab{5}\spadcommand{a1*b1 - ((a2*b2) :: Km)\free{a1 a2 b1 b2 Km Kn }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPagePatch11}
\begin{paste}{ugxProblemFiniteConversionPageFull11}{ugxProblemFiniteConversionPageEmpty11}
\pastebutton{ugxProblemFiniteConversionPageFull11}{\hidepaste}
\tab{5}\spadcommand{Km := FFCGX(K,m)\bound{Km2 }\free{K m }}
\indentrel{3}\begin{verbatim}
   (11)  FiniteFieldCyclicGroupExtension(PrimeField 3,4)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPageEmpty11}
\begin{paste}{ugxProblemFiniteConversionPageEmpty11}{ugxProblemFiniteConversionPagePatch11}
\pastebutton{ugxProblemFiniteConversionPageEmpty11}{\showpaste}
\tab{5}\spadcommand{Km := FFCGX(K,m)\bound{Km2 }\free{K m }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPagePatch12}
\begin{paste}{ugxProblemFiniteConversionPageFull12}{ugxProblemFiniteConversionPageEmpty12}
\pastebutton{ugxProblemFiniteConversionPageFull12}{\hidepaste}
\tab{5}\spadcommand{Kn := FFNBX(K,n)\bound{Kn2 }\free{K n }}
\indentrel{3}\begin{verbatim}
   (12)  FiniteFieldNormalBasisExtension(PrimeField 3,8)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPageEmpty12}
\begin{paste}{ugxProblemFiniteConversionPageEmpty12}{ugxProblemFiniteConversionPagePatch12}
\pastebutton{ugxProblemFiniteConversionPageEmpty12}{\showpaste}
\tab{5}\spadcommand{Kn := FFNBX(K,n)\bound{Kn2 }\free{K n }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPagePatch13}
\begin{paste}{ugxProblemFiniteConversionPageFull13}{ugxProblemFiniteConversionPageEmpty13}
\pastebutton{ugxProblemFiniteConversionPageFull13}{\hidepaste}
\tab{5}\spadcommand{(a1,b1) := (random()$Km,random()$Km)\bound{a12 b12 }\free{Km2 }}
\indentrel{3}\begin{verbatim}
            13
   (13)  %BF
  Type: FiniteFieldCyclicGroupExtension(PrimeField 3,4)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPageEmpty13}
\begin{paste}{ugxProblemFiniteConversionPageEmpty13}{ugxProblemFiniteConversionPagePatch13}
\pastebutton{ugxProblemFiniteConversionPageEmpty13}{\showpaste}
\tab{5}\spadcommand{(a1,b1) := (random()$Km,random()$Km)\bound{a12 b12 }\free{Km2 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPagePatch14}
\begin{paste}{ugxProblemFiniteConversionPageFull14}{ugxProblemFiniteConversionPageEmpty14}
\pastebutton{ugxProblemFiniteConversionPageFull14}{\hidepaste}
\tab{5}\spadcommand{a2 := a1 :: Kn\bound{a22 }\free{a12 Kn2 }}
\indentrel{3}\begin{verbatim}
   (14)
        6        5        4        2
       q        q        q        q        q
   2%BG   + 2%BG   + 2%BG   + 2%BG   + 2%BG  + 2%BG
  Type: FiniteFieldNormalBasisExtension(PrimeField 3,8)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPageEmpty14}
\begin{paste}{ugxProblemFiniteConversionPageEmpty14}{ugxProblemFiniteConversionPagePatch14}
\pastebutton{ugxProblemFiniteConversionPageEmpty14}{\showpaste}
\tab{5}\spadcommand{a2 := a1 :: Kn\bound{a22 }\free{a12 Kn2 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPagePatch15}
\begin{paste}{ugxProblemFiniteConversionPageFull15}{ugxProblemFiniteConversionPageEmpty15}
\pastebutton{ugxProblemFiniteConversionPageFull15}{\hidepaste}
\tab{5}\spadcommand{b2 := b1 :: Kn\bound{b22 }\free{b12 Kn2 }}
\indentrel{3}\begin{verbatim}
   (15)
          7       6       5       4        3       2
         q       q       q       q        q       q
     2%BG   + %BG   + %BG   + %BG   + 2%BG   + %BG
   + 
        q
     %BG  + %BG
  Type: FiniteFieldNormalBasisExtension(PrimeField 3,8)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPageEmpty15}
\begin{paste}{ugxProblemFiniteConversionPageEmpty15}{ugxProblemFiniteConversionPagePatch15}
\pastebutton{ugxProblemFiniteConversionPageEmpty15}{\showpaste}
\tab{5}\spadcommand{b2 := b1 :: Kn\bound{b22 }\free{b12 Kn2 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPagePatch16}
\begin{paste}{ugxProblemFiniteConversionPageFull16}{ugxProblemFiniteConversionPageEmpty16}
\pastebutton{ugxProblemFiniteConversionPageFull16}{\hidepaste}
\tab{5}\spadcommand{a1+b1 - ((a2+b2) :: Km)\free{a12 a22 b12 b22 Km2 }}
\indentrel{3}\begin{verbatim}
   (16)  0
  Type: FiniteFieldCyclicGroupExtension(PrimeField 3,4)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPageEmpty16}
\begin{paste}{ugxProblemFiniteConversionPageEmpty16}{ugxProblemFiniteConversionPagePatch16}
\pastebutton{ugxProblemFiniteConversionPageEmpty16}{\showpaste}
\tab{5}\spadcommand{a1+b1 - ((a2+b2) :: Km)\free{a12 a22 b12 b22 Km2 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPagePatch17}
\begin{paste}{ugxProblemFiniteConversionPageFull17}{ugxProblemFiniteConversionPageEmpty17}
\pastebutton{ugxProblemFiniteConversionPageFull17}{\hidepaste}
\tab{5}\spadcommand{a1*b1 - ((a2*b2) :: Km)\free{a12 a22 b12 b22 Km2 }}
\indentrel{3}\begin{verbatim}
   (17)  0
  Type: FiniteFieldCyclicGroupExtension(PrimeField 3,4)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteConversionPageEmpty17}
\begin{paste}{ugxProblemFiniteConversionPageEmpty17}{ugxProblemFiniteConversionPagePatch17}
\pastebutton{ugxProblemFiniteConversionPageEmpty17}{\showpaste}
\tab{5}\spadcommand{a1*b1 - ((a2*b2) :: Km)\free{a12 a22 b12 b22 Km2 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugxProblemFiniteUtilityPage}{ug08.ht}
{Utility Operations for Finite Fields}
\begin{chunk}{ug08.ht}
\begin{page}{ugxProblemFiniteUtilityPage}
{8.11.7. Utility Operations for Finite Fields}
\beginscroll

\axiomType{FiniteFieldPolynomialPackage} (abbreviation
\axiomType{FFPOLY})
provides operations for generating, counting and testing polynomials
over finite fields. Let's start with a couple of definitions:
\indent{4}
\beginitems
\item[-] A polynomial is {\it primitive} if its roots are primitive
elements in an extension of the coefficient field of degree equal
to the degree of the polynomial.
\item[-] A polynomial is {\it normal} over its coefficient field
if its roots are linearly independent
elements in an extension of the coefficient field of degree equal
to the degree of the polynomial.
\enditems
\indent{0}
In what follows, many of the generated polynomials have one
``anonymous'' variable.
This indeterminate is displayed as a question mark (\spadSyntax{?}).

\xtc{
To fix ideas, let's use the field with five elements for the first
few examples.
}{
\spadpaste{GF5 := PF 5; \bound{GF5}}
}
%
%
\xtc{
You can generate irreducible polynomials of any (positive) degree
(within the storage capabilities of the computer and your ability
to wait) by using
\axiomFunFrom{createIrreduciblePoly}{FiniteFieldPolynomialPackage}.
}{
\spadpaste{f := createIrreduciblePoly(8)\$FFPOLY(GF5) \bound{f}\free{GF5}}
}
%
\xtc{
Does this polynomial have other important properties? Use
\axiomFun{primitive?} to test whether it is a primitive polynomial.
}{
\spadpaste{primitive?(f)\$FFPOLY(GF5) \free{f}}
}
\xtc{
Use \axiomFun{normal?} to test whether it is a normal polynomial.
}{
\spadpaste{normal?(f)\$FFPOLY(GF5) \free{f}}
}
\noindent
Note that this is actually a trivial case,
because a normal polynomial of degree \smath{n}
must have a nonzero term of degree \smath{n-1}.
We will refer back to this later.

\xtc{
To get a primitive polynomial of degree 8 just issue this.
}{
\spadpaste{p := createPrimitivePoly(8)\$FFPOLY(GF5) \bound{p}\free{GF5}}
}
\xtc{
}{
\spadpaste{primitive?(p)\$FFPOLY(GF5) \free{p}}
}
\xtc{
This polynomial is not normal,
}{
\spadpaste{normal?(p)\$FFPOLY(GF5) \free{p}}
}
\xtc{
but if you want a normal one simply write this.
}{
\spadpaste{n := createNormalPoly(8)\$FFPOLY(GF5) \bound{n} \free{GF5}}
}
\xtc{
This polynomial is not primitive!
}{
\spadpaste{primitive?(n)\$FFPOLY(GF5) \free{n}}
}
This could have been seen directly, as
the constant term is 1 here, which is not a primitive
element up to the factor (\axiom{-1}) raised to the degree of the
polynomial.\footnote{Cf. Lidl, R. \& Niederreiter,
H., {\it Finite Fields,} Encycl. of Math. 20, (Addison-Wesley, 1983),
p.90, Th. 3.18.}

What about
polynomials that are both primitive and normal?
The existence of such a polynomial is by no means obvious.
\footnote{The existence of such polynomials is proved in
Lenstra, H. W. \& Schoof, R. J., {\it Primitive
Normal Bases for Finite Fields,} Math. Comp. 48, 1987, pp. 217-231.}
%
\xtc{
If you really need one use either
\axiomFunFrom{createPrimitiveNormalPoly}{FiniteFieldPolynomialPackage} or
\axiomFunFrom{createNormalPrimitivePoly}{FiniteFieldPolynomialPackage}.
}{
\spadpaste{createPrimitiveNormalPoly(8)\$FFPOLY(GF5) \free{GF5}}
}
%

If you want to obtain additional polynomials of the various types above
as given by the {\bf create...} operations above, you can use the {\bf
next...} operations.
For instance,
\axiomFunFrom{nextIrreduciblePoly}{FiniteFieldPolynomialPackage} yields
the next monic irreducible polynomial with the same degree as the input
polynomial.
By ``next'' we mean ``next in a natural order using the terms and
coefficients.''
This will become more clear in the following examples.

\xtc{
This is the field with five elements.
}{
\spadpaste{GF5 := PF 5; \bound{GF5}}
}
%
\xtc{
Our first example irreducible polynomial, say
of degree 3, must be ``greater'' than this.
}{
\spadpaste{h := monomial(1,8)\$SUP(GF5) \bound{h}\free{GF5}}
}
\xtc{
You can generate it by doing this.
}{
\spadpaste{nh := nextIrreduciblePoly(h)\$FFPOLY(GF5) \bound{nh}\free{h}}
}
%
\xtc{
Notice that this polynomial is not the same as the one
\axiomFunFrom{createIrreduciblePoly}{FiniteFieldPolynomialPackage}.
}{
\spadpaste{createIrreduciblePoly(3)\$FFPOLY(GF5) \free{GF5}}
}
\xtc{
You can step through all irreducible polynomials of degree 8 over
the field with 5 elements by repeatedly issuing this.
}{
\spadpaste{nh := nextIrreduciblePoly(nh)\$FFPOLY(GF5) \free{nh}}
}
\xtc{
You could also ask for the total number of these.
}{
\spadpaste{numberOfIrreduciblePoly(5)\$FFPOLY(GF5) \free{GF5}}
}

We hope that ``natural order'' on polynomials is now clear:
first we compare the number of monomials of
two polynomials (``more'' is ``greater'');
then, if necessary, the degrees of these monomials (lexicographically),
and lastly their coefficients (also
lexicographically, and using the operation \axiomFun{lookup} if
our field is not a prime field).
Also note that we make both polynomials monic before looking at the
coefficients:
multiplying either polynomial  by a nonzero constant
produces the same result.

%
\xtc{
The package
\axiomType{FiniteFieldPolynomialPackage} also provides similar
operations for primitive and normal polynomials. With
the exception of the number of primitive normal polynomials;
we're not aware of any known formula for this.
}{
\spadpaste{numberOfPrimitivePoly(3)\$FFPOLY(GF5) \free{GF5}}
}
%
%
\xtc{
Take these,
}{
\spadpaste{m := monomial(1,1)\$SUP(GF5) \bound{m}\free{GF5}}
}
\xtc{
}{
\spadpaste{f := m**3 + 4*m**2 + m + 2 \bound{fx}\free{m}}
}
%
%
\xtc{
and then we have:
}{
\spadpaste{f1 := nextPrimitivePoly(f)\$FFPOLY(GF5) \free{fx}\bound{f1}}
}
\xtc{
What happened?
}{
\spadpaste{nextPrimitivePoly(f1)\$FFPOLY(GF5) \free{f1}}
}
%
Well, for the ordering used in
\axiomFunFrom{nextPrimitivePoly}{FiniteFieldPolynomialPackage} we
use as first criterion a comparison of the constant terms of the
polynomials.
Analogously, in
\axiomFunFrom{nextNormalPoly}{FiniteFieldPolynomialPackage} we first
compare the monomials of degree 1 less than the degree of the
polynomials (which is nonzero, by an earlier remark).
%
\xtc{
}{
\spadpaste{f := m**3 + m**2 + 4*m + 1 \bound{fy} \free{m}}
}
\xtc{
}{
\spadpaste{f1 := nextNormalPoly(f)\$FFPOLY(GF5) \free{fy}\bound{f1y}}
}
\xtc{
}{
\spadpaste{nextNormalPoly(f1)\$FFPOLY(GF5) \free{f1y}}
}
%
\noindent
We don't have to restrict ourselves to prime fields.
%
\xtc{
Let's consider, say, a field with 16 elements.
}{
\spadpaste{GF16 := FFX(FFX(PF 2,2),2); \bound{GF16} }
}
%
%
\xtc{
We can apply any of the operations described above.
}{
\spadpaste{createIrreduciblePoly(5)\$FFPOLY(GF16) \free{GF16}}
}

\xtc{
Axiom also provides operations
for producing random polynomials of a given degree
}{
\spadpaste{random(5)\$FFPOLY(GF16) \free{GF16}}
}
\xtc{
or with degree between two given bounds.
}{
\spadpaste{random(3,9)\$FFPOLY(GF16) \free{GF16}}
}

\axiomType{\axiom{FiniteFieldPolynomialPackage2}} (abbreviation
\axiomType{FFPOLY2})
exports an operation \axiomFun{rootOfIrreduciblePoly}
for finding one root of an irreducible polynomial \axiom{f}
in an extension field of the coefficient field.
The degree of the extension has to be a multiple of the degree of \axiom{f}.
It is not checked whether \axiom{f} actually is irreducible.

%
\xtc{
To illustrate this operation, we fix a ground field \axiom{GF}
}{
\spadpaste{GF2 := PrimeField 2; \bound{GF2}}
}
%
%
\xtc{
and then an extension field.
}{
\spadpaste{F := FFX(GF2,12) \bound{F}\free{GF2}}
}
%
%
\xtc{
We construct an irreducible polynomial over \axiom{GF2}.
}{
\spadpaste{f := createIrreduciblePoly(6)\$FFPOLY(GF2) 
\bound{fz}\free{GF2}}
}
%
%
\xtc{
We compute a root of \axiom{f}.
}{
\spadpaste{root := rootOfIrreduciblePoly(f)\$FFPOLY2(F,GF2) 
\free{F GF2 fz}\bound{root}}
}
%
%and check the result
%\spadcommand{eval(f, monomial(1,1)\$SUP(F) = root) \free{fz F root}}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugxProblemFiniteUtilityPagePatch1}
\begin{paste}{ugxProblemFiniteUtilityPageFull1}{ugxProblemFiniteUtilityPageEmpty1}
\pastebutton{ugxProblemFiniteUtilityPageFull1}{\hidepaste}
\tab{5}\spadcommand{GF5 := PF 5;\bound{GF5 }}
\indentrel{3}\begin{verbatim}
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty1}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty1}{ugxProblemFiniteUtilityPagePatch1}
\pastebutton{ugxProblemFiniteUtilityPageEmpty1}{\showpaste}
\tab{5}\spadcommand{GF5 := PF 5;\bound{GF5 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch2}
\begin{paste}{ugxProblemFiniteUtilityPageFull2}{ugxProblemFiniteUtilityPageEmpty2}
\pastebutton{ugxProblemFiniteUtilityPageFull2}{\hidepaste}
\tab{5}\spadcommand{f := createIrreduciblePoly(8)$FFPOLY(GF5)\bound{f }\free{GF5 }}
\indentrel{3}\begin{verbatim}
         8    4
   (2)  ?  + ?  + 2
          Type: SparseUnivariatePolynomial PrimeField 5
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty2}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty2}{ugxProblemFiniteUtilityPagePatch2}
\pastebutton{ugxProblemFiniteUtilityPageEmpty2}{\showpaste}
\tab{5}\spadcommand{f := createIrreduciblePoly(8)$FFPOLY(GF5)\bound{f }\free{GF5 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch3}
\begin{paste}{ugxProblemFiniteUtilityPageFull3}{ugxProblemFiniteUtilityPageEmpty3}
\pastebutton{ugxProblemFiniteUtilityPageFull3}{\hidepaste}
\tab{5}\spadcommand{primitive?(f)$FFPOLY(GF5)\free{f }}
\indentrel{3}\begin{verbatim}
   (3)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty3}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty3}{ugxProblemFiniteUtilityPagePatch3}
\pastebutton{ugxProblemFiniteUtilityPageEmpty3}{\showpaste}
\tab{5}\spadcommand{primitive?(f)$FFPOLY(GF5)\free{f }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch4}
\begin{paste}{ugxProblemFiniteUtilityPageFull4}{ugxProblemFiniteUtilityPageEmpty4}
\pastebutton{ugxProblemFiniteUtilityPageFull4}{\hidepaste}
\tab{5}\spadcommand{normal?(f)$FFPOLY(GF5)\free{f }}
\indentrel{3}\begin{verbatim}
   (4)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty4}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty4}{ugxProblemFiniteUtilityPagePatch4}
\pastebutton{ugxProblemFiniteUtilityPageEmpty4}{\showpaste}
\tab{5}\spadcommand{normal?(f)$FFPOLY(GF5)\free{f }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch5}
\begin{paste}{ugxProblemFiniteUtilityPageFull5}{ugxProblemFiniteUtilityPageEmpty5}
\pastebutton{ugxProblemFiniteUtilityPageFull5}{\hidepaste}
\tab{5}\spadcommand{p := createPrimitivePoly(8)$FFPOLY(GF5)\bound{p }\free{GF5 }}
\indentrel{3}\begin{verbatim}
         8    3    2
   (5)  ?  + ?  + ?  + ? + 2
          Type: SparseUnivariatePolynomial PrimeField 5
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty5}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty5}{ugxProblemFiniteUtilityPagePatch5}
\pastebutton{ugxProblemFiniteUtilityPageEmpty5}{\showpaste}
\tab{5}\spadcommand{p := createPrimitivePoly(8)$FFPOLY(GF5)\bound{p }\free{GF5 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch6}
\begin{paste}{ugxProblemFiniteUtilityPageFull6}{ugxProblemFiniteUtilityPageEmpty6}
\pastebutton{ugxProblemFiniteUtilityPageFull6}{\hidepaste}
\tab{5}\spadcommand{primitive?(p)$FFPOLY(GF5)\free{p }}
\indentrel{3}\begin{verbatim}
   (6)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty6}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty6}{ugxProblemFiniteUtilityPagePatch6}
\pastebutton{ugxProblemFiniteUtilityPageEmpty6}{\showpaste}
\tab{5}\spadcommand{primitive?(p)$FFPOLY(GF5)\free{p }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch7}
\begin{paste}{ugxProblemFiniteUtilityPageFull7}{ugxProblemFiniteUtilityPageEmpty7}
\pastebutton{ugxProblemFiniteUtilityPageFull7}{\hidepaste}
\tab{5}\spadcommand{normal?(p)$FFPOLY(GF5)\free{p }}
\indentrel{3}\begin{verbatim}
   (7)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty7}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty7}{ugxProblemFiniteUtilityPagePatch7}
\pastebutton{ugxProblemFiniteUtilityPageEmpty7}{\showpaste}
\tab{5}\spadcommand{normal?(p)$FFPOLY(GF5)\free{p }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch8}
\begin{paste}{ugxProblemFiniteUtilityPageFull8}{ugxProblemFiniteUtilityPageEmpty8}
\pastebutton{ugxProblemFiniteUtilityPageFull8}{\hidepaste}
\tab{5}\spadcommand{n := createNormalPoly(8)$FFPOLY(GF5)\bound{n }\free{GF5 }}
\indentrel{3}\begin{verbatim}
         8     7    3
   (8)  ?  + 4?  + ?  + 1
          Type: SparseUnivariatePolynomial PrimeField 5
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty8}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty8}{ugxProblemFiniteUtilityPagePatch8}
\pastebutton{ugxProblemFiniteUtilityPageEmpty8}{\showpaste}
\tab{5}\spadcommand{n := createNormalPoly(8)$FFPOLY(GF5)\bound{n }\free{GF5 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch9}
\begin{paste}{ugxProblemFiniteUtilityPageFull9}{ugxProblemFiniteUtilityPageEmpty9}
\pastebutton{ugxProblemFiniteUtilityPageFull9}{\hidepaste}
\tab{5}\spadcommand{primitive?(n)$FFPOLY(GF5)\free{n }}
\indentrel{3}\begin{verbatim}
   (9)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty9}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty9}{ugxProblemFiniteUtilityPagePatch9}
\pastebutton{ugxProblemFiniteUtilityPageEmpty9}{\showpaste}
\tab{5}\spadcommand{primitive?(n)$FFPOLY(GF5)\free{n }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch10}
\begin{paste}{ugxProblemFiniteUtilityPageFull10}{ugxProblemFiniteUtilityPageEmpty10}
\pastebutton{ugxProblemFiniteUtilityPageFull10}{\hidepaste}
\tab{5}\spadcommand{createPrimitiveNormalPoly(8)$FFPOLY(GF5)\free{GF5 }}
\indentrel{3}\begin{verbatim}
          8     7     5
   (10)  ?  + 4?  + 2?  + 2
          Type: SparseUnivariatePolynomial PrimeField 5
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty10}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty10}{ugxProblemFiniteUtilityPagePatch10}
\pastebutton{ugxProblemFiniteUtilityPageEmpty10}{\showpaste}
\tab{5}\spadcommand{createPrimitiveNormalPoly(8)$FFPOLY(GF5)\free{GF5 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch11}
\begin{paste}{ugxProblemFiniteUtilityPageFull11}{ugxProblemFiniteUtilityPageEmpty11}
\pastebutton{ugxProblemFiniteUtilityPageFull11}{\hidepaste}
\tab{5}\spadcommand{GF5 := PF 5;\bound{GF5 }}
\indentrel{3}\begin{verbatim}
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty11}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty11}{ugxProblemFiniteUtilityPagePatch11}
\pastebutton{ugxProblemFiniteUtilityPageEmpty11}{\showpaste}
\tab{5}\spadcommand{GF5 := PF 5;\bound{GF5 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch12}
\begin{paste}{ugxProblemFiniteUtilityPageFull12}{ugxProblemFiniteUtilityPageEmpty12}
\pastebutton{ugxProblemFiniteUtilityPageFull12}{\hidepaste}
\tab{5}\spadcommand{h := monomial(1,8)$SUP(GF5)\bound{h }\free{GF5 }}
\indentrel{3}\begin{verbatim}
          8
   (12)  ?
          Type: SparseUnivariatePolynomial PrimeField 5
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty12}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty12}{ugxProblemFiniteUtilityPagePatch12}
\pastebutton{ugxProblemFiniteUtilityPageEmpty12}{\showpaste}
\tab{5}\spadcommand{h := monomial(1,8)$SUP(GF5)\bound{h }\free{GF5 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch13}
\begin{paste}{ugxProblemFiniteUtilityPageFull13}{ugxProblemFiniteUtilityPageEmpty13}
\pastebutton{ugxProblemFiniteUtilityPageFull13}{\hidepaste}
\tab{5}\spadcommand{nh := nextIrreduciblePoly(h)$FFPOLY(GF5)\bound{nh }\free{h }}
\indentrel{3}\begin{verbatim}
          8
   (13)  ?  + 2
Type: Union(SparseUnivariatePolynomial PrimeField 5,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty13}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty13}{ugxProblemFiniteUtilityPagePatch13}
\pastebutton{ugxProblemFiniteUtilityPageEmpty13}{\showpaste}
\tab{5}\spadcommand{nh := nextIrreduciblePoly(h)$FFPOLY(GF5)\bound{nh }\free{h }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch14}
\begin{paste}{ugxProblemFiniteUtilityPageFull14}{ugxProblemFiniteUtilityPageEmpty14}
\pastebutton{ugxProblemFiniteUtilityPageFull14}{\hidepaste}
\tab{5}\spadcommand{createIrreduciblePoly(3)$FFPOLY(GF5)\free{GF5 }}
\indentrel{3}\begin{verbatim}
          3
   (14)  ?  + ? + 1
          Type: SparseUnivariatePolynomial PrimeField 5
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty14}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty14}{ugxProblemFiniteUtilityPagePatch14}
\pastebutton{ugxProblemFiniteUtilityPageEmpty14}{\showpaste}
\tab{5}\spadcommand{createIrreduciblePoly(3)$FFPOLY(GF5)\free{GF5 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch15}
\begin{paste}{ugxProblemFiniteUtilityPageFull15}{ugxProblemFiniteUtilityPageEmpty15}
\pastebutton{ugxProblemFiniteUtilityPageFull15}{\hidepaste}
\tab{5}\spadcommand{nh := nextIrreduciblePoly(nh)$FFPOLY(GF5)\free{nh }}
\indentrel{3}\begin{verbatim}
          8
   (15)  ?  + 3
Type: Union(SparseUnivariatePolynomial PrimeField 5,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty15}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty15}{ugxProblemFiniteUtilityPagePatch15}
\pastebutton{ugxProblemFiniteUtilityPageEmpty15}{\showpaste}
\tab{5}\spadcommand{nh := nextIrreduciblePoly(nh)$FFPOLY(GF5)\free{nh }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch16}
\begin{paste}{ugxProblemFiniteUtilityPageFull16}{ugxProblemFiniteUtilityPageEmpty16}
\pastebutton{ugxProblemFiniteUtilityPageFull16}{\hidepaste}
\tab{5}\spadcommand{numberOfIrreduciblePoly(5)$FFPOLY(GF5)\free{GF5 }}
\indentrel{3}\begin{verbatim}
   (16)  624
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty16}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty16}{ugxProblemFiniteUtilityPagePatch16}
\pastebutton{ugxProblemFiniteUtilityPageEmpty16}{\showpaste}
\tab{5}\spadcommand{numberOfIrreduciblePoly(5)$FFPOLY(GF5)\free{GF5 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch17}
\begin{paste}{ugxProblemFiniteUtilityPageFull17}{ugxProblemFiniteUtilityPageEmpty17}
\pastebutton{ugxProblemFiniteUtilityPageFull17}{\hidepaste}
\tab{5}\spadcommand{numberOfPrimitivePoly(3)$FFPOLY(GF5)\free{GF5 }}
\indentrel{3}\begin{verbatim}
   (17)  20
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty17}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty17}{ugxProblemFiniteUtilityPagePatch17}
\pastebutton{ugxProblemFiniteUtilityPageEmpty17}{\showpaste}
\tab{5}\spadcommand{numberOfPrimitivePoly(3)$FFPOLY(GF5)\free{GF5 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch18}
\begin{paste}{ugxProblemFiniteUtilityPageFull18}{ugxProblemFiniteUtilityPageEmpty18}
\pastebutton{ugxProblemFiniteUtilityPageFull18}{\hidepaste}
\tab{5}\spadcommand{m := monomial(1,1)$SUP(GF5)\bound{m }\free{GF5 }}
\indentrel{3}\begin{verbatim}
   (18)  ?
          Type: SparseUnivariatePolynomial PrimeField 5
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty18}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty18}{ugxProblemFiniteUtilityPagePatch18}
\pastebutton{ugxProblemFiniteUtilityPageEmpty18}{\showpaste}
\tab{5}\spadcommand{m := monomial(1,1)$SUP(GF5)\bound{m }\free{GF5 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch19}
\begin{paste}{ugxProblemFiniteUtilityPageFull19}{ugxProblemFiniteUtilityPageEmpty19}
\pastebutton{ugxProblemFiniteUtilityPageFull19}{\hidepaste}
\tab{5}\spadcommand{f := m**3 + 4*m**2 + m + 2\bound{fx }\free{m }}
\indentrel{3}\begin{verbatim}
          3     2
   (19)  ?  + 4?  + ? + 2
          Type: SparseUnivariatePolynomial PrimeField 5
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty19}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty19}{ugxProblemFiniteUtilityPagePatch19}
\pastebutton{ugxProblemFiniteUtilityPageEmpty19}{\showpaste}
\tab{5}\spadcommand{f := m**3 + 4*m**2 + m + 2\bound{fx }\free{m }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch20}
\begin{paste}{ugxProblemFiniteUtilityPageFull20}{ugxProblemFiniteUtilityPageEmpty20}
\pastebutton{ugxProblemFiniteUtilityPageFull20}{\hidepaste}
\tab{5}\spadcommand{f1 := nextPrimitivePoly(f)$FFPOLY(GF5)\free{fx }\bound{f1 }}
\indentrel{3}\begin{verbatim}
          3     2
   (20)  ?  + 4?  + 4? + 2
Type: Union(SparseUnivariatePolynomial PrimeField 5,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty20}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty20}{ugxProblemFiniteUtilityPagePatch20}
\pastebutton{ugxProblemFiniteUtilityPageEmpty20}{\showpaste}
\tab{5}\spadcommand{f1 := nextPrimitivePoly(f)$FFPOLY(GF5)\free{fx }\bound{f1 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch21}
\begin{paste}{ugxProblemFiniteUtilityPageFull21}{ugxProblemFiniteUtilityPageEmpty21}
\pastebutton{ugxProblemFiniteUtilityPageFull21}{\hidepaste}
\tab{5}\spadcommand{nextPrimitivePoly(f1)$FFPOLY(GF5)\free{f1 }}
\indentrel{3}\begin{verbatim}
          3     2
   (21)  ?  + 2?  + 3
Type: Union(SparseUnivariatePolynomial PrimeField 5,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty21}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty21}{ugxProblemFiniteUtilityPagePatch21}
\pastebutton{ugxProblemFiniteUtilityPageEmpty21}{\showpaste}
\tab{5}\spadcommand{nextPrimitivePoly(f1)$FFPOLY(GF5)\free{f1 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch22}
\begin{paste}{ugxProblemFiniteUtilityPageFull22}{ugxProblemFiniteUtilityPageEmpty22}
\pastebutton{ugxProblemFiniteUtilityPageFull22}{\hidepaste}
\tab{5}\spadcommand{f := m**3 + m**2 + 4*m + 1\bound{fy }\free{m }}
\indentrel{3}\begin{verbatim}
          3    2
   (22)  ?  + ?  + 4? + 1
          Type: SparseUnivariatePolynomial PrimeField 5
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty22}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty22}{ugxProblemFiniteUtilityPagePatch22}
\pastebutton{ugxProblemFiniteUtilityPageEmpty22}{\showpaste}
\tab{5}\spadcommand{f := m**3 + m**2 + 4*m + 1\bound{fy }\free{m }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch23}
\begin{paste}{ugxProblemFiniteUtilityPageFull23}{ugxProblemFiniteUtilityPageEmpty23}
\pastebutton{ugxProblemFiniteUtilityPageFull23}{\hidepaste}
\tab{5}\spadcommand{f1 := nextNormalPoly(f)$FFPOLY(GF5)\free{fy }\bound{f1y }}
\indentrel{3}\begin{verbatim}
          3    2
   (23)  ?  + ?  + 4? + 3
Type: Union(SparseUnivariatePolynomial PrimeField 5,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty23}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty23}{ugxProblemFiniteUtilityPagePatch23}
\pastebutton{ugxProblemFiniteUtilityPageEmpty23}{\showpaste}
\tab{5}\spadcommand{f1 := nextNormalPoly(f)$FFPOLY(GF5)\free{fy }\bound{f1y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch24}
\begin{paste}{ugxProblemFiniteUtilityPageFull24}{ugxProblemFiniteUtilityPageEmpty24}
\pastebutton{ugxProblemFiniteUtilityPageFull24}{\hidepaste}
\tab{5}\spadcommand{nextNormalPoly(f1)$FFPOLY(GF5)\free{f1y }}
\indentrel{3}\begin{verbatim}
          3     2
   (24)  ?  + 2?  + 1
Type: Union(SparseUnivariatePolynomial PrimeField 5,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty24}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty24}{ugxProblemFiniteUtilityPagePatch24}
\pastebutton{ugxProblemFiniteUtilityPageEmpty24}{\showpaste}
\tab{5}\spadcommand{nextNormalPoly(f1)$FFPOLY(GF5)\free{f1y }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch25}
\begin{paste}{ugxProblemFiniteUtilityPageFull25}{ugxProblemFiniteUtilityPageEmpty25}
\pastebutton{ugxProblemFiniteUtilityPageFull25}{\hidepaste}
\tab{5}\spadcommand{GF16 := FFX(FFX(PF 2,2),2);\bound{GF16 }}
\indentrel{3}\begin{verbatim}
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty25}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty25}{ugxProblemFiniteUtilityPagePatch25}
\pastebutton{ugxProblemFiniteUtilityPageEmpty25}{\showpaste}
\tab{5}\spadcommand{GF16 := FFX(FFX(PF 2,2),2);\bound{GF16 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch26}
\begin{paste}{ugxProblemFiniteUtilityPageFull26}{ugxProblemFiniteUtilityPageEmpty26}
\pastebutton{ugxProblemFiniteUtilityPageFull26}{\hidepaste}
\tab{5}\spadcommand{createIrreduciblePoly(5)$FFPOLY(GF16)\free{GF16 }}
\indentrel{3}\begin{verbatim}
          5
   (26)  ?  + %CZ
Type: SparseUnivariatePolynomial FiniteFieldExtension(FiniteFieldExtension(PrimeField 2,2),2)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty26}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty26}{ugxProblemFiniteUtilityPagePatch26}
\pastebutton{ugxProblemFiniteUtilityPageEmpty26}{\showpaste}
\tab{5}\spadcommand{createIrreduciblePoly(5)$FFPOLY(GF16)\free{GF16 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch27}
\begin{paste}{ugxProblemFiniteUtilityPageFull27}{ugxProblemFiniteUtilityPageEmpty27}
\pastebutton{ugxProblemFiniteUtilityPageFull27}{\hidepaste}
\tab{5}\spadcommand{random(5)$FFPOLY(GF16)\free{GF16 }}
\indentrel{3}\begin{verbatim}
   (27)
      5             4                            3
     ?  + (%CV + 1)?  + ((%CV + 1)%CZ + %CV + 1)?
   + 
               2
     (%CV + 1)?  + ((%CV + 1)%CZ + %CV + 1)?
   + 
     (%CV + 1)%CZ + 1
Type: SparseUnivariatePolynomial FiniteFieldExtension(FiniteFieldExtension(PrimeField 2,2),2)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty27}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty27}{ugxProblemFiniteUtilityPagePatch27}
\pastebutton{ugxProblemFiniteUtilityPageEmpty27}{\showpaste}
\tab{5}\spadcommand{random(5)$FFPOLY(GF16)\free{GF16 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch28}
\begin{paste}{ugxProblemFiniteUtilityPageFull28}{ugxProblemFiniteUtilityPageEmpty28}
\pastebutton{ugxProblemFiniteUtilityPageFull28}{\hidepaste}
\tab{5}\spadcommand{random(3,9)$FFPOLY(GF16)\free{GF16 }}
\indentrel{3}\begin{verbatim}
   (28)
      4                   3                       2
     ?  + (%CZ + %CV + 1)?  + (%CV %CZ + %CV + 1)?
   + 
     (%CZ + %CV)? + (%CV + 1)%CZ
Type: SparseUnivariatePolynomial FiniteFieldExtension(FiniteFieldExtension(PrimeField 2,2),2)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty28}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty28}{ugxProblemFiniteUtilityPagePatch28}
\pastebutton{ugxProblemFiniteUtilityPageEmpty28}{\showpaste}
\tab{5}\spadcommand{random(3,9)$FFPOLY(GF16)\free{GF16 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch29}
\begin{paste}{ugxProblemFiniteUtilityPageFull29}{ugxProblemFiniteUtilityPageEmpty29}
\pastebutton{ugxProblemFiniteUtilityPageFull29}{\hidepaste}
\tab{5}\spadcommand{GF2 := PrimeField 2;\bound{GF2 }}
\indentrel{3}\begin{verbatim}
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty29}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty29}{ugxProblemFiniteUtilityPagePatch29}
\pastebutton{ugxProblemFiniteUtilityPageEmpty29}{\showpaste}
\tab{5}\spadcommand{GF2 := PrimeField 2;\bound{GF2 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch30}
\begin{paste}{ugxProblemFiniteUtilityPageFull30}{ugxProblemFiniteUtilityPageEmpty30}
\pastebutton{ugxProblemFiniteUtilityPageFull30}{\hidepaste}
\tab{5}\spadcommand{F := FFX(GF2,12)\bound{F }\free{GF2 }}
\indentrel{3}\begin{verbatim}
   (30)  FiniteFieldExtension(PrimeField 2,12)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty30}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty30}{ugxProblemFiniteUtilityPagePatch30}
\pastebutton{ugxProblemFiniteUtilityPageEmpty30}{\showpaste}
\tab{5}\spadcommand{F := FFX(GF2,12)\bound{F }\free{GF2 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch31}
\begin{paste}{ugxProblemFiniteUtilityPageFull31}{ugxProblemFiniteUtilityPageEmpty31}
\pastebutton{ugxProblemFiniteUtilityPageFull31}{\hidepaste}
\tab{5}\spadcommand{f := createIrreduciblePoly(6)$FFPOLY(GF2)\bound{fz }\free{GF2 }}
\indentrel{3}\begin{verbatim}
          6
   (31)  ?  + ? + 1
          Type: SparseUnivariatePolynomial PrimeField 2
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty31}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty31}{ugxProblemFiniteUtilityPagePatch31}
\pastebutton{ugxProblemFiniteUtilityPageEmpty31}{\showpaste}
\tab{5}\spadcommand{f := createIrreduciblePoly(6)$FFPOLY(GF2)\bound{fz }\free{GF2 }}
\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPagePatch32}
\begin{paste}{ugxProblemFiniteUtilityPageFull32}{ugxProblemFiniteUtilityPageEmpty32}
\pastebutton{ugxProblemFiniteUtilityPageFull32}{\hidepaste}
\tab{5}\spadcommand{root := rootOfIrreduciblePoly(f)$FFPOLY2(F,GF2)\free{F GF2 fz }\bound{root }}
\indentrel{3}\begin{verbatim}
            11      8      7      5
   (32)  %CS   + %CS  + %CS  + %CS  + %CS + 1
            Type: FiniteFieldExtension(PrimeField 2,12)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugxProblemFiniteUtilityPageEmpty32}
\begin{paste}{ugxProblemFiniteUtilityPageEmpty32}{ugxProblemFiniteUtilityPagePatch32}
\pastebutton{ugxProblemFiniteUtilityPageEmpty32}{\showpaste}
\tab{5}\spadcommand{root := rootOfIrreduciblePoly(f)$FFPOLY2(F,GF2)\free{F GF2 fz }\bound{root }}
\end{paste}\end{patch}

\end{chunk} 
\pagetitle{ugProblemIdealPage}{ug08.ht}{Primary Decomposition of Ideals} 
\begin{chunk}{ug08.ht} 
\begin{page}{ugProblemIdealPage}{8.12. Primary Decomposition of Ideals} 
\beginscroll 

Axiom provides a facility for
the primary decomposition of polynomial ideals over fields of
characteristic zero.  The algorithm 
and works in essentially two steps: 
\indent{4} 
\beginitems 
\item[1. ] the problem is solved for 0-dimensional ideals by ``generic''
projection on the last coordinate 
\item[2. ] a ``reduction process''
uses localization and ideal quotients to reduce the general case to
the 0-dimensional one.  
\enditems 
\indent{0} 

The Axiom constructor
\axiomType{PolynomialIdeals} represents ideals with coefficients in
any field and supports the basic ideal operations, including
intersection, sum and quotient.  \axiomType{IdealDecompositionPackage}
contains the specific operations for the primary decomposition and the
computation of the radical of an ideal with polynomial coefficients in
a field of characteristic 0 with an effective algorithm for factoring
polynomials.

The following examples illustrate the capabilities of this facility.
%
\xtc{
First consider the ideal generated by
\texht{$x^2 + y^2 - 1$}{\axiom{x**2 + y**2 - 1}}
(which defines a circle in the \axiom{(x,y)}-plane) and the ideal
generated by \texht{$x^2 - y^2$}{\axiom{x**2 - y**2}} (corresponding to the
straight lines \axiom{x = y} and \axiom{x = -y}.
}{
\spadpaste{(n,m) : List DMP([x,y],FRAC INT) \bound{nm}}
}
\xtc{
}{
\spadpaste{m := [x**2+y**2-1] \free{nm} \bound{m}}
}
\xtc{
}{
\spadpaste{n := [x**2-y**2] \free{nm} \bound{n}}
}
%
%
\xtc{
We find the equations defining the intersection of the two loci.
This correspond to the sum of the associated ideals.
}{
\spadpaste{id := ideal m  + ideal n \free{n m} \bound{id}}
}
%
%
\xtc{
We can check if the locus contains only a finite number of points,
that is, if the ideal is zero-dimensional.
}{
\spadpaste{zeroDim? id \free{id}}
}
\xtc{
}{
\spadpaste{zeroDim?(ideal m) \free{m}}
}
\xtc{
}{
\spadpaste{dimension ideal m \free{m}}
}
\xtc{
We can find polynomial relations among the generators
(\axiom{f} and \axiom{g} are the parametric equations of the knot).
}{
\spadpaste{(f,g):DMP([x,y],FRAC INT) \bound{fg}}
}
\xtc{
}{
\spadpaste{f := x**2-1 \free{fg} \bound{f}}
}
\xtc{
}{
\spadpaste{g := x*(x**2-1) \free{fg} \bound{g}}
}
\xtc{
}{
\spadpaste{relationsIdeal [f,g] \free{f g}}
}

\xtc{
We can compute the primary decomposition of an ideal.
}{
\spadpaste{l: List DMP([x,y,z],FRAC INT) \bound{ll}}
}
\xtc{
}{
\spadpaste{l:=[x**2+2*y**2,x*z**2-y*z,z**2-4] \free{ll} \bound{l}}
}
\xtc{
}{
\spadpaste{ld:=primaryDecomp ideal l \free{l} \bound{ld}}
}
\xtc{
We can intersect back.
}{
\spadpaste{reduce(intersect,ld) \free{ld}}
}

\xtc{
We can compute the radical of every primary component.
}{
\spadpaste{reduce(intersect,[radical ld.i for i in 1..2]) \free{ld}}
}
\xtc{
Their intersection is equal to the radical of the ideal of \axiom{l}.
}{
\spadpaste{radical ideal l \free{l}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugProblemIdealPagePatch1}
\begin{paste}{ugProblemIdealPageFull1}{ugProblemIdealPageEmpty1}
\pastebutton{ugProblemIdealPageFull1}{\hidepaste}
\tab{5}\spadcommand{(n,m) : List DMP([x,y],FRAC INT)\bound{nm }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPageEmpty1}
\begin{paste}{ugProblemIdealPageEmpty1}{ugProblemIdealPagePatch1}
\pastebutton{ugProblemIdealPageEmpty1}{\showpaste}
\tab{5}\spadcommand{(n,m) : List DMP([x,y],FRAC INT)\bound{nm }}
\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPagePatch2}
\begin{paste}{ugProblemIdealPageFull2}{ugProblemIdealPageEmpty2}
\pastebutton{ugProblemIdealPageFull2}{\hidepaste}
\tab{5}\spadcommand{m := [x**2+y**2-1]\free{nm }\bound{m }}
\indentrel{3}\begin{verbatim}
          2    2
   (2)  [x  + y  - 1]
Type: List DistributedMultivariatePolynomial([x,y],Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPageEmpty2}
\begin{paste}{ugProblemIdealPageEmpty2}{ugProblemIdealPagePatch2}
\pastebutton{ugProblemIdealPageEmpty2}{\showpaste}
\tab{5}\spadcommand{m := [x**2+y**2-1]\free{nm }\bound{m }}
\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPagePatch3}
\begin{paste}{ugProblemIdealPageFull3}{ugProblemIdealPageEmpty3}
\pastebutton{ugProblemIdealPageFull3}{\hidepaste}
\tab{5}\spadcommand{n := [x**2-y**2]\free{nm }\bound{n }}
\indentrel{3}\begin{verbatim}
          2    2
   (3)  [x  - y ]
Type: List DistributedMultivariatePolynomial([x,y],Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPageEmpty3}
\begin{paste}{ugProblemIdealPageEmpty3}{ugProblemIdealPagePatch3}
\pastebutton{ugProblemIdealPageEmpty3}{\showpaste}
\tab{5}\spadcommand{n := [x**2-y**2]\free{nm }\bound{n }}
\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPagePatch4}
\begin{paste}{ugProblemIdealPageFull4}{ugProblemIdealPageEmpty4}
\pastebutton{ugProblemIdealPageFull4}{\hidepaste}
\tab{5}\spadcommand{id := ideal m + ideal n\free{n m }\bound{id }}
\indentrel{3}\begin{verbatim}
          2   1  2   1
   (4)  [x  - Ä,y  - Ä]
              2      2
Type: PolynomialIdeals(Fraction Integer,DirectProduct(2,NonNegativeInteger),OrderedVariableList [x,y],DistributedMultivariatePolynomial([x,y],Fraction Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPageEmpty4}
\begin{paste}{ugProblemIdealPageEmpty4}{ugProblemIdealPagePatch4}
\pastebutton{ugProblemIdealPageEmpty4}{\showpaste}
\tab{5}\spadcommand{id := ideal m + ideal n\free{n m }\bound{id }}
\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPagePatch5}
\begin{paste}{ugProblemIdealPageFull5}{ugProblemIdealPageEmpty5}
\pastebutton{ugProblemIdealPageFull5}{\hidepaste}
\tab{5}\spadcommand{zeroDim? id\free{id }}
\indentrel{3}\begin{verbatim}
   (5)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPageEmpty5}
\begin{paste}{ugProblemIdealPageEmpty5}{ugProblemIdealPagePatch5}
\pastebutton{ugProblemIdealPageEmpty5}{\showpaste}
\tab{5}\spadcommand{zeroDim? id\free{id }}
\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPagePatch6}
\begin{paste}{ugProblemIdealPageFull6}{ugProblemIdealPageEmpty6}
\pastebutton{ugProblemIdealPageFull6}{\hidepaste}
\tab{5}\spadcommand{zeroDim?(ideal m)\free{m }}
\indentrel{3}\begin{verbatim}
   (6)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPageEmpty6}
\begin{paste}{ugProblemIdealPageEmpty6}{ugProblemIdealPagePatch6}
\pastebutton{ugProblemIdealPageEmpty6}{\showpaste}
\tab{5}\spadcommand{zeroDim?(ideal m)\free{m }}
\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPagePatch7}
\begin{paste}{ugProblemIdealPageFull7}{ugProblemIdealPageEmpty7}
\pastebutton{ugProblemIdealPageFull7}{\hidepaste}
\tab{5}\spadcommand{dimension ideal m\free{m }}
\indentrel{3}\begin{verbatim}
   (7)  1
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPageEmpty7}
\begin{paste}{ugProblemIdealPageEmpty7}{ugProblemIdealPagePatch7}
\pastebutton{ugProblemIdealPageEmpty7}{\showpaste}
\tab{5}\spadcommand{dimension ideal m\free{m }}
\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPagePatch8}
\begin{paste}{ugProblemIdealPageFull8}{ugProblemIdealPageEmpty8}
\pastebutton{ugProblemIdealPageFull8}{\hidepaste}
\tab{5}\spadcommand{(f,g):DMP([x,y],FRAC INT)\bound{fg }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPageEmpty8}
\begin{paste}{ugProblemIdealPageEmpty8}{ugProblemIdealPagePatch8}
\pastebutton{ugProblemIdealPageEmpty8}{\showpaste}
\tab{5}\spadcommand{(f,g):DMP([x,y],FRAC INT)\bound{fg }}
\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPagePatch9}
\begin{paste}{ugProblemIdealPageFull9}{ugProblemIdealPageEmpty9}
\pastebutton{ugProblemIdealPageFull9}{\hidepaste}
\tab{5}\spadcommand{f := x**2-1\free{fg }\bound{f }}
\indentrel{3}\begin{verbatim}
         2
   (9)  x  - 1
Type: DistributedMultivariatePolynomial([x,y],Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPageEmpty9}
\begin{paste}{ugProblemIdealPageEmpty9}{ugProblemIdealPagePatch9}
\pastebutton{ugProblemIdealPageEmpty9}{\showpaste}
\tab{5}\spadcommand{f := x**2-1\free{fg }\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPagePatch10}
\begin{paste}{ugProblemIdealPageFull10}{ugProblemIdealPageEmpty10}
\pastebutton{ugProblemIdealPageFull10}{\hidepaste}
\tab{5}\spadcommand{g := x*(x**2-1)\free{fg }\bound{g }}
\indentrel{3}\begin{verbatim}
          3
   (10)  x  - x
Type: DistributedMultivariatePolynomial([x,y],Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPageEmpty10}
\begin{paste}{ugProblemIdealPageEmpty10}{ugProblemIdealPagePatch10}
\pastebutton{ugProblemIdealPageEmpty10}{\showpaste}
\tab{5}\spadcommand{g := x*(x**2-1)\free{fg }\bound{g }}
\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPagePatch11}
\begin{paste}{ugProblemIdealPageFull11}{ugProblemIdealPageEmpty11}
\pastebutton{ugProblemIdealPageFull11}{\hidepaste}
\tab{5}\spadcommand{relationsIdeal [f,g]\free{f g }}
\indentrel{3}\begin{verbatim}
   (11)
         2      3      2           2           3
   [- %CY  + %CX  + %CX ] | [%CX= x  - 1,%CY= x  - x]
Type: SuchThat(List Polynomial Fraction Integer,List Equation Polynomial Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPageEmpty11}
\begin{paste}{ugProblemIdealPageEmpty11}{ugProblemIdealPagePatch11}
\pastebutton{ugProblemIdealPageEmpty11}{\showpaste}
\tab{5}\spadcommand{relationsIdeal [f,g]\free{f g }}
\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPagePatch12}
\begin{paste}{ugProblemIdealPageFull12}{ugProblemIdealPageEmpty12}
\pastebutton{ugProblemIdealPageFull12}{\hidepaste}
\tab{5}\spadcommand{l: List DMP([x,y,z],FRAC INT)\bound{ll }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPageEmpty12}
\begin{paste}{ugProblemIdealPageEmpty12}{ugProblemIdealPagePatch12}
\pastebutton{ugProblemIdealPageEmpty12}{\showpaste}
\tab{5}\spadcommand{l: List DMP([x,y,z],FRAC INT)\bound{ll }}
\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPagePatch13}
\begin{paste}{ugProblemIdealPageFull13}{ugProblemIdealPageEmpty13}
\pastebutton{ugProblemIdealPageFull13}{\hidepaste}
\tab{5}\spadcommand{l:=[x**2+2*y**2,x*z**2-y*z,z**2-4]\free{ll }\bound{l }}
\indentrel{3}\begin{verbatim}
           2     2    2        2
   (13)  [x  + 2y ,x z  - y z,z  - 4]
Type: List DistributedMultivariatePolynomial([x,y,z],Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPageEmpty13}
\begin{paste}{ugProblemIdealPageEmpty13}{ugProblemIdealPagePatch13}
\pastebutton{ugProblemIdealPageEmpty13}{\showpaste}
\tab{5}\spadcommand{l:=[x**2+2*y**2,x*z**2-y*z,z**2-4]\free{ll }\bound{l }}
\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPagePatch14}
\begin{paste}{ugProblemIdealPageFull14}{ugProblemIdealPageEmpty14}
\pastebutton{ugProblemIdealPageFull14}{\hidepaste}
\tab{5}\spadcommand{ld:=primaryDecomp ideal l\free{l }\bound{ld }}
\indentrel{3}\begin{verbatim}
               1    2             1    2
   (14)  [[x + Ä y,y ,z + 2],[x - Ä y,y ,z - 2]]
               2                  2
Type: List PolynomialIdeals(Fraction Integer,DirectProduct(3,NonNegativeInteger),OrderedVariableList [x,y,z],DistributedMultivariatePolynomial([x,y,z],Fraction Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPageEmpty14}
\begin{paste}{ugProblemIdealPageEmpty14}{ugProblemIdealPagePatch14}
\pastebutton{ugProblemIdealPageEmpty14}{\showpaste}
\tab{5}\spadcommand{ld:=primaryDecomp ideal l\free{l }\bound{ld }}
\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPagePatch15}
\begin{paste}{ugProblemIdealPageFull15}{ugProblemIdealPageEmpty15}
\pastebutton{ugProblemIdealPageFull15}{\hidepaste}
\tab{5}\spadcommand{reduce(intersect,ld)\free{ld }}
\indentrel{3}\begin{verbatim}
              1      2  2
   (15)  [x - Ä y z,y ,z  - 4]
              4
Type: PolynomialIdeals(Fraction Integer,DirectProduct(3,NonNegativeInteger),OrderedVariableList [x,y,z],DistributedMultivariatePolynomial([x,y,z],Fraction Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPageEmpty15}
\begin{paste}{ugProblemIdealPageEmpty15}{ugProblemIdealPagePatch15}
\pastebutton{ugProblemIdealPageEmpty15}{\showpaste}
\tab{5}\spadcommand{reduce(intersect,ld)\free{ld }}
\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPagePatch16}
\begin{paste}{ugProblemIdealPageFull16}{ugProblemIdealPageEmpty16}
\pastebutton{ugProblemIdealPageFull16}{\hidepaste}
\tab{5}\spadcommand{reduce(intersect,[radical ld.i for i in 1..2])\free{ld }}
\indentrel{3}\begin{verbatim}
               2
   (16)  [x,y,z  - 4]
Type: PolynomialIdeals(Fraction Integer,DirectProduct(3,NonNegativeInteger),OrderedVariableList [x,y,z],DistributedMultivariatePolynomial([x,y,z],Fraction Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPageEmpty16}
\begin{paste}{ugProblemIdealPageEmpty16}{ugProblemIdealPagePatch16}
\pastebutton{ugProblemIdealPageEmpty16}{\showpaste}
\tab{5}\spadcommand{reduce(intersect,[radical ld.i for i in 1..2])\free{ld }}
\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPagePatch17}
\begin{paste}{ugProblemIdealPageFull17}{ugProblemIdealPageEmpty17}
\pastebutton{ugProblemIdealPageFull17}{\hidepaste}
\tab{5}\spadcommand{radical ideal l\free{l }}
\indentrel{3}\begin{verbatim}
               2
   (17)  [x,y,z  - 4]
Type: PolynomialIdeals(Fraction Integer,DirectProduct(3,NonNegativeInteger),OrderedVariableList [x,y,z],DistributedMultivariatePolynomial([x,y,z],Fraction Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemIdealPageEmpty17}
\begin{paste}{ugProblemIdealPageEmpty17}{ugProblemIdealPagePatch17}
\pastebutton{ugProblemIdealPageEmpty17}{\showpaste}
\tab{5}\spadcommand{radical ideal l\free{l }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugProblemGaloisPage}{ug08.ht}{Computation of Galois Groups}
\pagepic{ps/v71ugproblemgaloispage.eps}{ugProblemGaloisPage}{0.50}
\pagefrom{FactoredFunctions2}{FactoredFnsTwoXmpPage}
\pageto{Factored}{FactoredXmpPage}
\pageto{Clef}{ugAvailCLEFPage}
\begin{chunk}{ug08.ht}
\begin{page}{ugProblemGaloisPage}{8.13. Computation of Galois Groups}
\beginscroll
%
As a sample use of Axiom's algebraic number facilities,
we compute
the Galois group of the polynomial
\texht{$p(x) = x^5 - 5 x + 12$}{\axiom{p(x) = x**5 - 5*x + 12}}.
%
\xtc{
}{
\spadpaste{p := x**5 - 5*x + 12 \bound{p}}
}
%
We would like to construct a polynomial \smath{f(x)}
such that the splitting
field
of \smath{p(x)} is generated by one root of \smath{f(x)}.
First we construct a polynomial \smath{r = r(x)} such that one
root of \smath{r(x)} generates the field generated by two roots of
the polynomial \smath{p(x)}.
(As it will turn out, the field generated by two roots of
\smath{p(x)} is, in fact, the splitting field of
\smath{p(x)}.)

From the proof of the primitive element theorem we know that
if \smath{a} and \smath{b} are
algebraic numbers, then the field
\texht{${\bf Q}(a,b)$}{\axiom{Q(a,b)}} is equal to
\texht{${\bf Q}(a+kb)$}{\axiom{Q(a + k*b)}} for an
appropriately chosen integer \smath{k}.
In our case, we construct the minimal polynomial of
\texht{$a_i - a_j$}{\axiom{a[i] - a[j]}}, where
\texht{$a_i$}{\axiom{a[i]}} and
\texht{$a_j$}{\axiom{a[j]}} are two roots of \smath{p(x)}.
We construct this polynomial using \axiomFun{resultant}.
The main result we  need is the following:
If \smath{f(x)} is a polynomial with roots
\texht{$a_i \ldots a_m$}{\axiom{a[1]...a[m]}} and
\smath{g(x)} is a polynomial
with roots
\texht{$b_i \ldots b_n$}{\axiom{b[1]...b[n]}}, then the polynomial
\axiom{h(x) = resultant(f(y), g(x-y), y)}
is a polynomial of degree \smath{m*n} with
roots
\texht{$a_i + b_j, i = 1 \ldots m, j = 1 \ldots n$}
{\axiom{a[i] + b[j], 1 <= i <= m, 1 <= j <= n}}.

\xtc{
For \smath{f(x)} we use the polynomial \smath{p(x)}.
For \smath{g(x)} we use the polynomial \smath{-p(-x)}.
Thus, the polynomial we  first construct is
\axiom{resultant(p(y), -p(y-x), y)}.
}{
\spadpaste{q := resultant(eval(p,x,y),-eval(p,x,y-x),y) \free{p} \bound{q}}
}
%
The roots of \smath{q(x)} are
\texht{$a_i - a_j, i \leq 1, j \leq 5$}
{\axiom{a[i] - a[j], 1 <= i,j <= 5}}.
Of course, there are five pairs \smath{(i,j)} with \smath{i = j},
so \axiom{0} is a 5-fold root of \smath{q(x)}.
%
\xtc{
Let's get rid of this factor.
}{
\spadpaste{q1 := exquo(q, x**5) \free{q} \bound{q1}}
}
\xtc{
Factor the polynomial \axiom{q1}.
}{
\spadpaste{factoredQ := factor q1 \free{q1} \bound{factoredQ}}
}

We see that \axiom{q1} has two irreducible factors, each of degree
\axiom{10}.  (The fact that the polynomial \axiom{q1} has two factors
of degree \axiom{10} is enough to show that the Galois group of
\smath{p(x)} is the dihedral group of order \axiom{10}.\footnote{See
McKay, Soicher, Computing Galois Groups over the Rationals, Journal of
Number Theory 20, 273-281 (1983).  We do not assume the results of
this paper, however, and we continue with the computation.}  Note that
the type of \axiom{factoredQ} is \axiomType{FR POLY INT}, that is,
\axiomType{Factored Polynomial Integer}.  This is a special data type
for recording factorizations of polynomials with integer coefficients
(see \downlink{`Factored'}{FactoredXmpPage} \ignore{Factored}).

\xtc{
We can access the individual factors using the operation
\axiomFunFrom{nthFactor}{Factored}.
}{
\spadpaste{r := nthFactor(factoredQ,1) \free{factoredQ} \bound{r}}
}
%

Consider the polynomial \smath{r = r(x)}.
This is the minimal polynomial of the difference of two roots of
\smath{p(x)}.
Thus, the splitting field of \smath{p(x)} contains a subfield of
degree \axiom{10}.
We show that this subfield is, in fact, the splitting field of
\smath{p(x)} by showing that \smath{p(x)} factors completely
over this field.
%
\xtc{
First we create a symbolic root of the polynomial \smath{r(x)}.
(We replaced \axiom{x} by \axiom{b} in the
polynomial \axiom{r} so that our symbolic root would be
printed as \axiom{b}.)
}{
\spadpaste{beta:AN := rootOf(eval(r,x,b)) \free{r} \bound{beta}}
}
\xtc{
We next tell Axiom to view \smath{p(x)} as a univariate polynomial
in \axiom{x}
with algebraic number coefficients.
This is accomplished with this type declaration.
}{
\spadpaste{p := p::UP(x,INT)::UP(x,AN) \free{p} \bound{declareP}}
}
%
%
\xtc{
Factor \smath{p(x)} over the field
\texht{${\bf Q}(\beta)$}{\axiom{Q(beta)}}.
(This computation will take some time!)
}{
\spadpaste{algFactors := factor(p,[beta]) \free{declareP beta} 
\bound{algFactors}}
}
%
When factoring over number fields, it is important to specify the
field over which the polynomial is to be factored, as polynomials
have different factorizations over different fields.
When you use the operation \axiomFun{factor}, the field over which
the polynomial is factored is the field generated by
\indent{4}
\beginitems
\item[1. ] the algebraic numbers that appear
in the coefficients of the polynomial, and
\item[2. ] the algebraic numbers that
appear in a list passed as an optional second argument of the operation.
\enditems
\indent{0}
In our case, the coefficients of \axiom{p}
are all rational integers and only \axiom{beta}
appears in the list, so the field is simply
\texht{${\bf Q}(\beta)$}{\axiom{Q(beta)}}.
%
\xtc{
It was necessary to give the list \axiom{[beta]}
as a second argument of the operation
because otherwise the polynomial would have been factored over the field
generated by its coefficients, namely the rational numbers.
}{
\spadpaste{factor(p) \free{declareP}}
}
%
We have shown that the splitting field of \smath{p(x)} has degree
\axiom{10}.
Since the symmetric group of degree 5 has only one transitive subgroup
of order \axiom{10}, we know that the Galois group of \smath{p(x)} must be
this group, the dihedral group
of order \axiom{10}.
Rather than stop here, we explicitly compute the action of the Galois
group on the roots of \smath{p(x)}.

First we assign the roots of \smath{p(x)} as the values of five
variables.
\xtc{
We can obtain an individual root by negating the constant coefficient of
one of the factors of \smath{p(x)}.
}{
\spadpaste{factor1 := nthFactor(algFactors,1) \free{algFactors} 
\bound{factor1}}
}
\xtc{
}{
\spadpaste{root1 := -coefficient(factor1,0) \free{factor1} \bound{root1}}
}
%
%
\xtc{
We can obtain a list of all the roots in this way.
}{
\spadpaste{
roots := [-coefficient(nthFactor(algFactors,i),0) for i in 1..5] 
\free{algFactors} \bound{roots}}
}

The expression
\begin{verbatim}
- coefficient(nthFactor(algFactors, i), 0)}
\end{verbatim}
is the \eth{\axiom{i }} root
of \smath{p(x)} and the elements of \axiom{roots} are the \eth{\axiom{i }}
roots of \smath{p(x)} as \axiom{i} ranges from \axiom{1} to \axiom{5}.

\xtc{
Assign the roots as the values of the variables \axiom{a1,...,a5}.
}{
\spadpaste{
(a1,a2,a3,a4,a5) := (roots.1,roots.2,roots.3,roots.4,roots.5) 
\free{roots} \bound{ais}}
}
%

Next we express the roots of \smath{r(x)} as polynomials in
\axiom{beta}.  We could obtain these roots by calling the operation
\axiomFun{factor}: \axiom{factor(r, [beta])} factors \axiom{r(x)} over
\texht{${\bf Q}(\beta)$}{\axiom{Q(beta)}}.  However, this is a lengthy
computation and we can obtain the roots of \smath{r(x)} as differences
of the roots \axiom{a1,...,a5} of \smath{p(x)}.  Only ten of these
differences are roots of \smath{r(x)} and the other ten are roots of
the other irreducible factor of \axiom{q1}.  We can determine if a
given value is a root of \smath{r(x)} by evaluating \smath{r(x)} at
that particular value.  (Of course, the order in which factors are
returned by the operation \axiomFun{factor} is unimportant and may
change with different implementations of the operation.  Therefore, we
cannot predict in advance which differences are roots of \smath{r(x)}
and which are not.)

\xtc{
Let's look at four examples (two are roots of \smath{r(x)} and
two are not).
}{
\spadpaste{eval(r,x,a1 - a2) \free{ais}}
}
\xtc{
}{
\spadpaste{eval(r,x,a1 - a3) \free{ais}}
}
\xtc{
}{
\spadpaste{eval(r,x,a1 - a4) \free{ais}}
}
\xtc{
}{
\spadpaste{eval(r,x,a1 - a5) \free{ais}}
}
%

Take one of the differences that was a root of \smath{r(x)}
and assign it to the variable \axiom{bb}.
\xtc{
For example, if \axiom{eval(r,x,a1 - a4)} returned \axiom{0}, you would
enter this.
}{
\spadpaste{bb := a1 - a4 \free{ais} \bound{bb}}
}
Of course, if the difference is, in fact, equal to the root \axiom{beta},
you should choose another root of \smath{r(x)}.

Automorphisms of the splitting field are given by mapping a generator of
the field, namely \axiom{beta}, to other roots of its minimal polynomial.
Let's see what happens when \axiom{beta} is mapped to \axiom{bb}.
%
\xtc{
We compute the images of the roots \axiom{a1,...,a5}
under this automorphism:
}{
\spadpaste{aa1 := subst(a1,beta = bb) \free{beta bb ais} \bound{aa1}}
}
\xtc{
}{
\spadpaste{aa2 := subst(a2,beta = bb) \free{beta bb ais} \bound{aa2}}
}
\xtc{
}{
\spadpaste{aa3 := subst(a3,beta = bb) \free{beta bb ais} \bound{aa3}}
}
\xtc{
}{
\spadpaste{aa4 := subst(a4,beta = bb) \free{beta bb ais} \bound{aa4}}
}
\xtc{
}{
\spadpaste{aa5 := subst(a5,beta = bb) \free{beta bb ais} \bound{aa5}}
}
%
Of course, the values \axiom{aa1,...,aa5} are simply a permutation 
of the values \axiom{a1,...,a5}.
%
\xtc{
Let's find the value of \axiom{aa1} (execute as many of the 
following five commands as necessary).
}{
\spadpaste{(aa1 = a1) :: Boolean \free{aa1}}
}
\xtc{
}{
\spadpaste{(aa1 = a2) :: Boolean \free{aa1}}
}
\xtc{
}{
\spadpaste{(aa1 = a3) :: Boolean \free{aa1}}
}
\xtc{
}{
\spadpaste{(aa1 = a4) :: Boolean \free{aa1}}
}
\xtc{
}{
\spadpaste{(aa1 = a5) :: Boolean \free{aa1}}
}

Proceeding in this fashion, you can find the values of
\axiom{aa2,...aa5}.\footnote{Here you should use the \Clef{} line
editor.  See \downlink{``Clef''}{ugAvailCLEFPage} in
Section 1.1.1\ignore{ugAvailCLEF} for more information
about \Clef{}.}  You have represented the automorphism \axiom{beta ->
bb} as a permutation of the roots \axiom{a1,...,a5}.  If you wish, you
can repeat this computation for all the roots of \smath{r(x)} and
represent the Galois group of \smath{p(x)} as a subgroup of the
symmetric group on five letters.

Here are two other problems that you may attack in a similar fashion:
\indent{4}
\beginitems
\item[1. ] Show that the Galois group of
\texht{$p(x) = x^4 + 2 x^3 - 2 x^2 - 3 x + 1$}{\axiom{
p(x) = x**4 + 2*x**3 - 2*x**2 - 3*x + 1}}
is the dihedral group of order eight.
(The splitting field of this polynomial is the Hilbert class field
of
the quadratic field
\texht{${\bf Q}(\sqrt{145})$}{\axiom{Q(sqrt(145))}}.)
\item[2. ] Show that the Galois group of
\texht{$p(x) = x^6 + 108$}{\axiom{p(x) = x**6 + 108}}
has order 6 and is
isomorphic to \texht{$S_3,$}{} the symmetric group on three letters.
(The splitting field of this polynomial is the splitting field of
\texht{$x^3 - 2$}{\axiom{x**3 - 2}}.)
\enditems
\indent{0}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugProblemGaloisPagePatch1}
\begin{paste}{ugProblemGaloisPageFull1}{ugProblemGaloisPageEmpty1}
\pastebutton{ugProblemGaloisPageFull1}{\hidepaste}
\tab{5}\spadcommand{p := x**5 - 5*x + 12\bound{p }}
\indentrel{3}\begin{verbatim}
         5
   (1)  x  - 5x + 12
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty1}
\begin{paste}{ugProblemGaloisPageEmpty1}{ugProblemGaloisPagePatch1}
\pastebutton{ugProblemGaloisPageEmpty1}{\showpaste}
\tab{5}\spadcommand{p := x**5 - 5*x + 12\bound{p }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch2}
\begin{paste}{ugProblemGaloisPageFull2}{ugProblemGaloisPageEmpty2}
\pastebutton{ugProblemGaloisPageFull2}{\hidepaste}
\tab{5}\spadcommand{q := resultant(eval(p,x,y),-eval(p,x,y-x),y)\free{p }\bound{q }}
\indentrel{3}\begin{verbatim}
   (2)
      25      21        17         15        13
     x   - 50x   - 2375x   + 90000x   - 5000x
   + 
             11          9            7            5
     2700000x   + 250000x  + 18000000x  + 64000000x
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty2}
\begin{paste}{ugProblemGaloisPageEmpty2}{ugProblemGaloisPagePatch2}
\pastebutton{ugProblemGaloisPageEmpty2}{\showpaste}
\tab{5}\spadcommand{q := resultant(eval(p,x,y),-eval(p,x,y-x),y)\free{p }\bound{q }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch3}
\begin{paste}{ugProblemGaloisPageFull3}{ugProblemGaloisPageEmpty3}
\pastebutton{ugProblemGaloisPageFull3}{\hidepaste}
\tab{5}\spadcommand{q1 := exquo(q, x**5)\free{q }\bound{q1 }}
\indentrel{3}\begin{verbatim}
   (3)
      20      16        12         10        8           6
     x   - 50x   - 2375x   + 90000x   - 5000x  + 2700000x
   + 
            4            2
     250000x  + 18000000x  + 64000000
                    Type: Union(Polynomial Integer,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty3}
\begin{paste}{ugProblemGaloisPageEmpty3}{ugProblemGaloisPagePatch3}
\pastebutton{ugProblemGaloisPageEmpty3}{\showpaste}
\tab{5}\spadcommand{q1 := exquo(q, x**5)\free{q }\bound{q1 }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch4}
\begin{paste}{ugProblemGaloisPageFull4}{ugProblemGaloisPageEmpty4}
\pastebutton{ugProblemGaloisPageFull4}{\hidepaste}
\tab{5}\spadcommand{factoredQ := factor q1\free{q1 }\bound{factoredQ }}
\indentrel{3}\begin{verbatim}
   (4)
       10      8      6        4        2
     (x   - 10x  - 75x  + 1500x  - 5500x  + 16000)
  *
       10      8       6       4        2
     (x   + 10x  + 125x  + 500x  + 2500x  + 4000)
                      Type: Factored Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty4}
\begin{paste}{ugProblemGaloisPageEmpty4}{ugProblemGaloisPagePatch4}
\pastebutton{ugProblemGaloisPageEmpty4}{\showpaste}
\tab{5}\spadcommand{factoredQ := factor q1\free{q1 }\bound{factoredQ }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch5}
\begin{paste}{ugProblemGaloisPageFull5}{ugProblemGaloisPageEmpty5}
\pastebutton{ugProblemGaloisPageFull5}{\hidepaste}
\tab{5}\spadcommand{r := nthFactor(factoredQ,1)\free{factoredQ }\bound{r }}
\indentrel{3}\begin{verbatim}
         10      8      6        4        2
   (5)  x   - 10x  - 75x  + 1500x  - 5500x  + 16000
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty5}
\begin{paste}{ugProblemGaloisPageEmpty5}{ugProblemGaloisPagePatch5}
\pastebutton{ugProblemGaloisPageEmpty5}{\showpaste}
\tab{5}\spadcommand{r := nthFactor(factoredQ,1)\free{factoredQ }\bound{r }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch6}
\begin{paste}{ugProblemGaloisPageFull6}{ugProblemGaloisPageEmpty6}
\pastebutton{ugProblemGaloisPageFull6}{\hidepaste}
\tab{5}\spadcommand{beta:AN := rootOf(eval(r,x,b))\free{r }\bound{beta }}
\indentrel{3}\begin{verbatim}
   (6)  b
                                  Type: AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty6}
\begin{paste}{ugProblemGaloisPageEmpty6}{ugProblemGaloisPagePatch6}
\pastebutton{ugProblemGaloisPageEmpty6}{\showpaste}
\tab{5}\spadcommand{beta:AN := rootOf(eval(r,x,b))\free{r }\bound{beta }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch7}
\begin{paste}{ugProblemGaloisPageFull7}{ugProblemGaloisPageEmpty7}
\pastebutton{ugProblemGaloisPageFull7}{\hidepaste}
\tab{5}\spadcommand{p := p::UP(x,INT)::UP(x,AN)\free{p }\bound{declareP }}
\indentrel{3}\begin{verbatim}
         5
   (7)  x  - 5x + 12
          Type: UnivariatePolynomial(x,AlgebraicNumber)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty7}
\begin{paste}{ugProblemGaloisPageEmpty7}{ugProblemGaloisPagePatch7}
\pastebutton{ugProblemGaloisPageEmpty7}{\showpaste}
\tab{5}\spadcommand{p := p::UP(x,INT)::UP(x,AN)\free{p }\bound{declareP }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch8}
\begin{paste}{ugProblemGaloisPageFull8}{ugProblemGaloisPageEmpty8}
\pastebutton{ugProblemGaloisPageFull8}{\hidepaste}
\tab{5}\spadcommand{algFactors := factor(p,[beta])\free{declareP beta }\bound{algFactors }}
\indentrel{3}\begin{verbatim}
   (8)
       x
     + 
                9       8       7        6         5
           - 85b  - 116b  + 780b  + 2640b  + 14895b
         + 
                  4          3          2
           - 8820b  - 127050b  - 327000b  - 405200b
         + 
           2062400
      /
         1339200
  *
               8       6        4         2
          - 17b  + 156b  + 2979b  - 25410b  - 14080
     (x + ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ)
                            66960
  *
       x
     + 
               8        6         4          2
           143b  - 2100b  - 10485b  + 290550b  - 334800b
         + 
           - 960800
      /
         669600
  *
       x
     + 
               8        6         4          2
           143b  - 2100b  - 10485b  + 290550b  + 334800b
         + 
           - 960800
      /
         669600
  *
       x
     + 
              9       8       7        6         5
           85b  - 116b  - 780b  + 2640b  - 14895b
         + 
                  4          3          2
           - 8820b  + 127050b  - 327000b  + 405200b
         + 
           2062400
      /
         1339200
 Type: Factored UnivariatePolynomial(x,AlgebraicNumber)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty8}
\begin{paste}{ugProblemGaloisPageEmpty8}{ugProblemGaloisPagePatch8}
\pastebutton{ugProblemGaloisPageEmpty8}{\showpaste}
\tab{5}\spadcommand{algFactors := factor(p,[beta])\free{declareP beta }\bound{algFactors }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch9}
\begin{paste}{ugProblemGaloisPageFull9}{ugProblemGaloisPageEmpty9}
\pastebutton{ugProblemGaloisPageFull9}{\hidepaste}
\tab{5}\spadcommand{factor(p)\free{declareP }}
\indentrel{3}\begin{verbatim}
         5
   (9)  x  - 5x + 12
 Type: Factored UnivariatePolynomial(x,AlgebraicNumber)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty9}
\begin{paste}{ugProblemGaloisPageEmpty9}{ugProblemGaloisPagePatch9}
\pastebutton{ugProblemGaloisPageEmpty9}{\showpaste}
\tab{5}\spadcommand{factor(p)\free{declareP }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch10}
\begin{paste}{ugProblemGaloisPageFull10}{ugProblemGaloisPageEmpty10}
\pastebutton{ugProblemGaloisPageFull10}{\hidepaste}
\tab{5}\spadcommand{factor1 := nthFactor(algFactors,1)\free{algFactors }\bound{factor1 }}
\indentrel{3}\begin{verbatim}
   (10)
     x
   + 
              9       8       7        6         5
         - 85b  - 116b  + 780b  + 2640b  + 14895b
       + 
              4          3          2
       - 8820b  - 127050b  - 327000b  - 405200b + 2062400
    /
       1339200
          Type: UnivariatePolynomial(x,AlgebraicNumber)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty10}
\begin{paste}{ugProblemGaloisPageEmpty10}{ugProblemGaloisPagePatch10}
\pastebutton{ugProblemGaloisPageEmpty10}{\showpaste}
\tab{5}\spadcommand{factor1 := nthFactor(algFactors,1)\free{algFactors }\bound{factor1 }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch11}
\begin{paste}{ugProblemGaloisPageFull11}{ugProblemGaloisPageEmpty11}
\pastebutton{ugProblemGaloisPageFull11}{\hidepaste}
\tab{5}\spadcommand{root1 := -coefficient(factor1,0)\free{factor1 }\bound{root1 }}
\indentrel{3}\begin{verbatim}
   (11)
          9       8       7        6         5        4
       85b  + 116b  - 780b  - 2640b  - 14895b  + 8820b
     + 
              3          2
       127050b  + 327000b  + 405200b - 2062400
  /
     1339200
                                  Type: AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty11}
\begin{paste}{ugProblemGaloisPageEmpty11}{ugProblemGaloisPagePatch11}
\pastebutton{ugProblemGaloisPageEmpty11}{\showpaste}
\tab{5}\spadcommand{root1 := -coefficient(factor1,0)\free{factor1 }\bound{root1 }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch12}
\begin{paste}{ugProblemGaloisPageFull12}{ugProblemGaloisPageEmpty12}
\pastebutton{ugProblemGaloisPageFull12}{\hidepaste}
\tab{5}\spadcommand{roots := [-coefficient(nthFactor(algFactors,i),0) for i in 1..5]\free{algFactors }\bound{roots }}
\indentrel{3}\begin{verbatim}
   (12)
   [
            9       8       7        6         5        4
         85b  + 116b  - 780b  - 2640b  - 14895b  + 8820b
       + 
                3          2
         127050b  + 327000b  + 405200b - 2062400
    /
       1339200
     ,
       8       6        4         2
    17b  - 156b  - 2979b  + 25410b  + 14080
    ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ,
                     66960

               8        6         4          2
         - 143b  + 2100b  + 10485b  - 290550b  + 334800b
       + 
         960800
    /
       669600
     ,

               8        6         4          2
         - 143b  + 2100b  + 10485b  - 290550b  - 334800b
       + 
         960800
    /
       669600
     ,

              9       8       7        6         5
         - 85b  + 116b  + 780b  - 2640b  + 14895b
       + 
              4          3          2
         8820b  - 127050b  + 327000b  - 405200b - 2062400
    /
       1339200
     ]
                             Type: List AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty12}
\begin{paste}{ugProblemGaloisPageEmpty12}{ugProblemGaloisPagePatch12}
\pastebutton{ugProblemGaloisPageEmpty12}{\showpaste}
\tab{5}\spadcommand{roots := [-coefficient(nthFactor(algFactors,i),0) for i in 1..5]\free{algFactors }\bound{roots }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch13}
\begin{paste}{ugProblemGaloisPageFull13}{ugProblemGaloisPageEmpty13}
\pastebutton{ugProblemGaloisPageFull13}{\hidepaste}
\tab{5}\spadcommand{(a1,a2,a3,a4,a5) := (roots.1,roots.2,roots.3,roots.4,roots.5)\free{roots }\bound{ais }}
\indentrel{3}\begin{verbatim}
   (13)
            9       8       7        6         5        4
       - 85b  + 116b  + 780b  - 2640b  + 14895b  + 8820b
     + 
                3          2
       - 127050b  + 327000b  - 405200b - 2062400
  /
     1339200
                                  Type: AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty13}
\begin{paste}{ugProblemGaloisPageEmpty13}{ugProblemGaloisPagePatch13}
\pastebutton{ugProblemGaloisPageEmpty13}{\showpaste}
\tab{5}\spadcommand{(a1,a2,a3,a4,a5) := (roots.1,roots.2,roots.3,roots.4,roots.5)\free{roots }\bound{ais }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch14}
\begin{paste}{ugProblemGaloisPageFull14}{ugProblemGaloisPageEmpty14}
\pastebutton{ugProblemGaloisPageFull14}{\hidepaste}
\tab{5}\spadcommand{eval(r,x,a1 - a2)\free{ais }}
\indentrel{3}\begin{verbatim}
   (14)  0
                       Type: Polynomial AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty14}
\begin{paste}{ugProblemGaloisPageEmpty14}{ugProblemGaloisPagePatch14}
\pastebutton{ugProblemGaloisPageEmpty14}{\showpaste}
\tab{5}\spadcommand{eval(r,x,a1 - a2)\free{ais }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch15}
\begin{paste}{ugProblemGaloisPageFull15}{ugProblemGaloisPageEmpty15}
\pastebutton{ugProblemGaloisPageFull15}{\hidepaste}
\tab{5}\spadcommand{eval(r,x,a1 - a3)\free{ais }}
\indentrel{3}\begin{verbatim}
   (15)
             9         8          7          6           5
       47905b  + 66920b  - 536100b  - 980400b  - 3345075b
     + 
                 4            3             2
       - 5787000b  + 75572250b  + 161688000b  - 184600000b
     + 
       - 710912000
  /
     4464
                       Type: Polynomial AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty15}
\begin{paste}{ugProblemGaloisPageEmpty15}{ugProblemGaloisPagePatch15}
\pastebutton{ugProblemGaloisPageEmpty15}{\showpaste}
\tab{5}\spadcommand{eval(r,x,a1 - a3)\free{ais }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch16}
\begin{paste}{ugProblemGaloisPageFull16}{ugProblemGaloisPageEmpty16}
\pastebutton{ugProblemGaloisPageFull16}{\hidepaste}
\tab{5}\spadcommand{eval(r,x,a1 - a4)\free{ais }}
\indentrel{3}\begin{verbatim}
   (16)  0
                       Type: Polynomial AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty16}
\begin{paste}{ugProblemGaloisPageEmpty16}{ugProblemGaloisPagePatch16}
\pastebutton{ugProblemGaloisPageEmpty16}{\showpaste}
\tab{5}\spadcommand{eval(r,x,a1 - a4)\free{ais }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch17}
\begin{paste}{ugProblemGaloisPageFull17}{ugProblemGaloisPageEmpty17}
\pastebutton{ugProblemGaloisPageFull17}{\hidepaste}
\tab{5}\spadcommand{eval(r,x,a1 - a5)\free{ais }}
\indentrel{3}\begin{verbatim}
             8        6         4          2
         405b  + 3450b  - 19875b  - 198000b  - 588000
   (17)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                              31
                       Type: Polynomial AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty17}
\begin{paste}{ugProblemGaloisPageEmpty17}{ugProblemGaloisPagePatch17}
\pastebutton{ugProblemGaloisPageEmpty17}{\showpaste}
\tab{5}\spadcommand{eval(r,x,a1 - a5)\free{ais }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch18}
\begin{paste}{ugProblemGaloisPageFull18}{ugProblemGaloisPageEmpty18}
\pastebutton{ugProblemGaloisPageFull18}{\hidepaste}
\tab{5}\spadcommand{bb := a1 - a4\free{ais }\bound{bb }}
\indentrel{3}\begin{verbatim}
   (18)
          9       8       7        6         5         4
       85b  + 402b  - 780b  - 6840b  - 14895b  - 12150b
     + 
              3          2
       127050b  + 908100b  + 1074800b - 3984000
  /
     1339200
                                  Type: AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty18}
\begin{paste}{ugProblemGaloisPageEmpty18}{ugProblemGaloisPagePatch18}
\pastebutton{ugProblemGaloisPageEmpty18}{\showpaste}
\tab{5}\spadcommand{bb := a1 - a4\free{ais }\bound{bb }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch19}
\begin{paste}{ugProblemGaloisPageFull19}{ugProblemGaloisPageEmpty19}
\pastebutton{ugProblemGaloisPageFull19}{\hidepaste}
\tab{5}\spadcommand{aa1 := subst(a1,beta = bb)\free{beta bb ais }\bound{aa1 }}
\indentrel{3}\begin{verbatim}
   (19)
             8        6         4          2
       - 143b  + 2100b  + 10485b  - 290550b  + 334800b
     + 
       960800
  /
     669600
                                  Type: AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty19}
\begin{paste}{ugProblemGaloisPageEmpty19}{ugProblemGaloisPagePatch19}
\pastebutton{ugProblemGaloisPageEmpty19}{\showpaste}
\tab{5}\spadcommand{aa1 := subst(a1,beta = bb)\free{beta bb ais }\bound{aa1 }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch20}
\begin{paste}{ugProblemGaloisPageFull20}{ugProblemGaloisPageEmpty20}
\pastebutton{ugProblemGaloisPageFull20}{\hidepaste}
\tab{5}\spadcommand{aa2 := subst(a2,beta = bb)\free{beta bb ais }\bound{aa2 }}
\indentrel{3}\begin{verbatim}
   (20)
            9       8       7        6         5        4
       - 85b  + 116b  + 780b  - 2640b  + 14895b  + 8820b
     + 
                3          2
       - 127050b  + 327000b  - 405200b - 2062400
  /
     1339200
                                  Type: AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty20}
\begin{paste}{ugProblemGaloisPageEmpty20}{ugProblemGaloisPagePatch20}
\pastebutton{ugProblemGaloisPageEmpty20}{\showpaste}
\tab{5}\spadcommand{aa2 := subst(a2,beta = bb)\free{beta bb ais }\bound{aa2 }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch21}
\begin{paste}{ugProblemGaloisPageFull21}{ugProblemGaloisPageEmpty21}
\pastebutton{ugProblemGaloisPageFull21}{\hidepaste}
\tab{5}\spadcommand{aa3 := subst(a3,beta = bb)\free{beta bb ais }\bound{aa3 }}
\indentrel{3}\begin{verbatim}
   (21)
          9       8       7        6         5        4
       85b  + 116b  - 780b  - 2640b  - 14895b  + 8820b
     + 
              3          2
       127050b  + 327000b  + 405200b - 2062400
  /
     1339200
                                  Type: AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty21}
\begin{paste}{ugProblemGaloisPageEmpty21}{ugProblemGaloisPagePatch21}
\pastebutton{ugProblemGaloisPageEmpty21}{\showpaste}
\tab{5}\spadcommand{aa3 := subst(a3,beta = bb)\free{beta bb ais }\bound{aa3 }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch22}
\begin{paste}{ugProblemGaloisPageFull22}{ugProblemGaloisPageEmpty22}
\pastebutton{ugProblemGaloisPageFull22}{\hidepaste}
\tab{5}\spadcommand{aa4 := subst(a4,beta = bb)\free{beta bb ais }\bound{aa4 }}
\indentrel{3}\begin{verbatim}
   (22)
             8        6         4          2
       - 143b  + 2100b  + 10485b  - 290550b  - 334800b
     + 
       960800
  /
     669600
                                  Type: AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty22}
\begin{paste}{ugProblemGaloisPageEmpty22}{ugProblemGaloisPagePatch22}
\pastebutton{ugProblemGaloisPageEmpty22}{\showpaste}
\tab{5}\spadcommand{aa4 := subst(a4,beta = bb)\free{beta bb ais }\bound{aa4 }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch23}
\begin{paste}{ugProblemGaloisPageFull23}{ugProblemGaloisPageEmpty23}
\pastebutton{ugProblemGaloisPageFull23}{\hidepaste}
\tab{5}\spadcommand{aa5 := subst(a5,beta = bb)\free{beta bb ais }\bound{aa5 }}
\indentrel{3}\begin{verbatim}
            8       6        4         2
         17b  - 156b  - 2979b  + 25410b  + 14080
   (23)  ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                          66960
                                  Type: AlgebraicNumber
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty23}
\begin{paste}{ugProblemGaloisPageEmpty23}{ugProblemGaloisPagePatch23}
\pastebutton{ugProblemGaloisPageEmpty23}{\showpaste}
\tab{5}\spadcommand{aa5 := subst(a5,beta = bb)\free{beta bb ais }\bound{aa5 }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch24}
\begin{paste}{ugProblemGaloisPageFull24}{ugProblemGaloisPageEmpty24}
\pastebutton{ugProblemGaloisPageFull24}{\hidepaste}
\tab{5}\spadcommand{(aa1 = a1) :: Boolean\free{aa1 }}
\indentrel{3}\begin{verbatim}
   (24)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty24}
\begin{paste}{ugProblemGaloisPageEmpty24}{ugProblemGaloisPagePatch24}
\pastebutton{ugProblemGaloisPageEmpty24}{\showpaste}
\tab{5}\spadcommand{(aa1 = a1) :: Boolean\free{aa1 }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch25}
\begin{paste}{ugProblemGaloisPageFull25}{ugProblemGaloisPageEmpty25}
\pastebutton{ugProblemGaloisPageFull25}{\hidepaste}
\tab{5}\spadcommand{(aa1 = a2) :: Boolean\free{aa1 }}
\indentrel{3}\begin{verbatim}
   (25)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty25}
\begin{paste}{ugProblemGaloisPageEmpty25}{ugProblemGaloisPagePatch25}
\pastebutton{ugProblemGaloisPageEmpty25}{\showpaste}
\tab{5}\spadcommand{(aa1 = a2) :: Boolean\free{aa1 }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch26}
\begin{paste}{ugProblemGaloisPageFull26}{ugProblemGaloisPageEmpty26}
\pastebutton{ugProblemGaloisPageFull26}{\hidepaste}
\tab{5}\spadcommand{(aa1 = a3) :: Boolean\free{aa1 }}
\indentrel{3}\begin{verbatim}
   (26)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty26}
\begin{paste}{ugProblemGaloisPageEmpty26}{ugProblemGaloisPagePatch26}
\pastebutton{ugProblemGaloisPageEmpty26}{\showpaste}
\tab{5}\spadcommand{(aa1 = a3) :: Boolean\free{aa1 }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch27}
\begin{paste}{ugProblemGaloisPageFull27}{ugProblemGaloisPageEmpty27}
\pastebutton{ugProblemGaloisPageFull27}{\hidepaste}
\tab{5}\spadcommand{(aa1 = a4) :: Boolean\free{aa1 }}
\indentrel{3}\begin{verbatim}
   (27)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty27}
\begin{paste}{ugProblemGaloisPageEmpty27}{ugProblemGaloisPagePatch27}
\pastebutton{ugProblemGaloisPageEmpty27}{\showpaste}
\tab{5}\spadcommand{(aa1 = a4) :: Boolean\free{aa1 }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPagePatch28}
\begin{paste}{ugProblemGaloisPageFull28}{ugProblemGaloisPageEmpty28}
\pastebutton{ugProblemGaloisPageFull28}{\hidepaste}
\tab{5}\spadcommand{(aa1 = a5) :: Boolean\free{aa1 }}
\indentrel{3}\begin{verbatim}
   (28)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGaloisPageEmpty28}
\begin{paste}{ugProblemGaloisPageEmpty28}{ugProblemGaloisPagePatch28}
\pastebutton{ugProblemGaloisPageEmpty28}{\showpaste}
\tab{5}\spadcommand{(aa1 = a5) :: Boolean\free{aa1 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugProblemGeneticPage}{ug08.ht}
{Non-Associative Algebras and Genetic Laws}
\pageto{notitle}{OctonionXmpPage}
\begin{chunk}{ug08.ht}
\begin{page}{ugProblemGeneticPage}
{8.14. Non-Associative Algebras and Genetic Laws}
\beginscroll

Many algebraic structures of mathematics and Axiom
have a multiplication operation \axiomOp{*} that satisfies
the associativity law
\texht{$a*(b*c) = (a*b)*c$}{\spad{a*(b*c) = (a*b)*c}}
for all \smath{a}, \smath{b} and \smath{c}.
The octonions (see 
\downlink{`Octonion'}{OctonionXmpPage}\ignore{Octonion}) 
are a well known exception.
There are many other interesting non-associative structures, 
such as the class of
Lie algebras.\footnote{Two Axiom implementations of Lie algebras
are \spadtype{LieSquareMatrix} and \spadtype{FreeNilpotentLie}.}
Lie algebras can be used, for example, to analyse Lie symmetry 
algebras of partial differential equations.
In this section we show a different application of non-associative 
algebras, the modelling of genetic laws.

The Axiom library contains several constructors for
creating non-assoc\-i\-a\-tive structures,
ranging from the categories \spadtype{Monad},
\spadtype{NonAssociativeRng}, and
\spadtype{FramedNonAssociativeAlgebra}, to the domains
\spadtype{AlgebraGivenByStructuralConstants} and
\spadtype{GenericNonAssociativeAlgebra}.
Furthermore, the package \spadtype{AlgebraPackage} provides
operations for analysing the structure of such algebras.\footnote{%
The interested reader can learn more about these aspects of the
Axiom library from the paper
``Computations in Algebras of Finite Rank,''
by Johannes Grabmeier and Robert Wisbauer,
Technical Report, IBM Heidelberg Scientific Center, 1992.}

Mendel's genetic laws are often written in a form like
\texht{
\narrowDisplay{
Aa \times Aa = {1\over 4}AA + {1\over 2}Aa + {1\over 4}aa.}}
{\spad{Aa * Aa = (1/4)*AA + (1/2)*Aa + (1/4)*aa.}
}
The implementation of general algebras in Axiom allows us to
use this as the definition for multiplication in an algebra.
Hence, it is possible to study
questions of genetic inheritance using Axiom.
To demonstrate this more precisely,  we discuss one example from a
monograph of \texht{A. W\"orz-Busekros}{A. Woerz-Busekros},
where you can also find a general setting of this theory.\footnote{%
\texht{W\"{o}rz-Busekros}{Woerz-Busekros}, A.,
{\it Algebras in Genetics},
Springer Lectures Notes in Biomathematics 36, Berlin e.a. (1980).
In particular, see example 1.3.}

We assume that there is an infinitely large random mating population.
Random mating of two gametes \texht{$a_i$}{\spad{ai}}  and
\texht{$a_j$}{\spad{aj}} gives zygotes
\texht{$a_ia_j$}{\spad{ai aj}}, which produce new gametes.
In classical Mendelian segregation we have
\texht{$a_ia_j = {1 \over 2}a_i+{1 \over 2}a_j$}
{\spad{ai aj = (1/2)*ai+(1/2)*aj}}.
In general, we have
\texht{\narrowDisplay{a_ia_j = \sum_{k=1}^n \gamma_{i,j}^k\ a_k.}}%
{\spad{ai aj = gammaij1 a1 + gammaij2 a2 + ... + gammaijn an}}
The segregation rates \texht{$\gamma_{i,j}$}{\spad{gammaij}}
are  the structural constants of an
\smath{n}-dimensional algebra.
This is provided in Axiom by
the constructor \spadtype{AlgebraGivenByStructuralConstants}
(abbreviation \spadtype{ALGSC}).

Consider two coupled autosomal loci with alleles
\smath{A},\smath{a}, \smath{B}, and \smath{b}, building four
different gametes
\texht{$a_1 =  AB, a_2 =  Ab, a_3 =  aB,$ and $a_4 =  ab$}%
{\spad{a1 :=  AB, a2 :=  Ab, a3 :=  aB,} and \spad{a4 :=  ab}}.
The zygotes \texht{$a_ia_j$}{\spad{ai aj}}
produce gametes \texht{$a_i$}{\spad{ai}} and
\texht{$a_j$}{\spad{aj}}
with classical Mendelian segregation.
Zygote \texht{$a_1a_4$}{a1 a4} undergoes transition
to \texht{$a_2a_3$}{\spad{a2 a3}}
and vice versa with probability
\texht{$0 \le \theta \le {1\over 2}$}{0 <= theta <= 1/2}.

\xtc{
Define a list
\texht{$[(\gamma_{i,j}^k) 1 \le k \le 4]$}{\spad{[(gammaijk) 1 <= k <= 4]}}
of four four-by-four matrices giving the segregation
rates.
We use the value \smath{1/10} for \smath{\theta}.
}{
\spadpaste{segregationRates : List SquareMatrix(4,FRAC INT) := 
[matrix [ [1, 1/2, 1/2, 9/20], [1/2, 0, 1/20, 0], [1/2, 1/20, 0, 0], 
[9/20, 0, 0, 0] ], matrix [ [0, 1/2, 0, 1/20], [1/2, 1, 9/20, 1/2], 
[0, 9/20, 0, 0], [1/20, 1/2, 0, 0] ], matrix [ [0, 0, 1/2, 1/20], 
[0, 0, 9/20, 0], [1/2, 9/20, 1, 1/2], [1/20, 0, 1/2, 0] ], 
matrix [ [0, 0, 0, 9/20], [0, 0, 1/20, 1/2], [0, 1/20, 0, 1/2], 
[9/20, 1/2, 1/2, 1] ] ] \bound{segregationRates}}
}
\xtc{
Choose the appropriate symbols for the basis of gametes,
}{
\spadpaste{gametes := ['AB,'Ab,'aB,'ab]  \bound{gametes}}
}
\xtc{
Define the algebra.
}{
\spadpaste{A := ALGSC(FRAC INT, 4, gametes, segregationRates);
\bound{A}\free{gametes, segregationRates}}
}

\xtc{
What are the probabilities for zygote
\texht{$a_1a_4$}{a1 a4} to produce the different gametes?
}{
\spadpaste{a := basis()\$A;  a.1*a.4}
}

Elements in this algebra whose coefficients sum to one play a
distinguished role.
They represent a population with the distribution of gametes
reflected by the coefficients with respect to the basis of
gametes.

Random mating of different populations \smath{x} and \smath{y} 
is described by their product \smath{x*y}.

\xtc{
This product is commutative only
if the gametes are not sex-dependent, as in our example.
}{
\spadpaste{commutative?()\$A \free{A}}
}
\xtc{
In general, it is not associative.
}{
\spadpaste{associative?()\$A \free{A}}
}

Random mating within a population \smath{x} is described by
\smath{x*x.}
The next generation is \smath{(x*x)*(x*x).}

\xtc{
Use decimal numbers to compare the distributions more easily.
}{
\spadpaste{x : ALGSC(DECIMAL, 4, gametes, segregationRates) :=  
convert [3/10, 1/5, 1/10, 2/5]\bound{x}\free{gametes, segregationRates}}
}
\xtc{
To compute directly the gametic distribution in the fifth
generation, we use \spadfun{plenaryPower}.
}{
\spadpaste{plenaryPower(x,5) \free{x}}
}

We now ask two questions:
Does this distribution converge to an equilibrium state?
What are the distributions that are stable?

\xtc{
This is an invariant of the algebra and it is used to answer
the first question.
The new indeterminates describe a symbolic distribution.
}{
\spadpaste{q := leftRankPolynomial()
\$GCNAALG(FRAC INT, 4, gametes, segregationRates) :: 
UP(Y, POLY FRAC INT)\bound{q}\free{gametes, segregationRates}}
}
\xtc{
Because the coefficient \texht{${9 \over 20}$}{\axiom{9/20}} has absolute
value less than 1, all distributions do converge,
by a theorem of this theory.
}{
\spadpaste{factor(q :: POLY FRAC INT) \free{q}}
}
\xtc{
The second question is answered by searching for idempotents in the
algebra.
}{
\spadpaste{cI := conditionsForIdempotents()
\$GCNAALG(FRAC INT, 4, gametes, segregationRates)
\bound{cI} \free{gametes, segregationRates}}
}
\xtc{
Solve these equations and look at the first solution.
}{
\spadpaste{gbs:= groebnerFactorize cI; gbs.1\free{cI}\bound{gbs}}
}

Further analysis using the package \spadtype{PolynomialIdeals}
shows that there is a two-dimensional variety of equilibrium states and all
other solutions are contained in it.

\xtc{
Choose one equilibrium state by setting two indeterminates to
concrete values.
}{
\spadpaste{sol := solve concat(gbs.1,[\%x1-1/10,\%x2-1/10])
\bound{sol} \free{gbs}}
}
\xtc{
}{
\spadpaste{e : A := represents reverse (map(rhs, sol.1) 
:: List FRAC INT)\bound{e} \free{A, sol}}
}
\xtc{
Verify the result.
}{
\spadpaste{e*e-e \free{e}}
}
\endscroll
\autobuttons
\end{page}

\begin{patch}{ugProblemGeneticPagePatch1}
\begin{paste}{ugProblemGeneticPageFull1}{ugProblemGeneticPageEmpty1}
\pastebutton{ugProblemGeneticPageFull1}{\hidepaste}
\tab{5}\spadcommand{segregationRates : List SquareMatrix(4,FRAC INT) := [matrix [ [1, 1/2, 1/2, 9/20], [1/2, 0, 1/20, 0], [1/2, 1/20, 0, 0], [9/20, 0, 0, 0] ], matrix [ [0, 1/2, 0, 1/20], [1/2, 1, 9/20, 1/2], [0, 9/20, 0, 0], [1/20, 1/2, 0, 0] ], matrix [ [0, 0, 1/2, 1/20], [0, 0, 9/20, 0], [1/2, 9/20, 1, 1/2], [1/20, 0, 1/2, 0] ], matrix [ [0, 0, 0, 9/20], [0, 0, 1/20, 1/2], [0, 1/20, 0, 1/2], [9/20, 1/2, 1/2, 1] ] ]\bound{segregationRates }}
\indentrel{3}\begin{verbatim}
   (1)
    Ú    1   1    9¿  Ú    1        1¿  Ú        1    1¿
    ³1   Ä   Ä   ÄÄ³  ³0   Ä   0   ÄÄ³  ³0   0   Ä   ÄÄ³
    ³    2   2   20³  ³    2       20³  ³        2   20³
    ³              ³  ³              ³  ³              ³
    ³1        1    ³  ³1        9  1 ³  ³         9    ³
    ³Ä   0   ÄÄ  0 ³  ³Ä   1   ÄÄ  Ä ³  ³0   0   ÄÄ  0 ³
    ³2       20    ³  ³2       20  2 ³  ³        20    ³
   [³              ³, ³              ³, ³              ³,
    ³1    1        ³  ³     9        ³  ³1    9      1 ³
    ³Ä   ÄÄ  0   0 ³  ³0   ÄÄ  0   0 ³  ³Ä   ÄÄ  1   Ä ³
    ³2   20        ³  ³    20        ³  ³2   20      2 ³
    ³              ³  ³              ³  ³              ³
    ³ 9            ³  ³ 1  1         ³  ³ 1      1     ³
    ³ÄÄ  0   0   0 ³  ³ÄÄ  Ä   0   0 ³  ³ÄÄ  0   Ä   0 ³
    À20            Ù  À20  2         Ù  À20      2     Ù
    Ú             9¿
    ³0   0   0   ÄÄ³
    ³            20³
    ³              ³
    ³         1  1 ³
    ³0   0   ÄÄ  Ä ³
    ³        20  2 ³
    ³              ³]
    ³     1      1 ³
    ³0   ÄÄ  0   Ä ³
    ³    20      2 ³
    ³              ³
    ³ 9  1   1     ³
    ³ÄÄ  Ä   Ä   1 ³
    À20  2   2     Ù
            Type: List SquareMatrix(4,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPageEmpty1}
\begin{paste}{ugProblemGeneticPageEmpty1}{ugProblemGeneticPagePatch1}
\pastebutton{ugProblemGeneticPageEmpty1}{\showpaste}
\tab{5}\spadcommand{segregationRates : List SquareMatrix(4,FRAC INT) := [matrix [ [1, 1/2, 1/2, 9/20], [1/2, 0, 1/20, 0], [1/2, 1/20, 0, 0], [9/20, 0, 0, 0] ], matrix [ [0, 1/2, 0, 1/20], [1/2, 1, 9/20, 1/2], [0, 9/20, 0, 0], [1/20, 1/2, 0, 0] ], matrix [ [0, 0, 1/2, 1/20], [0, 0, 9/20, 0], [1/2, 9/20, 1, 1/2], [1/20, 0, 1/2, 0] ], matrix [ [0, 0, 0, 9/20], [0, 0, 1/20, 1/2], [0, 1/20, 0, 1/2], [9/20, 1/2, 1/2, 1] ] ]\bound{segregationRates }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPagePatch2}
\begin{paste}{ugProblemGeneticPageFull2}{ugProblemGeneticPageEmpty2}
\pastebutton{ugProblemGeneticPageFull2}{\hidepaste}
\tab{5}\spadcommand{gametes := ['AB,'Ab,'aB,'ab]\bound{gametes }}
\indentrel{3}\begin{verbatim}
   (2)  [AB,Ab,aB,ab]
           Type: List OrderedVariableList [AB,Ab,aB,ab]
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPageEmpty2}
\begin{paste}{ugProblemGeneticPageEmpty2}{ugProblemGeneticPagePatch2}
\pastebutton{ugProblemGeneticPageEmpty2}{\showpaste}
\tab{5}\spadcommand{gametes := ['AB,'Ab,'aB,'ab]\bound{gametes }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPagePatch3}
\begin{paste}{ugProblemGeneticPageFull3}{ugProblemGeneticPageEmpty3}
\pastebutton{ugProblemGeneticPageFull3}{\hidepaste}
\tab{5}\spadcommand{A := ALGSC(FRAC INT, 4, gametes, segregationRates);\bound{A }\free{gametes segregationRates }}
\indentrel{3}\begin{verbatim}
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPageEmpty3}
\begin{paste}{ugProblemGeneticPageEmpty3}{ugProblemGeneticPagePatch3}
\pastebutton{ugProblemGeneticPageEmpty3}{\showpaste}
\tab{5}\spadcommand{A := ALGSC(FRAC INT, 4, gametes, segregationRates);\bound{A }\free{gametes segregationRates }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPagePatch4}
\begin{paste}{ugProblemGeneticPageFull4}{ugProblemGeneticPageEmpty4}
\pastebutton{ugProblemGeneticPageFull4}{\hidepaste}
\tab{5}\spadcommand{a := basis()$A; a.1*a.4}
\indentrel{3}\begin{verbatim}
         9       1       1       9
   (4)  ÄÄ ab + ÄÄ aB + ÄÄ Ab + ÄÄ AB
        20      20      20      20
Type: AlgebraGivenByStructuralConstants(Fraction Integer,4,[AB,Ab,aB,ab],[MATRIX,MATRIX,MATRIX,MATRIX])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPageEmpty4}
\begin{paste}{ugProblemGeneticPageEmpty4}{ugProblemGeneticPagePatch4}
\pastebutton{ugProblemGeneticPageEmpty4}{\showpaste}
\tab{5}\spadcommand{a := basis()$A; a.1*a.4}
\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPagePatch5}
\begin{paste}{ugProblemGeneticPageFull5}{ugProblemGeneticPageEmpty5}
\pastebutton{ugProblemGeneticPageFull5}{\hidepaste}
\tab{5}\spadcommand{commutative?()$A\free{A }}
\indentrel{3}\begin{verbatim}
   algebra is commutative
   (5)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPageEmpty5}
\begin{paste}{ugProblemGeneticPageEmpty5}{ugProblemGeneticPagePatch5}
\pastebutton{ugProblemGeneticPageEmpty5}{\showpaste}
\tab{5}\spadcommand{commutative?()$A\free{A }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPagePatch6}
\begin{paste}{ugProblemGeneticPageFull6}{ugProblemGeneticPageEmpty6}
\pastebutton{ugProblemGeneticPageFull6}{\hidepaste}
\tab{5}\spadcommand{associative?()$A\free{A }}
\indentrel{3}\begin{verbatim}
   algebra is not associative
   (6)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPageEmpty6}
\begin{paste}{ugProblemGeneticPageEmpty6}{ugProblemGeneticPagePatch6}
\pastebutton{ugProblemGeneticPageEmpty6}{\showpaste}
\tab{5}\spadcommand{associative?()$A\free{A }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPagePatch7}
\begin{paste}{ugProblemGeneticPageFull7}{ugProblemGeneticPageEmpty7}
\pastebutton{ugProblemGeneticPageFull7}{\hidepaste}
\tab{5}\spadcommand{x : ALGSC(DECIMAL, 4, gametes, segregationRates) := convert [3/10, 1/5, 1/10, 2/5]\bound{x }\free{gametes segregationRates }}
\indentrel{3}\begin{verbatim}
   (7)  0.4ab + 0.1aB + 0.2Ab + 0.3AB
Type: AlgebraGivenByStructuralConstants(DecimalExpansion,4,[AB,Ab,aB,ab],[MATRIX,MATRIX,MATRIX,MATRIX])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPageEmpty7}
\begin{paste}{ugProblemGeneticPageEmpty7}{ugProblemGeneticPagePatch7}
\pastebutton{ugProblemGeneticPageEmpty7}{\showpaste}
\tab{5}\spadcommand{x : ALGSC(DECIMAL, 4, gametes, segregationRates) := convert [3/10, 1/5, 1/10, 2/5]\bound{x }\free{gametes segregationRates }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPagePatch8}
\begin{paste}{ugProblemGeneticPageFull8}{ugProblemGeneticPageEmpty8}
\pastebutton{ugProblemGeneticPageFull8}{\hidepaste}
\tab{5}\spadcommand{plenaryPower(x,5)\free{x }}
\indentrel{3}\begin{verbatim}
   (8)  0.36561ab + 0.13439aB + 0.23439Ab + 0.26561AB
Type: AlgebraGivenByStructuralConstants(DecimalExpansion,4,[AB,Ab,aB,ab],[MATRIX,MATRIX,MATRIX,MATRIX])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPageEmpty8}
\begin{paste}{ugProblemGeneticPageEmpty8}{ugProblemGeneticPagePatch8}
\pastebutton{ugProblemGeneticPageEmpty8}{\showpaste}
\tab{5}\spadcommand{plenaryPower(x,5)\free{x }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPagePatch9}
\begin{paste}{ugProblemGeneticPageFull9}{ugProblemGeneticPageEmpty9}
\pastebutton{ugProblemGeneticPageFull9}{\hidepaste}
\tab{5}\spadcommand{q := leftRankPolynomial()$GCNAALG(FRAC INT, 4, gametes, segregationRates) :: UP(Y, POLY FRAC INT)\bound{q }\free{gametes segregationRates }}
\indentrel{3}\begin{verbatim}
   (9)
      3      29       29       29       29      2
     Y  + (- ÄÄ %x4 - ÄÄ %x3 - ÄÄ %x2 - ÄÄ %x1)Y
             20       20       20       20
   + 
          9    2     9        9        9            9    2
         ÄÄ %x4  + (ÄÄ %x3 + ÄÄ %x2 + ÄÄ %x1)%x4 + ÄÄ %x3
         20         10       10       10           20
       + 
           9        9            9    2    9
         (ÄÄ %x2 + ÄÄ %x1)%x3 + ÄÄ %x2  + ÄÄ %x1 %x2
          10       10           20        10
       + 
          9    2
         ÄÄ %x1
         20
    *
       Y
Type: UnivariatePolynomial(Y,Polynomial Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPageEmpty9}
\begin{paste}{ugProblemGeneticPageEmpty9}{ugProblemGeneticPagePatch9}
\pastebutton{ugProblemGeneticPageEmpty9}{\showpaste}
\tab{5}\spadcommand{q := leftRankPolynomial()$GCNAALG(FRAC INT, 4, gametes, segregationRates) :: UP(Y, POLY FRAC INT)\bound{q }\free{gametes segregationRates }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPagePatch10}
\begin{paste}{ugProblemGeneticPageFull10}{ugProblemGeneticPageEmpty10}
\pastebutton{ugProblemGeneticPageFull10}{\hidepaste}
\tab{5}\spadcommand{factor(q :: POLY FRAC INT)\free{q }}
\indentrel{3}\begin{verbatim}
   (10)
     (Y - %x4 - %x3 - %x2 - %x1)
  *
           9        9        9        9
     (Y - ÄÄ %x4 - ÄÄ %x3 - ÄÄ %x2 - ÄÄ %x1)Y
          20       20       20       20
             Type: Factored Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPageEmpty10}
\begin{paste}{ugProblemGeneticPageEmpty10}{ugProblemGeneticPagePatch10}
\pastebutton{ugProblemGeneticPageEmpty10}{\showpaste}
\tab{5}\spadcommand{factor(q :: POLY FRAC INT)\free{q }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPagePatch11}
\begin{paste}{ugProblemGeneticPageFull11}{ugProblemGeneticPageEmpty11}
\pastebutton{ugProblemGeneticPageFull11}{\hidepaste}
\tab{5}\spadcommand{cI := conditionsForIdempotents()$GCNAALG(FRAC INT, 4, gametes, segregationRates)\bound{cI }\free{gametes segregationRates }}
\indentrel{3}\begin{verbatim}
   (11)
     9             1                              2
   [ÄÄ %x1 %x4 + (ÄÄ %x2 + %x1)%x3 + %x1 %x2 + %x1  - %x1,
    10            10
            1            9              2
    (%x2 + ÄÄ %x1)%x4 + ÄÄ %x2 %x3 + %x2  + (%x1 - 1)%x2,
           10           10
            1              2     9
    (%x3 + ÄÄ %x1)%x4 + %x3  + (ÄÄ %x2 + %x1 - 1)%x3,
           10                   10
       2                 9                1
    %x4  + (%x3 + %x2 + ÄÄ %x1 - 1)%x4 + ÄÄ %x2 %x3]
                        10               10
                 Type: List Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPageEmpty11}
\begin{paste}{ugProblemGeneticPageEmpty11}{ugProblemGeneticPagePatch11}
\pastebutton{ugProblemGeneticPageEmpty11}{\showpaste}
\tab{5}\spadcommand{cI := conditionsForIdempotents()$GCNAALG(FRAC INT, 4, gametes, segregationRates)\bound{cI }\free{gametes segregationRates }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPagePatch12}
\begin{paste}{ugProblemGeneticPageFull12}{ugProblemGeneticPageEmpty12}
\pastebutton{ugProblemGeneticPageFull12}{\hidepaste}
\tab{5}\spadcommand{gbs:= groebnerFactorize cI; gbs.1\free{cI }\bound{gbs }}
\indentrel{3}\begin{verbatim}
   (12)
   [%x4 + %x3 + %x2 + %x1 - 1,
                                  2
    (%x2 + %x1)%x3 + %x1 %x2 + %x1  - %x1]
                 Type: List Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPageEmpty12}
\begin{paste}{ugProblemGeneticPageEmpty12}{ugProblemGeneticPagePatch12}
\pastebutton{ugProblemGeneticPageEmpty12}{\showpaste}
\tab{5}\spadcommand{gbs:= groebnerFactorize cI; gbs.1\free{cI }\bound{gbs }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPagePatch13}
\begin{paste}{ugProblemGeneticPageFull13}{ugProblemGeneticPageEmpty13}
\pastebutton{ugProblemGeneticPageFull13}{\hidepaste}
\tab{5}\spadcommand{sol := solve concat(gbs.1,[\%x1-1/10,\%x2-1/10])\bound{sol }\free{gbs }}
\indentrel{3}\begin{verbatim}
                2      2       1       1
   (13)  [[%x4= Ä,%x3= Ä,%x2= ÄÄ,%x1= ÄÄ]]
                5      5      10      10
   Type: List List Equation Fraction Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPageEmpty13}
\begin{paste}{ugProblemGeneticPageEmpty13}{ugProblemGeneticPagePatch13}
\pastebutton{ugProblemGeneticPageEmpty13}{\showpaste}
\tab{5}\spadcommand{sol := solve concat(gbs.1,[\%x1-1/10,\%x2-1/10])\bound{sol }\free{gbs }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPagePatch14}
\begin{paste}{ugProblemGeneticPageFull14}{ugProblemGeneticPageEmpty14}
\pastebutton{ugProblemGeneticPageFull14}{\hidepaste}
\tab{5}\spadcommand{e : A := represents reverse (map(rhs, sol.1) :: List FRAC INT)\bound{e }\free{A sol }}
\indentrel{3}\begin{verbatim}
         2      2       1       1
   (14)  Ä ab + Ä aB + ÄÄ Ab + ÄÄ AB
         5      5      10      10
Type: AlgebraGivenByStructuralConstants(Fraction Integer,4,[AB,Ab,aB,ab],[MATRIX,MATRIX,MATRIX,MATRIX])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPageEmpty14}
\begin{paste}{ugProblemGeneticPageEmpty14}{ugProblemGeneticPagePatch14}
\pastebutton{ugProblemGeneticPageEmpty14}{\showpaste}
\tab{5}\spadcommand{e : A := represents reverse (map(rhs, sol.1) :: List FRAC INT)\bound{e }\free{A sol }}
\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPagePatch15}
\begin{paste}{ugProblemGeneticPageFull15}{ugProblemGeneticPageEmpty15}
\pastebutton{ugProblemGeneticPageFull15}{\hidepaste}
\tab{5}\spadcommand{e*e-e\free{e }}
\indentrel{3}\begin{verbatim}
   (15)  0
Type: AlgebraGivenByStructuralConstants(Fraction Integer,4,[AB,Ab,aB,ab],[MATRIX,MATRIX,MATRIX,MATRIX])
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugProblemGeneticPageEmpty15}
\begin{paste}{ugProblemGeneticPageEmpty15}{ugProblemGeneticPagePatch15}
\pastebutton{ugProblemGeneticPageEmpty15}{\showpaste}
\tab{5}\spadcommand{e*e-e\free{e }}
\end{paste}\end{patch}

\end{chunk}
\chapter{Users Guide Chapter 10 (ug10.ht)}
\pagetitle{ugIntProgPage}{ug10.ht}{Interactive Programming}
\pageto{notitle}{ugAppGraphicsPage}
\pageto{notitle}{ugIntProgDrawingPage}
\pageto{notitle}{ugIntProgRibbonPage}
\pageto{notitle}{ugIntProgColorPage}
\pageto{notitle}{ugIntProgPLCPage}
\pageto{notitle}{ugIntProgColorArrPage}
\pageto{notitle}{ugIntProgVecFieldsPage}
\pageto{notitle}{ugIntProgCompFunsPage}
\pageto{notitle}{ugIntProgFunctionsPage}
\pageto{notitle}{ugIntProgNewtonPage}
\begin{chunk}{ug10.ht}
\begin{page}{ugIntProgPage}{10. Interactive Programming}
\beginscroll

Programming in the interpreter is easy.
So is the use of Axiom's graphics facility.
Both are rather flexible and allow you to use them for many
interesting applications.
However, both require learning some basic ideas and skills.

All graphics examples in the \Gallery{} section are either
produced directly by interactive commands or by interpreter
programs.
Four of these programs are introduced here.
By the end of this chapter you will know enough about graphics and
programming in the interpreter to not only understand all these
examples, but to tackle interesting and difficult problems on your
own.
\downlink{``Programs for Axiom Images''}{ugAppGraphicsPage} in 
Appendix G\ignore{ugAppGraphics} lists 
all the remaining commands and
programs used to create these images.

\beginmenu
\menudownlink{{10.1. Drawing Ribbons Interactively}}
{ugIntProgDrawingPage}
\menudownlink{{10.2. A Ribbon Program}}
{ugIntProgRibbonPage}
\menudownlink{{10.3. Coloring and Positioning Ribbons}}
{ugIntProgColorPage}
\menudownlink{{10.4. Points, Lines, and Curves}}
{ugIntProgPLCPage}
\menudownlink{{10.5. A Bouquet of Arrows}}
{ugIntProgColorArrPage}
\menudownlink{{10.6. Drawing Complex Vector Fields}}
{ugIntProgVecFieldsPage}
\menudownlink{{10.7. Drawing Complex Functions}}
{ugIntProgCompFunsPage}
\menudownlink{{10.8. Functions Producing Functions}}
{ugIntProgFunctionsPage}
\menudownlink{{10.9. Automatic Newton Iteration Formulas}}
{ugIntProgNewtonPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugIntProgDrawingPage}{ug10.ht}{Drawing Ribbons Interactively}
\pageto{notitle}{ugGraphPage}
\begin{chunk}{ug10.ht}
\begin{page}{ugIntProgDrawingPage}{10.1. Drawing Ribbons Interactively}
\beginscroll
%

We begin our discussion of interactive graphics with the creation
of a useful facility: plotting ribbons of two-graphs in
three-space.
Suppose you want to draw the \twodim{} graphs of \smath{n}
functions \texht{$f_i(x), 1 \leq i \leq n,$}{\spad{f_i(x), 1 <= i
<= 5,}} all over some fixed range of \smath{x}.
One approach is to create a \twodim{} graph for each one, then
superpose one on top of the other.
What you will more than likely get is a jumbled mess.
Even if you make each function a different color, the result is
likely to be confusing.

A better approach is to display each of the \smath{f_i(x)} in three
dimensions as a ``ribbon'' of some appropriate width along the
\smath{y}-direction, laying down each  ribbon next to the
previous one.
A ribbon is simply a function of \smath{x} and \smath{y} depending
only on \smath{x.}

We illustrate this for \smath{f_i(x)} defined as simple powers of
\smath{x} for \smath{x} ranging between \smath{-1} and \smath{1}.

\psXtc{
Draw the ribbon for \texht{$z = x^2$}{\spad{z=x ** 2}}.
}{
\graphpaste{draw(x**2,x=-1..1,y=0..1)}
}{
\epsffile[0 0 295 295]{../ps/ribbon1.ps}
}

Now that was easy!
What you get is a ``wire-mesh'' rendition of the ribbon.
That's fine for now.
Notice that the mesh-size is small in both the \smath{x} and the
\smath{y} directions.
Axiom normally computes points in both these directions.
This is unnecessary.
One step is all we need in the \smath{y}-direction.
To have Axiom economize on \spad{y}-points, we re-draw the
ribbon with option \spad{var2Steps == 1}.

\psXtc{
Re-draw the ribbon, but with option \spad{var2Steps == 1}
so that only \spad{1} step is computed in the
\smath{y} direction.
}{
\graphpaste{vp := draw(x**2,x=-1..1,y=0..1,var2Steps==1) \bound{d1}}
}{
\epsffile[0 0 295 295]{../ps/ribbon2.ps}
}

The operation has created a viewport, that is, a graphics window
on your screen.
We assigned the viewport to \spad{vp} and now we manipulate
its contents.


Graphs are objects, like numbers and algebraic expressions.
You may want to do some experimenting with graphs.
For example, say
\begin{verbatim}
showRegion(vp, "on")
\end{verbatim}
to put a bounding box around the ribbon.
Try it!
Issue \spad{rotate(vp, -45, 90)} to rotate the
figure \smath{-45} longitudinal degrees and \smath{90} latitudinal
degrees.

\psXtc{
Here is a different rotation.
This turns the graph so you can view it along the \smath{y}-axis.
}{
\spadpaste{rotate(vp, 0, -90)\bound{d3}\free{d1}}
}{
\epsffile[0 0 295 295]{../ps/ribbon2r.ps}
}

There are many other things you can do.
In fact, most everything you can do interactively using the
\threedim{} control panel (such as translating, zooming, resizing,
coloring, perspective and lighting selections) can also be done
directly by operations (see \downlink{``Graphics''}{ugGraphPage} 
in Chapter 7\ignore{ugGraph} for more details).

When you are done experimenting, say \spad{reset(vp)} to restore the
picture to its original position and settings.


Let's add another ribbon to our picture---one
for \texht{$x^3$}{\spad{x**3}}.
Since \smath{y} ranges from \smath{0} to \smath{1} for the
first ribbon, now let \smath{y} range from \smath{1} to
\smath{2.}
This puts the second ribbon next to the first one.

How do you add a second ribbon to the viewport?
One method is
to extract the ``space'' component from the
viewport using the operation
\spadfunFrom{subspace}{ThreeDimensionalViewport}.
You can think of the space component as the object inside the
window (here, the ribbon).
Let's call it \spad{sp}.
To add the second ribbon, you draw the second ribbon using the
option \spad{space == sp}.

\xtc{
Extract the space component of \spad{vp}.
}{
\spadpaste{sp := subspace(vp)\bound{d5}\free{d1}}
}

\psXtc{
Add the ribbon for
\texht{$x^3$}{\spad{x**3}} alongside that for
\texht{$x^2$}{\spad{x**2}}.
}{
\graphpaste{vp := draw(x**3,x=-1..1,y=1..2,var2Steps==1, space==sp)
\bound{d6}\free{d5}}
}{
\epsffile[0 0 295 295]{../ps/ribbons.ps}
}

Unless you moved the original viewport, the new viewport covers
the old one.
You might want to check that the old object is still there by
moving the top window.

Let's show quadrilateral polygon outlines on the ribbons and then
enclose the ribbons in a box.

\psXtc{
Show quadrilateral polygon outlines.
}{
\spadpaste{drawStyle(vp,"shade");outlineRender(vp,"on")
\bound{d10}\free{d6}}
}{
\epsffile[0 0 295 295]{../ps/ribbons2.ps}
}
\psXtc{
Enclose the ribbons in a box.
}{
\spadpaste{rotate(vp,20,-60); showRegion(vp,"on")\bound{d11}\free{d10}}
}{
\epsffile[0 0 295 295]{../ps/ribbons2b.ps}
}

This process has become tedious!
If we had to add two or three more ribbons, we would have to
repeat the above steps several more times.
It is time to write an interpreter program to help us take care of
the details.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntProgDrawingPagePatch1}
\begin{paste}{ugIntProgDrawingPageFull1}{ugIntProgDrawingPageEmpty1}
\pastebutton{ugIntProgDrawingPageFull1}{\hidepaste}
\tab{5}\spadgraph{draw(x**2,x=-1..1,y=0..1)}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/ugintprogdrawingpage1.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/ugintprogdrawingpage1}}
\end{paste}\end{patch}

\begin{patch}{ugIntProgDrawingPageEmpty1}
\begin{paste}{ugIntProgDrawingPageEmpty1}{ugIntProgDrawingPagePatch1}
\pastebutton{ugIntProgDrawingPageEmpty1}{\showpaste}
\tab{5}\spadgraph{draw(x**2,x=-1..1,y=0..1)}
\end{paste}\end{patch}

\begin{patch}{ugIntProgDrawingPagePatch2}
\begin{paste}{ugIntProgDrawingPageFull2}{ugIntProgDrawingPageEmpty2}
\pastebutton{ugIntProgDrawingPageFull2}{\hidepaste}
\tab{5}\spadgraph{vp := draw(x**2,x=-1..1,y=0..1,var2Steps==1)\bound{d1 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/ugintprogdrawingpage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/ugintprogdrawingpage2}}
\end{paste}\end{patch}

\begin{patch}{ugIntProgDrawingPageEmpty2}
\begin{paste}{ugIntProgDrawingPageEmpty2}{ugIntProgDrawingPagePatch2}
\pastebutton{ugIntProgDrawingPageEmpty2}{\showpaste}
\tab{5}\spadgraph{vp := draw(x**2,x=-1..1,y=0..1,var2Steps==1)\bound{d1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgDrawingPagePatch3}
\begin{paste}{ugIntProgDrawingPageFull3}{ugIntProgDrawingPageEmpty3}
\pastebutton{ugIntProgDrawingPageFull3}{\hidepaste}
\tab{5}\spadcommand{rotate(vp, 0, -90)\bound{d3 }\free{d1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgDrawingPageEmpty3}
\begin{paste}{ugIntProgDrawingPageEmpty3}{ugIntProgDrawingPagePatch3}
\pastebutton{ugIntProgDrawingPageEmpty3}{\showpaste}
\tab{5}\spadcommand{rotate(vp, 0, -90)\bound{d3 }\free{d1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgDrawingPagePatch4}
\begin{paste}{ugIntProgDrawingPageFull4}{ugIntProgDrawingPageEmpty4}
\pastebutton{ugIntProgDrawingPageFull4}{\hidepaste}
\tab{5}\spadcommand{sp := subspace(vp)\bound{d5 }\free{d1 }}
\indentrel{3}\begin{verbatim}
   (4)  3-Space with 1 component
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgDrawingPageEmpty4}
\begin{paste}{ugIntProgDrawingPageEmpty4}{ugIntProgDrawingPagePatch4}
\pastebutton{ugIntProgDrawingPageEmpty4}{\showpaste}
\tab{5}\spadcommand{sp := subspace(vp)\bound{d5 }\free{d1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgDrawingPagePatch5}
\begin{paste}{ugIntProgDrawingPageFull5}{ugIntProgDrawingPageEmpty5}
\pastebutton{ugIntProgDrawingPageFull5}{\hidepaste}
\tab{5}\spadgraph{vp := draw(x**3,x=-1..1,y=1..2,var2Steps==1, space==sp)\bound{d6 }\free{d5 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/ugintprogdrawingpage5.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/ugintprogdrawingpage5}}
\end{paste}\end{patch}

\begin{patch}{ugIntProgDrawingPageEmpty5}
\begin{paste}{ugIntProgDrawingPageEmpty5}{ugIntProgDrawingPagePatch5}
\pastebutton{ugIntProgDrawingPageEmpty5}{\showpaste}
\tab{5}\spadgraph{vp := draw(x**3,x=-1..1,y=1..2,var2Steps==1, space==sp)\bound{d6 }\free{d5 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgDrawingPagePatch6}
\begin{paste}{ugIntProgDrawingPageFull6}{ugIntProgDrawingPageEmpty6}
\pastebutton{ugIntProgDrawingPageFull6}{\hidepaste}
\tab{5}\spadcommand{drawStyle(vp,"shade");outlineRender(vp,"on")\bound{d10 }\free{d6 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgDrawingPageEmpty6}
\begin{paste}{ugIntProgDrawingPageEmpty6}{ugIntProgDrawingPagePatch6}
\pastebutton{ugIntProgDrawingPageEmpty6}{\showpaste}
\tab{5}\spadcommand{drawStyle(vp,"shade");outlineRender(vp,"on")\bound{d10 }\free{d6 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgDrawingPagePatch7}
\begin{paste}{ugIntProgDrawingPageFull7}{ugIntProgDrawingPageEmpty7}
\pastebutton{ugIntProgDrawingPageFull7}{\hidepaste}
\tab{5}\spadcommand{rotate(vp,20,-60); showRegion(vp,"on")\bound{d11 }\free{d10 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgDrawingPageEmpty7}
\begin{paste}{ugIntProgDrawingPageEmpty7}{ugIntProgDrawingPagePatch7}
\pastebutton{ugIntProgDrawingPageEmpty7}{\showpaste}
\tab{5}\spadcommand{rotate(vp,20,-60); showRegion(vp,"on")\bound{d11 }\free{d10 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntProgRibbonPage}{ug10.ht}{A Ribbon Program}
\pageto{notitle}{ugUserPage}
\pageto{notitle}{ugLangBlocksPage}
\begin{chunk}{ug10.ht}
\begin{page}{ugIntProgRibbonPage}{10.2. A Ribbon Program}
\beginscroll
%

The above approach creates a new viewport for each additional
ribbon.
A better approach is to build one object composed of all ribbons
before creating a viewport.
To do this, use \spadfun{makeObject} rather than \spadfun{draw}.
The operations have similar formats, but
\spadfun{draw} returns a viewport and
\spadfun{makeObject} returns a space object.

We now create a function \userfun{drawRibbons} of two arguments:
\spad{flist}, a list of formulas for the ribbons you want to draw,
and \spad{xrange}, the range over which you want them drawn.
Using this function, you can just say
\begin{verbatim}
drawRibbons([x**2, x**3], x=-1..1)
\end{verbatim}
to do all of the work required in the last section.
Here is the \userfun{drawRibbons} program.
Invoke your favorite editor and create a file called {\bf ribbon.input}
containing the following program.

\beginImportant
  
\noindent
{\tt 1.\ \ \ drawRibbons(flist,\ xrange)\ ==}\newline
{\tt 2.\ \ \ \ \ sp\ :=\ createThreeSpace()}\newline
{\tt 3.\ \ \ \ \ y0\ :=\ 0}\newline
{\tt 4.\ \ \ \ \ for\ f\ in\ flist\ repeat}\newline
{\tt 5.\ \ \ \ \ \ \ makeObject(f,\ xrange,\ y=y0..y0+1,\ }\newline
{\tt 6.\ \ \ \ \ \ \ \ \ \ space==sp,\ var2Steps\ ==\ 1)}\newline
{\tt 7.\ \ \ \ \ \ \ y0\ :=\ y0\ +\ 1}\newline
{\tt 8.\ \ \ \ \ vp\ :=\ makeViewport3D(sp,\ "Ribbons")}\newline
{\tt 9.\ \ \ \ \ drawStyle(vp,\ "shade")}\newline
{\tt 10.\ \ \ \ outlineRender(vp,\ "on")}\newline
{\tt 11.\ \ \ \ showRegion(vp,"on")}\newline
{\tt 12.\ \ \ \ n\ :=\ \#\ flist}\newline
{\tt 13.\ \ \ \ zoom(vp,n,1,n)}\newline
{\tt 14.\ \ \ \ rotate(vp,0,75)}\newline
{\tt 15.\ \ \ \ vp}\newline
\caption{The first \protect\pspadfun{drawRibbons} function.}
\label{fig-ribdraw1}
\endImportant

Here are some remarks on the syntax used in the \pspadfun{drawRibbons}
function (consult 
\downlink{``User-Defined Functions, Macros and Rules''}{ugUserPage} 
in Chapter 6\ignore{ugUser} for more details).  Unlike most other
programming languages which use semicolons, parentheses, or {\it
begin}--{\it end} brackets to delineate the structure of programs, the
structure of an Axiom program is determined by indentation.  The first
line of the function definition always begins in column 1.  All other
lines of the function are indented with respect to the first line and
form a \spadgloss{pile} (see
\downlink{``Blocks''}{ugLangBlocksPage} in Section
5.2\ignore{ugLangBlocks}).

The definition of \userfun{drawRibbons} consists of a pile of
expressions to be executed one after another.  Each expression of the
pile is indented at the same level.  Lines 4-7 designate one single
expression: since lines 5-7 are indented with respect to the others,
these lines are treated as a continuation of line 4.  Also since lines
5 and 7 have the same indentation level, these lines designate a pile
within the outer pile.

The last line of a pile usually gives the value returned by the pile.
Here it is also the value returned by the function.  Axiom knows this
is the last line of the function because it is the last line of the
file.  In other cases, a new expression beginning in column one
signals the end of a function.

The line \spad{drawStyle(vp,"shade")} is given after the viewport has
been created to select the draw style.  We have also used the
\spadfunFrom{zoom}{ThreeDimensionalViewport} option.  Without the
zoom, the viewport region would be scaled equally in all three
coordinate directions.

Let's try the function \userfun{drawRibbons}.
First you must read the file to give Axiom the function definition.

\xtc{
Read the input file.
}{
\spadpaste{)read ribbon \bound{s0}}
}
\psXtc{
Draw ribbons for \texht{$x, x^2,\dots, x^5$}{x, x**2,...,x**5}
for \texht{$-1 \leq x \leq 1$}{-1 <= x <= 1}
}{
\graphpaste{drawRibbons([x**i for i in 1..5],x=-1..1) \free{s0}}
}{
\epsffile[0 0 295 295]{../ps/ribbons5.ps}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntProgRibbonPagePatch1}
\begin{paste}{ugIntProgRibbonPageFull1}{ugIntProgRibbonPageEmpty1}
\pastebutton{ugIntProgRibbonPageFull1}{\hidepaste}
\tab{5}\spadcommand{)read ribbon\bound{s0 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgRibbonPageEmpty1}
\begin{paste}{ugIntProgRibbonPageEmpty1}{ugIntProgRibbonPagePatch1}
\pastebutton{ugIntProgRibbonPageEmpty1}{\showpaste}
\tab{5}\spadcommand{)read ribbon\bound{s0 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgRibbonPagePatch2}
\begin{paste}{ugIntProgRibbonPageFull2}{ugIntProgRibbonPageEmpty2}
\pastebutton{ugIntProgRibbonPageFull2}{\hidepaste}
\tab{5}\spadgraph{drawRibbons([x**i for i in 1..5],x=-1..1)\free{s0 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/ugintprogribbonpage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/ugintprogribbonpage2}}
\end{paste}\end{patch}

\begin{patch}{ugIntProgRibbonPageEmpty2}
\begin{paste}{ugIntProgRibbonPageEmpty2}{ugIntProgRibbonPagePatch2}
\pastebutton{ugIntProgRibbonPageEmpty2}{\showpaste}
\tab{5}\spadgraph{drawRibbons([x**i for i in 1..5],x=-1..1)\free{s0 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntProgColorPage}{ug10.ht}{Coloring and Positioning Ribbons}
\begin{chunk}{ug10.ht}
\begin{page}{ugIntProgColorPage}{10.3. Coloring and Positioning Ribbons}
\beginscroll
%

Before leaving the ribbon example, we  make two improvements.
Normally, the color given to each point in the space is a
function of its height within a bounding box.
The points at the bottom of the
box are red, those at the top are purple.

To change the normal coloring, you can give
an option \spad{colorFunction == {\it function}}.
When Axiom goes about displaying the data, it
determines the range of colors used for all points within the box.
Axiom then distributes these numbers uniformly over the number of hues.
Here we use the simple color function
\texht{$(x,y) \mapsto i$}{(x,y) +-> i} for the
\eth{\smath{i}} ribbon.

Also, we add an argument \spad{yrange} so you can give the range of
\spad{y} occupied by the ribbons.
For example, if the \spad{yrange} is given as
\spad{y=0..1} and there are \smath{5} ribbons to be displayed, each
ribbon would have width \smath{0.2} and would appear in the
range \texht{$0 \leq y \leq 1$}{\spad{0 <= y <= 1}}.

Refer to lines 4-9.
Line 4 assigns to \spad{yVar} the variable part of the
\spad{yrange} (after all, it need not be \spad{y}).
Suppose that \spad{yrange} is given as \spad{t = a..b} where \spad{a} and
\spad{b} have numerical values.
Then line 5 assigns the value of \spad{a} to the variable \spad{y0}.
Line 6 computes the width of the ribbon by dividing the difference of
\spad{a} and \spad{b} by the number, \spad{num}, of ribbons.
The result is assigned to the variable \spad{width}.
Note that in the for-loop in line 7, we are iterating in parallel; it is
not a nested loop.

\beginImportant
  
\noindent
{\tt 1.\ \ \ drawRibbons(flist,\ xrange,\ yrange)\ ==}\newline
{\tt 2.\ \ \ \ \ sp\ :=\ createThreeSpace()}\newline
{\tt 3.\ \ \ \ \ num\ :=\ \#\ flist}\newline
{\tt 4.\ \ \ \ \ yVar\ :=\ variable\ yrange}\newline
{\tt 5.\ \ \ \ \ y0:Float\ \ \ \ :=\ lo\ segment\ yrange}\newline
{\tt 6.\ \ \ \ \ width:Float\ :=\ (hi\ segment\ yrange\ -\ y0)/num}
\newline
{\tt 7.\ \ \ \ \ for\ f\ in\ flist\ for\ color\ in\ 1..num\ repeat}
\newline
{\tt 8.\ \ \ \ \ \ \ makeObject(f,\ xrange,\ yVar\ =\ y0..y0+width,}
\newline
{\tt 9.\ \ \ \ \ \ \ \ \ var2Steps\ ==\ 1,\ colorFunction\ ==\ 
(x,y)\ +->\ color,\ \_}\newline
{\tt 10.\ \ \ \ \ \ \ \ space\ ==\ sp)}\newline
{\tt 11.\ \ \ \ \ \ y0\ :=\ y0\ +\ width}\newline
{\tt 12.\ \ \ \ vp\ :=\ makeViewport3D(sp,\ "Ribbons")}\newline
{\tt 13.\ \ \ \ drawStyle(vp,\ "shade")}\newline
{\tt 14.\ \ \ \ outlineRender(vp,\ "on")}\newline
{\tt 15.\ \ \ \ showRegion(vp,\ "on")}\newline
{\tt 16.\ \ \ \ vp}\newline
\caption{The final \protect\pspadfun{drawRibbons} function.}
\label{fig-ribdraw2}
\endImportant


\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugIntProgPLCPage}{ug10.ht}{Points, Lines, and Curves}
\begin{chunk}{ug10.ht}
\begin{page}{ugIntProgPLCPage}{10.4. Points, Lines, and Curves}
\beginscroll
%
What you have seen so far is a high-level program using the
graphics facility.
We now turn to the more basic notions of points, lines, and curves
in \threedim{} graphs.
These facilities use small floats (objects
of type \spadtype{DoubleFloat}) for data.
Let us first give names to the small float values \smath{0} and
\smath{1}.
\xtc{
The small float 0.
}{
\spadpaste{zero := 0.0@DFLOAT \bound{d1}}
}
\xtc{
The small float 1.
}{
\spadpaste{one  := 1.0@DFLOAT \bound{d2}}
}
The \spadSyntax{@} sign means ``of the type.'' Thus \spad{zero} is
\smath{0.0} of the type \spadtype{DoubleFloat}.
You can also say \spad{0.0::DFLOAT}.

Points can have four small float components: \smath{x, y, z}
coordinates and an optional color.  A ``curve'' is simply a list of
points connected by straight line segments.
\xtc{
Create the point \spad{origin} with color zero, that is, the lowest color
on the color map.
}{
\spadpaste{origin := point [zero,zero,zero,zero] \free{d1}\bound{d3}}
}
\xtc{
Create the point \spad{unit} with color zero.
}{
\spadpaste{unit := point [one,one,one,zero] \free{d1 d2}\bound{d4}}
}
\xtc{
Create the curve (well, here, a line) from
\spad{origin} to \spad{unit}.
}{
\spadpaste{line := [origin, unit] \free{d3 d4} \bound{d5}}
}

We make this line segment into an arrow by adding an arrowhead.
The arrowhead extends to,
say, \spad{p3} on the left, and to, say, \spad{p4} on the right.
To describe an arrow, you tell Axiom to draw the two curves
\spad{[p1, p2, p3]} and \spad{[p2, p4].}
We also decide through experimentation on
values for \spad{arrowScale}, the ratio of the size of
the arrowhead to the stem of the arrow, and \spad{arrowAngle},
the angle between the arrowhead and the arrow.

Invoke your favorite editor and create
an input file called {\bf arrows.input}.
This input file first defines the values of
%\spad{origin},\spad{unit},
\spad{arrowAngle} and \spad{arrowScale}, then
defines the function \userfun{makeArrow}\texht{$(p_1, p_2)$}{(p1, p2)} to
draw an arrow from point \texht{$p_1$}{p1} to \texht{$p_2$}{p2}.

\beginImportant
  
\noindent
{\tt 1.\ \ \ arrowAngle\ :=\ \%pi-\%pi/10.0@DFLOAT}\newline
{\tt 2.\ \ \ arrowScale\ :=\ 0.2@DFLOAT}\newline
{\tt 3.\ \ \ }\newline
{\tt 4.\ \ \ makeArrow(p1,\ p2)\ ==}\newline
{\tt 5.\ \ \ \ \ delta\ :=\ p2\ -\ p1}\newline
{\tt 6.\ \ \ \ \ len\ :=\ arrowScale\ *\ length\ delta}\newline
{\tt 7.\ \ \ \ \ theta\ :=\ atan(delta.1,\ delta.2)}\newline
{\tt 8.\ \ \ \ \ c1\ :=\ len*cos(theta\ +\ arrowAngle)}\newline
{\tt 9.\ \ \ \ \ s1\ :=\ len*sin(theta\ +\ arrowAngle)}\newline
{\tt 10.\ \ \ \ c2\ :=\ len*cos(theta\ -\ arrowAngle)}\newline
{\tt 11.\ \ \ \ s2\ :=\ len*sin(theta\ -\ arrowAngle)}\newline
{\tt 12.\ \ \ \ z\ \ :=\ p2.3*(1\ -\ arrowScale)}\newline
{\tt 13.\ \ \ \ p3\ :=\ point\ [p2.1\ +\ c1,\ p2.2\ +\ s1,\ z,\ p2.4]}
\newline
{\tt 14.\ \ \ \ p4\ :=\ point\ [p2.1\ +\ c2,\ p2.2\ +\ s2,\ z,\ p2.4]}
\newline
{\tt 15.\ \ \ \ [[p1,\ p2,\ p3],\ [p2,\ p4]]}\newline
\endImportant

Read the file and then create
an arrow from the point \spad{origin} to the point \spad{unit}.
\xtc{
Read the input file defining \userfun{makeArrow}.
}{
\spadpaste{)read arrows\bound{v1}}
}
\xtc{
Construct the arrow (a list of two curves).
}{
\spadpaste{arrow := makeArrow(origin,unit)\bound{v2}\free{v1 d3 d4}}
}
\xtc{
Create an empty object \spad{sp} of type \spad{ThreeSpace}.
}{
\spadpaste{sp := createThreeSpace()\bound{c1}}
}
\xtc{
Add each curve of the arrow to the space \spad{sp}.
}{
\spadpaste{for a in arrow repeat sp := curve(sp,a)
\bound{v3}\free{v2}\free{c1}}
}
\psXtc{
Create a \threedim{} viewport containing that space.
}{
\graphpaste{vp := makeViewport3D(sp,"Arrow")\bound{v4}\free{v3}}
}{
\epsffile[0 0 295 295]{../ps/arrow.ps}
}
\psXtc{
Here is a better viewing angle.
}{
\spadpaste{rotate(vp,200,-60)\bound{v5}\free{v4}}
}{
\epsffile[0 0 295 295]{../ps/arrowr.ps}
}


\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntProgPLCPagePatch1}
\begin{paste}{ugIntProgPLCPageFull1}{ugIntProgPLCPageEmpty1}
\pastebutton{ugIntProgPLCPageFull1}{\hidepaste}
\tab{5}\spadcommand{zero := 0.0@DFLOAT\bound{d1 }}
\indentrel{3}\begin{verbatim}
   (1)  0.0
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgPLCPageEmpty1}
\begin{paste}{ugIntProgPLCPageEmpty1}{ugIntProgPLCPagePatch1}
\pastebutton{ugIntProgPLCPageEmpty1}{\showpaste}
\tab{5}\spadcommand{zero := 0.0@DFLOAT\bound{d1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgPLCPagePatch2}
\begin{paste}{ugIntProgPLCPageFull2}{ugIntProgPLCPageEmpty2}
\pastebutton{ugIntProgPLCPageFull2}{\hidepaste}
\tab{5}\spadcommand{one := 1.0@DFLOAT\bound{d2 }}
\indentrel{3}\begin{verbatim}
   (2)  1.0
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgPLCPageEmpty2}
\begin{paste}{ugIntProgPLCPageEmpty2}{ugIntProgPLCPagePatch2}
\pastebutton{ugIntProgPLCPageEmpty2}{\showpaste}
\tab{5}\spadcommand{one := 1.0@DFLOAT\bound{d2 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgPLCPagePatch3}
\begin{paste}{ugIntProgPLCPageFull3}{ugIntProgPLCPageEmpty3}
\pastebutton{ugIntProgPLCPageFull3}{\hidepaste}
\tab{5}\spadcommand{origin := point [zero,zero,zero,zero]\free{d1 }\bound{d3 }}
\indentrel{3}\begin{verbatim}
   (3)  [0.0,0.0,0.0,0.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgPLCPageEmpty3}
\begin{paste}{ugIntProgPLCPageEmpty3}{ugIntProgPLCPagePatch3}
\pastebutton{ugIntProgPLCPageEmpty3}{\showpaste}
\tab{5}\spadcommand{origin := point [zero,zero,zero,zero]\free{d1 }\bound{d3 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgPLCPagePatch4}
\begin{paste}{ugIntProgPLCPageFull4}{ugIntProgPLCPageEmpty4}
\pastebutton{ugIntProgPLCPageFull4}{\hidepaste}
\tab{5}\spadcommand{unit := point [one,one,one,zero]\free{d1 d2 }\bound{d4 }}
\indentrel{3}\begin{verbatim}
   (4)  [1.0,1.0,1.0,0.0]
                                Type: Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgPLCPageEmpty4}
\begin{paste}{ugIntProgPLCPageEmpty4}{ugIntProgPLCPagePatch4}
\pastebutton{ugIntProgPLCPageEmpty4}{\showpaste}
\tab{5}\spadcommand{unit := point [one,one,one,zero]\free{d1 d2 }\bound{d4 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgPLCPagePatch5}
\begin{paste}{ugIntProgPLCPageFull5}{ugIntProgPLCPageEmpty5}
\pastebutton{ugIntProgPLCPageFull5}{\hidepaste}
\tab{5}\spadcommand{line := [origin, unit]\free{d3 d4 }\bound{d5 }}
\indentrel{3}\begin{verbatim}
   (5)  [[0.0,0.0,0.0,0.0],[1.0,1.0,1.0,0.0]]
                           Type: List Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgPLCPageEmpty5}
\begin{paste}{ugIntProgPLCPageEmpty5}{ugIntProgPLCPagePatch5}
\pastebutton{ugIntProgPLCPageEmpty5}{\showpaste}
\tab{5}\spadcommand{line := [origin, unit]\free{d3 d4 }\bound{d5 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgPLCPagePatch6}
\begin{paste}{ugIntProgPLCPageFull6}{ugIntProgPLCPageEmpty6}
\pastebutton{ugIntProgPLCPageFull6}{\hidepaste}
\tab{5}\spadcommand{)read arrows\bound{v1 }}
\indentrel{3}\begin{verbatim}
   (6)  2.8274333882308138
                                      Type: DoubleFloat
   (7)  0.20000000000000001
                                      Type: DoubleFloat
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgPLCPageEmpty6}
\begin{paste}{ugIntProgPLCPageEmpty6}{ugIntProgPLCPagePatch6}
\pastebutton{ugIntProgPLCPageEmpty6}{\showpaste}
\tab{5}\spadcommand{)read arrows\bound{v1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgPLCPagePatch7}
\begin{paste}{ugIntProgPLCPageFull7}{ugIntProgPLCPageEmpty7}
\pastebutton{ugIntProgPLCPageFull7}{\hidepaste}
\tab{5}\spadcommand{arrow := makeArrow(origin,unit)\bound{v2 }\free{v1 d3 d4 }}
\indentrel{3}\begin{verbatim}
   (9)
   [
     [[0.0,0.0,0.0,0.0], [1.0,1.0,1.0,0.0],

       [0.69134628604607973, 0.842733077659504,
        0.80000000000000004, 0.0]
       ]
     ,

     [[1.0,1.0,1.0,0.0],

       [0.842733077659504, 0.69134628604607973,
        0.80000000000000004, 0.0]
       ]
     ]
                      Type: List List Point DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgPLCPageEmpty7}
\begin{paste}{ugIntProgPLCPageEmpty7}{ugIntProgPLCPagePatch7}
\pastebutton{ugIntProgPLCPageEmpty7}{\showpaste}
\tab{5}\spadcommand{arrow := makeArrow(origin,unit)\bound{v2 }\free{v1 d3 d4 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgPLCPagePatch8}
\begin{paste}{ugIntProgPLCPageFull8}{ugIntProgPLCPageEmpty8}
\pastebutton{ugIntProgPLCPageFull8}{\hidepaste}
\tab{5}\spadcommand{sp := createThreeSpace()\bound{c1 }}
\indentrel{3}\begin{verbatim}
   (10)  3-Space with 0 components
                           Type: ThreeSpace DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgPLCPageEmpty8}
\begin{paste}{ugIntProgPLCPageEmpty8}{ugIntProgPLCPagePatch8}
\pastebutton{ugIntProgPLCPageEmpty8}{\showpaste}
\tab{5}\spadcommand{sp := createThreeSpace()\bound{c1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgPLCPagePatch9}
\begin{paste}{ugIntProgPLCPageFull9}{ugIntProgPLCPageEmpty9}
\pastebutton{ugIntProgPLCPageFull9}{\hidepaste}
\tab{5}\spadcommand{for a in arrow repeat sp := curve(sp,a)\bound{v3 }\free{v2 }\free{c1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgPLCPageEmpty9}
\begin{paste}{ugIntProgPLCPageEmpty9}{ugIntProgPLCPagePatch9}
\pastebutton{ugIntProgPLCPageEmpty9}{\showpaste}
\tab{5}\spadcommand{for a in arrow repeat sp := curve(sp,a)\bound{v3 }\free{v2 }\free{c1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgPLCPagePatch10}
\begin{paste}{ugIntProgPLCPageFull10}{ugIntProgPLCPageEmpty10}
\pastebutton{ugIntProgPLCPageFull10}{\hidepaste}
\tab{5}\spadgraph{vp := makeViewport3D(sp,"Arrow")\bound{v4 }\free{v3 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/ugintprogplcpage10.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/ugintprogplcpage10}}
\end{paste}\end{patch}

\begin{patch}{ugIntProgPLCPageEmpty10}
\begin{paste}{ugIntProgPLCPageEmpty10}{ugIntProgPLCPagePatch10}
\pastebutton{ugIntProgPLCPageEmpty10}{\showpaste}
\tab{5}\spadgraph{vp := makeViewport3D(sp,"Arrow")\bound{v4 }\free{v3 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgPLCPagePatch11}
\begin{paste}{ugIntProgPLCPageFull11}{ugIntProgPLCPageEmpty11}
\pastebutton{ugIntProgPLCPageFull11}{\hidepaste}
\tab{5}\spadcommand{rotate(vp,200,-60)\bound{v5 }\free{v4 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgPLCPageEmpty11}
\begin{paste}{ugIntProgPLCPageEmpty11}{ugIntProgPLCPagePatch11}
\pastebutton{ugIntProgPLCPageEmpty11}{\showpaste}
\tab{5}\spadcommand{rotate(vp,200,-60)\bound{v5 }\free{v4 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntProgColorArrPage}{ug10.ht}{A Bouquet of Arrows}
\begin{chunk}{ug10.ht}
\begin{page}{ugIntProgColorArrPage}{10.5. A Bouquet of Arrows}
\beginscroll

Let's draw a ``bouquet'' of arrows.
Each arrow is identical. The arrowheads are
uniformly placed on a circle parallel to the \smath{xy}-plane.
Thus the position of each arrow differs only
by the angle \texht{$\theta$}{theta},
\texht{$0 \leq \theta < 2\pi$}{\spad{0 <= theta < 2*\%pi}},
between the arrow and
the \smath{x}-axis on the \smath{xy}-plane.

Our bouquet is rather special: each arrow has a different
color (which won't be evident here, unfortunately).
This is arranged by letting the color of each successive arrow be
denoted by \texht{$\theta$}{theta}.
In this way, the color of arrows ranges from red to green to violet.
Here is a program to draw a bouquet of \smath{n} arrows.

\beginImportant
  
\noindent
{\tt 1.\ \ \ drawBouquet(n,title)\ ==}\newline
{\tt 2.\ \ \ \ \ angle\ :=\ 0.0@DFLOAT}\newline
{\tt 3.\ \ \ \ \ sp\ :=\ createThreeSpace()}\newline
{\tt 4.\ \ \ \ \ for\ i\ in\ 0..n-1\ repeat}\newline
{\tt 5.\ \ \ \ \ \ \ start\ :=\ point\ 
[0.0@DFLOAT,0.0@DFLOAT,0.0@DFLOAT,angle]\ }\newline
{\tt 6.\ \ \ \ \ \ \ end\ \ \ :=\ point\ 
[cos\ angle,\ sin\ angle,\ 1.0@DFLOAT,\ angle]}\newline
{\tt 7.\ \ \ \ \ \ \ arrow\ :=\ makeArrow(start,end)}\newline
{\tt 8.\ \ \ \ \ \ \ for\ a\ in\ makeArrow(start,end)\ repeat\ }\newline
{\tt 9.\ \ \ \ \ \ \ \ \ curve(sp,a)}\newline
{\tt 10.\ \ \ \ \ \ angle\ :=\ angle\ +\ 2*\%pi/n}\newline
{\tt 11.\ \ \ \ makeViewport3D(sp,title)}\newline
\endImportant

\xtc{
Read the input file.
}{
\spadpaste{)read bouquet\bound{b1}}
}
\psXtc{
A bouquet of a dozen arrows.
}{
\graphpaste{drawBouquet(12,"A Dozen Arrows")\free{b1}}
}{
\epsffile[0 0 295 295]{../ps/bouquet.ps}
}
\ 

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntProgColorArrPagePatch1}
\begin{paste}{ugIntProgColorArrPageFull1}{ugIntProgColorArrPageEmpty1}
\pastebutton{ugIntProgColorArrPageFull1}{\hidepaste}
\tab{5}\spadcommand{)read bouquet\bound{b1 }}
\indentrel{3}\begin{verbatim}
   (1)  0.20000000000000001
                                      Type: DoubleFloat
   (2)  2.8274333882308138
                                      Type: DoubleFloat
                                             Type: Void
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgColorArrPageEmpty1}
\begin{paste}{ugIntProgColorArrPageEmpty1}{ugIntProgColorArrPagePatch1}
\pastebutton{ugIntProgColorArrPageEmpty1}{\showpaste}
\tab{5}\spadcommand{)read bouquet\bound{b1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgColorArrPagePatch2}
\begin{paste}{ugIntProgColorArrPageFull2}{ugIntProgColorArrPageEmpty2}
\pastebutton{ugIntProgColorArrPageFull2}{\hidepaste}
\tab{5}\spadgraph{drawBouquet(12,"A Dozen Arrows")\free{b1 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/ugintprogcolorarrpage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/ugintprogcolorarrpage2}}
\end{paste}\end{patch}

\begin{patch}{ugIntProgColorArrPageEmpty2}
\begin{paste}{ugIntProgColorArrPageEmpty2}{ugIntProgColorArrPagePatch2}
\pastebutton{ugIntProgColorArrPageEmpty2}{\showpaste}
\tab{5}\spadgraph{drawBouquet(12,"A Dozen Arrows")\free{b1 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntProgVecFieldsPage}{ug10.ht}{Drawing Complex Vector Fields}
\begin{chunk}{ug10.ht}
\begin{page}{ugIntProgVecFieldsPage}{10.6. Drawing Complex Vector Fields}
\beginscroll

We now put our arrows to good use drawing complex vector fields.
These vector fields give a representation of complex-valued
functions of complex variables.
Consider a Cartesian coordinate grid of points \smath{(x, y)} in
the plane, and some complex-valued function \smath{f} defined on
this grid.
At every point on this grid, compute the value of \texht{$f(x +
iy)$}{f(x + y*\%i)} and call it \smath{z}.
Since \smath{z} has both a real and imaginary value for a given
\smath{(x,y)} grid point, there are four dimensions to plot.
What do we do?
We represent the values of \smath{z} by arrows planted at each
grid point.
Each arrow represents the value of \smath{z} in polar coordinates
\texht{$(r,\theta)$}{(r, theta)}.
The length of the arrow is proportional to \smath{r}.
Its direction is given by \texht{$\theta$}{theta}.

The code for drawing vector fields is in the file {\bf vectors.input}.
We discuss its contents from top to bottom.

Before showing you the code, we have two small
matters to take care of.
First, what if the function has large spikes, say, ones that go off
to infinity?
We define a variable \spad{clipValue} for this purpose. When
\spad{r} exceeds the value of \spad{clipValue}, then the value of
\spad{clipValue} is used instead of that for \spad{r}.
For convenience, we define a function \spad{clipFun(x)} which uses
\spad{clipValue} to ``clip'' the value of \spad{x}.

%
\beginImportant
  
\noindent
{\tt 1.\ \ \ clipValue\ :\ DFLOAT\ :=\ 6}\newline
{\tt 2.\ \ \ clipFun(x)\ ==\ min(max(x,-clipValue),clipValue)}\newline
\endImportant

Notice that we identify \spad{clipValue} as a small float but do
not declare the type of the function \userfun{clipFun}.
As it turns out, \userfun{clipFun} is called with a
small float value.
This declaration ensures that \userfun{clipFun} never does a
conversion when it is called.

The second matter concerns the possible ``poles'' of a
function, the actual points where the spikes have infinite
values.
Axiom uses normal \spadtype{DoubleFloat} arithmetic  which
does not directly handle infinite values.
If your function has poles, you must adjust your step size to
avoid landing directly on them (Axiom calls \spadfun{error}
when asked to divide a value by \axiom{0}, for example).

We set the variables \spad{realSteps} and \spad{imagSteps} to
hold the number of steps taken in the real and imaginary
directions, respectively.
Most examples will have ranges centered around the origin.
To avoid a pole at the origin, the number of points is taken
to be odd.

\beginImportant
  
\noindent
{\tt 1.\ \ \ realSteps:\ INT\ :=\ 25}\newline
{\tt 2.\ \ \ imagSteps:\ INT\ :=\ 25}\newline
{\tt 3.\ \ \ )read\ arrows}\newline
\endImportant

Now define the function \userfun{drawComplexVectorField} to draw the
arrows.  It is good practice to declare the type of the main function
in the file.  This one declaration is usually sufficient to ensure
that other lower-level functions are compiled with the correct types.

\beginImportant
  
\noindent
{\tt 4.\ \ \ C\ :=\ Complex\ DoubleFloat}\newline
{\tt 5.\ \ \ S\ :=\ Segment\ DoubleFloat}\newline
{\tt 6.\ \ \ drawComplexVectorField:\ (C\ ->\ C,\ S,\ S)\ ->\ VIEW3D}\newline
\endImportant

The first argument is a function mapping complex small floats into
complex small floats.
The second and third arguments give the range of real and
imaginary values as segments like \spad{a..b}.
The result is a \threedim{} viewport.
Here is the full function definition:

\beginImportant
  
\noindent
{\tt 7.\ \ \ drawComplexVectorField(f,\ realRange,imagRange)\ ==}\newline
{\tt 8.\ \ \ \ \ delReal\ :=\ (hi(realRange)-lo(realRange))/realSteps}
\newline
{\tt 9.\ \ \ \ \ delImag\ :=\ (hi(imagRange)-lo(imagRange))/imagSteps}
\newline
{\tt 10.\ \ \ \ sp\ :=\ createThreeSpace()}\newline
{\tt 11.\ \ \ \ real\ :=\ lo(realRange)}\newline
{\tt 12.\ \ \ \ for\ i\ in\ 1..realSteps+1\ repeat}\newline
{\tt 13.\ \ \ \ \ \ imag\ :=\ lo(imagRange)}\newline
{\tt 14.\ \ \ \ \ \ for\ j\ in\ 1..imagSteps+1\ repeat}\newline
{\tt 15.\ \ \ \ \ \ \ \ z\ :=\ f\ complex(real,imag)}\newline
{\tt 16.\ \ \ \ \ \ \ \ arg\ :=\ argument\ z}\newline
{\tt 17.\ \ \ \ \ \ \ \ len\ :=\ clipFun\ sqrt\ norm\ z}\newline
{\tt 18.\ \ \ \ \ \ \ \ p1\ :=\ \ point\ 
[real,\ imag,\ 0.0@DFLOAT,\ arg]}\newline
{\tt 19.\ \ \ \ \ \ \ \ scaleLen\ :=\ delReal\ *\ len}\newline
{\tt 20.\ \ \ \ \ \ \ \ p2\ :=\ point\ 
[p1.1\ +\ scaleLen*cos(arg),}\newline
{\tt 21.\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ p1.2\ +\ 
scaleLen*sin(arg),0.0@DFLOAT,\ arg]}\newline
{\tt 22.\ \ \ \ \ \ \ \ arrow\ :=\ makeArrow(p1,\ p2)}\newline
{\tt 23.\ \ \ \ \ \ \ \ for\ a\ in\ arrow\ repeat\ curve(sp,\ a)}\newline
{\tt 24.\ \ \ \ \ \ \ \ imag\ :=\ imag\ +\ delImag}\newline
{\tt 25.\ \ \ \ \ \ real\ :=\ real\ +\ delReal}\newline
{\tt 26.\ \ \ \ makeViewport3D(sp,\ "Complex\ Vector\ Field")}\newline
\endImportant

As a first example, let us draw \spad{f(z) == sin(z)}.  There is no
need to create a user function: just pass the
\spadfunFrom{sin}{Complex DoubleFloat} from 
\spadtype{Complex DoubleFloat}.
\xtc{
Read the file.
}{
\spadpaste{)read vectors \bound{readVI}}
}
\psXtc{
Draw the complex vector field of \spad{sin(x)}.
}{
\graphpaste{drawComplexVectorField(sin,-2..2,-2..2) \free{readVI}}
}{
\epsffile[0 0 295 295]{../ps/vectorsin.ps}
}
\ 

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntProgVecFieldsPagePatch1}
\begin{paste}{ugIntProgVecFieldsPageFull1}{ugIntProgVecFieldsPageEmpty1}
\pastebutton{ugIntProgVecFieldsPageFull1}{\hidepaste}
\tab{5}\spadcommand{)read vectors\bound{readVI }}
\indentrel{3}\begin{verbatim}
   (1)  2.8274333882308138
                                      Type: DoubleFloat
   (2)  0.20000000000000001
                                      Type: DoubleFloat
                                             Type: Void
   (4)  6.0
                                      Type: DoubleFloat
                                             Type: Void
   (6)  25
                                          Type: Integer
   (7)  25
                                          Type: Integer
   (8)  Complex DoubleFloat
                                           Type: Domain
   (9)  Segment DoubleFloat
                                           Type: Domain
                                             Type: Void
                                             Type: Void
                                             Type: Void
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgVecFieldsPageEmpty1}
\begin{paste}{ugIntProgVecFieldsPageEmpty1}{ugIntProgVecFieldsPagePatch1}
\pastebutton{ugIntProgVecFieldsPageEmpty1}{\showpaste}
\tab{5}\spadcommand{)read vectors\bound{readVI }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgVecFieldsPagePatch2}
\begin{paste}{ugIntProgVecFieldsPageFull2}{ugIntProgVecFieldsPageEmpty2}
\pastebutton{ugIntProgVecFieldsPageFull2}{\hidepaste}
\tab{5}\spadgraph{drawComplexVectorField(sin,-2..2,-2..2)\free{readVI }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/ugintprogvecfieldspage2.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/ugintprogvecfieldspage2}}
\end{paste}\end{patch}

\begin{patch}{ugIntProgVecFieldsPageEmpty2}
\begin{paste}{ugIntProgVecFieldsPageEmpty2}{ugIntProgVecFieldsPagePatch2}
\pastebutton{ugIntProgVecFieldsPageEmpty2}{\showpaste}
\tab{5}\spadgraph{drawComplexVectorField(sin,-2..2,-2..2)\free{readVI }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntProgCompFunsPage}{ug10.ht}{Drawing Complex Functions}
\pageto{notitle}{ugGraphPage}
\begin{chunk}{ug10.ht}
\begin{page}{ugIntProgCompFunsPage}{10.7. Drawing Complex Functions}
\beginscroll

Here is another way to graph a complex function of complex arguments.
For each complex value \smath{z}, compute \smath{f(z)}, again
expressing the value in polar coordinates \smath{(r,\theta{})}.  We
draw the complex valued function, again considering the
\smath{(x,y)}-plane as the complex plane, using \smath{r} as the
height (or \smath{z}-coordinate) and \smath{\theta} as the color.
This is a standard plot---we learned how to do this in
\downlink{``Graphics''}{ugGraphPage} in Chapter
7\ignore{ugGraph}---but here we write a new program to
illustrate the creation of polygon meshes, or grids.

Call this function \userfun{drawComplex}.
It displays the points using the ``mesh'' of points.
The function definition is in three parts.

\beginImportant
  
\noindent
{\tt 1.\ \ \ drawComplex:\ (C\ ->\ C,\ S,\ S)\ ->\ VIEW3D}\newline
{\tt 2.\ \ \ drawComplex(f,\ realRange,\ imagRange)\ ==}\newline
{\tt 3.\ \ \ \ \ delReal\ :=\ (hi(realRange)-lo(realRange))/realSteps}
\newline
{\tt 4.\ \ \ \ \ delImag\ :=\ (hi(imagRange)-lo(imagRange))/imagSteps}
\newline
{\tt 5.\ \ \ \ \ llp:List\ List\ Point\ DFLOAT\ :=\ []}\newline
\endImportant

Variables \spad{delReal} and \spad{delImag} give the step sizes along
the real and imaginary directions as computed by the values of the
global variables \spad{realSteps} and \spad{imagSteps}.  The mesh is
represented by a list of lists of points \spad{llp}, initially empty.
Now \spad{[ ]} alone is ambiguous, so to set this initial value you
have to tell Axiom what type of empty list it is.  Next comes the loop
which builds \spad{llp}.

\beginImportant
  
\noindent
{\tt 1.\ \ \ \ \ real\ :=\ lo(realRange)}\newline
{\tt 2.\ \ \ \ \ for\ i\ in\ 1..realSteps+1\ repeat}\newline
{\tt 3.\ \ \ \ \ \ \ imag\ :=\ lo(imagRange)}\newline
{\tt 4.\ \ \ \ \ \ \ lp\ :=\ []\$(List\ Point\ DFLOAT)}\newline
{\tt 5.\ \ \ \ \ \ \ for\ j\ in\ 1..imagSteps+1\ repeat}\newline
{\tt 6.\ \ \ \ \ \ \ \ \ z\ :=\ f\ complex(real,imag)}\newline
{\tt 7.\ \ \ \ \ \ \ \ \ pt\ :=\ point\ 
[real,imag,\ clipFun\ sqrt\ norm\ z,\ }\newline
{\tt 8.\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ argument\ z]}
\newline
{\tt 9.\ \ \ \ \ \ \ \ \ lp\ :=\ cons(pt,lp)}\newline
{\tt 10.\ \ \ \ \ \ \ \ imag\ :=\ imag\ +\ delImag}\newline
{\tt 11.\ \ \ \ \ \ real\ :=\ real\ +\ delReal}\newline
{\tt 12.\ \ \ \ \ \ llp\ :=\ cons(lp,\ llp)}\newline
\endImportant

The code consists of both an inner and outer loop.  Each pass through
the inner loop adds one list \spad{lp} of points to the list of lists
of points \spad{llp}.  The elements of \spad{lp} are collected in
reverse order.

\beginImportant
  
\noindent
{\tt 13.\ \ \ \ makeViewport3D(mesh(llp),\ "Complex\ Function")}\newline
\endImportant

The operation \spadfun{mesh} then creates an object of type
\spadtype{ThreeSpace(DoubleFloat)} from the list of lists of points.
This is then passed to \spadfun{makeViewport3D} to display the
image.

Now add this function directly to your {\bf vectors.input} file and
re-read the file using \spad{)read vectors}.  We try
\userfun{drawComplex} using a user-defined function \spad{f}.

\xtc{
Read the file.
}{
\spadpaste{)read vectors \bound{readVI}}
}
\xtc{
This one has a pole at \smath{z=0}.
}{
\spadpaste{f(z) == exp(1/z)\bound{e1}}
}
\psXtc{
Draw it with an odd number of steps to avoid the pole.
}{
\graphpaste{drawComplex(f,-2..2,-2..2)\free{e1 readVI}}
}{
\epsffile[0 0 295 295]{../ps/complexexp.ps}
}
\ 

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntProgCompFunsPagePatch1}
\begin{paste}{ugIntProgCompFunsPageFull1}{ugIntProgCompFunsPageEmpty1}
\pastebutton{ugIntProgCompFunsPageFull1}{\hidepaste}
\tab{5}\spadcommand{)read vectors\bound{readVI }}
\indentrel{3}\begin{verbatim}
   (1)  2.8274333882308138
                                      Type: DoubleFloat
   (2)  0.20000000000000001
                                      Type: DoubleFloat
                                             Type: Void
   (4)  6.0
                                      Type: DoubleFloat
                                             Type: Void
   (6)  25
                                          Type: Integer
   (7)  25
                                          Type: Integer
   (8)  Complex DoubleFloat
                                           Type: Domain
   (9)  Segment DoubleFloat
                                           Type: Domain
                                             Type: Void
                                             Type: Void
                                             Type: Void
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgCompFunsPageEmpty1}
\begin{paste}{ugIntProgCompFunsPageEmpty1}{ugIntProgCompFunsPagePatch1}
\pastebutton{ugIntProgCompFunsPageEmpty1}{\showpaste}
\tab{5}\spadcommand{)read vectors\bound{readVI }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgCompFunsPagePatch2}
\begin{paste}{ugIntProgCompFunsPageFull2}{ugIntProgCompFunsPageEmpty2}
\pastebutton{ugIntProgCompFunsPageFull2}{\hidepaste}
\tab{5}\spadcommand{f(z) == exp(1/z)\bound{e1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgCompFunsPageEmpty2}
\begin{paste}{ugIntProgCompFunsPageEmpty2}{ugIntProgCompFunsPagePatch2}
\pastebutton{ugIntProgCompFunsPageEmpty2}{\showpaste}
\tab{5}\spadcommand{f(z) == exp(1/z)\bound{e1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgCompFunsPagePatch3}
\begin{paste}{ugIntProgCompFunsPageFull3}{ugIntProgCompFunsPageEmpty3}
\pastebutton{ugIntProgCompFunsPageFull3}{\hidepaste}
\tab{5}\spadgraph{drawComplex(f,-2..2,-2..2)\free{e1 readVI }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/ugintprogcompfunspage3.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/ugintprogcompfunspage3}}
\end{paste}\end{patch}

\begin{patch}{ugIntProgCompFunsPageEmpty3}
\begin{paste}{ugIntProgCompFunsPageEmpty3}{ugIntProgCompFunsPagePatch3}
\pastebutton{ugIntProgCompFunsPageEmpty3}{\showpaste}
\tab{5}\spadgraph{drawComplex(f,-2..2,-2..2)\free{e1 readVI }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntProgFunctionsPage}{ug10.ht}{Functions Producing Functions}
\pageto{notitle}{ugUserMakePage}
\begin{chunk}{ug10.ht}
\begin{page}{ugIntProgFunctionsPage}{10.8. Functions Producing Functions}
\beginscroll

In \downlink{``Making Functions from Objects''}{ugUserMakePage} in Section
6.14\ignore{ugUserMake}, you learned how to use the
operation \spadfun{function} to create a function from symbolic
formulas.  Here we introduce a similar operation which not only
creates functions, but functions from functions.

The facility we need is provided by the package
\spadtype{MakeUnaryCompiledFunction(E,S,T)}.  This package produces a
unary (one-argument) compiled function from some symbolic data
generated by a previous computation.\footnote{%
\spadtype{MakeBinaryCompiledFunction} is available for binary
functions.}  The \spad{E} tells where the symbolic data comes from;
the \spad{S} and \spad{T} give Axiom the source and target type of the
function, respectively.  The compiled function produced has type
\spadsig{\spad{S}}{\spad{T}}.  To produce a compiled function with
definition \spad{p(x) == expr}, call \spad{compiledFunction(expr, x)}
from this package.  The function you get has no name.  You must to
assign the function to the variable \spad{p} to give it that name.  %
\xtc{ Do some computation.  }{ \spadpaste{(x+1/3)**5\bound{p1}} }
\xtc{ Convert this to an anonymous function of \spad{x}.  Assign it to
the variable \spad{p} to give the function a name.  }{ \spadpaste{p :=
compiledFunction(\%,x)\$MakeUnaryCompiledFunction(POLY FRAC
INT,DFLOAT,DFLOAT)\bound{p2}\free{p1}} } \xtc{ Apply the function.  }{
\spadpaste{p(sin(1.3))\bound{p3}\free{p2}} }

For a more sophisticated application, read on.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntProgFunctionsPagePatch1}
\begin{paste}{ugIntProgFunctionsPageFull1}{ugIntProgFunctionsPageEmpty1}
\pastebutton{ugIntProgFunctionsPageFull1}{\hidepaste}
\tab{5}\spadcommand{(x+1/3)**5\bound{p1 }}
\indentrel{3}\begin{verbatim}
         5   5  4   10  3   10  2    5      1
   (1)  x  + Ä x  + ÄÄ x  + ÄÄ x  + ÄÄ x + ÄÄÄ
             3       9      27      81     243
                      Type: Polynomial Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgFunctionsPageEmpty1}
\begin{paste}{ugIntProgFunctionsPageEmpty1}{ugIntProgFunctionsPagePatch1}
\pastebutton{ugIntProgFunctionsPageEmpty1}{\showpaste}
\tab{5}\spadcommand{(x+1/3)**5\bound{p1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgFunctionsPagePatch2}
\begin{paste}{ugIntProgFunctionsPageFull2}{ugIntProgFunctionsPageEmpty2}
\pastebutton{ugIntProgFunctionsPageFull2}{\hidepaste}
\tab{5}\spadcommand{p := compiledFunction(\%,x)$MakeUnaryCompiledFunction(POLY FRAC INT,DFLOAT,DFLOAT)\bound{p2 }\free{p1 }}
\indentrel{3}\begin{verbatim}
   (2)  theMap(MKUCFUNC;unaryFunction;SM;2!0,350)
                     Type: (DoubleFloat -> DoubleFloat)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgFunctionsPageEmpty2}
\begin{paste}{ugIntProgFunctionsPageEmpty2}{ugIntProgFunctionsPagePatch2}
\pastebutton{ugIntProgFunctionsPageEmpty2}{\showpaste}
\tab{5}\spadcommand{p := compiledFunction(\%,x)$MakeUnaryCompiledFunction(POLY FRAC INT,DFLOAT,DFLOAT)\bound{p2 }\free{p1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgFunctionsPagePatch3}
\begin{paste}{ugIntProgFunctionsPageFull3}{ugIntProgFunctionsPageEmpty3}
\pastebutton{ugIntProgFunctionsPageFull3}{\hidepaste}
\tab{5}\spadcommand{p(sin(1.3))\bound{p3 }\free{p2 }}
\indentrel{3}\begin{verbatim}
   (3)  3.668751115057229
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgFunctionsPageEmpty3}
\begin{paste}{ugIntProgFunctionsPageEmpty3}{ugIntProgFunctionsPagePatch3}
\pastebutton{ugIntProgFunctionsPageEmpty3}{\showpaste}
\tab{5}\spadcommand{p(sin(1.3))\bound{p3 }\free{p2 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugIntProgNewtonPage}{ug10.ht}
{Automatic Newton Iteration Formulas}
\pageto{notitle}{MappingPackageOneXmpPage}
\begin{chunk}{ug10.ht}
\begin{page}{ugIntProgNewtonPage}
{10.9. Automatic Newton Iteration Formulas}
\beginscroll

We resume
our continuing saga of arrows and complex functions.
Suppose we want to investigate the behavior of Newton's iteration function
in the complex plane.
Given a function \smath{f}, we want to find the complex values
\smath{z} such that \smath{f(z) = 0}.

The first step is to produce a Newton iteration formula for
a given \smath{f}:
\texht{$x_{n+1} = x_n - {{f(x_n)}\over{f'(x_n)}}.$}{%
\spad{x(n+1) = x(n) - f(x(n))/f'(x(n))}.}
We represent this formula by a function \smath{g}
that performs the computation on the right-hand side, that is,
\texht{$x_{n+1} = {g}(x_n)$}{\spad{x(n+1) = g(x(n))}}.

The type \spadtype{Expression Integer} (abbreviated \spadtype{EXPR
INT}) is used to represent general symbolic expressions in
Axiom.
To make our facility as general as possible, we assume
\smath{f} has this type.
Given \smath{f}, we want
to produce a Newton iteration function \spad{g} which,
given a complex point \texht{$x_n$}{x(n)}, delivers the next
Newton iteration point \texht{$x_{n+1}$}{x(n+1)}.

This time we write an input file called {\bf newton.input}.
We need to import \spadtype{MakeUnaryCompiledFunction} (discussed
in the last section), call it with appropriate types, and then define
the function \spad{newtonStep} which references it.
Here is the function \spad{newtonStep}:

\beginImportant
  
\noindent
{\tt 1.\ \ \ C\ :=\ Complex\ DoubleFloat}\newline
{\tt 2.\ \ \ complexFunPack:=MakeUnaryCompiledFunction(EXPR\ INT,C,C)}
\newline
{\tt 3.\ \ \ }\newline
{\tt 4.\ \ \ newtonStep(f)\ ==}\newline
{\tt 5.\ \ \ \ \ fun\ \ :=\ complexNumericFunction\ f}\newline
{\tt 6.\ \ \ \ \ deriv\ :=\ complexDerivativeFunction(f,1)}\newline
{\tt 7.\ \ \ \ \ (x:C):C\ +->}\newline
{\tt 8.\ \ \ \ \ \ \ x\ -\ fun(x)/deriv(x)}\newline
{\tt 9.\ \ \ }\newline
{\tt 10.\ \ complexNumericFunction\ f\ ==}\newline
{\tt 11.\ \ \ \ v\ :=\ theVariableIn\ f}\newline
{\tt 12.\ \ \ \ compiledFunction(f,\ v)\$complexFunPack}\newline
{\tt 13.\ \ }\newline
{\tt 14.\ \ complexDerivativeFunction(f,n)\ ==}\newline
{\tt 15.\ \ \ \ v\ :=\ theVariableIn\ f}\newline
{\tt 16.\ \ \ \ df\ :=\ D(f,v,n)}\newline
{\tt 17.\ \ \ \ compiledFunction(df,\ v)\$complexFunPack}\newline
{\tt 18.\ \ }\newline
{\tt 19.\ \ theVariableIn\ f\ ==\ \ }\newline
{\tt 20.\ \ \ \ vl\ :=\ variables\ f}\newline
{\tt 21.\ \ \ \ nv\ :=\ \#\ vl}\newline
{\tt 22.\ \ \ \ nv\ >\ 1\ =>\ error\ "Expression\ is\ not\ univariate."}
\newline
{\tt 23.\ \ \ \ nv\ =\ 0\ =>\ 'x}\newline
{\tt 24.\ \ \ \ first\ vl}\newline
\endImportant

Do you see what is going on here?
A formula \spad{f} is passed into the function \userfun{newtonStep}.
First, the function turns \spad{f} into a compiled program mapping
complex numbers into complex numbers.  Next, it does the same thing
for the derivative of \spad{f}.  Finally, it returns a function which
computes a single step of Newton's iteration.

The function \userfun{complexNumericFunction} extracts the variable
from the expression \spad{f} and then turns \spad{f} into a function
which maps complex numbers into complex numbers. The function
\userfun{complexDerivativeFunction} does the same thing for the
derivative of \spad{f}.  The function \userfun{theVariableIn}
extracts the variable from the expression \spad{f}, calling the function
\spadfun{error} if \spad{f} has more than one variable.
It returns the dummy variable \spad{x} if \spad{f} has no variables.

Let's now apply \userfun{newtonStep} to the formula for computing
cube roots of two.
%
\xtc{
Read the input file with the definitions.
}{
\spadpaste{)read newton\bound{n1}}
}
\xtc{}{
\spadpaste{)read vectors \bound{n1a}}
}

\xtc{
The cube root of two.
}{
\spadpaste{f := x**3 - 2\bound{n2}\free{n1 n1a}}
}
\xtc{
Get Newton's iteration formula.
}{
\spadpaste{g := newtonStep f\bound{n3}\free{n2}}
}
\xtc{
Let \spad{a} denote the result of
applying Newton's iteration once to the complex number \spad{1 + \%i}.
}{
\spadpaste{a := g(1.0 + \%i)\bound{n4}\free{n3}}
}
\xtc{
Now apply it repeatedly. How fast does it converge?
}{
\spadpaste{[(a := g(a)) for i in 1..]\bound{n5}\free{n4}}
}
\xtc{
Check the accuracy of the last iterate.
}{
\spadpaste{a**3\bound{n6}\free{n5}}
}

In
\downlink{`MappingPackage1'}{MappingPackageOneXmpPage}
\ignore{MappingPackage1},
we show how functions can be manipulated as objects in Axiom.  A
useful operation to consider here is \spadop{*}, which means
composition.  For example \spad{g*g} causes the Newton iteration
formula to be applied twice.  Correspondingly, \spad{g**n} means to
apply the iteration formula \spad{n} times.

%
\xtc{
Apply \spad{g} twice to the point \spad{1 + \%i}.
}{
\spadpaste{(g*g) (1.0 + \%i)\bound{n10}\free{n3}}
}
\xtc{
Apply \spad{g} 11 times.
}{
\spadpaste{(g**11) (1.0 + \%i)\bound{n11}\free{n10}}
}

Look now at the vector field and surface generated
after two steps of Newton's formula for the cube root of two.
The poles in these pictures represent bad starting values, and the
flat areas are the regions of convergence to the three roots.
%
\psXtc{
The vector field.
}{
\graphpaste{drawComplexVectorField(g**3,-3..3,-3..3)\free{n3}}
}{
\epsffile[0 0 295 295]{../ps/vectorroot.ps}
}
\psXtc{
The surface.
}{
\graphpaste{drawComplex(g**3,-3..3,-3..3)\free{n3}}
}{
\epsffile[0 0 295 295]{../ps/complexroot.ps}
}
\ 

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugIntProgNewtonPagePatch1}
\begin{paste}{ugIntProgNewtonPageFull1}{ugIntProgNewtonPageEmpty1}
\pastebutton{ugIntProgNewtonPageFull1}{\hidepaste}
\tab{5}\spadcommand{)read newton\bound{n1 }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
   (2)
  MakeUnaryCompiledFunction(Expression Integer,Complex Do
  ubleFloat,Complex DoubleFloat)
                                           Type: Domain
                                             Type: Void
                                             Type: Void
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPageEmpty1}
\begin{paste}{ugIntProgNewtonPageEmpty1}{ugIntProgNewtonPagePatch1}
\pastebutton{ugIntProgNewtonPageEmpty1}{\showpaste}
\tab{5}\spadcommand{)read newton\bound{n1 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPagePatch2}
\begin{paste}{ugIntProgNewtonPageFull2}{ugIntProgNewtonPageEmpty2}
\pastebutton{ugIntProgNewtonPageFull2}{\hidepaste}
\tab{5}\spadcommand{)read vectors\bound{n1a }}
\indentrel{3}\begin{verbatim}
   (6)  2.8274333882308138
                                      Type: DoubleFloat
   (7)  0.20000000000000001
                                      Type: DoubleFloat
                                             Type: Void
   (9)  6.0
                                      Type: DoubleFloat
                                             Type: Void
   (11)  25
                                          Type: Integer
   (12)  25
                                          Type: Integer
   (13)  Complex DoubleFloat
                                           Type: Domain
   (14)  Segment DoubleFloat
                                           Type: Domain
                                             Type: Void
                                             Type: Void
                                             Type: Void
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPageEmpty2}
\begin{paste}{ugIntProgNewtonPageEmpty2}{ugIntProgNewtonPagePatch2}
\pastebutton{ugIntProgNewtonPageEmpty2}{\showpaste}
\tab{5}\spadcommand{)read vectors\bound{n1a }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPagePatch3}
\begin{paste}{ugIntProgNewtonPageFull3}{ugIntProgNewtonPageEmpty3}
\pastebutton{ugIntProgNewtonPageFull3}{\hidepaste}
\tab{5}\spadcommand{f := x**3 - 2\bound{n2 }\free{n1 n1a }}
\indentrel{3}\begin{verbatim}
          3
   (19)  x  - 2
                               Type: Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPageEmpty3}
\begin{paste}{ugIntProgNewtonPageEmpty3}{ugIntProgNewtonPagePatch3}
\pastebutton{ugIntProgNewtonPageEmpty3}{\showpaste}
\tab{5}\spadcommand{f := x**3 - 2\bound{n2 }\free{n1 n1a }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPagePatch4}
\begin{paste}{ugIntProgNewtonPageFull4}{ugIntProgNewtonPageEmpty4}
\pastebutton{ugIntProgNewtonPageFull4}{\hidepaste}
\tab{5}\spadcommand{g := newtonStep f\bound{n3 }\free{n2 }}
\indentrel{3}\begin{verbatim}
   (20)  theMap(LAMBDA_f3lkwh_704,484)
     Type: (Complex DoubleFloat -> Complex DoubleFloat)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPageEmpty4}
\begin{paste}{ugIntProgNewtonPageEmpty4}{ugIntProgNewtonPagePatch4}
\pastebutton{ugIntProgNewtonPageEmpty4}{\showpaste}
\tab{5}\spadcommand{g := newtonStep f\bound{n3 }\free{n2 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPagePatch5}
\begin{paste}{ugIntProgNewtonPageFull5}{ugIntProgNewtonPageEmpty5}
\pastebutton{ugIntProgNewtonPageFull5}{\hidepaste}
\tab{5}\spadcommand{a := g(1.0 + \%i)\bound{n4 }\free{n3 }}
\indentrel{3}\begin{verbatim}
   (21)  0.66666666666666674 + 0.33333333333333337%i
                              Type: Complex DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPageEmpty5}
\begin{paste}{ugIntProgNewtonPageEmpty5}{ugIntProgNewtonPagePatch5}
\pastebutton{ugIntProgNewtonPageEmpty5}{\showpaste}
\tab{5}\spadcommand{a := g(1.0 + \%i)\bound{n4 }\free{n3 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPagePatch6}
\begin{paste}{ugIntProgNewtonPageFull6}{ugIntProgNewtonPageEmpty6}
\pastebutton{ugIntProgNewtonPageFull6}{\hidepaste}
\tab{5}\spadcommand{[(a := g(a)) for i in 1..]\bound{n5 }\free{n4 }}
\indentrel{3}\begin{verbatim}
   (22)
   [1.1644444444444444 - 0.73777777777777775%i,
    0.92614004697164776 - 0.17463006425584393%i,
    1.3164444838140228 + 0.15690694583015852%i,
    1.2462991025761463 + 0.015454763610132094%i,
    1.2598725296532081 - 0.00033827162059311272%i,
    1.259920960928212 + 2.6023534653422681e-08%i,
    1.259921049894879 - 3.6751942591616685e-15%i,
    1.2599210498948732 - 3.3132158019282496e-29%i,
    1.2599210498948732 - 5.6051938572992683e-45%i,
    1.2599210498948732, ...]
                       Type: Stream Complex DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPageEmpty6}
\begin{paste}{ugIntProgNewtonPageEmpty6}{ugIntProgNewtonPagePatch6}
\pastebutton{ugIntProgNewtonPageEmpty6}{\showpaste}
\tab{5}\spadcommand{[(a := g(a)) for i in 1..]\bound{n5 }\free{n4 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPagePatch7}
\begin{paste}{ugIntProgNewtonPageFull7}{ugIntProgNewtonPageEmpty7}
\pastebutton{ugIntProgNewtonPageFull7}{\hidepaste}
\tab{5}\spadcommand{a**3\bound{n6 }\free{n5 }}
\indentrel{3}\begin{verbatim}
   (23)  2.0
                              Type: Complex DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPageEmpty7}
\begin{paste}{ugIntProgNewtonPageEmpty7}{ugIntProgNewtonPagePatch7}
\pastebutton{ugIntProgNewtonPageEmpty7}{\showpaste}
\tab{5}\spadcommand{a**3\bound{n6 }\free{n5 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPagePatch8}
\begin{paste}{ugIntProgNewtonPageFull8}{ugIntProgNewtonPageEmpty8}
\pastebutton{ugIntProgNewtonPageFull8}{\hidepaste}
\tab{5}\spadcommand{(g*g) (1.0 + \%i)\bound{n10 }\free{n3 }}
\indentrel{3}\begin{verbatim}
   (24)  1.1644444444444444 - 0.73777777777777775%i
                              Type: Complex DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPageEmpty8}
\begin{paste}{ugIntProgNewtonPageEmpty8}{ugIntProgNewtonPagePatch8}
\pastebutton{ugIntProgNewtonPageEmpty8}{\showpaste}
\tab{5}\spadcommand{(g*g) (1.0 + \%i)\bound{n10 }\free{n3 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPagePatch9}
\begin{paste}{ugIntProgNewtonPageFull9}{ugIntProgNewtonPageEmpty9}
\pastebutton{ugIntProgNewtonPageFull9}{\hidepaste}
\tab{5}\spadcommand{(g**11) (1.0 + \%i)\bound{n11 }\free{n10 }}
\indentrel{3}\begin{verbatim}
   (25)  1.2599210498948732
                              Type: Complex DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPageEmpty9}
\begin{paste}{ugIntProgNewtonPageEmpty9}{ugIntProgNewtonPagePatch9}
\pastebutton{ugIntProgNewtonPageEmpty9}{\showpaste}
\tab{5}\spadcommand{(g**11) (1.0 + \%i)\bound{n11 }\free{n10 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPagePatch10}
\begin{paste}{ugIntProgNewtonPageFull10}{ugIntProgNewtonPageEmpty10}
\pastebutton{ugIntProgNewtonPageFull10}{\hidepaste}
\tab{5}\spadgraph{drawComplexVectorField(g**3,-3..3,-3..3)\free{n3 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/ugintprognewtonpage10.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/ugintprognewtonpage10}}
\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPageEmpty10}
\begin{paste}{ugIntProgNewtonPageEmpty10}{ugIntProgNewtonPagePatch10}
\pastebutton{ugIntProgNewtonPageEmpty10}{\showpaste}
\tab{5}\spadgraph{drawComplexVectorField(g**3,-3..3,-3..3)\free{n3 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPagePatch11}
\begin{paste}{ugIntProgNewtonPageFull11}{ugIntProgNewtonPageEmpty11}
\pastebutton{ugIntProgNewtonPageFull11}{\hidepaste}
\tab{5}\spadgraph{drawComplex(g**3,-3..3,-3..3)\free{n3 }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/ugintprognewtonpage11.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/ugintprognewtonpage11}}
\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPageEmpty11}
\begin{paste}{ugIntProgNewtonPageEmpty11}{ugIntProgNewtonPagePatch11}
\pastebutton{ugIntProgNewtonPageEmpty11}{\showpaste}
\tab{5}\spadgraph{drawComplex(g**3,-3..3,-3..3)\free{n3 }}
\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPagePatch12}
\begin{paste}{ugIntProgNewtonPageFull12}{ugIntProgNewtonPageEmpty12}
\pastebutton{ugIntProgNewtonPageFull12}{\hidepaste}
\tab{5}\spadcommand{all}
\indentrel{3}\begin{verbatim}
   (28)  all
                                     Type: Variable all
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugIntProgNewtonPageEmpty12}
\begin{paste}{ugIntProgNewtonPageEmpty12}{ugIntProgNewtonPagePatch12}
\pastebutton{ugIntProgNewtonPageEmpty12}{\showpaste}
\tab{5}\spadcommand{all}
\end{paste}\end{patch}

\end{chunk}
\chapter{Users Guide Chapter 11 (ug11.ht)}
\pagetitle{ugPackagesPage}{ug11.ht}{Packages}
\pageto{notitle}{ugIntProgPage}
\pageto{notitle}{ugIntProgPage}
\pageto{notitle}{ugPackagesNamesPage}
\pageto{notitle}{ugPackagesSyntaxPage}
\pageto{notitle}{ugPackagesAbstractPage}
\pageto{notitle}{ugPackagesCapsulesPage}
\pageto{notitle}{ugPackagesInputFilesPage}
\pageto{notitle}{ugPackagesPackagesPage}
\pageto{notitle}{ugPackagesParametersPage}
\pageto{notitle}{ugPackagesCondsPage}
\pageto{notitle}{ugPackagesCompilingPage}
\pageto{notitle}{ugPackagesHowPage}
\begin{chunk}{ug11.ht}
\begin{page}{ugPackagesPage}{11. Packages}
\beginscroll

Packages provide the bulk of
Axiom's algorithmic library, from numeric packages for computing
special functions to symbolic facilities for
differential equations, symbolic integration, and limits.

In \downlink{``Interactive Programming''}{ugIntProgPage} in Chapter
10\ignore{ugIntProg}, we developed several useful
functions for drawing vector fields and complex functions.  We now
show you how you can add these functions to the Axiom library to make
them available for general use.

The way we created the functions in
\downlink{``Interactive Programming''}{ugIntProgPage} in Chapter
10\ignore{ugIntProg} is typical of how you, as an
advanced Axiom user, may interact with Axiom.  You have an
application.  You go to your editor and create an input file defining
some functions for the application.  Then you run the file and try the
functions.  Once you get them all to work, you will often want to
extend them, add new features, perhaps write additional functions.

Eventually, when you have a useful set of functions for your
application, you may want to add them to your local Axiom library.  To
do this, you embed these function definitions in a package and add
that package to the library.

To introduce new packages, categories, and domains into the system,
you need to use the Axiom compiler to convert the constructors into
executable machine code.  An existing compiler in Axiom is available
on an ``as-is'' basis.  A new, faster compiler will be available in
version 2.0 of Axiom.

\beginImportant
  
\noindent
\label{pak-cdraw}
{\tt 1.\ \ \ C\ \ \ \ \ \ ==>\ Complex\ DoubleFloat}\newline
{\tt 2.\ \ \ S\ \ \ \ \ \ ==>\ Segment\ DoubleFloat}\newline
{\tt 3.\ \ \ INT\ \ \ \ ==>\ Integer}\newline
{\tt 4.\ \ \ DFLOAT\ ==>\ DoubleFloat}\newline
{\tt 5.\ \ \ VIEW3D\ ==>\ ThreeDimensionalViewport}\newline
{\tt 6.\ \ \ CURVE\ \ ==>\ List\ List\ Point\ DFLOAT}\newline
{\tt 7.\ \ \ }\newline
{\tt 8.\ \ \ )abbrev\ package\ DRAWCX\ DrawComplex}\newline
{\tt 9.\ \ \ DrawComplex():\ Exports\ ==\ Implementation\ where}\newline
{\tt 10.\ \ }\newline
{\tt 11.\ \ \ \ Exports\ ==\ with}\newline
{\tt 12.\ \ \ \ \ \ drawComplex:\ (C\ ->\ C,S,S,Boolean)\ ->\ VIEW3D}\newline
{\tt 13.\ \ \ \ \ \ 
drawComplexVectorField:\ (C\ ->\ C,S,S)\ ->\ VIEW3D}\newline
{\tt 14.\ \ \ \ \ \ setRealSteps:\ INT\ ->\ INT}\newline
{\tt 15.\ \ \ \ \ \ setImagSteps:\ INT\ ->\ INT}\newline
{\tt 16.\ \ \ \ \ \ setClipValue:\ DFLOAT->\ DFLOAT}\newline
{\tt 17.\ \ }\newline
{\tt 18.\ \ \ \ Implementation\ ==\ add}\newline
{\tt 19.\ \ \ \ \ \ arrowScale\ :\ DFLOAT\ :=\ (0.2)::DFLOAT\ --relative\ size}\newline
{\tt 20.\ \ \ \ \ \ 
arrowAngle\ :\ DFLOAT\ :=\ pi()-pi()/(20::DFLOAT)}\newline
{\tt 21.\ \ \ \ \ \ 
realSteps\ \ :\ INT\ :=\ 11\ --\#\ real\ steps}\newline
{\tt 22.\ \ \ \ \ \ 
imagSteps\ \ :\ INT\ :=\ 11\ --\#\ imaginary\ steps}\newline
{\tt 23.\ \ \ \ \ \ 
clipValue\ \ :\ DFLOAT\ \ :=\ 10::DFLOAT\ --maximum\ vector\ length}\newline
{\tt 24.\ \ }\newline
{\tt 25.\ \ \ \ \ \ setRealSteps(n)\ ==\ realSteps\ :=\ n}\newline
{\tt 26.\ \ \ \ \ \ setImagSteps(n)\ ==\ imagSteps\ :=\ n}\newline
{\tt 27.\ \ \ \ \ \ setClipValue(c)\ ==\ clipValue\ :=\ c}\newline
{\tt 28.\ \ }\newline
{\tt 29.\ \ \ \ \ \ 
clipFun:\ DFLOAT\ ->\ DFLOAT\ --Clip\ large\ magnitudes.}\newline
{\tt 30.\ \ \ \ \ \ 
clipFun(x)\ ==\ min(max(x,\ -clipValue),\ clipValue)}\newline
{\tt 31.\ \ }\newline
{\tt 32.\ \ \ \ \ \ 
makeArrow:\ (Point\ DFLOAT,Point\ DFLOAT,DFLOAT,DFLOAT)\ ->\ CURVE}\newline
{\tt 33.\ \ \ \ \ \ makeArrow(p1,\ p2,\ len,\ arg)\ ==\ ...}\newline
{\tt 34.\ \ }\newline
{\tt 35.\ \ \ \ \ \ 
drawComplex(f,\ realRange,\ imagRange,\ arrows?)\ ==\ ...}\newline
\caption{The DrawComplex package.}\label{fig-pak-cdraw}
\endImportant

\beginmenu
\menudownlink{{11.1. Names, Abbreviations, and File Structure}}
{ugPackagesNamesPage}
\menudownlink{{11.2. Syntax}}{ugPackagesSyntaxPage}
\menudownlink{{11.3. Abstract Datatypes}}{ugPackagesAbstractPage}
\menudownlink{{11.4. Capsules}}{ugPackagesCapsulesPage}
\menudownlink{{11.5. Input Files vs. Packages}}{ugPackagesInputFilesPage}
\menudownlink{{11.6. Compiling Packages}}{ugPackagesPackagesPage}
\menudownlink{{11.7. Parameters}}{ugPackagesParametersPage}
\menudownlink{{11.8. Conditionals}}{ugPackagesCondsPage}
\menudownlink{{11.9. Testing}}{ugPackagesCompilingPage}
\menudownlink{{11.10. How Packages Work}}{ugPackagesHowPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugPackagesNamesPage}{ug11.ht}
{Names, Abbreviations, and File Structure}
\pageto{notitle}{ugIntProgPage}
\pageto{notitle}{ugTypesWritingAbbrPage}
\begin{chunk}{ug11.ht}
\begin{page}{ugPackagesNamesPage} 
{11.1. Names, Abbreviations, and File Structure} 
\beginscroll 
% 

Each package has a name and an abbreviation.  For a package of the
complex draw functions from
\downlink{``Interactive Programming''}{ugIntProgPage} in Chapter
10\ignore{ugIntProg}, we choose the name
\nonLibAxiomType{DrawComplex} and abbreviation
\nonLibAxiomType{DRAWCX}.\footnote{An abbreviation can be any string
of between two and seven capital letters and digits, beginning with a
letter.  See
\downlink{``Abbreviations''}{ugTypesWritingAbbrPage} in
Section 2.5.5\ignore{ugTypesWritingAbbr} for more
information.}  To be sure that you have not chosen a name or
abbreviation already used by the system, issue the system command
\spadcmd{)show} for both the name and the abbreviation.

Once you have named the package and its abbreviation, you can choose
any new filename you like with extension ``{\bf \spadFileExt{}}'' to
hold the definition of your package.  We choose the name {\bf
drawpak\spadFileExt{}}.  If your application involves more than one
package, you can put them all in the same file.  Axiom assumes no
relationship between the name of a library file, and the name or
abbreviation of a package.

Near the top of the ``{\bf \spadFileExt{}}'' file, list all the
abbreviations for the packages using \spadcmd{)abbrev}, each command
beginning in column one.  Macros giving names to Axiom expressions can
also be placed near the top of the file.  The macros are only usable
from their point of definition until the end of the file.

Consider the definition of
\nonLibAxiomType{DrawComplex} in Figure \ref{fig-pak-cdraw}.
After the macro
definition
\begin{verbatim}
S      ==> Segment DoubleFloat
\end{verbatim}
the name
{\tt S} can be used in the file as a
shorthand for \axiomType{Segment DoubleFloat}.
\footnote{The interpreter also allows
{\tt macro} for macro definitions.}
The abbreviation command for the package
\begin{verbatim}
)abbrev package DRAWCX DrawComplex
\end{verbatim}
is given after the macros (although it could precede them).

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugPackagesSyntaxPage}{ug11.ht}{Syntax}
\begin{chunk}{ug11.ht}
\begin{page}{ugPackagesSyntaxPage}{11.2. Syntax}
\beginscroll

The definition of a package has the syntax:
\centerline{{\frenchspacing{\it PackageForm {\tt :} 
Exports\quad{\tt ==}\quad Implementation}}} 
The syntax for defining a package
constructor is the same as that for defining any function in Axiom.
In practice, the definition extends over many lines so that this
syntax is not practical.  Also, the type of a package is expressed by
the operator \axiom{with} \spadkey{with} followed by an explicit list
of operations.  A preferable way to write the definition of a package
is with a \axiom{where} \spadkey{where} expression:

\beginImportant
The definition of a package usually has the form: \newline
{\tt%
{\it PackageForm} : Exports  ==  Implementation where \newline
\texht{\hspace*{.75pc}}{\tab{3}} {\it optional type declarations}\newline
\texht{\hspace*{.75pc}}{\tab{3}} Exports  ==   with \newline
\texht{\hspace*{2.0pc}}{\tab{6}}   {\it list of exported operations}\newline
\texht{\hspace*{.75pc}}{\tab{3}} Implementation == add \newline
\texht{\hspace*{2.0pc}}{\tab{6}}   
{\it list of function definitions for exported operations}
}
\endImportant

The \axiomType{DrawComplex} package takes no parameters and exports five
operations, each a separate item of a \spadgloss{pile}.
Each operation is described as a \spadgloss{declaration}: a name, followed
by a colon (\axiomSyntax{:}), followed by the type of the operation.
All operations have types expressed as \spadglossSee{mappings}{mapping} with
the syntax
\centerline{{{\it}}
\centerline{{source\quad{\tt ->}\quad target}}
\centerline{{}}}

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugPackagesAbstractPage}{ug11.ht}{Abstract Datatypes}
\pageto{notitle}{ugIntProgCompFunsPage}
\begin{chunk}{ug11.ht}
\begin{page}{ugPackagesAbstractPage}{11.3. Abstract Datatypes}
\beginscroll

A constructor as defined in Axiom is called an \spadgloss{abstract
datatype} in the computer science literature.  Abstract datatypes
separate ``specification'' (what operations are provided) from
``implementation'' (how the operations are implemented).  The {\tt
Exports} (specification) part of a constructor is said to be
``public'' (it provides the user interface to the package) whereas the
{\tt Implementation} part is ``private'' (information here is
effectively hidden---programs cannot take advantage of it).

The {\tt Exports} part specifies what operations the package provides
to users.  As an author of a package, you must ensure that the {\tt
Implementation} part provides a function for each operation in the
{\tt Exports} part.\footnote{The \spadtype{DrawComplex} package
enhances the facility described in
\downlink{``Drawing Complex Functions''}{ugIntProgCompFunsPage} in
Chapter 10.7\ignore{ugIntProgCompFuns} by allowing
a complex function to have arrows emanating from the surface to
indicate the direction of the complex argument.}

An important difference between interactive programming and the use of
packages is in the handling of global variables such as
\axiom{realSteps} and \axiom{imagSteps}.  In interactive programming,
you simply change the values of variables by \spadgloss{assignment}.
With packages, such variables are local to the package---their values
can only be set using functions exported by the package.  In our
example package, we provide two functions \fakeAxiomFun{setRealSteps}
and \fakeAxiomFun{setImagSteps} for this purpose.

Another local variable is \axiom{clipValue} which can be changed using
the exported operation \fakeAxiomFun{setClipValue}.  This value is
referenced by the internal function \fakeAxiomFun{clipFun} that
decides whether to use the computed value of the function at a point
or, if the magnitude of that value is too large, the value assigned to
\axiom{clipValue} (with the appropriate sign).

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugPackagesCapsulesPage}{ug11.ht}{Capsules}
\begin{chunk}{ug11.ht}
\begin{page}{ugPackagesCapsulesPage}{11.4. Capsules}
\beginscroll
%
The part to the right of {\tt add} in the {\tt Implementation}
\spadkey{add}
part of the definition is called a \spadgloss{capsule}.
The purpose of a capsule is:
\indent{4}
\beginitems
\item[-] to define a function for each exported operation, and
\item[-] to define a \spadgloss{local environment} 
for these functions to run.
\enditems
\indent{0}

What is a local environment?
First, what is an environment?
Think of the capsule as an input file that Axiom reads from top to
bottom.
Think of the input file as having a \axiom{)clear all} at the top
so that initially no variables or functions are defined.
When this file is read, variables such as \axiom{realSteps} and
\axiom{arrowSize} in \nonLibAxiomType{DrawComplex} are set to initial 
values. Also, all the functions defined in the capsule are compiled.
These include those that are exported (like \axiom{drawComplex}), and
those that are not (like \axiom{makeArrow}).
At the end, you get a set of name-value pairs:
variable names (like \axiom{realSteps} and \axiom{arrowSize})
are paired with assigned values, while
operation names (like \axiom{drawComplex} and \axiom{makeArrow})
are paired with function values.

This set of name-value pairs is called an \spadgloss{environment}.
Actually, we call this environment the ``initial environment'' of a
package: it is the environment that exists immediately after the
package is first built.  Afterwards, functions of this capsule can
access or reset a variable in the environment.  The environment is
called {\it local} since any changes to the value of a variable in
this environment can be seen {\it only} by these functions.

Only the functions from the package can change the variables in the
local environment.  When two functions are called successively from a
package, any changes caused by the first function called are seen by
the second.

Since the environment is local to the package, its names don't get
mixed up with others in the system or your workspace.  If you happen
to have a variable called \axiom{realSteps} in your workspace, it does
not affect what the \nonLibAxiomType{DrawComplex} functions do in any
way.

The functions in a package are compiled into machine code.  Unlike
function definitions in input files that may be compiled repeatedly as
you use them with varying argument types, functions in packages have a
unique type (generally parameterized by the argument parameters of a
package) and a unique compilation residing on disk.

The capsule itself is turned into a compiled function.  This so-called
{\it capsule function} is what builds the initial environment spoken
of above.  If the package has arguments (see below), then each call to
the package constructor with a distinct pair of arguments builds a
distinct package, each with its own local environment.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugPackagesInputFilesPage}{ug11.ht}{Input Files vs. Packages}
\begin{chunk}{ug11.ht}
\begin{page}{ugPackagesInputFilesPage}{11.5. Input Files vs. Packages}
\beginscroll
%
A good question at this point would be 
``Is writing a package more difficult than writing an input file?''

The programs in input files are designed for flexibility and
ease-of-use.  Axiom can usually work out all of your types as it reads
your program and does the computations you request.  Let's say that
you define a one-argument function without giving its type.  When you
first apply the function to a value, this value is understood by Axiom
as identifying the type for the argument parameter.  Most of the time
Axiom goes through the body of your function and figures out the
target type that you have in mind.  Axiom sometimes fails to get it
right.  Then---and only then---do you need a declaration to tell Axiom
what type you want.

Input files are usually written to be read by Axiom---and by you.
Without suitable documentation and declarations, your input files
are likely incomprehensible to a colleague---and to you some
months later!

Packages are designed for legibility, as well as run-time efficiency.
There are few new concepts you need to learn to write
packages. Rather, you just have to be explicit about types and type
conversions.  The types of all functions are pre-declared so that
Axiom---and the reader--- knows precisely what types of arguments can
be passed to and from the functions (certainly you don't want a
colleague to guess or to have to work this out from context!).  The
types of local variables are also declared.  Type conversions are
explicit, never automatic.\footnote{There is one exception to this
rule: conversions from a subdomain to a domain are automatic.  After
all, the objects both have the domain as a common type.}

In summary, packages are more tedious to write than input files.  When
writing input files, you can casually go ahead, giving some facts now,
leaving others for later.  Writing packages requires forethought, care
and discipline.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugPackagesPackagesPage}{ug11.ht}{Compiling Packages}
\begin{chunk}{ug11.ht}
\begin{page}{ugPackagesPackagesPage}{11.6. Compiling Packages}
\beginscroll
%

Once you have defined the package \nonLibAxiomType{DrawComplex}, you
need to compile and test it.  To compile the package, issue the system
command \spadcmd{)compile drawpak}.  Axiom reads the file {\bf
drawpak\spadFileExt{}} and compiles its contents into machine binary.
If all goes well, the file {\bf DRAWCX.nrlib} is created in your local
directory for the package.  To test the package, you must load the
package before trying an operation.

\nullXtc{
Compile the package.
}{
\spadpaste{)compile drawpak}
}
\xtc{
Expose the package.
}{
\spadpaste{)expose DRAWCX \bound{dp}}
}
\xtc{
Use an odd step size to avoid
a pole at the origin.
}{
\spadpaste{setRealSteps 51 \free{dp}\bound{srs}}
}
\xtc{
}{
\spadpaste{setImagSteps 51 \free{dp}\bound{scs}}
}
\xtc{
Define \userfun{f} to be the Gamma function.
}{
\spadpaste{f(z) == Gamma(z) \bound{f}}
}
\xtc{
Clip values of function with magnitude larger than 7.
}{
\spadpaste{setClipValue 7}
}
\psXtc{
Draw the \spadfun{Gamma} function.
}{
\graphpaste{drawComplex(f,-\%pi..\%pi,-\%pi..\%pi, false) \free{srs scs f}}
}{
\epsffile[0 0 300 300]{../ps/3dgamma11.ps}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugPackagesPackagesPagePatch1}
\begin{paste}{ugPackagesPackagesPageFull1}{ugPackagesPackagesPageEmpty1}
\pastebutton{ugPackagesPackagesPageFull1}{\hidepaste}
\tab{5}\spadcommand{)compile drawpak}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugPackagesPackagesPageEmpty1}
\begin{paste}{ugPackagesPackagesPageEmpty1}{ugPackagesPackagesPagePatch1}
\pastebutton{ugPackagesPackagesPageEmpty1}{\showpaste}
\tab{5}\spadcommand{)compile drawpak}
\end{paste}\end{patch}

\begin{patch}{ugPackagesPackagesPagePatch2}
\begin{paste}{ugPackagesPackagesPageFull2}{ugPackagesPackagesPageEmpty2}
\pastebutton{ugPackagesPackagesPageFull2}{\hidepaste}
\tab{5}\spadcommand{)expose DRAWCX\bound{dp }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugPackagesPackagesPageEmpty2}
\begin{paste}{ugPackagesPackagesPageEmpty2}{ugPackagesPackagesPagePatch2}
\pastebutton{ugPackagesPackagesPageEmpty2}{\showpaste}
\tab{5}\spadcommand{)expose DRAWCX\bound{dp }}
\end{paste}\end{patch}

\begin{patch}{ugPackagesPackagesPagePatch3}
\begin{paste}{ugPackagesPackagesPageFull3}{ugPackagesPackagesPageEmpty3}
\pastebutton{ugPackagesPackagesPageFull3}{\hidepaste}
\tab{5}\spadcommand{setRealSteps 51\free{dp }\bound{srs }}
\indentrel{3}\begin{verbatim}
   (1)  51
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugPackagesPackagesPageEmpty3}
\begin{paste}{ugPackagesPackagesPageEmpty3}{ugPackagesPackagesPagePatch3}
\pastebutton{ugPackagesPackagesPageEmpty3}{\showpaste}
\tab{5}\spadcommand{setRealSteps 51\free{dp }\bound{srs }}
\end{paste}\end{patch}

\begin{patch}{ugPackagesPackagesPagePatch4}
\begin{paste}{ugPackagesPackagesPageFull4}{ugPackagesPackagesPageEmpty4}
\pastebutton{ugPackagesPackagesPageFull4}{\hidepaste}
\tab{5}\spadcommand{setImagSteps 51\free{dp }\bound{scs }}
\indentrel{3}\begin{verbatim}
   (2)  51
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugPackagesPackagesPageEmpty4}
\begin{paste}{ugPackagesPackagesPageEmpty4}{ugPackagesPackagesPagePatch4}
\pastebutton{ugPackagesPackagesPageEmpty4}{\showpaste}
\tab{5}\spadcommand{setImagSteps 51\free{dp }\bound{scs }}
\end{paste}\end{patch}

\begin{patch}{ugPackagesPackagesPagePatch5}
\begin{paste}{ugPackagesPackagesPageFull5}{ugPackagesPackagesPageEmpty5}
\pastebutton{ugPackagesPackagesPageFull5}{\hidepaste}
\tab{5}\spadcommand{f(z) == Gamma(z)\bound{f }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugPackagesPackagesPageEmpty5}
\begin{paste}{ugPackagesPackagesPageEmpty5}{ugPackagesPackagesPagePatch5}
\pastebutton{ugPackagesPackagesPageEmpty5}{\showpaste}
\tab{5}\spadcommand{f(z) == Gamma(z)\bound{f }}
\end{paste}\end{patch}

\begin{patch}{ugPackagesPackagesPagePatch6}
\begin{paste}{ugPackagesPackagesPageFull6}{ugPackagesPackagesPageEmpty6}
\pastebutton{ugPackagesPackagesPageFull6}{\hidepaste}
\tab{5}\spadcommand{setClipValue 7}
\indentrel{3}\begin{verbatim}
   (4)  7.0
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugPackagesPackagesPageEmpty6}
\begin{paste}{ugPackagesPackagesPageEmpty6}{ugPackagesPackagesPagePatch6}
\pastebutton{ugPackagesPackagesPageEmpty6}{\showpaste}
\tab{5}\spadcommand{setClipValue 7}
\end{paste}\end{patch}

\begin{patch}{ugPackagesPackagesPagePatch7}
\begin{paste}{ugPackagesPackagesPageFull7}{ugPackagesPackagesPageEmpty7}
\pastebutton{ugPackagesPackagesPageFull7}{\hidepaste}
\tab{5}\spadgraph{drawComplex(f,-\%pi..\%pi,-\%pi..\%pi, false)\free{srs scs f }}
\center{\unixcommand{\inputimage{\env{AXIOM}/doc/viewports/ugpackagespackagespage7.view/image}}{viewalone\space{1} \env{AXIOM}/doc/viewports/ugpackagespackagespage7}}
\end{paste}\end{patch}

\begin{patch}{ugPackagesPackagesPageEmpty7}
\begin{paste}{ugPackagesPackagesPageEmpty7}{ugPackagesPackagesPagePatch7}
\pastebutton{ugPackagesPackagesPageEmpty7}{\showpaste}
\tab{5}\spadgraph{drawComplex(f,-\%pi..\%pi,-\%pi..\%pi, false)\free{srs scs f }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugPackagesParametersPage}{ug11.ht}{Parameters}
\pageto{notitle}{ugTypesPage}
\pageto{notitle}{ugUserBlocksPage}
\pageto{notitle}{ugCategoriesAttributesPage}
\begin{chunk}{ug11.ht}
\begin{page}{ugPackagesParametersPage}{11.7. Parameters}
\beginscroll

The power of packages becomes evident when packages have parameters.
Usually these parameters are domains and the exported operations have
types involving these parameters.

In \downlink{``Using Types and Modes''}{ugTypesPage} in Chapter
2\ignore{ugTypes}, you learned that categories denote
classes of domains.  Although we cover this notion in detail in the
next chapter, we now give you a sneak preview of its usefulness.

In \downlink{``Functions Defined with Blocks''}{ugUserBlocksPage} in
Section 6.15\ignore{ugUserBlocks}, we defined functions
\axiom{bubbleSort(m)} and \axiom{insertionSort(m)} to sort a list of
integers.  If you look at the code for these functions, you see that
they may be used to sort {\it any} structure \axiom{m} with the right
properties.  Also, the functions can be used to sort lists of {\it
any} elements---not just integers.  Let us now recall the code for
\axiom{bubbleSort}.

\begin{verbatim}
bubbleSort(m) ==
  n := #m
  for i in 1..(n-1) repeat
    for j in n..(i+1) by -1 repeat
      if m.j < m.(j-1) then swap!(m,j,j-1)
  m
\end{verbatim}

What properties of ``lists of integers'' are assumed by the sorting
algorithm?  In the first line, the operation \spadfun{\#} computes the
maximum index of the list.  The first obvious property is that
\axiom{m} must have a finite number of elements.  In Axiom, this is
done by your telling Axiom that \axiom{m} has the ``attribute''
\spadatt{finiteAggregate}.  An \spadgloss{attribute} is a property
that a domain either has or does not have.  As we show later in
\downlink{``Attributes''}{ugCategoriesAttributesPage}
in Section 12.9\ignore{ugCategoriesAttributes}, programs
can query domains as to the presence or absence of an attribute.

The operation \spadfunX{swap} swaps elements of \axiom{m}.
Using \Browse{}, you find that \spadfunX{swap} requires its
elements to come from a domain of category
\axiomType{IndexedAggregate} with attribute
\spadatt{shallowlyMutable}.
This attribute means that you can change the internal components
of \axiom{m} without changing its external structure.
Shallowly-mutable data structures include lists, streams, one- and
two-dimensional arrays, vectors, and matrices.

The category \axiomType{IndexedAggregate} designates the class of
aggregates whose elements can be accessed by the notation
\axiom{m.s} for suitable selectors \axiom{s}.
The category \axiomType{IndexedAggregate} takes two arguments:
\axiom{Index}, a domain of selectors for the aggregate, and
\axiom{Entry}, a domain of entries for the aggregate.
Since the sort functions access elements by integers, we must
choose \axiom{Index = }\axiomType{Integer}.
The most general class of domains for which \axiom{bubbleSort} and
\axiom{insertionSort} are defined are those of
category \spadtype{IndexedAggregate(Integer,Entry)} with the two
attributes \spadatt{shallowlyMutable} and
\spadatt{finiteAggregate}.

Using \Browse{}, you can also discover that Axiom has many kinds of
domains with attribute \spadatt{shallowlyMutable}.  Those of class
\axiomType{IndexedAggregate(Integer,Entry)} include \axiomType{Bits},
\axiomType{FlexibleArray}, \axiomType{OneDimensionalArray},
\axiomType{List}, \axiomType{String}, and \axiomType{Vector}, and also
\axiomType{HashTable} and \axiomType{EqTable} with integer keys.
Although you may never want to sort all such structures, we
nonetheless demonstrate Axiom's ability to do so.

Another requirement is that \nonLibAxiomType{Entry} has an operation
\axiomOp{<}.  One way to get this operation is to assume that
\nonLibAxiomType{Entry} has category \axiomType{OrderedSet}.  By
definition, will then export a \axiomOp{<} operation.  A more general
approach is to allow any comparison function \axiom{f} to be used for
sorting.  This function will be passed as an argument to the sorting
functions.

Our sorting package then takes two arguments: a domain \axiom{S} of
objects of {\it any} type, and a domain \axiom{A}, an aggregate of
type \axiomType{IndexedAggregate(Integer, S)} with the above two
attributes.  Here is its definition using what are close to the
original definitions of \axiom{bubbleSort} and \axiom{insertionSort}
for sorting lists of integers.  The symbol \axiomSyntax{!} is added to
the ends of the operation names.  This uniform naming convention is
used for Axiom operation names that destructively change one or more
of their arguments.

\beginImportant
  
\noindent
{\tt 1.\ \ \ SortPackage(S,A)\ :\ Exports\ ==\ Implementation\ where}
\newline
{\tt 2.\ \ \ \ \ S:\ Object}\newline
{\tt 3.\ \ \ \ \ A:\ IndexedAggregate(Integer,S)}\newline
{\tt 4.\ \ \ \ \ \ \ with\ (finiteAggregate;\ shallowlyMutable)}
\newline
{\tt 5.\ \ \ }\newline
{\tt 6.\ \ \ \ \ Exports\ ==\ with}\newline
{\tt 7.\ \ \ \ \ \ \ bubbleSort!:\ (A,(S,S)\ ->\ Boolean)\ ->\ A}
\newline
{\tt 8.\ \ \ \ \ \ \ 
insertionSort!:\ (A,\ (S,S)\ ->\ Boolean)\ ->\ A}\newline
{\tt 9.\ \ \ }\newline
{\tt 10.\ \ \ \ Implementation\ ==\ add}\newline
{\tt 11.\ \ \ \ \ \ bubbleSort!(m,f)\ ==}\newline
{\tt 12.\ \ \ \ \ \ \ \ n\ :=\ \#m}\newline
{\tt 13.\ \ \ \ \ \ \ \ for\ i\ in\ 1..(n-1)\ repeat}\newline
{\tt 14.\ \ \ \ \ \ \ \ \ \ 
for\ j\ in\ n..(i+1)\ by\ -1\ repeat}\newline
{\tt 15.\ \ \ \ \ \ \ \ \ \ \ \ 
if\ f(m.j,m.(j-1))\ then\ swap!(m,j,j-1)}\newline
{\tt 16.\ \ \ \ \ \ \ \ m}\newline
{\tt 17.\ \ \ \ \ \ insertionSort!(m,f)\ ==}\newline
{\tt 18.\ \ \ \ \ \ \ \ for\ i\ in\ 2..\#m\ repeat}\newline
{\tt 19.\ \ \ \ \ \ \ \ \ \ j\ :=\ i}\newline
{\tt 20.\ \ \ \ \ \ \ \ \ \ 
while\ j\ >\ 1\ and\ f(m.j,m.(j-1))\ repeat}\newline
{\tt 21.\ \ \ \ \ \ \ \ \ \ \ \ swap!(m,j,j-1)}\newline
{\tt 22.\ \ \ \ \ \ \ \ \ \ \ \ 
j\ :=\ (j\ -\ 1)\ pretend\ PositiveInteger}\newline
{\tt 23.\ \ \ \ \ \ \ \ m}\newline
\endImportant

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugPackagesCondsPage}{ug11.ht}{Conditionals}
\pageto{notitle}{ugUserBlocksPage}
\begin{chunk}{ug11.ht}
\begin{page}{ugPackagesCondsPage}{11.8. Conditionals}
\beginscroll

When packages have parameters, you can say that an operation is or is
not exported depending on the values of those parameters.  When the
domain of objects \axiom{S} has an \axiomOp{<} operation, we can
supply one-argument versions of \axiom{bubbleSort} and
\axiom{insertionSort} which use this operation for sorting.  The
presence of the operation \axiomOp{<} is guaranteed when \axiom{S} is
an ordered set.

\beginImportant
  
\noindent
{\tt 1.\ \ \ Exports\ ==\ with}\newline
{\tt 2.\ \ \ \ \ \ \ bubbleSort!:\ (A,(S,S)\ ->\ Boolean)\ ->\ A}
\newline
{\tt 3.\ \ \ \ \ \ \ 
insertionSort!:\ (A,\ (S,S)\ ->\ Boolean)\ ->\ A}\newline
{\tt 4.\ \ \ }\newline
{\tt 5.\ \ \ \ \ \ \ if\ S\ has\ OrderedSet\ then}\newline
{\tt 6.\ \ \ \ \ \ \ \ \ bubbleSort!:\ A\ ->\ A}\newline
{\tt 7.\ \ \ \ \ \ \ \ \ insertionSort!:\ A\ ->\ A}\newline
\endImportant

In addition to exporting the one-argument sort operations
conditionally, we must provide conditional definitions for the
operations in the {\tt Implementation} part.
This is easy: just have the one-argument functions call the
corresponding two-argument functions with the operation
\axiomOp{<} from \axiom{S}.

\beginImportant
  
\noindent
{\tt 1.\ \ \ \ \ Implementation\ ==\ add}\newline
{\tt 2.\ \ \ \ \ \ \ \ \ \ ...}\newline
{\tt 3.\ \ \ \ \ \ \ if\ S\ has\ OrderedSet\ then}\newline
{\tt 4.\ \ \ \ \ \ \ \ \ 
bubbleSort!(m)\ ==\ bubbleSort!(m,<\$S)}\newline
{\tt 5.\ \ \ \ \ \ \ \ \ 
insertionSort!(m)\ ==\ insertionSort!(m,<\$S)}\newline
\endImportant

In \downlink{``Functions Defined with Blocks''}{ugUserBlocksPage} in 
Section 6.15\ignore{ugUserBlocks}, we give an alternative
definition of \fakeAxiomFun{bubbleSort} using
\spadfunFrom{first}{List} and \spadfunFrom{rest}{List} that is more
efficient for a list (for which access to any element requires
traversing the list from its first node).  To implement a more
efficient algorithm for lists, we need the operation \spadfun{setelt}
which allows us to destructively change the \spadfun{first} and
\spadfun{rest} of a list.  Using \Browse{}, you find that these
operations come from category \axiomType{UnaryRecursiveAggregate}.
Several aggregate types are unary recursive aggregates including those
of \axiomType{List} and \axiomType{AssociationList}.  We provide two
different implementations for \fakeAxiomFun{bubbleSort!} and
\fakeAxiomFun{insertionSort!}: one for list-like structures, another
for array-like structures.

\beginImportant
  
\noindent
{\tt 1.\ \ \ Implementation\ ==\ add}\newline
{\tt 2.\ \ \ \ \ \ \ \ \ \ \ ...}\newline
{\tt 3.\ \ \ \ \ \ \ if\ A\ has\ UnaryRecursiveAggregate(S)\ then}
\newline
{\tt 4.\ \ \ \ \ \ \ \ \ bubbleSort!(m,fn)\ ==}\newline
{\tt 5.\ \ \ \ \ \ \ \ \ \ \ empty?\ m\ =>\ m}\newline
{\tt 6.\ \ \ \ \ \ \ \ \ \ \ l\ :=\ m}\newline
{\tt 7.\ \ \ \ \ \ \ \ \ \ \ 
while\ not\ empty?\ (r\ :=\ l.rest)\ repeat}\newline
{\tt 8.\ \ \ \ \ \ \ \ \ \ \ \ \ \ r\ :=\ bubbleSort!\ r}\newline
{\tt 9.\ \ \ \ \ \ \ \ \ \ \ \ \ \ x\ :=\ l.first}\newline
{\tt 10.\ \ \ \ \ \ \ \ \ \ \ \ \ if\ fn(r.first,x)\ then}\newline
{\tt 11.\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ l.first\ :=\ r.first}\newline
{\tt 12.\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ r.first\ :=\ x}\newline
{\tt 13.\ \ \ \ \ \ \ \ \ \ \ \ \ l.rest\ :=\ r}\newline
{\tt 14.\ \ \ \ \ \ \ \ \ \ \ \ \ l\ :=\ l.rest}\newline
{\tt 15.\ \ \ \ \ \ \ \ \ \ \ m}\newline
{\tt 16.\ \ \ \ \ \ \ \ \ insertionSort!(m,fn)\ ==}\newline
{\tt 17.\ \ \ \ \ \ \ \ \ \ \ \ ...}\newline
\endImportant

The ordering of definitions is important.
The standard definitions come first and
then the predicate
\begin{verbatim}
A has UnaryRecursiveAggregate(S)
\end{verbatim}
is evaluated.
If {\tt true}, the special definitions cover up the standard ones.

Another equivalent way to write the capsule is to use an
\axiom{if-then-else} expression:
\spadkey{if}

\beginImportant
  
\noindent
{\tt 1.\ \ \ \ \ \ \ \ if\ A\ has\ UnaryRecursiveAggregate(S)\ then}
\newline
{\tt 2.\ \ \ \ \ \ \ \ \ \ \ ...}\newline
{\tt 3.\ \ \ \ \ \ \ \ else}\newline
{\tt 4.\ \ \ \ \ \ \ \ \ \ \ ...}\newline
\endImportant

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugPackagesCompilingPage}{ug11.ht}{Testing}
\pageto{notitle}{EqTableXmpPage}
\begin{chunk}{ug11.ht}
\begin{page}{ugPackagesCompilingPage}{11.9. Testing}
\beginscroll

Once you have written the package, embed it in a file, for example,
{\bf sortpak\spadFileExt{}}.  Be sure to include an \axiom{)abbrev}
command at the top of the file:
\begin{verbatim}
)abbrev package SORTPAK SortPackage
\end{verbatim}
Now compile the file (using \spadcmd{)compile sortpak\spadFileExt{}}).
\xtc{
Expose the constructor.
You are then ready to begin testing.
}{
\spadpaste{)expose SORTPAK}
}
\xtc{
Define a list.
}{
\spadpaste{l := [1,7,4,2,11,-7,3,2]}
}
\xtc{
Since the integers are an ordered set,
a one-argument operation will do.
}{
\spadpaste{bubbleSort!(l)}
}
\xtc{
Re-sort it using ``greater than.''
}{
\spadpaste{bubbleSort!(l,(x,y) +-> x > y)}
}
\xtc{
Now sort it again using \axiomOp{<} on integers.
}{
\spadpaste{bubbleSort!(l, <\$Integer)}
}
\xtc{
A string is an aggregate of characters so we can sort them as well.
}{
\spadpaste{bubbleSort! "Mathematical Sciences"}
}
\xtc{
Is \axiomOp{<} defined on booleans?
}{
\spadpaste{false < true}
}
\xtc{
Good! Create a bit string representing ten consecutive
boolean values \axiom{true}.
}{
\spadpaste{u : Bits := new(10,true)}
}
\xtc{
Set bits 3 through 5 to \axiom{false}, then display the result.
}{
\spadpaste{u(3..5) := false; u}
}
\xtc{
Now sort these booleans.
}{
\spadpaste{bubbleSort! u}
}
\xtc{
Create an ``eq-table'' (see 
\downlink{`EqTable'}{EqTableXmpPage}\ignore{EqTable}), a
table having integers as keys
and strings as values.
}{
\spadpaste{t : EqTable(Integer,String) := table()}
}
\xtc{
Give the table a first entry.
}{
\spadpaste{t.1 := "robert"}
}
\xtc{
And a second.
}{
\spadpaste{t.2 := "richard"}
}
\xtc{
What does the table look like?
}{
\spadpaste{t}
}
\xtc{
Now sort it.
}{
\spadpaste{bubbleSort! t}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugPackagesCompilingPagePatch1}
\begin{paste}{ugPackagesCompilingPageFull1}{ugPackagesCompilingPageEmpty1}
\pastebutton{ugPackagesCompilingPageFull1}{\hidepaste}
\tab{5}\spadcommand{)expose SORTPAK}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPageEmpty1}
\begin{paste}{ugPackagesCompilingPageEmpty1}{ugPackagesCompilingPagePatch1}
\pastebutton{ugPackagesCompilingPageEmpty1}{\showpaste}
\tab{5}\spadcommand{)expose SORTPAK}
\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPagePatch2}
\begin{paste}{ugPackagesCompilingPageFull2}{ugPackagesCompilingPageEmpty2}
\pastebutton{ugPackagesCompilingPageFull2}{\hidepaste}
\tab{5}\spadcommand{l := [1,7,4,2,11,-7,3,2]}
\indentrel{3}\begin{verbatim}
   (1)  [1,7,4,2,11,- 7,3,2]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPageEmpty2}
\begin{paste}{ugPackagesCompilingPageEmpty2}{ugPackagesCompilingPagePatch2}
\pastebutton{ugPackagesCompilingPageEmpty2}{\showpaste}
\tab{5}\spadcommand{l := [1,7,4,2,11,-7,3,2]}
\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPagePatch3}
\begin{paste}{ugPackagesCompilingPageFull3}{ugPackagesCompilingPageEmpty3}
\pastebutton{ugPackagesCompilingPageFull3}{\hidepaste}
\tab{5}\spadcommand{bubbleSort!(l)}
\indentrel{3}\begin{verbatim}
   (2)  [- 7,1,2,2,3,4,7,11]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPageEmpty3}
\begin{paste}{ugPackagesCompilingPageEmpty3}{ugPackagesCompilingPagePatch3}
\pastebutton{ugPackagesCompilingPageEmpty3}{\showpaste}
\tab{5}\spadcommand{bubbleSort!(l)}
\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPagePatch4}
\begin{paste}{ugPackagesCompilingPageFull4}{ugPackagesCompilingPageEmpty4}
\pastebutton{ugPackagesCompilingPageFull4}{\hidepaste}
\tab{5}\spadcommand{bubbleSort!(l,(x,y) +-> x > y)}
\indentrel{3}\begin{verbatim}
   (3)  [11,7,4,3,2,2,1,- 7]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPageEmpty4}
\begin{paste}{ugPackagesCompilingPageEmpty4}{ugPackagesCompilingPagePatch4}
\pastebutton{ugPackagesCompilingPageEmpty4}{\showpaste}
\tab{5}\spadcommand{bubbleSort!(l,(x,y) +-> x > y)}
\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPagePatch5}
\begin{paste}{ugPackagesCompilingPageFull5}{ugPackagesCompilingPageEmpty5}
\pastebutton{ugPackagesCompilingPageFull5}{\hidepaste}
\tab{5}\spadcommand{bubbleSort!(l, <$Integer)}
\indentrel{3}\begin{verbatim}
   (4)  [- 7,1,2,2,3,4,7,11]
                                     Type: List Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPageEmpty5}
\begin{paste}{ugPackagesCompilingPageEmpty5}{ugPackagesCompilingPagePatch5}
\pastebutton{ugPackagesCompilingPageEmpty5}{\showpaste}
\tab{5}\spadcommand{bubbleSort!(l, <$Integer)}
\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPagePatch6}
\begin{paste}{ugPackagesCompilingPageFull6}{ugPackagesCompilingPageEmpty6}
\pastebutton{ugPackagesCompilingPageFull6}{\hidepaste}
\tab{5}\spadcommand{bubbleSort! "Mathematical Sciences"}
\indentrel{3}\begin{verbatim}
   (5)  " MSaaaccceeehiilmnstt"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPageEmpty6}
\begin{paste}{ugPackagesCompilingPageEmpty6}{ugPackagesCompilingPagePatch6}
\pastebutton{ugPackagesCompilingPageEmpty6}{\showpaste}
\tab{5}\spadcommand{bubbleSort! "Mathematical Sciences"}
\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPagePatch7}
\begin{paste}{ugPackagesCompilingPageFull7}{ugPackagesCompilingPageEmpty7}
\pastebutton{ugPackagesCompilingPageFull7}{\hidepaste}
\tab{5}\spadcommand{false < true}
\indentrel{3}\begin{verbatim}
   (6)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPageEmpty7}
\begin{paste}{ugPackagesCompilingPageEmpty7}{ugPackagesCompilingPagePatch7}
\pastebutton{ugPackagesCompilingPageEmpty7}{\showpaste}
\tab{5}\spadcommand{false < true}
\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPagePatch8}
\begin{paste}{ugPackagesCompilingPageFull8}{ugPackagesCompilingPageEmpty8}
\pastebutton{ugPackagesCompilingPageFull8}{\hidepaste}
\tab{5}\spadcommand{u : Bits := new(10,true)}
\indentrel{3}\begin{verbatim}
   (7)  "1111111111"
                                             Type: Bits
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPageEmpty8}
\begin{paste}{ugPackagesCompilingPageEmpty8}{ugPackagesCompilingPagePatch8}
\pastebutton{ugPackagesCompilingPageEmpty8}{\showpaste}
\tab{5}\spadcommand{u : Bits := new(10,true)}
\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPagePatch9}
\begin{paste}{ugPackagesCompilingPageFull9}{ugPackagesCompilingPageEmpty9}
\pastebutton{ugPackagesCompilingPageFull9}{\hidepaste}
\tab{5}\spadcommand{u(3..5) := false; u}
\indentrel{3}\begin{verbatim}
   (8)  "1100011111"
                                             Type: Bits
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPageEmpty9}
\begin{paste}{ugPackagesCompilingPageEmpty9}{ugPackagesCompilingPagePatch9}
\pastebutton{ugPackagesCompilingPageEmpty9}{\showpaste}
\tab{5}\spadcommand{u(3..5) := false; u}
\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPagePatch10}
\begin{paste}{ugPackagesCompilingPageFull10}{ugPackagesCompilingPageEmpty10}
\pastebutton{ugPackagesCompilingPageFull10}{\hidepaste}
\tab{5}\spadcommand{bubbleSort! u}
\indentrel{3}\begin{verbatim}
   (9)  "0001111111"
                                             Type: Bits
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPageEmpty10}
\begin{paste}{ugPackagesCompilingPageEmpty10}{ugPackagesCompilingPagePatch10}
\pastebutton{ugPackagesCompilingPageEmpty10}{\showpaste}
\tab{5}\spadcommand{bubbleSort! u}
\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPagePatch11}
\begin{paste}{ugPackagesCompilingPageFull11}{ugPackagesCompilingPageEmpty11}
\pastebutton{ugPackagesCompilingPageFull11}{\hidepaste}
\tab{5}\spadcommand{t : EqTable(Integer,String) := table()}
\indentrel{3}\begin{verbatim}
   (10)  table()
                          Type: EqTable(Integer,String)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPageEmpty11}
\begin{paste}{ugPackagesCompilingPageEmpty11}{ugPackagesCompilingPagePatch11}
\pastebutton{ugPackagesCompilingPageEmpty11}{\showpaste}
\tab{5}\spadcommand{t : EqTable(Integer,String) := table()}
\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPagePatch12}
\begin{paste}{ugPackagesCompilingPageFull12}{ugPackagesCompilingPageEmpty12}
\pastebutton{ugPackagesCompilingPageFull12}{\hidepaste}
\tab{5}\spadcommand{t.1 := "robert"}
\indentrel{3}\begin{verbatim}
   (11)  "robert"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPageEmpty12}
\begin{paste}{ugPackagesCompilingPageEmpty12}{ugPackagesCompilingPagePatch12}
\pastebutton{ugPackagesCompilingPageEmpty12}{\showpaste}
\tab{5}\spadcommand{t.1 := "robert"}
\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPagePatch13}
\begin{paste}{ugPackagesCompilingPageFull13}{ugPackagesCompilingPageEmpty13}
\pastebutton{ugPackagesCompilingPageFull13}{\hidepaste}
\tab{5}\spadcommand{t.2 := "richard"}
\indentrel{3}\begin{verbatim}
   (12)  "richard"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPageEmpty13}
\begin{paste}{ugPackagesCompilingPageEmpty13}{ugPackagesCompilingPagePatch13}
\pastebutton{ugPackagesCompilingPageEmpty13}{\showpaste}
\tab{5}\spadcommand{t.2 := "richard"}
\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPagePatch14}
\begin{paste}{ugPackagesCompilingPageFull14}{ugPackagesCompilingPageEmpty14}
\pastebutton{ugPackagesCompilingPageFull14}{\hidepaste}
\tab{5}\spadcommand{t}
\indentrel{3}\begin{verbatim}
   (13)  table(2= "richard",1= "robert")
                          Type: EqTable(Integer,String)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPageEmpty14}
\begin{paste}{ugPackagesCompilingPageEmpty14}{ugPackagesCompilingPagePatch14}
\pastebutton{ugPackagesCompilingPageEmpty14}{\showpaste}
\tab{5}\spadcommand{t}
\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPagePatch15}
\begin{paste}{ugPackagesCompilingPageFull15}{ugPackagesCompilingPageEmpty15}
\pastebutton{ugPackagesCompilingPageFull15}{\hidepaste}
\tab{5}\spadcommand{bubbleSort! t}
\indentrel{3}\begin{verbatim}
   (14)  table(2= "robert",1= "richard")
                          Type: EqTable(Integer,String)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugPackagesCompilingPageEmpty15}
\begin{paste}{ugPackagesCompilingPageEmpty15}{ugPackagesCompilingPagePatch15}
\pastebutton{ugPackagesCompilingPageEmpty15}{\showpaste}
\tab{5}\spadcommand{bubbleSort! t}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugPackagesHowPage}{ug11.ht}{How Packages Work}
\pageto{notitle}{ugCategoriesHierPage}
\begin{chunk}{ug11.ht}
\begin{page}{ugPackagesHowPage}{11.10. How Packages Work}
\beginscroll

Recall that packages as abstract datatypes are compiled independently
and put into the library.  The curious reader may ask: ``How is the
interpreter able to find an operation such as
\fakeAxiomFun{bubbleSort!}?  Also, how is a single compiled function
such as \fakeAxiomFun{bubbleSort!} able to sort data of different
types?''

After the interpreter loads the package \nonLibAxiomType{SortPackage},
the four operations from the package become known to the interpreter.
Each of these operations is expressed as a {\it modemap} in which the
type of the operation is written in terms of symbolic domains.

\nullXtc{
See the modemaps for \fakeAxiomFun{bubbleSort!}.
}{
\spadpaste{)display op bubbleSort!}
}
\begin{verbatim}
There are 2 exposed functions called bubbleSort! :

   [1] D1 -> D1 from SortPackage(D2,D1)
         if D2 has ORDSET and D2 has OBJECT and D1 has
         IndexedAggregate(Integer, D2) with
              finiteAggregate
              shallowlyMutable

   [2] (D1,((D3,D3) -> Boolean)) -> D1 from SortPackage(D3,D1)
         if D3 has OBJECT and D1 has
         IndexedAggregate(Integer,D3) with
              finiteAggregate
              shallowlyMutable
\end{verbatim}

What happens if you ask for \axiom{bubbleSort!([1,-5,3])}?
There is a unique modemap for an operation named
\fakeAxiomFun{bubbleSort!} with one argument.
Since \axiom{[1,-5,3]} is a list of integers, the symbolic domain
\axiom{D1} is defined as \axiomType{List(Integer)}.
For some operation to apply, it must satisfy the predicate for
some \axiom{D2}.
What \axiom{D2}?
The third expression of the \axiom{and} requires {\tt D1 has
IndexedAggregate(Integer, D2) with} two attributes.
So the interpreter searches for an \axiomType{IndexedAggregate}
among the ancestors of \axiomType{List (Integer)} (see

\downlink{``Hierarchies''}{ugCategoriesHierPage} in Section
12.4\ignore{ugCategoriesHier}).  It finds one:
\axiomType{IndexedAggregate(Integer, Integer)}.  The interpreter tries
defining \axiom{D2} as \axiomType{Integer}.  After substituting for
\axiom{D1} and \axiom{D2}, the predicate evaluates to \axiom{true}.
An applicable operation has been found!

Now Axiom builds the package \axiomType{SortPackage(List(Integer),
Integer)}.  According to its definition, this package exports the
required operation: \fakeAxiomFun{bubbleSort!}: \spadsig{List
Integer}{List Integer}.  The interpreter then asks the package for a
function implementing this operation.  The package gets all the
functions it needs (for example, \axiomFun{rest} and \axiomFunX{swap})
from the appropriate domains and then it returns a
\fakeAxiomFun{bubbleSort!} to the interpreter together with the local
environment for \fakeAxiomFun{bubbleSort!}.  The interpreter applies
the function to the argument \axiom{[1,-5,3]}.  The
\fakeAxiomFun{bubbleSort!} function is executed in its local
environment and produces the result.  \endscroll \autobuttons
\end{page}

\begin{patch}{ugPackagesHowPagePatch1}
\begin{paste}{ugPackagesHowPageFull1}{ugPackagesHowPageEmpty1}
\pastebutton{ugPackagesHowPageFull1}{\hidepaste}
\tab{5}\spadcommand{)display op bubbleSort!}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugPackagesHowPageEmpty1}
\begin{paste}{ugPackagesHowPageEmpty1}{ugPackagesHowPagePatch1}
\pastebutton{ugPackagesHowPageEmpty1}{\showpaste}
\tab{5}\spadcommand{)display op bubbleSort!}
\end{paste}\end{patch}

\end{chunk}
\chapter{Users Guide Chapter 12 (ug12.ht)}
\pagetitle{ugCategoriesPage}{ug12.ht}{Categories}
\pagefrom{Domain Constructors}{ugTypesBasicDomainConsPage}
\pageto{Domain Constructors}{ugTypesBasicDomainConsPage}
\pageto{Definitions}{ugCategoriesDefsPage}
\pageto{Exports}{ugCategoriesExportsPage}
\pageto{Documentation}{ugCategoriesDocPage}
\pageto{Hierarchies}{ugCategoriesHierPage}
\pageto{Membership}{ugCategoriesMembershipPage}
\pageto{Defaults}{ugCategoriesDefaultsPage}
\pageto{Axioms}{ugCategoriesAxiomsPage}
\pageto{Correctness}{ugCategoriesCorrectnessPage}
\pageto{Attributes}{ugCategoriesAttributesPage}
\pageto{Parameters}{ugCategoriesParametersPage}
\pageto{Conditionals}{ugCategoriesConditionalsPage}
\pageto{Anonymous Categories}{ugCategoriesAndPackagesPage}
\begin{chunk}{ug12.ht}
\begin{page}{ugCategoriesPage}{12. Categories}
\beginscroll

This chapter unravels the mysteries of categories---what
they are, how they are related to domains and packages,
how they are defined in Axiom, and how you can extend the
system to include new categories of your own.

We assume that you have read the introductory material on domains and
categories in
\downlink{``Domain Constructors''}{ugTypesBasicDomainConsPage}
in Section 2.1.1\ignore{ugTypesBasicDomainCons}.  There
you learned that the notion of packages covered in the previous
chapter are special cases of domains.  While this is in fact the case,
it is useful here to regard domains as distinct from packages.

Think of a domain as a datatype, a collection of objects (the objects
of the domain).  From your ``sneak preview'' in the previous chapter,
you might conclude that categories are simply named clusters of
operations exported by domains.  As it turns out, categories have a
much deeper meaning.  Categories are fundamental to the design of
Axiom.  They control the interactions between domains and algorithmic
packages, and, in fact, between all the components of Axiom.

Categories form hierarchies as shown on the inside cover pages of this
book.  The inside front-cover pages illustrate the basic algebraic
hierarchy of the Axiom programming language.  The inside back-cover
pages show the hierarchy for data structures.

Think of the category structures of Axiom as a foundation for a city
on which superstructures (domains) are built.  The algebraic
hierarchy, for example, serves as a foundation for constructive
mathematical algorithms embedded in the domains of Axiom.  Once in
place, domains can be constructed, either independently or from one
another.

Superstructures are built for quality---domains are compiled into
machine code for run-time efficiency.  You can extend the foundation
in directions beyond the space directly beneath the superstructures,
then extend selected superstructures to cover the space.  Because of
the compilation strategy, changing components of the foundation
generally means that the existing superstructures (domains) built on
the changed parts of the foundation (categories) have to be
rebuilt---that is, recompiled.

Before delving into some of the interesting facts about categories,
let's see how you define them in Axiom.

\beginmenu
\menudownlink{{12.1. Definitions}}{ugCategoriesDefsPage}
\menudownlink{{12.2. Exports}}{ugCategoriesExportsPage}
\menudownlink{{12.3. Documentation}}{ugCategoriesDocPage}
\menudownlink{{12.4. Hierarchies}}{ugCategoriesHierPage}
\menudownlink{{12.5. Membership}}{ugCategoriesMembershipPage}
\menudownlink{{12.6. Defaults}}{ugCategoriesDefaultsPage}
\menudownlink{{12.7. Axioms}}{ugCategoriesAxiomsPage}
\menudownlink{{12.8. Correctness}}{ugCategoriesCorrectnessPage}
\menudownlink{{12.9. Attributes}}{ugCategoriesAttributesPage}
\menudownlink{{12.10. Parameters}}{ugCategoriesParametersPage}
\menudownlink{{12.11. Conditionals}}{ugCategoriesConditionalsPage}
\menudownlink{{12.12. Anonymous Categories}}{ugCategoriesAndPackagesPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugCategoriesDefsPage}{ug12.ht}{Definitions}
\pagefrom{Categories}{ugCategoriesPage}
\pageto{notitle}{ugTypesPage}
\begin{chunk}{ug12.ht}
\begin{page}{ugCategoriesDefsPage}{12.1. Definitions}
\beginscroll

A category is defined by a function with exactly the same format as
any other function in Axiom.

\beginImportant
The definition of a category has the syntax:
\centerline{{{\it CategoryForm} : {\tt Category\quad{}==\quad{}} 
{\it Extensions} {\tt [ with} {\it Exports} {\tt ]}}}

The brackets {\tt [ ]} here indicate optionality.
\endImportant


The first example of a category definition is
\spadtype{SetCategory},
the most basic of the algebraic categories in Axiom.

\beginImportant
  
\noindent
{\tt 1.\ \ \ SetCategory():\ Category\ ==}\newline
{\tt 2.\ \ \ \ \ \ Join(Type,CoercibleTo\ OutputForm)\ with}\newline
{\tt 3.\ \ \ \ \ \ \ \ \ "="\ :\ (\$,\ \$)\ ->\ Boolean}\newline
\endImportant

The definition starts off with the name of the
category (\spadtype{SetCategory}); this is
always in column one in the source file.
%% maybe talk about naming conventions for source files? .spad or .ax?
All parts of a category definition are then indented with respect to this
first line.

In \downlink{``Using Types and Modes''}{ugTypesPage} in Chapter
2\ignore{ugTypes}, we talked about \spadtype{Ring} as
denoting the class of all domains that are rings, in short, the class
of all rings.  While this is the usual naming convention in Axiom, it
is also common to use the word ``Category'' at the end of a category
name for clarity.  The interpretation of the name
\spadtype{SetCategory} is, then, ``the category of all domains that
are (mathematical) sets.''

The name \spadtype{SetCategory} is followed in the definition by its
formal parameters enclosed in parentheses \spadSyntax{()}.
Here there are no parameters.
As required, the type of the result of this category function is the
distinguished name {\sf Category}.

Then comes the \spadSyntax{==}.
As usual, what appears to the right of the \spadSyntax{==} is a
definition, here, a category definition.
A category definition always has two parts separated by the reserved word
\spadkey{with}
\spad{with}.
%\footnote{Debugging hint: it is very easy to forget
%the \spad{with}!}

The first part tells what categories the category extends.
Here, the category extends two categories: \spadtype{Type}, the
category of all domains, and
\spadtype{CoercibleTo(OutputForm)}.
%\footnote{\spadtype{CoercibleTo(OutputForm)}
%can also be written (and is written in the definition above) without
%parentheses.}
The operation \spad{Join} is a system-defined operation that
\spadkey{Join}
forms a single category from two or more other categories.

Every category other than \spadtype{Type} is an extension of some other
category.
If, for example, \spadtype{SetCategory} extended only the category
\spadtype{Type}, the definition here would read ``{\tt Type with
...}''.
In fact, the {\tt Type} is optional in this line; ``{\tt with
...}'' suffices.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugCategoriesExportsPage}{ug12.ht}{Exports}
\pagefrom{Categories}{ugCategoriesPage}
\begin{chunk}{ug12.ht}
\begin{page}{ugCategoriesExportsPage}{12.2. Exports}
\beginscroll

To the right of the \spad{with} is a list of
\spadkey{with}
all the \spadglossSee{exports}{export} of the category.
Each exported operation has a name and a type expressed by a
\spadgloss{declaration} of the form
``{\frenchspacing\tt {\it name}: {\it type}}''.

Categories can export symbols, as well as
{\tt 0} and {\tt 1} which denote
domain constants.\footnote{The
numbers {\tt 0} and {\tt 1} are operation names in Axiom.}
In the current implementation, all other exports are operations with
types expressed as \spadglossSee{mappings}{mapping} with the syntax
\centerline{{{\it}}
\centerline{{source\quad{\tt ->}\quad target}}
\centerline{{}}}

The category \spadtype{SetCategory} has a single export: the operation
\spadop{=} whose type is given by the mapping {\tt (\$, \$) -> Boolean}.
The \spadSyntax{\$} in a mapping type always means ``the domain.'' Thus
the operation \spadop{=} takes two arguments from the domain and
returns a value of type \spadtype{Boolean}.

The source part of the mapping here is given by a {\it tuple}
consisting of two or more types separated by commas and enclosed in
parentheses.
If an operation takes only one argument, you can drop the parentheses
around the source type.
If the mapping has no arguments, the source part of the mapping is either
left blank or written as \spadSyntax{()}.
Here are examples of formats of various operations with some
contrived names.

\begin{verbatim}
someIntegerConstant  :    $
aZeroArgumentOperation:   () -> Integer
aOneArgumentOperation:    Integer -> $
aTwoArgumentOperation:    (Integer,$) -> Void
aThreeArgumentOperation:  ($,Integer,$) -> Fraction($)
\end{verbatim}

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugCategoriesDocPage}{ug12.ht}{Documentation}
\pagefrom{Categories}{ugCategoriesPage}
\begin{chunk}{ug12.ht}
\begin{page}{ugCategoriesDocPage}{12.3. Documentation}
\beginscroll

The definition of \spadtype{SetCategory} above is  missing
an important component: its library documentation.
Here is its definition, complete with documentation.

\beginImportant
  
\noindent
{\tt 1.\ \ \ ++\ Description:}\newline
{\tt 2.\ \ \ ++\ 
\bs{}axiomType\{SetCategory\}\ is\ the\ basic\ category}\newline
{\tt 3.\ \ \ ++\ 
for\ describing\ a\ collection\ of\ elements\ with}\newline
{\tt 4.\ \ \ ++\ 
\bs{}axiomOp\{=\}\ (equality)\ and\ a\ \bs{}axiomFun\{coerce\}}\newline
{\tt 5.\ \ \ ++\ to\ \bs{}axiomType\{OutputForm\}.}\newline
{\tt 6.\ \ \ }\newline
{\tt 7.\ \ \ SetCategory():\ Category\ ==}\newline
{\tt 8.\ \ \ \ \ Join(Type,\ CoercibleTo\ OutputForm)\ with}\newline
{\tt 9.\ \ \ \ \ \ \ "=":\ (\$,\ \$)\ ->\ Boolean}\newline
{\tt 10.\ \ \ \ \ \ \ \ ++\ 
\bs{}axiom\{x\ =\ y\}\ tests\ if\ \bs{}axiom\{x\}\ and}\newline
{\tt 11.\ \ \ \ \ \ \ \ ++\ \bs{}axiom\{y\}\ are\ equal.}\newline
\endImportant

Documentary comments are an important part of constructor definitions.
Documentation is given both for the category itself and for
each export.
A description for the category precedes the code.
Each line of the description begins in column one with \axiomSyntax{++}.
The description starts with the word {\tt Description:}.\footnote{Other
information such as the author's name, date of creation, and so on,
can go in this
area as well but are currently ignored by Axiom.}
All lines of the description following the initial line are
indented by the same amount.

{\texht{\sloppy}{} Surround the name of any constructor (with or
without parameters) with an
\texht{\verb+\axiomType{}+}{\\axiomType\{\}}.  Similarly, surround an
operator name with \texht{\verb+\axiomOp{}+}{\\axiomOp\{\}}, an Axiom
operation with \texht{\verb+\axiomFun{}+}{\\axiomFun\{\}}, and a
variable or Axiom expression with
\texht{\verb+\axiom{}+}{\\axiom\{\}}.  Library documentation is given
in a \TeX{}-like language so that it can be used both for hard-copy
and for \Browse{}.  These different wrappings cause operations and
types to have mouse-active buttons in \Browse{}.  For hard-copy
output, wrapped expressions appear in a different font.  The above
documentation appears in hard-copy as:

}
%
\texht{\begin{quotation}}{\indent{3}}
%
\axiomType{SetCategory} is the basic category
for describing a collection of elements with \axiomOp{=}
(equality) and a \spadfun{coerce} to \axiomType{OutputForm}.
%
\texht{\end{quotation}}{\indent{0}}
%
and
%
\texht{\begin{quotation}}{\indent{3}}
%
\axiom{x = y} tests if \axiom{x} and \axiom{y} are equal.
%
\texht{\end{quotation}}{\indent{0}}
%

For our purposes in this chapter, we omit the documentation from further
category descriptions.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugCategoriesHierPage}{ug12.ht}{Hierarchies}
\pagefrom{Categories}{ugCategoriesPage}
\begin{chunk}{ug12.ht}
\begin{page}{ugCategoriesHierPage}{12.4. Hierarchies}
\beginscroll

A second example of a category is
\spadtype{SemiGroup}, defined by:

\beginImportant
  
\noindent
{\tt 1.\ \ \ SemiGroup():\ Category\ ==\ SetCategory\ with}\newline
{\tt 2.\ \ \ \ \ \ \ \ \ "*":\ \ (\$,\$)\ ->\ \$}\newline
{\tt 3.\ \ \ \ \ \ \ \ \ "**":\ (\$,\ PositiveInteger)\ ->\ \$}\newline
\endImportant

This definition is as simple as that for \spadtype{SetCategory},
except that there are two exported operations.
Multiple exported operations are written as a \spadgloss{pile},
that is, they all begin in the same column.
Here you see that the category mentions another type,
\spadtype{PositiveInteger}, in a signature.
Any domain can be used in a signature.

Since categories extend one another, they form hierarchies.
Each category other than \spadtype{Type} has one or more parents given
by the one or more categories mentioned before the \spad{with} part of
the definition.
\spadtype{SemiGroup} extends \spadtype{SetCategory} and
\spadtype{SetCategory} extends both \spadtype{Type} and
\spadtype{CoercibleTo (OutputForm)}.
Since \spadtype{CoercibleTo (OutputForm)} also extends \spadtype{Type},
the mention of \spadtype{Type} in the definition is unnecessary but
included for emphasis.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugCategoriesMembershipPage}{ug12.ht}{Membership}
\pagefrom{Categories}{ugCategoriesPage}
\begin{chunk}{ug12.ht}
\begin{page}{ugCategoriesMembershipPage}{12.5. Membership}
\beginscroll

We say a category designates a class of domains.
What class of domains?
That is, how does Axiom know what domains belong to what categories?
The simple answer to this basic question is key to the design of
Axiom:

\beginImportant
\centerline{{{\bf Domains belong to categories by assertion.}}}
\endImportant

When a domain is defined, it is asserted to belong to one or more
categories.
Suppose, for example, that an author of domain \spadtype{String} wishes to
use the binary operator \spadop{*} to denote concatenation.
Thus \spad{"hello " * "there"} would produce the string
\spad{"hello there"}\footnote{Actually, concatenation of strings in
Axiom is done by juxtaposition or by using the operation
\spadfunFrom{concat}{String}.
The expression \spad{"hello " "there"} produces the string
\spad{"hello there"}.}.
The author of \spadtype{String} could then assert that \spadtype{String}
is a member of \spadtype{SemiGroup}.
According to our definition of \spadtype{SemiGroup}, strings
would then also have the operation \spadop{**} defined automatically.
Then \spad{"--" ** 4} would produce a string of eight dashes
\spad{"--------"}.
Since \spadtype{String} is a member of \spadtype{SemiGroup}, it also is
a member of \spadtype{SetCategory} and thus has an operation
\spadop{=} for testing that two strings are equal.

\texht{Now turn to the algebraic category hierarchy inside the
front cover of this book.}{}
Any domain that is a member of a
category extending \spadtype{SemiGroup} is a member of
\spadtype{SemiGroup} (that is, it {\it is} a semigroup).
In particular, any domain asserted to be a \spadtype{Ring} is a
semigroup since \spadtype{Ring} extends \spadtype{Monoid}, that,
in turn, extends \spadtype{SemiGroup}.
The definition of \spadtype{Integer} in Axiom asserts that
\spadtype{Integer} is a member of category
\spadtype{IntegerNumberSystem}, that, in turn, asserts that it is
a member of \spadtype{EuclideanDomain}.
Now \spadtype{EuclideanDomain} extends
\spadtype{PrincipalIdealDomain} and so on.
If you trace up the hierarchy, you see that
\spadtype{EuclideanDomain} extends \spadtype{Ring}, and,
therefore, \spadtype{SemiGroup}.
Thus \spadtype{Integer} is a semigroup and also exports the
operations \spadop{*} and \spadop{**}.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugCategoriesDefaultsPage}{ug12.ht}{Defaults}
\pagefrom{Categories}{ugCategoriesPage}
\pageto{Hierarchies}{ugCategoriesHierPage}
\pageto{Packages}{ugPackagesPage}
\begin{chunk}{ug12.ht}
\begin{page}{ugCategoriesDefaultsPage}{12.6. Defaults}
\beginscroll

We actually omitted the last
part of the definition of
\spadtype{SemiGroup} in
\downlink{``Hierarchies''}{ugCategoriesHierPage} 
in Section 12.4\ignore{ugCategoriesHier}.
Here now is its complete Axiom definition.

\beginImportant
  
\noindent
{\tt 1.\ \ \ SemiGroup():\ Category\ ==\ SetCategory\ with}\newline
{\tt 2.\ \ \ \ \ \ \ \ \ "*":\ (\$,\ \$)\ ->\ \$}\newline
{\tt 3.\ \ \ \ \ \ \ \ \ "**":\ (\$,\ PositiveInteger)\ ->\ \$}\newline
{\tt 4.\ \ \ \ \ \ \ add}\newline
{\tt 5.\ \ \ \ \ \ \ \ \ import\ RepeatedSquaring(\$)}\newline
{\tt 6.\ \ \ \ \ \ \ \ \ 
x:\ \$\ **\ n:\ PositiveInteger\ ==\ expt(x,n)}\newline
\endImportant

The \spad{add} part at the end is used to give ``default definitions''
for \spadkey{add} exported operations.  Once you have a multiplication
operation \spadop{*}, you can define exponentiation for positive
integer exponents using repeated multiplication: 
\centerline{{\spad{x ** n = x * x * ... * x} 
( \spad{n} copies of \spad{x} )}} This
definition for \spadop{**} is called a {\it default} definition.  In
general, a category can give default definitions for any operation it
exports.  Since \spadtype{SemiGroup} and all its category descendants
in the hierarchy export \spadop{**}, any descendant category may
redefine \spadop{**} as well.

A domain of category \spadtype{SemiGroup} (such as \spadtype{Integer})
may or may not choose to define its own \spadop{**} operation.  If it
does not, a default definition that is closest (in a ``tree-distance''
sense of the hierarchy) to the domain is chosen.

The part of the category definition following an \spadop{add} operation
is a \spadgloss{capsule}, as discussed in
\texht{the previous chapter.}
{\downlink{``Packages''}{ugPackagesPage} 
in Chapter 11\ignore{ugPackages}.}
The line
\begin{verbatim}
import RepeatedSquaring($)
\end{verbatim}
references the package
\spadtype{RepeatedSquaring(\$)}, that is, the package
\spadtype{RepeatedSquaring} that takes ``this domain'' as its
parameter.
For example, if the semigroup \spadtype{Polynomial (Integer)}
does not define its own exponentiation operation, the
definition used may come from the package
\spadtype{RepeatedSquaring (Polynomial (Integer))}.
The next line gives the definition in terms of \spadfun{expt} from that
package.

The default definitions are collected to form a ``default package''
for the category.  The name of the package is the same as the category
but with an ampersand (\spadSyntax{\&}) added at the end.  A default
package always takes an additional argument relative to the category.
Here is the definition of the default package \pspadtype{SemiGroup\&}
as automatically generated by Axiom from the above definition of
\spadtype{SemiGroup}.

\beginImportant
  
\noindent
{\tt 1.\ \ \ SemiGroup\_\&(\$):\ Exports\ ==\ Implementation\ where}
\newline
{\tt 2.\ \ \ \ \ \$:\ SemiGroup}\newline
{\tt 3.\ \ \ \ \ Exports\ ==\ with}\newline
{\tt 4.\ \ \ \ \ \ \ "**":\ (\$,\ PositiveInteger)\ ->\ \$}\newline
{\tt 5.\ \ \ \ \ Implementation\ ==\ add}\newline
{\tt 6.\ \ \ \ \ \ \ import\ RepeatedSquaring(\$)}\newline
{\tt 7.\ \ \ \ \ \ \ x:\$\ **\ n:PositiveInteger\ ==\ expt(x,n)}\newline
\endImportant

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugCategoriesAxiomsPage}{ug12.ht}{Axioms}
\pagefrom{Categories}{ugCategoriesPage}
\pageto{Defaults}{ugCategoriesDefaultsPage}
\begin{chunk}{ug12.ht}
\begin{page}{ugCategoriesAxiomsPage}{12.7. Axioms}
\beginscroll

In \texht{the previous section}
{\downlink{``Defaults''}{ugCategoriesDefaultsPage}
in Section 12.6\ignore{ugCategoriesDefaults}}
you saw the complete Axiom program defining \index{axiom}
\spadtype{SemiGroup}.  According to this definition, semigroups (that
is, are sets with the operations \spadopFrom{*}{SemiGroup} and
\spadopFrom{**}{SemiGroup}.

You might ask: ``Aside from the notion of default packages, isn't a
category just a \spadgloss{macro}, that is, a shorthand equivalent to
the two operations \spadop{*} and \spadop{**} with their types?'' If a
category were a macro, every time you saw the word
\spadtype{SemiGroup}, you would rewrite it by its list of exported
operations.  Furthermore, every time you saw the exported operations
of \spadtype{SemiGroup} among the exports of a constructor, you could
conclude that the constructor exported \spadtype{SemiGroup}.

A category is {\it not} a macro and here is why.
The definition for \spadtype{SemiGroup} has documentation that states:

\texht{\begin{quotation}}{\indent{3}}
    Category \spadtype{SemiGroup} denotes the class of all multiplicative
    semigroups, that is, a set with an associative operation \spadop{*}.

    \texht{\vskip .5\baselineskip}{}
    {Axioms:}

    {\small\tt associative("*" : (\$,\$)->\$) -- (x*y)*z = x*(y*z)}
\texht{\end{quotation}}{\indent{3}}

According to the author's remarks, the mere exporting of an operation
named \spadop{*} and \spadop{**} is not enough to qualify the domain
as a \spadtype{SemiGroup}.  In fact, a domain can be a semigroup only
if it explicitly exports a \spadop{**} and a \spadop{*} satisfying the
associativity axiom.

In general, a category name implies a set of axioms, even mathematical
theorems.  There are numerous axioms from \spadtype{Ring}, for
example, that are well-understood from the literature.  No attempt is
made to list them all.  Nonetheless, all such mathematical facts are
implicit by the use of the name \spadtype{Ring}.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugCategoriesCorrectnessPage}{ug12.ht}{Correctness}
\pagefrom{Categories}{ugCategoriesPage}
\begin{chunk}{ug12.ht}
\begin{page}{ugCategoriesCorrectnessPage}{12.8. Correctness}
\beginscroll

While such statements are only comments,
Axiom can enforce their intention simply by shifting the burden of
responsibility onto the author of a domain.
A domain belongs to category \spad{Ring} only if the
author asserts that the domain  belongs to \spadtype{Ring} or
to a category that extends \spadtype{Ring}.

This principle of assertion is important for large user-extendable
systems.
Axiom has a large library of operations offering facilities in
many areas.
Names such as \spadfun{norm} and \spadfun{product}, for example, have
diverse meanings in diverse contexts.
An inescapable hindrance to users would be to force those who wish to
extend Axiom to always invent new names for operations.
%>> I don't think disambiguate is really a word, though I like it
Axiom allows you to reuse names, and then use context to disambiguate one
from another.

Here is another example of why this is important.  Some languages,
such as {\bf APL}, denote the \spadtype{Boolean} constants \spad{true}
and \spad{false} by the integers \spad{1} and \spad{0}.  You may want
to let infix operators \spadop{+} and \spadop{*} serve as the logical
operators \spadfun{or} and \spadfun{and}, respectively.  But note
this: \spadtype{Boolean} is not a ring.  The {\it inverse axiom} for
\spadtype{Ring} states:

\centerline{
{Every element \spad{x} has an additive inverse \spad{y} such that}}
\centerline{{\spad{x + y = 0}.}}
%
\spadtype{Boolean} is not a ring since \spad{true} has
no inverse---there is no inverse element \spad{a} such that
\spad{1 + a = 0} (in terms of booleans, \spad{(true or a) = false}).
Nonetheless, Axiom {\it could} easily and correctly implement
\spadtype{Boolean} this way.
\spadtype{Boolean} simply would not assert that it is of category
\spadtype{Ring}.
Thus the \spadop{+} for \spadtype{Boolean} values
is not confused with the one for \spadtype{Ring}.
Since the \spadtype{Polynomial} constructor requires its argument
to be a ring, Axiom would then refuse to build the
domain \spadtype{Polynomial(Boolean)}. Also, Axiom would refuse to
wrongfully apply algorithms to \spadtype{Boolean} elements that  
presume that the ring axioms for \spadop{+} hold.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugCategoriesAttributesPage}{ug12.ht}{Attributes}
\pagefrom{Categories}{ugCategoriesPage}
\pageto{Category Assertions}{ugDomainsAssertionsPage}
\begin{chunk}{ug12.ht}
\begin{page}{ugCategoriesAttributesPage}{12.9. Attributes}
\beginscroll

Most axioms are not computationally useful.
Those that are can be explicitly expressed by what Axiom calls an
\spadgloss{attribute}.
The attribute \spadatt{commutative("*")}, for example, is used to assert
that a domain has commutative multiplication.
Its definition is given by its documentation:

\texht{\begingroup \parindent=1pc \narrower\noindent}{\indent{3}}%
    A domain \spad{R} has \spadatt{commutative("*")}
    if it has an operation "*": \spadsig{(R,R)}{R} 
such that \spad{x * y = y * x}.
\texht{\par\endgroup}{\indent{0}}

Just as you can test whether a domain has the category \spadtype{Ring}, you
can test that a domain has a given attribute.

\xtc{
Do polynomials over the integers
have commutative multiplication?
}{
\spadpaste{Polynomial Integer has commutative("*")}
}
\xtc{
Do matrices over the integers
have commutative multiplication?
}{
\spadpaste{Matrix Integer has commutative("*")}
}

Attributes are used to conditionally export and define
operations for a domain (see 
\downlink{``Category Assertions''}{ugDomainsAssertionsPage} in 
Section 13.3\ignore{ugDomainsAssertions}).
Attributes can also be asserted in a category definition.

After mentioning category \spadtype{Ring} many times in this book,
it is high time that we show you its definition:

\beginImportant
  
\noindent
{\tt 1.\ \ \ Ring():\ Category\ ==}\newline
{\tt 2.\ \ \ \ \ Join(Rng,Monoid,LeftModule(\$:\ Rng))\ with}\newline
{\tt 3.\ \ \ \ \ \ \ \ \ characteristic:\ ->\ NonNegativeInteger}\newline
{\tt 4.\ \ \ \ \ \ \ \ \ coerce:\ Integer\ ->\ \$}\newline
{\tt 5.\ \ \ \ \ \ \ \ \ unitsKnown}\newline
{\tt 6.\ \ \ \ \ \ \ add}\newline
{\tt 7.\ \ \ \ \ \ \ \ \ n:Integer}\newline
{\tt 8.\ \ \ \ \ \ \ \ \ coerce(n)\ ==\ n\ *\ 1\$\$}\newline
\endImportant

There are only two new things here.  First, look at the
\spadSyntax{\$\$} on the last line.  This is not a typographic error!
The first \spadSyntax{\$} says that the \spad{1} is to come from some
domain.  The second \spadSyntax{\$} says that the domain is ``this
domain.''  If \spadSyntax{\$} is \spadtype{Fraction(Integer)}, this
line reads {\tt coerce(n) == n * 1\$Fraction(Integer)}.

The second new thing is the presence of attribute
``\spad{unitsKnown}''.  Axiom can always distinguish an attribute from
an operation.  An operation has a name and a type. An attribute has no
type.  The attribute \spadatt{unitsKnown} asserts a rather subtle
mathematical fact that is normally taken for granted when working with
rings.\footnote{With this axiom, the units of a domain are the set of
elements \spad{x} that each have a multiplicative inverse \spad{y} in
the domain.  Thus \spad{1} and \spad{-1} are units in domain
\spadtype{Integer}.  Also, for \spadtype{Fraction Integer}, the domain
of rational numbers, all non-zero elements are units.}  Because
programs can test for this attribute, Axiom can correctly handle
rather more complicated mathematical structures (ones that are similar
to rings but do not have this attribute).

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugCategoriesAttributesPagePatch1}
\begin{paste}{ugCategoriesAttributesPageFull1}{ugCategoriesAttributesPageEmpty1}
\pastebutton{ugCategoriesAttributesPageFull1}{\hidepaste}
\tab{5}\spadcommand{Polynomial Integer has commutative("*")}
\indentrel{3}\begin{verbatim}
   (1)  true
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugCategoriesAttributesPageEmpty1}
\begin{paste}{ugCategoriesAttributesPageEmpty1}{ugCategoriesAttributesPagePatch1}
\pastebutton{ugCategoriesAttributesPageEmpty1}{\showpaste}
\tab{5}\spadcommand{Polynomial Integer has commutative("*")}
\end{paste}\end{patch}

\begin{patch}{ugCategoriesAttributesPagePatch2}
\begin{paste}{ugCategoriesAttributesPageFull2}{ugCategoriesAttributesPageEmpty2}
\pastebutton{ugCategoriesAttributesPageFull2}{\hidepaste}
\tab{5}\spadcommand{Matrix Integer has commutative("*")}
\indentrel{3}\begin{verbatim}
   (2)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugCategoriesAttributesPageEmpty2}
\begin{paste}{ugCategoriesAttributesPageEmpty2}{ugCategoriesAttributesPagePatch2}
\pastebutton{ugCategoriesAttributesPageEmpty2}{\showpaste}
\tab{5}\spadcommand{Matrix Integer has commutative("*")}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugCategoriesParametersPage}{ug12.ht}{Parameters}
\pagefrom{Categories}{ugCategoriesPage}
\begin{chunk}{ug12.ht}
\begin{page}{ugCategoriesParametersPage}{12.10. Parameters}
\beginscroll

Like domain constructors, category constructors can also have
parameters.  For example, category \spadtype{MatrixCategory} is a
parameterized category for defining matrices over a ring \spad{R} so
that the matrix domains can have different representations and
indexing schemes.  Its definition has the form:

\beginImportant
  
\noindent
{\tt 1.\ \ \ MatrixCategory(R,Row,Col):\ Category\ ==}\newline
{\tt 2.\ \ \ \ \ \ \ TwoDimensionalArrayCategory(R,Row,Col)\ with\ ...}\newline
\endImportant

The category extends \spadtype{TwoDimensionalArrayCategory} with the
same arguments.  You cannot find
\spadtype{TwoDimensionalArrayCategory} in the algebraic hierarchy
listing.  Rather, it is a member of the data structure hierarchy,
given inside the back cover of this book.  In particular,
\spadtype{TwoDimensionalArrayCategory} is an extension of
\spadtype{HomogeneousAggregate} since its elements are all one type.

The domain \spadtype{Matrix(R)}, the class of matrices with coefficients
from domain \spad{R}, asserts that it is a member of category
\spadtype{MatrixCategory(R, Vector(R), Vector(R))}.
The parameters of a category must also have types.
The first parameter to \spadtype{MatrixCategory}
\spad{R} is required to be a ring.
The second and third are required to be domains of category
\spadtype{FiniteLinearAggregate(R)}.\footnote{%
This is another extension of
\spadtype{HomogeneousAggregate} that you can see in
the data structure hierarchy.}
In practice, examples of categories having parameters other than
domains are rare.

Adding the declarations for parameters to the definition for
\spadtype{MatrixCategory}, we have:

\beginImportant
  
\noindent
{\tt 1.\ \ \ R:\ Ring}\newline
{\tt 2.\ \ \ (Row,\ Col):\ FiniteLinearAggregate(R)}\newline
{\tt 3.\ \ \ }\newline
{\tt 4.\ \ \ MatrixCategory(R,\ Row,\ Col):\ Category\ ==}\newline
{\tt 5.\ \ \ \ \ \ \ 
TwoDimensionalArrayCategory(R,\ Row,\ Col)\ with\ ...}\newline
\endImportant

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugCategoriesConditionalsPage}{ug12.ht}{Conditionals}
\pagefrom{Categories}{ugCategoriesPage}
\pageto{Conditionals}{ugPackagesCondsPage}
\begin{chunk}{ug12.ht}
\begin{page}{ugCategoriesConditionalsPage}{12.11. Conditionals}
\beginscroll

As categories have parameters, the actual operations exported by a
category can depend on these parameters.
As an example, the operation \spadfunFrom{determinant}{MatrixCategory}
from category \spadtype{MatrixCategory} is only exported when the
underlying domain \spad{R} has commutative multiplication:

\begin{verbatim}
if R has commutative("*") then
   determinant: $ -> R
\end{verbatim}

Conditionals can also define conditional extensions of a category.
Here is a portion of the definition of \spadtype{QuotientFieldCategory}:

\beginImportant
  
\noindent
{\tt 1.\ \ \ QuotientFieldCategory(R)\ :\ Category\ ==\ ...\ with\ ...}\newline
{\tt 2.\ \ \ \ \ \ \ \ if\ R\ has\ OrderedSet\ then\ OrderedSet}\newline
{\tt 3.\ \ \ \ \ \ \ \ if\ R\ has\ IntegerNumberSystem\ then}\newline
{\tt 4.\ \ \ \ \ \ \ \ \ \ ceiling:\ \$\ ->\ R}\newline
{\tt 5.\ \ \ \ \ \ \ \ \ \ \ \ ...}\newline
\endImportant

Think of category \spadtype{QuotientFieldCategory(R)} as
denoting the domain \spadtype{Fraction(R)}, the
class of all fractions of the form \smath{a/b} for elements of \spad{R}.
The first conditional means in English:
``If the elements of \spad{R} are totally ordered (\spad{R}
is an \spadtype{OrderedSet}), then so are the fractions \smath{a/b}''.

The second conditional is used to conditionally export an
operation \spadfun{ceiling} which returns the smallest integer
greater than or equal to its argument.
Clearly, ``ceiling'' makes sense for integers but not for
polynomials and other algebraic structures.
Because of this conditional,
the domain \spadtype{Fraction(Integer)} exports
an operation
\spadfun{ceiling}: \spadsig{Fraction Integer}{Integer}, but
\spadtype{Fraction Polynomial Integer} does not.

Conditionals can also appear in the default definitions for the
operations of a category.
For example, a default definition for \spadfunFrom{ceiling}{Field}
within the part following the \spadop{add} reads:

\begin{verbatim}
if R has IntegerNumberSystem then
    ceiling x == ...
\end{verbatim}

Here the predicate used is identical to the predicate in the {\tt
Exports} part.  This need not be the case.  See
\downlink{``Conditionals''}{ugPackagesCondsPage} in Section
11.8\ignore{ugPackagesConds} for a more complicated
example.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugCategoriesAndPackagesPage}{ug12.ht}{Anonymous Categories}
\pagefrom{Categories}{ugCategoriesPage}
\pageto{Abstract Datatypes}{ugPackagesAbstractPage}
\begin{chunk}{ug12.ht}
\begin{page}{ugCategoriesAndPackagesPage}{12.12. Anonymous Categories}
\beginscroll

The part of a category to the right of a {\tt with} is also regarded
as a category---an ``anonymous category.''  Thus you have already seen
a category definition The {\tt Exports} part of the package
\pspadtype{DrawComplex}
(\downlink{``Abstract Datatypes''}{ugPackagesAbstractPage} in
Section 11.3\ignore{ugPackagesAbstract}) is an
anonymous category.  This is not necessary.  We could, instead, give
this category a name:

%
\beginImportant
  
\noindent
{\tt 1.\ \ \ DrawComplexCategory():\ Category\ ==\ with}\newline
{\tt 2.\ \ \ \ \ \ 
drawComplex:\ (C\ ->\ C,S,S,Boolean)\ ->\ VIEW3D}\newline
{\tt 3.\ \ \ \ \ \ 
drawComplexVectorField:\ (C\ ->\ C,S,S)\ ->\ VIEW3D}\newline
{\tt 4.\ \ \ \ \ \ setRealSteps:\ INT\ ->\ INT}\newline
{\tt 5.\ \ \ \ \ \ setImagSteps:\ INT\ ->\ INT}\newline
{\tt 6.\ \ \ \ \ \ setClipValue:\ DFLOAT->\ DFLOAT}\newline
\endImportant
%
and then define \spadtype{DrawComplex} by:
%
\beginImportant
  
\noindent
{\tt 1.\ \ \ DrawComplex():\ DrawComplexCategory\ ==\ Implementation}
\newline
{\tt 2.\ \ \ \ \ \ where}\newline
{\tt 3.\ \ \ \ \ \ \ \ \ ...}\newline
\endImportant
%

There is no reason, however, to give this list of exports a name
since no other domain or package exports it.
In fact, it is rare for a package to export a named category.
As you will see in the next chapter, however, it is very common
for the definition of domains to mention one or more category
before the {\tt with}.
\spadkey{with}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\chapter{Users Guide Chapter 13 (ug13.ht)}
\pagetitle{ugDomainsPage}{ug13.ht}{Domains}
\pageto{notitle}{ugPackagesDomsPage}
\pageto{notitle}{ugDomainsDefsPage}
\pageto{notitle}{ugDomainsAssertionsPage}
\pageto{notitle}{ugDomainsDemoPage}
\pageto{notitle}{ugDomainsBrowsePage}
\pageto{notitle}{ugDomainsRepPage}
\pageto{notitle}{ugDomainsMultipleRepsPage}
\pageto{notitle}{ugDomainsAddDomainPage}
\pageto{notitle}{ugDomainsDefaultsPage}
\pageto{notitle}{ugDomainsOriginsPage}
\pageto{notitle}{ugDomainsShortFormsPage}
\pageto{notitle}{ugDomainsCliffordPage}
\pageto{notitle}{ugDomsinsDatabasePage}
\begin{chunk}{ug13.ht}
\begin{page}{ugDomainsPage}{13. Domains}
\beginscroll

We finally come to the \spadgloss{domain constructor}.  A few subtle
differences between packages and domains turn up some interesting
issues.  We first discuss these differences then describe the
resulting issues by illustrating a program for the
\axiomType{QuadraticForm} constructor.  After a short example of an
algebraic constructor, \axiomType{CliffordAlgebra}, we show how you
use domain constructors to build a database query facility.

\beginmenu
\menudownlink{{13.1. Domains vs. Packages}}{ugPackagesDomsPage}
\menudownlink{{13.2. Definitions}}{ugDomainsDefsPage}
\menudownlink{{13.3. Category Assertions}}{ugDomainsAssertionsPage}
\menudownlink{{13.4. A Demo}}{ugDomainsDemoPage}
\menudownlink{{13.5. Browse}}{ugDomainsBrowsePage}
\menudownlink{{13.6. Representation}}{ugDomainsRepPage}
\menudownlink{{13.7. Multiple Representations}}{ugDomainsMultipleRepsPage}
\menudownlink{{13.8. Add Domain}}{ugDomainsAddDomainPage}
\menudownlink{{13.9. Defaults}}{ugDomainsDefaultsPage}
\menudownlink{{13.10. Origins}}{ugDomainsOriginsPage}
\menudownlink{{13.11. Short Forms}}{ugDomainsShortFormsPage}
\menudownlink{{13.12. Example 1: Clifford Algebra}}{ugDomainsCliffordPage}
\menudownlink{{13.13. Example 2: Building A Query Facility}}
{ugDomsinsDatabasePage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugPackagesDomsPage}{ug13.ht}{Domains vs. Packages}
\pageto{notitle}{ugPackagesPage}
\begin{chunk}{ug13.ht}
\begin{page}{ugPackagesDomsPage}{13.1. Domains vs. Packages}
\beginscroll

Packages are special cases of domains.  What is the difference between
a package and a domain that is not a package?  By definition, there is
only one difference: a domain that is not a package has the symbol
\axiomSyntax{\$} appearing somewhere among the types of its exported
operations.  The \axiomSyntax{\$} denotes ``this domain.'' If the
\axiomSyntax{\$} appears before the \axiomSyntax{->} in the type of a
signature, it means the operation takes an element from the domain as
an argument.  If it appears after the \axiomSyntax{->}, then the
operation returns an element of the domain.

If no exported operations mention \axiomSyntax{\$}, then evidently
there is nothing of interest to do with the objects of the domain.
You might then say that a package is a ``boring'' domain!  But, as you
saw in \downlink{``Packages''}{ugPackagesPage} in Chapter
11\ignore{ugPackages}, packages are a very useful
notion indeed.  The exported operations of a package depend solely on
the parameters to the package constructor and other explicit domains.

To summarize, domain constructors are versatile structures that serve
two distinct practical purposes: Those like \axiomType{Polynomial} and
\axiomType{List} describe classes of computational objects; others,
like \pspadtype{SortPackage}, describe packages of useful operations.
As in the last chapter, we focus here on the first kind.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugDomainsDefsPage}{ug13.ht}{Definitions}
\begin{chunk}{ug13.ht}
\begin{page}{ugDomainsDefsPage}{13.2. Definitions}
\beginscroll
%

The syntax for defining a domain constructor is the same as for any
function in Axiom:
\centerline{{\frenchspacing{\tt {\it DomainForm} : {\it Exports} == 
{\it Implementation}}}}
As this definition usually extends over many lines, a
\axiom{where} expression is generally used instead.
\spadkey{where}

\beginImportant
A recommended format for the definition of a domain is:\newline
{\tt%
{\it DomainForm} : Exports  ==  Implementation where \newline
\texht{\hspace*{.75pc}}{\tab{8}} 
{\it optional type declarations} \newline
\texht{\hspace*{.75pc}}{\tab{3}} 
Exports  ==  [{\it Category Assertions}] with \newline
\texht{\hspace*{2.0pc}}{\tab{8}} 
{\it list of exported operations} \newline
\texht{\hspace*{.75pc}}{\tab{3}} 
Implementation  ==  [{\it Add Domain}] add \newline
\texht{\hspace*{2.0pc}}{\tab{6}} 
[Rep := {\it Representation}] \newline
\texht{\hspace*{2.0pc}}{\tab{8}} 
{\it list of function definitions for exported operations}
}

\texht{\vskip 4pt}{}
Note: The brackets {\tt [ ]} here denote optionality.
\endImportant

A complete domain constructor definition for
\axiomType{QuadraticForm} is shown in Figure \ref{fig-quadform}.
Interestingly, this little domain illustrates all the new
concepts you need to learn.

\beginImportant
  
\noindent
{\tt 1.\ \ \ )abbrev\ domain\ QFORM\ QuadraticForm}\newline
{\tt 2.\ \ \ }\newline
{\tt 3.\ \ \ ++\ Description:}\newline
{\tt 4.\ \ \ ++\ \ \ 
This\ domain\ provides\ modest\ support\ for}\newline
{\tt 5.\ \ \ ++\ \ \ quadratic\ forms.}\newline
{\tt 6.\ \ \ 
QuadraticForm(n,\ K):\ Exports\ ==\ Implementation\ where}\newline
{\tt 7.\ \ \ \ \ \ \ n:\ PositiveInteger}\newline
{\tt 8.\ \ \ \ \ \ \ K:\ Field}\newline
{\tt 9.\ \ \ }\newline
{\tt 10.\ \ \ \ \ \ Exports\ ==\ AbelianGroup\ with}\newline
{\tt 11.\ \ \ \ \ \ \ \ quadraticForm:\ SquareMatrix(n,K)\ ->\ \$}\newline
{\tt 12.\ \ \ \ \ \ \ \ \ \ ++\ 
\bs{}axiom\{quadraticForm(m)\}\ creates\ a\ quadratic}\newline
{\tt 13.\ \ \ \ \ \ \ \ \ \ ++\ 
quadratic\ form\ from\ a\ symmetric,}\newline
{\tt 14.\ \ \ \ \ \ \ \ \ \ ++\ square\ matrix\ \bs{}axiom\{m\}.}\newline
{\tt 15.\ \ \ \ \ \ \ \ matrix:\ \$\ ->\ SquareMatrix(n,K)}\newline
{\tt 16.\ \ \ \ \ \ \ \ \ \ ++\ 
\bs{}axiom\{matrix(qf)\}\ creates\ a\ square\ matrix}\newline
{\tt 17.\ \ \ \ \ \ \ \ \ \ ++\ 
from\ the\ quadratic\ form\ \bs{}axiom\{qf\}.}\newline
{\tt 18.\ \ \ \ \ \ \ \ elt:\ (\$,\ DirectProduct(n,K))\ ->\ K}\newline
{\tt 19.\ \ \ \ \ \ \ \ \ \ ++\ 
\bs{}axiom\{qf(v)\}\ evaluates\ the\ quadratic\ form}\newline
{\tt 20.\ \ \ \ \ \ \ \ \ \ ++\ 
\bs{}axiom\{qf\}\ on\ the\ vector\ \bs{}axiom\{v\},}\newline
{\tt 21.\ \ \ \ \ \ \ \ \ \ ++\ producing\ a\ scalar.}\newline
{\tt 22.\ \ }\newline
{\tt 23.\ \ \ \ \ \ Implementation\ ==\ SquareMatrix(n,K)\ add}\newline
{\tt 24.\ \ \ \ \ \ \ \ Rep\ :=\ SquareMatrix(n,K)}\newline
{\tt 25.\ \ \ \ \ \ \ \ quadraticForm\ m\ ==}\newline
{\tt 26.\ \ \ \ \ \ \ \ \ \ not\ symmetric?\ m\ =>\ error}\newline
{\tt 27.\ \ \ \ \ \ \ \ \ \ \ \ 
"quadraticForm\ requires\ a\ symmetric\ matrix"}\newline
{\tt 28.\ \ \ \ \ \ \ \ \ \ m\ ::\ \$}\newline
{\tt 29.\ \ \ \ \ \ \ \ matrix\ q\ ==\ q\ ::\ Rep}\newline
{\tt 30.\ \ \ \ \ \ \ \ elt(q,v)\ ==\ dot(v,\ (matrix\ q\ *\ v))}\newline
%
\caption{The \protect\axiomType{QuadraticForm} domain.}\label{fig-quadform}
\endImportant

A domain constructor can take any number and type of parameters.
\axiomType{QuadraticForm} takes a positive integer \axiom{n} and a field
\axiom{K} as arguments.
Like a package, a domain has a set of explicit exports and an
implementation described by a capsule.
Domain constructors are documented in the same way as package constructors.

Domain \axiomType{QuadraticForm(n, K)}, for a given positive integer
\axiom{n} and domain \axiom{K}, explicitly exports three operations:
%
\indent{4}
\beginitems
\item\axiom{quadraticForm(A)} creates a quadratic form from a matrix
\axiom{A}.
\item\axiom{matrix(q)} returns the matrix \axiom{A} used to create
the quadratic form \axiom{q}.
\item\axiom{q.v} computes the scalar \texht{$v^TAv$}{transpose(v)*A*v}
for a given vector \axiom{v}.
\enditems
\indent{0}

Compared with the corresponding syntax given for the definition of a
package, you see that a domain constructor has three optional parts to
its definition: {\it Category Assertions}, {\it Add Domain}, and
{\it Representation}.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugDomainsAssertionsPage}{ug13.ht}{Category Assertions}
\pageto{notitle}{ugCategoriesCorrectnessPage}
\pageto{notitle}{ugCategoriesConditionalsPage}
\begin{chunk}{ug13.ht}
\begin{page}{ugDomainsAssertionsPage}{13.3. Category Assertions}
\beginscroll
%

The {\it Category Assertions} part of your domain constructor
definition lists those categories of which all domains created by the
constructor are unconditionally members.  The word ``unconditionally''
means that membership in a category does not depend on the values of
the parameters to the domain constructor.  This part thus defines the
link between the domains and the category hierarchies given on the
inside covers of this book.  As described in
\downlink{``Correctness''}{ugCategoriesCorrectnessPage}
in Section 12.8\ignore{ugCategoriesCorrectness}, it is
this link that makes it possible for you to pass objects of the
domains as arguments to other operations in Axiom.

Every \axiomType{QuadraticForm} domain is declared to be
unconditionally a member of category \axiomType{AbelianGroup}.  An
abelian group is a collection of elements closed under addition.
Every object {\it x} of an abelian group has an additive inverse {\it
y} such that \texht{$x + y = 0$}{\axiom{{\it x} + {\it y} = 0}}.  The
exports of an abelian group include \axiom{0}, \axiomOp{+},
\axiomOp{-}, and scalar multiplication by an integer.  After asserting
that \axiomType{QuadraticForm} domains are abelian groups, it is
possible to pass quadratic forms to algorithms that only assume
arguments to have these abelian group properties.

In
\downlink{``Conditionals''}{ugCategoriesConditionalsPage}
in Section 12.11\ignore{ugCategoriesConditionals}, you
saw that \axiomType{Fraction(R)}, a member of
\axiomType{QuotientFieldCategory(R)}, is a member of
\axiomType{OrderedSet} if \axiom{R} is a member of
\axiomType{OrderedSet}.  Likewise, from the {\tt Exports} part of the
definition of \axiomType{ModMonic(R, S)}, \begin{verbatim}
UnivariatePolynomialCategory(R) with
  if R has Finite then Finite
     ...
\end{verbatim}
you see that \axiomType{ModMonic(R, S)} is a member of
\axiomType{Finite} is \axiom{R} is.

The {\tt Exports} part of a domain definition is the same kind of
expression that can appear to the right of an \axiomSyntax{==} in a
category definition.  If a domain constructor is unconditionally a
member of two or more categories, a \axiom{Join} form is used.
\spadkey{Join} The {\tt Exports} part of the definition of
\axiomType{FlexibleArray(S)} reads, for example:
\begin{verbatim}
Join(ExtensibleLinearAggregate(S),
     OneDimensionalArrayAggregate(S)) with...
\end{verbatim}

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugDomainsDemoPage}{ug13.ht}{A Demo}
\begin{chunk}{ug13.ht}
\begin{page}{ugDomainsDemoPage}{13.4. A Demo}
\beginscroll
%
Before looking at the {\it Implementation} part of \axiomType{QuadraticForm},
let's try some examples.

\texht{\vskip 2pc}{}
\xtc{
Build a domain \axiom{QF}.
}{
\spadpaste{QF := QuadraticForm(2,Fraction Integer)\bound{x2}\free{x1}}
}
\xtc{
Define a matrix to be used to construct
a quadratic form.
}{
\spadpaste{A := matrix [[-1,1/2],[1/2,1]]\bound{x3}\free{x2}}
}
\xtc{
Construct the quadratic form.
A package call {\tt \$QF} is necessary since there
are other \axiomType{QuadraticForm} domains.
}{
\spadpaste{q : QF := quadraticForm(A)\bound{x4}\free{x3}}
}
\xtc{
Looks like a matrix. Try computing
the number of rows.
Axiom won't let you.
}{
\spadpaste{nrows q\free{x3}}
}
\xtc{
Create a direct product element \axiom{v}.
A package call is again necessary, but Axiom
understands your list as denoting a vector.
}{
\spadpaste{v := directProduct([2,-1])\$DirectProduct(2,Fraction Integer)
\bound{x5}\free{x4}}
}
\xtc{
Compute the product \texht{$v^TAv$}{transpose(v)*A*v}.
}{
\spadpaste{q.v\free{x5}}
}
\xtc{
What is 3 times \axiom{q} minus \axiom{q} plus \axiom{q}?
}{
\spadpaste{3*q-q+q\free{x4}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugDomainsDemoPagePatch1}
\begin{paste}{ugDomainsDemoPageFull1}{ugDomainsDemoPageEmpty1}
\pastebutton{ugDomainsDemoPageFull1}{\hidepaste}
\tab{5}\spadcommand{QF := QuadraticForm(2,Fraction Integer)\bound{x2 }\free{x1 }}
\indentrel{3}\begin{verbatim}
   (1)  QuadraticForm(2,Fraction Integer)
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsDemoPageEmpty1}
\begin{paste}{ugDomainsDemoPageEmpty1}{ugDomainsDemoPagePatch1}
\pastebutton{ugDomainsDemoPageEmpty1}{\showpaste}
\tab{5}\spadcommand{QF := QuadraticForm(2,Fraction Integer)\bound{x2 }\free{x1 }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsDemoPagePatch2}
\begin{paste}{ugDomainsDemoPageFull2}{ugDomainsDemoPageEmpty2}
\pastebutton{ugDomainsDemoPageFull2}{\hidepaste}
\tab{5}\spadcommand{A := matrix [[-1,1/2],[1/2,1]]\bound{x3 }\free{x2 }}
\indentrel{3}\begin{verbatim}
        Ú     1¿
        ³- 1  Ä³
        ³     2³
   (2)  ³      ³
        ³ 1    ³
        ³ Ä   1³
        À 2    Ù
                          Type: Matrix Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsDemoPageEmpty2}
\begin{paste}{ugDomainsDemoPageEmpty2}{ugDomainsDemoPagePatch2}
\pastebutton{ugDomainsDemoPageEmpty2}{\showpaste}
\tab{5}\spadcommand{A := matrix [[-1,1/2],[1/2,1]]\bound{x3 }\free{x2 }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsDemoPagePatch3}
\begin{paste}{ugDomainsDemoPageFull3}{ugDomainsDemoPageEmpty3}
\pastebutton{ugDomainsDemoPageFull3}{\hidepaste}
\tab{5}\spadcommand{q : QF := quadraticForm(A)\bound{x4 }\free{x3 }}
\indentrel{3}\begin{verbatim}
        Ú     1¿
        ³- 1  Ä³
        ³     2³
   (3)  ³      ³
        ³ 1    ³
        ³ Ä   1³
        À 2    Ù
                Type: QuadraticForm(2,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsDemoPageEmpty3}
\begin{paste}{ugDomainsDemoPageEmpty3}{ugDomainsDemoPagePatch3}
\pastebutton{ugDomainsDemoPageEmpty3}{\showpaste}
\tab{5}\spadcommand{q : QF := quadraticForm(A)\bound{x4 }\free{x3 }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsDemoPagePatch4}
\begin{paste}{ugDomainsDemoPageFull4}{ugDomainsDemoPageEmpty4}
\pastebutton{ugDomainsDemoPageFull4}{\hidepaste}
\tab{5}\spadcommand{nrows q\free{x3 }}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsDemoPageEmpty4}
\begin{paste}{ugDomainsDemoPageEmpty4}{ugDomainsDemoPagePatch4}
\pastebutton{ugDomainsDemoPageEmpty4}{\showpaste}
\tab{5}\spadcommand{nrows q\free{x3 }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsDemoPagePatch5}
\begin{paste}{ugDomainsDemoPageFull5}{ugDomainsDemoPageEmpty5}
\pastebutton{ugDomainsDemoPageFull5}{\hidepaste}
\tab{5}\spadcommand{v := directProduct([2,-1])$DirectProduct(2,Fraction Integer)\bound{x5 }\free{x4 }}
\indentrel{3}\begin{verbatim}
   (4)  [2,- 1]
                Type: DirectProduct(2,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsDemoPageEmpty5}
\begin{paste}{ugDomainsDemoPageEmpty5}{ugDomainsDemoPagePatch5}
\pastebutton{ugDomainsDemoPageEmpty5}{\showpaste}
\tab{5}\spadcommand{v := directProduct([2,-1])$DirectProduct(2,Fraction Integer)\bound{x5 }\free{x4 }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsDemoPagePatch6}
\begin{paste}{ugDomainsDemoPageFull6}{ugDomainsDemoPageEmpty6}
\pastebutton{ugDomainsDemoPageFull6}{\hidepaste}
\tab{5}\spadcommand{q.v\free{x5 }}
\indentrel{3}\begin{verbatim}
   (5)  - 5
                                 Type: Fraction Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsDemoPageEmpty6}
\begin{paste}{ugDomainsDemoPageEmpty6}{ugDomainsDemoPagePatch6}
\pastebutton{ugDomainsDemoPageEmpty6}{\showpaste}
\tab{5}\spadcommand{q.v\free{x5 }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsDemoPagePatch7}
\begin{paste}{ugDomainsDemoPageFull7}{ugDomainsDemoPageEmpty7}
\pastebutton{ugDomainsDemoPageFull7}{\hidepaste}
\tab{5}\spadcommand{3*q-q+q\free{x4 }}
\indentrel{3}\begin{verbatim}
        Ú     3¿
        ³- 3  Ä³
        ³     2³
   (6)  ³      ³
        ³ 3    ³
        ³ Ä   3³
        À 2    Ù
                Type: QuadraticForm(2,Fraction Integer)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsDemoPageEmpty7}
\begin{paste}{ugDomainsDemoPageEmpty7}{ugDomainsDemoPagePatch7}
\pastebutton{ugDomainsDemoPageEmpty7}{\showpaste}
\tab{5}\spadcommand{3*q-q+q\free{x4 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugDomainsBrowsePage}{ug13.ht}{Browse}
\begin{chunk}{ug13.ht}
\begin{page}{ugDomainsBrowsePage}{13.5. Browse}
\beginscroll

The \Browse{} facility of Hyperdoc is useful for
investigating
the properties of domains, packages, and categories.
From the main Hyperdoc menu, move your mouse to {\bf Browse} and
click on the left mouse button.
This brings up the \Browse{} first page.
Now, with your mouse pointer somewhere in this window, enter the
string ``quadraticform'' into the input area (all lower case
letters will do).
Move your mouse to {\bf Constructors} and click.
Up comes a page describing \axiomType{QuadraticForm}.

From here, click on {\bf Description}.
This gives you a page that includes a part labeled by ``{\it
Description:}''.
You also see the types for arguments \axiom{n} and \axiom{K}
displayed as well as the fact that \axiomType{QuadraticForm}
returns an \axiomType{AbelianGroup}.
You can go and experiment a bit by selecting {\bf Field} with
your mouse.
Eventually, use
\UpButton{}
several times to return to the first page on
\axiomType{QuadraticForm}.

Select {\bf Operations} to get a list of operations for
\axiomType{QuadraticForm}.
You can select an operation by clicking on it
to get an individual page with information about that operation.
Or you can select the buttons along the bottom to see alternative
views or get additional information on the operations.
Then return to the page on \axiomType{QuadraticForm}.

Select {\bf Cross Reference} to get another menu.
This menu has buttons for {\bf Parents}, {\bf Ancestors}, and
others.
Clicking on {\bf Parents}, you see that \axiomType{QuadraticForm}
has one parent \axiomType{AbelianMonoid}.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugDomainsRepPage}{ug13.ht}{Representation}
\pageto{notitle}{ugDomainsDemoPage}
\begin{chunk}{ug13.ht}
\begin{page}{ugDomainsRepPage}{13.6. Representation}
\beginscroll
%
The {\tt Implementation} part of an Axiom capsule for a
domain constructor uses the special variable \axiom{Rep} to
identify the lower level data type used to represent the objects
of the domain.
The \axiom{Rep} for quadratic forms is \axiomType{SquareMatrix(n, K)}.
This means that all objects of the domain are required to be
\axiom{n} by \axiom{n} matrices with elements from \axiomType{K}.

The code for \axiomFun{quadraticForm} in Figure \ref{fig-quadform} on
page \pageref{fig-quadform} checks that the matrix is symmetric and
then converts it to \axiomSyntax{\$}, which means, as usual, ``this
domain.'' Such explicit conversions \index{conversion} are generally
required by the compiler.  Aside from checking that the matrix is
symmetric, the code for this function essentially does nothing.  The
{\frenchspacing\tt m :: \$} on line 28 coerces \axiom{m} to a
quadratic form.  In fact, the quadratic form you created in step (3)
of \downlink{``A Demo''}{ugDomainsDemoPage} in Section
13.4\ignore{ugDomainsDemo} is just the matrix you
passed it in disguise!  Without seeing this definition, you would not
know that.  Nor can you take advantage of this fact now that you do
know!  When we try in the next step of
\downlink{``A Demo''}{ugDomainsDemoPage} in Section
13.4\ignore{ugDomainsDemo} to regard \axiom{q} as a
matrix by asking for \axiomFun{nrows}, the number of its rows, Axiom
gives you an error message saying, in effect, ``Good try, but this
won't work!''

The definition for the \spadfunFrom{matrix}{QuadraticForm}
function could hardly be simpler:
it just returns its argument after explicitly
\spadglossSee{coercing}{coerce} its argument to a matrix.
Since the argument is already a matrix, this coercion does no 
computation.

Within the context of a capsule, an object of \axiomSyntax{\$} is
regarded both as a quadratic form {\it and} as a
matrix.\footnote{In case each of \axiomSyntax{\$} and \axiom{Rep}
have the same named operation available,
the one from \axiom{\$} takes precedence.
Thus, if you want the one from \axiomSyntax{Rep}, you must
package call it using a \axiomSyntax{\$Rep} suffix.}
This makes the definition of \axiom{q.v} easy---it
just calls the \spadfunFrom{dot}{DirectProduct} product from
\axiomType{DirectProduct} to perform the indicated operation.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugDomainsMultipleRepsPage}{ug13.ht}{Multiple Representations}
\pageto{notitle}{ugTypesUnionsPage}
\begin{chunk}{ug13.ht}
\begin{page}{ugDomainsMultipleRepsPage}{13.7. Multiple Representations}
\beginscroll
%

To write functions that implement the operations of a domain, you
want to choose the most computationally efficient
data structure to represent the elements of your domain.

A classic problem in computer algebra is the optimal choice for an
internal representation of polynomials.
If you create a polynomial, say \texht{$3x^2+ 5$}{\axiom{3*x**2 + 5}}, 
how does Axiom hold this value internally?
There are many ways.
Axiom has nearly a dozen different representations of
polynomials, one to suit almost any purpose.
Algorithms for solving polynomial equations work most
efficiently with polynomials represented one way, whereas those for
factoring polynomials are most efficient using another.
One often-used representation is  a list of terms, each term
consisting of exponent-coefficient records written in the order
of decreasing exponents.
For example, the polynomial \texht{$3x^2+5$}{3*x**2+5} is
%>> I changed the k's in next line to e's as I thought that was
%>> clearer.
represented by the list \axiom{[[e:2, c:3], [e:0, c:5]]}.

What is the optimal data structure for a matrix?
It depends on the application.
For large sparse matrices, a linked-list structure of records
holding only the non-zero elements may be optimal.
If the elements can be defined by a simple formula
\texht{$f(i,j)$}{\axiom{f(i,j)}}, then a compiled function for
\axiom{f} may be optimal.
Some programmers prefer to represent ordinary matrices as vectors
of vectors.
Others prefer to represent matrices by one big linear array where
elements are accessed with linearly computable indexes.

While all these simultaneous structures tend to be confusing,
Axiom provides a helpful organizational tool for such a purpose:
categories.
\axiomType{PolynomialCategory}, for example, provides a uniform user
interface across all polynomial types.
Each kind of polynomial implements functions for
all these operations, each in its own way.
If you use only the top-level operations in
\axiomType{PolynomialCategory} you usually do not care what kind
of polynomial implementation is used.

%>> I've often thought, though, that it would be nice to be
%>> be able to use conditionals for representations.

Within a given domain, however, you define (at most) one
representation.\footnote{You can make that representation a
\pspadtype{Union} type, however.  See
\downlink{``Unions''}{ugTypesUnionsPage} in Section
2.5\ignore{ugTypesUnions} for examples of unions.}
If you want to have multiple representations (that is, several
domains, each with its own representation), use a category to describe
the {\tt Exports}, then define separate domains for each
representation.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugDomainsAddDomainPage}{ug13.ht}{Add Domain}
\pageto{notitle}{ugDomainsDemoPage}
\begin{chunk}{ug13.ht}
\begin{page}{ugDomainsAddDomainPage}{13.8. Add Domain}
\beginscroll
%

The capsule part of {\tt Implementation} defines functions that
implement the operations exported by the domain---usually only some of
the operations.  In our demo in
\downlink{``A Demo''}{ugDomainsDemoPage} in Section
13.4\ignore{ugDomainsDemo}, we asked for the value of
\axiom{3*q-q+q}.  Where do the operations \axiomOp{*}, \axiomOp{+},
and \axiomOp{-} come from?  There is no definition for them in the
capsule!

The {\tt Implementation} part of a definition can optionally specify
an ``add-domain'' to the left of an {\tt add} \spadkey{add} (for
\axiomType{QuadraticForm}, defines \axiomType{SquareMatrix(n,K)} is
the add-domain).  The meaning of an add-domain is simply this: if the
capsule part of the {\tt Implementation} does not supply a function
for an operation, Axiom goes to the add-domain to find the function.
So do \axiomOpFrom{*}{QuadraticForm}, \axiomOpFrom{+}{QuadraticForm}
and \axiomOpFrom{-}{QuadraticForm} come from
\axiomType{SquareMatrix(n,K)}?

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugDomainsDefaultsPage}{ug13.ht}{Defaults}
\pageto{notitle}{ugPackagesPage}
\pageto{notitle}{ugCategoriesDefaultsPage}
\begin{chunk}{ug13.ht}
\begin{page}{ugDomainsDefaultsPage}{13.9. Defaults}
\beginscroll
%
In \downlink{``Packages''}{ugPackagesPage} in 
Chapter 11\ignore{ugPackages}, we saw that 
categories can provide
default implementations for their operations.
How and when are they used?
When Axiom finds that \axiomType{QuadraticForm(2, Fraction Integer)} 
does not implement the operations \axiomOp{*},
\axiomOp{+}, and \axiomOp{-}, it goes to
\axiomType{SquareMatrix(2,Fraction Integer)} to find it.
As it turns out, \axiomType{SquareMatrix(2, Fraction Integer)} does
not implement {\it any} of these operations!

What does Axiom do then?  Here is its overall strategy.  First, Axiom
looks for a function in the capsule for the domain.  If it is not
there, Axiom looks in the add-domain for the operation.  If that
fails, Axiom searches the add-domain of the add-domain, and so on.  If
all those fail, it then searches the default packages for the
categories of which the domain is a member.  In the case of
\axiomType{QuadraticForm}, it searches \axiomType{AbelianGroup}, then
its parents, grandparents, and so on.  If this fails, it then searches
the default packages of the add-domain.  Whenever a function is found,
the search stops immediately and the function is returned.  When all
fails, the system calls \axiomFun{error} to report this unfortunate
news to you.  To find out the actual order of constructors searched
for \axiomType{QuadraticForm}, consult \Browse{}: from the
\axiomType{QuadraticForm}, click on {\bf Cross Reference}, then on
{\bf Lineage}.

Let's apply this search strategy for our example \axiom{3*q-q+q}.  The
scalar multiplication comes first.  Axiom finds a default
implementation in \axiomType{AbelianGroup\&}.  Remember from
\downlink{``Defaults''}{ugCategoriesDefaultsPage} in
Section 12.6\ignore{ugCategoriesDefaults} that
\axiomType{SemiGroup} provides a default definition for
\texht{$x^n$}{x**n} by repeated squaring?  \axiomType{AbelianGroup}
similarly provides a definition for \texht{$n x$}{n*x} by repeated
doubling.

But the search of the defaults for \axiomType{QuadraticForm} fails to
find any \axiomOp{+} or \axiomOp{*} in the default packages for the
ancestors of \axiomType{QuadraticForm}.  So it now searches among
those for \axiomType{SquareMatrix}.  Category
\axiomType{MatrixCategory}, which provides a uniform interface for all
matrix domains, is a grandparent of \axiomType{SquareMatrix} and has a
capsule defining many functions for matrices, including matrix
addition, subtraction, and scalar multiplication.  The default package
\axiomType{MatrixCategory\&} is where the functions for
\axiomOpFrom{+}{QuadraticForm} and \spadfunFrom{-}{QuadraticForm} come
from.

You can use \Browse{} to discover where the operations for
\axiomType{QuadraticForm} are implemented.  First, get the page
describing \axiomType{QuadraticForm}.  With your mouse somewhere in
this window, type a ``2'', press the \texht{\fbox{\bf Tab}}{{\bf Tab}}
key, and then enter ``Fraction Integer'' to indicate that you want the
domain \axiomType{QuadraticForm(2, Fraction Integer)}.  Now click on
{\bf Operations} to get a table of operations and on \axiomOp{*} to
get a page describing the \axiomOp{*} operation.  Finally, click on
{\bf implementation} at the bottom.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugDomainsOriginsPage}{ug13.ht}{Origins}
\begin{chunk}{ug13.ht}
\begin{page}{ugDomainsOriginsPage}{13.10. Origins}
\beginscroll
%

Aside from the notion of where an operation is implemented, a useful
notion is the {\it origin} or ``home'' of an operation.  When an
operation (such as \spadfunFrom{quadraticForm}{QuadraticForm}) is
explicitly exported by a domain (such as \axiomType{QuadraticForm}),
you can say that the origin of that operation is that domain.  If an
operation is not explicitly exported from a domain, it is inherited
from, and has as origin, the (closest) category that explicitly
exports it.  The operations \axiomOpFrom{+}{AbelianMonoid} and
\axiomOpFrom{-}{AbelianMonoid} of \axiomType{QuadraticForm}, for
example, are inherited from \axiomType{AbelianMonoid}.  As it turns
out, \axiomType{AbelianMonoid} is the origin of virtually every
\axiomOp{+} operation in Axiom!

Again, you can use \Browse{} to discover the origins of operations.
From the \Browse{} page on \axiomType{QuadraticForm}, click on {\bf
Operations}, then on {\bf origins} at the bottom of the page.

The origin of the operation is the {\it only} place where on-line
documentation is given.  However, you can re-export an operation to
give it special documentation.  Suppose you have just invented the
world's fastest algorithm for inverting matrices using a particular
internal representation for matrices.  If your matrix domain just
declares that it exports \axiomType{MatrixCategory}, it exports the
\axiomFun{inverse} operation, but the documentation the user gets from
\Browse{} is the standard one from \axiomType{MatrixCategory}.  To
give your version of \axiomFun{inverse} the attention it deserves,
simply export the operation explicitly with new documentation.  This
redundancy gives \axiomFun{inverse} a new origin and tells \Browse{}
to present your new documentation.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugDomainsShortFormsPage}{ug13.ht}{Short Forms}
\begin{chunk}{ug13.ht}
\begin{page}{ugDomainsShortFormsPage}{13.11. Short Forms}
\beginscroll

In Axiom, a domain could be defined using only an add-domain and no
capsule.  Although we talk about rational numbers as quotients of
integers, there is no type \pspadtype{RationalNumber} in Axiom.  To
create such a type, you could compile the following ``short-form''
definition:

\beginImportant
  
\noindent
{\tt 1.\ \ \ RationalNumber()\ ==\ Fraction(Integer)}\newline
\endImportant

The {\tt Exports} part of this definition is missing and is taken to
be equivalent to that of \axiomType{Fraction(Integer)}.  Because of
the add-domain philosophy, you get precisely what you want.  The
effect is to create a little stub of a domain.  When a user asks to
add two rational numbers, Axiom would ask \pspadtype{RationalNumber}
for a function implementing this \axiomOp{+}.  Since the domain has no
capsule, the domain then immediately sends its request to
\axiomType{Fraction (Integer)}.

The short form definition for domains is used to
define such domains as \axiomType{MultivariatePolynomial}:

\beginImportant
  
\noindent
{\tt 1.\ \ \ MultivariatePolynomial(vl:\ List\ Symbol,\ R:\ Ring)\ ==}
\newline
{\tt 2.\ \ \ \ \ \ SparseMultivariatePolynomial(R,}\newline
{\tt 3.\ \ \ \ \ \ \ \ \ OrderedVariableList\ vl)}\newline
\endImportant

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugDomainsCliffordPage}{ug13.ht}{Example 1: Clifford Algebra}
\pageto{notitle}{CliffordAlgebraXmpPage}
\begin{chunk}{ug13.ht}
\begin{page}{ugDomainsCliffordPage}{13.12. Example 1: Clifford Algebra}
\beginscroll
%

Now that we have \axiomType{QuadraticForm} available,
let's put it to use.
Given some quadratic form \smath{Q} described by an
\smath{n} by \smath{n} matrix over a field \smath{K}, the domain
\axiomType{CliffordAlgebra(n, K, Q)} defines a vector space of
dimension \texht{$2^n$}{2**n} over \smath{K}.
This is an interesting domain since complex numbers, quaternions,
exterior algebras and spin algebras are all examples of Clifford
algebras.

The basic idea is this:
the quadratic form \axiom{Q} defines a basis
\texht{$e_1,e_2\ldots,e_n$}{e1,e2,...,en} for the
vector space \texht{$K^n$}{K**n}---the direct product of \axiom{K}
with itself \axiom{n} times.
From this, the Clifford algebra generates a basis of
\texht{$2^n$}{2**n} elements given by all the possible products
of the \texht{$e_i$}{\axiom{ei}} in order without duplicates, that is,
\texht{
1,
$e_1$,
$e_2$,
$e_1e_2$,
$e_3$,
$e_1e_3$,
$e_2e_3$,
$e_1e_2,e_3$}{1, e1, e2, e1*e2, e3, e1*e3, e2*e3, e1*e2*e3},
and so on.

The algebra is defined by the relations
\begin{verbatim}
ei*ei = Q(ei)
ei*ej = -ej*ei,  i ^= j
\end{verbatim}

Now look at the snapshot of its definition given in Figure
\ref{fig-clifalg}.
Lines 9-10 show part of the definitions of the {\tt Exports}.
A Clifford algebra over a field \axiom{K} is asserted to be a ring,
an algebra over \axiom{K}, and a vector space over \axiom{K}.
Its explicit exports include
\axiom{e(n),} which returns the \eth{\axiom{n}} unit element.

\beginImportant
  
\noindent
{\tt 1.\ \ \ NNI\ ==>\ NonNegativeInteger}\newline
{\tt 2.\ \ \ PI\ \ ==>\ PositiveInteger}\newline
{\tt 3.\ \ \ }\newline
{\tt 4.\ \ \ 
CliffordAlgebra(n,K,q):\ Exports\ ==\ Implementation\ where}\newline
{\tt 5.\ \ \ \ \ \ \ n:\ PI}\newline
{\tt 6.\ \ \ \ \ \ \ K:\ Field}\newline
{\tt 7.\ \ \ \ \ \ \ q:\ QuadraticForm(n,\ K)}\newline
{\tt 8.\ \ \ }\newline
{\tt 9.\ \ \ \ \ \ \ 
Exports\ ==\ Join(Ring,Algebra(K),VectorSpace(K))\ with}\newline
{\tt 10.\ \ \ \ \ \ \ \ e:\ PI\ ->\ \$}\newline
{\tt 11.\ \ \ \ \ \ \ \ \ \ \ \ ...\ \ \ \ \ \ \ \ }\newline
{\tt 12.\ \ }\newline
{\tt 13.\ \ \ \ \ \ Implementation\ ==\ add}\newline
{\tt 14.\ \ \ \ \ \ \ \ Qeelist\ :=\ \ }\newline
{\tt 15.\ \ \ \ \ \ \ \ \ \ 
[q.unitVector(i::PI)\ for\ i\ in\ 1..n]}\newline
{\tt 16.\ \ \ \ \ \ \ \ dim\ \ \ \ \ :=\ \ 2**n}\newline
{\tt 17.\ \ \ \ \ \ \ \ Rep\ \ \ \ \ :=\ PrimitiveArray\ K}\newline
{\tt 18.\ \ \ \ \ \ \ \ New\ ==>\ new(dim,\ 0\$K)\$Rep}\newline
{\tt 19.\ \ \ \ \ \ \ \ x\ +\ y\ ==}\newline
{\tt 20.\ \ \ \ \ \ \ \ \ \ z\ :=\ New}\newline
{\tt 21.\ \ \ \ \ \ \ \ \ \ 
for\ i\ in\ 0..dim-1\ repeat\ z.i\ :=\ x.i\ +\ y.i}\newline
{\tt 22.\ \ \ \ \ \ \ \ \ \ z}\newline
{\tt 23.\ \ \ \ \ \ \ \ 
addMonomProd:\ (K,\ NNI,\ K,\ NNI,\ \$)\ ->\ \$}\newline
{\tt 24.\ \ \ \ \ \ \ \ 
addMonomProd(c1,\ b1,\ c2,\ b2,\ z)\ ==\ \ ...}\newline
{\tt 25.\ \ \ \ \ \ \ \ x\ *\ y\ ==}\newline
{\tt 26.\ \ \ \ \ \ \ \ \ \ z\ :=\ New}\newline
{\tt 27.\ \ \ \ \ \ \ \ \ \ for\ ix\ in\ 0..dim-1\ repeat}\newline
{\tt 28.\ \ \ \ \ \ \ \ \ \ \ \ 
if\ x.ix\ \notequal{}\ 0\ then\ for\ iy\ in\ 0..dim-1\ repeat}\newline
{\tt 29.\ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ y.iy\ \notequal{}\ 0}\newline
{\tt 30.\ \ \ \ \ \ \ \ \ \ \ \ \ \ 
then\ addMonomProd(x.ix,ix,y.iy,iy,z)}\newline
{\tt 31.\ \ \ \ \ \ \ \ \ \ \ \ z}\newline
{\tt 32.\ \ \ \ \ \ \ \ \ \ \ \ \ ...}\newline
\caption{Part of the \protect\axiomType{CliffordAlgebra} domain.}
\label{fig-clifalg}
\endImportant

The {\tt Implementation} part begins by defining a local variable
\axiom{Qeelist} to hold the list of all \axiom{q.v} where \axiom{v}
runs over the unit vectors from 1 to the dimension \axiom{n}.
Another local variable \axiom{dim} is set to \texht{$2^n$}{2**n},
computed once and for all.
The representation for the domain is
\axiomType{PrimitiveArray(K)},
which is a basic array of elements from domain \axiom{K}.
Line 18 defines \axiom{New} as shorthand for the more lengthy
expression \axiom{new(dim, 0\$K)\$Rep}, which computes a primitive
array of length \texht{$2^n$}{2**n} filled with \axiom{0}'s from
domain \axiom{K}.

Lines 19-22 define the sum of two elements \axiom{x} and \axiom{y}
straightforwardly.
First, a new array of all \axiom{0}'s is created, then filled with
the sum of the corresponding elements.
Indexing for primitive arrays starts at 0.
The definition of the product of \axiom{x} and \axiom{y} first requires
the definition of a local function \userfun{addMonomProd}.
Axiom knows it is local since it is not an exported function.
The types of all local functions must be declared.

For a demonstration of \axiomType{CliffordAlgebra}, see
\downlink{`CliffordAlgebra'}{CliffordAlgebraXmpPage}
\ignore{CliffordAlgebra}.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugDomsinsDatabasePage}{ug13.ht}
{Example 2: Building A Query Facility}
\pageto{notitle}{ugDomainsQueryLanguagePage}
\pageto{notitle}{ugDomainsDatabaseConstructorPage}
\pageto{notitle}{ugDomainsQueryEquationsPage}
\pageto{notitle}{ugDomainsDataListsPage}
\pageto{notitle}{ugDomainsDatabasePage}
\pageto{notitle}{ugDomainsCreatingPage}
\pageto{notitle}{ugDomainsPuttingPage}
\pageto{notitle}{ugDomainsExamplesPage}
\begin{chunk}{ug13.ht}
\begin{page}{ugDomsinsDatabasePage}
{13.13. Example 2: Building A Query Facility}
\beginscroll
%
We now turn to an entirely different kind of application,
building a query language for a database.

Here is the practical problem to solve.
The \Browse{} facility of Axiom has a
database for all operations and constructors which is
stored on disk and accessed by Hyperdoc.
For our purposes here, we regard each line of this file as having
eight fields:
{\tt class, name, type, nargs, exposed, kind, origin,} and {\tt condition.}
Here is an example entry:

\begin{verbatim}
o`determinant`$->R`1`x`d`Matrix(R)`has(R,commutative("*"))
\end{verbatim}

In English, the entry means:
\texht{\begin{quotation}}{\newline}
\texht{\raggedright}{}
The operation \axiomFun{determinant}: \spadsig{\$}{R} with {\it 1} 
argument, is
{\it exposed} and is exported by {\it domain} \axiomType{Matrix(R)}
if {\tt R has commutative("*")}.
\texht{\end{quotation}}{\newline}

Our task is to create a little query language that allows us
to get useful information from this database.

\beginmenu
\menudownlink{{13.13.1. A Little Query Language}}
{ugDomainsQueryLanguagePage}
\menudownlink{{13.13.2. The Database Constructor}}
{ugDomainsDatabaseConstructorPage}
\menudownlink{{13.13.3. Query Equations}}{ugDomainsQueryEquationsPage}
\menudownlink{{13.13.4. DataLists}}{ugDomainsDataListsPage}
\menudownlink{{13.13.5. Index Cards}}{ugDomainsDatabasePage}
\menudownlink{{13.13.6. Creating a Database}}{ugDomainsCreatingPage}
\menudownlink{{13.13.7. Putting It All Together}}{ugDomainsPuttingPage}
\menudownlink{{13.13.8. Example Queries}}{ugDomainsExamplesPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugDomainsQueryLanguagePage}{ug13.ht}{A Little Query Language}
\begin{chunk}{ug13.ht}
\begin{page}{ugDomainsQueryLanguagePage}{13.13.1. A Little Query Language}
\beginscroll

First we design a simple language for accessing information from
the database.
We have the following simple model in mind for its design.
Think of the database as a box of index cards.
There is only one search operation---it
takes the name of a field and a predicate
(a boolean-valued function) defined on the fields of the
index cards.
When applied, the search operation goes through the entire box
selecting only those index cards for which the predicate is true.
The result of a search is a new box of index cards.
This process can be repeated again and again.

The predicates all have a particularly simple form: {\it symbol}
{\tt =} {\it pattern}, where {\it symbol} designates one of the
fields, and {\it pattern} is a ``search string''---a string
that may contain a ``{\tt *}'' as a
wildcard.
Wildcards match any substring, including the empty string.
Thus the pattern {\tt "*ma*t"} matches
{\tt "mat", "doormat"} and {\tt "smart".}

To illustrate how queries are given, we give you a sneak preview
of the facility we are about to create.

\xtc{
Extract the database of all Axiom operations.
}{
\spadpaste{ops := getDatabase("o")\bound{o1}}
}
\xtc{
How many exposed three-argument \axiomFun{map} operations involving 
streams?
}{
\spadpaste{ops.(name="map").(nargs="3").(type="*Stream*")
\bound{o2}\free{o1}}
}

As usual, the arguments of \axiomFun{elt} (\axiomSyntax{.})
associate to the left.
The first \axiomFun{elt} produces the set of all operations with
name {\tt map}.
The second \axiomFun{elt} produces the set of all map operations
with three arguments.
The third \axiomFun{elt} produces the set of all three-argument map
operations having a type mentioning \axiomType{Stream}.

Another thing we'd like to do is to extract one field from each of
the index cards in the box and look at the result.
Here is an example of that kind of request.

\xtc{
What constructors explicitly export a \axiomFun{determinant} operation?
}{
\spadpaste{
elt(elt(elt(elt(ops,name="determinant"),origin),sort),unique)\free{o1}}
}

The first \axiomFun{elt} produces the set of all index cards with
name {\tt determinant}.
The second \axiomFun{elt} extracts the {\tt origin} component from
each index card. Each origin component
is the name of a constructor which directly
exports the operation represented by the index card.
Extracting a component from each index card produces what we call
a {\it datalist}.
The third \axiomFun{elt}, {\tt sort}, causes the datalist of
origins to be sorted in alphabetic
order.
The fourth, {\tt unique}, causes duplicates to be removed.

Before giving you a more extensive demo of this facility,
we now build the necessary domains and packages to implement it.
%We will introduce a few of our minor conveniences.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugDomainsQueryLanguagePagePatch1}
\begin{paste}{ugDomainsQueryLanguagePageFull1}{ugDomainsQueryLanguagePageEmpty1}
\pastebutton{ugDomainsQueryLanguagePageFull1}{\hidepaste}
\tab{5}\spadcommand{ops := getDatabase("o")\bound{o1 }}
\indentrel{3}\begin{verbatim}
   (1)  6315
                               Type: Database IndexCard
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsQueryLanguagePageEmpty1}
\begin{paste}{ugDomainsQueryLanguagePageEmpty1}{ugDomainsQueryLanguagePagePatch1}
\pastebutton{ugDomainsQueryLanguagePageEmpty1}{\showpaste}
\tab{5}\spadcommand{ops := getDatabase("o")\bound{o1 }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsQueryLanguagePagePatch2}
\begin{paste}{ugDomainsQueryLanguagePageFull2}{ugDomainsQueryLanguagePageEmpty2}
\pastebutton{ugDomainsQueryLanguagePageFull2}{\hidepaste}
\tab{5}\spadcommand{ops.(name="map").(nargs="3").(type="*Stream*")\bound{o2 }\free{o1 }}
\indentrel{3}\begin{verbatim}
   (2)  3
                               Type: Database IndexCard
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsQueryLanguagePageEmpty2}
\begin{paste}{ugDomainsQueryLanguagePageEmpty2}{ugDomainsQueryLanguagePagePatch2}
\pastebutton{ugDomainsQueryLanguagePageEmpty2}{\showpaste}
\tab{5}\spadcommand{ops.(name="map").(nargs="3").(type="*Stream*")\bound{o2 }\free{o1 }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsQueryLanguagePagePatch3}
\begin{paste}{ugDomainsQueryLanguagePageFull3}{ugDomainsQueryLanguagePageEmpty3}
\pastebutton{ugDomainsQueryLanguagePageFull3}{\hidepaste}
\tab{5}\spadcommand{elt(elt(elt(elt(ops,name="determinant"),origin),sort),unique)\free{o1 }}
\indentrel{3}\begin{verbatim}
   (3)
   ["InnerMatrixLinearAlgebraFunctions",
    "MatrixCategory", "MatrixLinearAlgebraFunctions",
    "SquareMatrixCategory"]
                                  Type: DataList String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsQueryLanguagePageEmpty3}
\begin{paste}{ugDomainsQueryLanguagePageEmpty3}{ugDomainsQueryLanguagePagePatch3}
\pastebutton{ugDomainsQueryLanguagePageEmpty3}{\showpaste}
\tab{5}\spadcommand{elt(elt(elt(elt(ops,name="determinant"),origin),sort),unique)\free{o1 }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugDomainsDatabaseConstructorPage}{ug13.ht}
{The Database Constructor}
\begin{chunk}{ug13.ht}
\begin{page}{ugDomainsDatabaseConstructorPage}
{13.13.2. The Database Constructor}
\beginscroll

We work from the top down. First, we define a database,
our box of index cards, as an abstract datatype.
For sake of illustration and generality,
we assume that an index card is some type \axiom{S}, and
that a database is a box of objects of type \axiom{S}.
Here is the Axiom program defining the \pspadtype{Database}
domain.

\beginImportant
  
\noindent
{\tt 1.\ \ \ PI\ ==>\ PositiveInteger}\newline
{\tt 2.\ \ \ Database(S):\ Exports\ ==\ Implementation\ where}\newline
{\tt 3.\ \ \ \ \ S:\ Object\ with\ }\newline
{\tt 4.\ \ \ \ \ \ \ elt:\ (\$,\ Symbol)\ ->\ String}\newline
{\tt 5.\ \ \ \ \ \ \ display:\ \$\ ->\ Void}\newline
{\tt 6.\ \ \ \ \ \ \ fullDisplay:\ \$\ ->\ Void}\newline
{\tt 7.\ \ \ }\newline
{\tt 8.\ \ \ \ \ Exports\ ==\ with}\newline
{\tt 9.\ \ \ \ \ \ \ elt:\ (\$,QueryEquation)\ ->\ \$}\newline
{\tt 10.\ \ \ \ \ \ elt:\ (\$,\ Symbol)\ ->\ DataList\ String}\newline
{\tt 11.\ \ \ \ \ \ "+":\ (\$,\$)\ ->\ \$}\newline
{\tt 12.\ \ \ \ \ \ "-":\ (\$,\$)\ ->\ \$}\newline
{\tt 13.\ \ \ \ \ \ display:\ \$\ ->\ Void}\newline
{\tt 14.\ \ \ \ \ \ fullDisplay:\ \$\ ->\ Void}\newline
{\tt 15.\ \ \ \ \ \ fullDisplay:\ (\$,PI,PI)\ ->\ Void}\newline
{\tt 16.\ \ \ \ \ \ coerce:\ \$\ ->\ OutputForm}\newline
{\tt 17.\ \ \ \ Implementation\ ==\ add}\newline
{\tt 18.\ \ \ \ \ \ \ \ ...}\newline
\endImportant

The domain constructor takes a parameter \axiom{S}, which
stands for the class of index cards.
We describe an index card later.
Here think of an index card as a string which has
the eight fields mentioned above.

First, we tell Axiom what operations we are going to require
from index cards.
We need an \axiomFun{elt} to extract the contents of a field
(such as {\tt name} and {\tt type}) as a string.
For example,
\axiom{c.name} returns a string that is the content of the
\axiom{name} field on the index card \axiom{c}.
We need to display an index card in two ways:
\pspadfun{display} shows only the name and type of an
operation;
\pspadfun{fullDisplay} displays all fields.
The display operations return no useful information and thus have
return type \axiomType{Void}.

Next, we tell Axiom what operations the user can apply
to the database.
This part defines our little query language.
The most important operation is
{\frenchspacing\tt db . field = pattern} which
returns a new database, consisting of all index
cards of {\tt db} such that the \axiom{field} part of the index
card is matched by the string pattern called \axiom{pattern}.
The expression {\tt field = pattern} is an object of type
\axiomType{QueryEquation} (defined in the next section).

Another \axiomFun{elt} is needed to produce a \pspadtype{DataList}
object.
Operation \axiomOp{+} is to merge two databases together;
\axiomOp{-} is used to subtract away common entries in a second
database from an initial database.
There are three display functions.
The \pspadfun{fullDisplay} function has two versions: one
that prints all the records, the other that prints only a fixed
number of records.
A \axiomFun{coerce} to \axiomType{OutputForm} creates a display
object.

The {\tt Implementation} part of \axiomType{Database} is straightforward.
\beginImportant
  
\noindent
{\tt 1.\ \ \ \ \ Implementation\ ==\ add}\newline
{\tt 2.\ \ \ \ \ \ \ s:\ Symbol}\newline
{\tt 3.\ \ \ \ \ \ \ Rep\ :=\ List\ S}\newline
{\tt 4.\ \ \ \ \ \ \ elt(db,equation)\ ==\ ...}\newline
{\tt 5.\ \ \ \ \ \ \ 
elt(db,key)\ ==\ [x.key\ for\ x\ in\ db]::DataList(String)}\newline
{\tt 6.\ \ \ \ \ \ \ 
display(db)\ ==\ \ for\ x\ in\ db\ repeat\ display\ x}\newline
{\tt 7.\ \ \ \ \ \ \ 
fullDisplay(db)\ ==\ for\ x\ in\ db\ repeat\ fullDisplay\ x}\newline
{\tt 8.\ \ \ \ \ \ \ 
fullDisplay(db,\ n,\ m)\ ==\ for\ x\ in\ db\ for\ i\ in\ 1..m}\newline
{\tt 9.\ \ \ \ \ \ \ \ \ repeat}\newline
{\tt 10.\ \ \ \ \ \ \ \ \ \ if\ i\ >=\ n\ then\ fullDisplay\ x}\newline
{\tt 11.\ \ \ \ \ \ x+y\ ==\ removeDuplicates!\ merge(x,y)}\newline
{\tt 12.\ \ \ \ \ \ x-y\ ==\ mergeDifference(copy(x::Rep),}\newline
{\tt 13.\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 
y::Rep)\$MergeThing(S)}\newline
{\tt 14.\ \ \ \ \ \ coerce(db):\ OutputForm\ ==\ (\#db)::\ OutputForm}
\newline
\endImportant

The database is represented by a list of elements of \axiom{S} 
(index cards).
We leave the definition of the first \axiomFun{elt} operation
(on line 4) until the next section.
The second \axiomFun{elt} collects all the strings with field name
{\it key} into a list.
The \axiomFun{display} function and first \axiomFun{fullDisplay} function
simply call the corresponding functions from \axiom{S}.
The second \axiomFun{fullDisplay} function provides an efficient way of
printing out a portion of a large list.
The \axiomOp{+} is defined by using the existing
\spadfunFrom{merge}{List} operation defined on lists, then
removing duplicates from the result.
The \axiomOp{-} operation requires writing a corresponding
subtraction operation.
A package \axiomType{MergeThing} (not shown) provides this.

The \axiomFun{coerce} function converts the database to an
\axiomType{OutputForm} by computing the number of index cards.
This is a good example of the independence of
the representation of an Axiom object from how it presents
itself to the user. We usually do not want to look at a database---but
do care how many ``hits'' we get for a given query.
So we define the output representation of a database to be simply
the number of index cards our query finds.
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugDomainsQueryEquationsPage}{ug13.ht}{Query Equations}
\begin{chunk}{ug13.ht}
\begin{page}{ugDomainsQueryEquationsPage}{13.13.3. Query Equations}
\beginscroll

The predicate for our search is given by an object of type
\pspadtype{QueryEquation}.
Axiom does not have such an object yet so we
have to invent it.

\beginImportant
  
\noindent
{\tt 1.\ \ \ QueryEquation():\ Exports\ ==\ Implementation\ where}\newline
{\tt 2.\ \ \ \ \ Exports\ ==\ with}\newline
{\tt 3.\ \ \ \ \ \ \ equation:\ (Symbol,\ String)\ ->\ \$}\newline
{\tt 4.\ \ \ \ \ \ \ variable:\ \$\ ->\ Symbol}\newline
{\tt 5.\ \ \ \ \ \ \ value:\\ \\ \\ \\ \$\ ->\ String}\newline
{\tt 6.\ \ \ }\newline
{\tt 7.\ \ \ \ \ Implementation\ ==\ add}\newline
{\tt 8.\ \ \ \ \ \ \ Rep\ :=\ Record(var:Symbol,\ val:String)}\newline
{\tt 9.\ \ \ \ \ \ \ equation(x,\ s)\ ==\ [x,\ s]}\newline
{\tt 10.\ \ \ \ \ \ variable\ q\ ==\ q.var}\newline
{\tt 11.\ \ \ \ \ \ value\\ \\ \\ \\ q\ ==\ q.val}\newline
\endImportant

Axiom converts an input expression of the form
\axiom{{\it a} = {\it b}} to \axiom{equation({\it a, b})}.
Our equations always have a symbol on the left and a string
on the right.
The {\tt Exports} part thus specifies an operation
\axiomFun{equation} to create a query equation, and
\pspadfun{variable} and \pspadfun{value} to select the left- and
right-hand sides.
The {\tt Implementation} part uses \pspadtype{Record} for a
space-efficient representation of an equation.

Here is the missing definition for the \axiomFun{elt} function of
\pspadtype{Database} in the last section:

\beginImportant
  
\noindent
{\tt 1.\ \ \ \ \ \ \ elt(db,eq)\ ==}\newline
{\tt 2.\ \ \ \ \ \ \ \ \ field\\ \ :=\ variable\ eq}\newline
{\tt 3.\ \ \ \ \ \ \ \ \ value\ :=\ value\ eq}\newline
{\tt 4.\ \ \ \ \ \ \ \ \ 
[x\ for\ x\ in\ db\ |\ matches?(value,x.field)]}\newline
\endImportant

Recall that a database is represented by a list.
Line 4 simply runs over that list collecting all elements
such that the pattern (that is, \axiom{value})
matches the selected field of the element.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugDomainsDataListsPage}{ug13.ht}{DataLists}
\begin{chunk}{ug13.ht}
\begin{page}{ugDomainsDataListsPage}{13.13.4. DataLists}
\beginscroll

Type \pspadtype{DataList} is a new type invented to hold the result
of selecting one field from each of the index cards in the box.
It is useful to make datalists extensions of lists---lists that
have special \axiomFun{elt} operations defined on them for
sorting and removing duplicates.

\beginImportant
  
\noindent
{\tt 1.\ \ \ DataList(S:OrderedSet)\ :\ Exports\ ==\ 
Implementation\ where}\newline
{\tt 2.\ \ \ \ \ Exports\ ==\ ListAggregate(S)\ with}\newline
{\tt 3.\ \ \ \ \ \ \ elt:\ (\$,"unique")\ ->\ \$}\newline
{\tt 4.\ \ \ \ \ \ \ elt:\ (\$,"sort")\ ->\ \$}\newline
{\tt 5.\ \ \ \ \ \ \ elt:\ (\$,"count")\ ->\ NonNegativeInteger}\newline
{\tt 6.\ \ \ \ \ \ \ coerce:\ List\ S\ ->\ \$}\newline
{\tt 7.\ \ \ }\newline
{\tt 8.\ \ \ \ \ Implementation\ ==\ \ List(S)\ add}\newline
{\tt 9.\ \ \ \ \ \ \ Rep\ :=\ List\ S}\newline
{\tt 10.\ \ \ \ \ \ elt(x,"unique")\ ==\ removeDuplicates(x)}\newline
{\tt 11.\ \ \ \ \ \ elt(x,"sort")\ ==\ sort(x)}\newline
{\tt 12.\ \ \ \ \ \ elt(x,"count")\ ==\ \#x}\newline
{\tt 13.\ \ \ \ \ \ coerce(x:List\ S)\ ==\ x\ ::\ \$}\newline
\endImportant

The {\tt Exports} part asserts that datalists belong to the
category \axiomType{ListAggregate}.
Therefore, you can use all the usual list operations on datalists,
such as \spadfunFrom{first}{List}, \spadfunFrom{rest}{List}, and
\spadfunFrom{concat}{List}.
In addition, datalists have four explicit operations.
Besides the three \axiomFun{elt} operations, there is a
\axiomFun{coerce} operation that creates datalists from lists.

The {\tt Implementation} part needs only to define four functions.
All the rest are obtained from \axiomType{List(S)}.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugDomainsDatabasePage}{ug13.ht}{Index Cards}
\begin{chunk}{ug13.ht}
\begin{page}{ugDomainsDatabasePage}{13.13.5. Index Cards}
\beginscroll

An index card comes from a file as one long string.  We define
functions that extract substrings from the long string.  Each field
has a name that is passed as a second argument to \axiomFun{elt}.

\beginImportant
  
\noindent
{\tt 1.\ \ \ IndexCard()\ ==\ Implementation\ where}\newline
{\tt 2.\ \ \ \ \ Exports\ ==\ with}\newline
{\tt 3.\ \ \ \ \ \ \ elt:\ (\$,\ Symbol)\ ->\ String}\newline
{\tt 4.\ \ \ \ \ \ \ display:\ \$\ ->\ Void}\newline
{\tt 5.\ \ \ \ \ \ \ fullDisplay:\ \$\ ->\ Void}\newline
{\tt 6.\ \ \ \ \ \ \ coerce:\ String\ ->\ \$}\newline
{\tt 7.\ \ \ \ \ Implementation\ ==\ String\ add\ ...}\newline
\endImportant

We leave the {\tt Implementation} part to the reader.
All operations involve straightforward string manipulations.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugDomainsCreatingPage}{ug13.ht}{Creating a Database}
\begin{chunk}{ug13.ht}
\begin{page}{ugDomainsCreatingPage}{13.13.6. Creating a Database}
\beginscroll

We must not forget one important operation: one that builds the
database in the first place!  We'll name it \pspadfun{getDatabase} and
put it in a package.  This function is implemented by calling the
\Lisp{} function \axiom{getBrowseDatabase(s)} to get appropriate
information from \Browse{}.  This operation takes a string indicating
which lines you want from the database: \axiom{"o"} gives you all
operation lines, and \axiom{"k"}, all constructor lines.  Similarly,
\axiom{"c"}, \axiom{"d"}, and \axiom{"p"} give you all category,
domain and package lines respectively.

\beginImportant
  
\noindent
{\tt 1.\ \ \ OperationsQuery():\ Exports\ ==\ Implementation\ where}
\newline
{\tt 2.\ \ \ \ \ Exports\ ==\ with}\newline
{\tt 3.\ \ \ \ \ \ \ getDatabase:\ String\ ->\ Database(IndexCard)}
\newline
{\tt 4.\ \ \ }\newline
{\tt 5.\ \ \ \ \ Implementation\ ==\ add}\newline
{\tt 6.\ \ \ \ \ \ \ getDatabase(s)\ ==\ getBrowseDatabase(s)\$Lisp}
\newline
\endImportant

We do not bother creating a special name for databases of index
cards.
\pspadtype{Database (IndexCard)} will do.
Notice that we used the package \pspadtype{OperationsQuery} to
create, in effect,
a new kind of domain: \pspadtype{Database(IndexCard)}.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugDomainsPuttingPage}{ug13.ht}{Putting It All Together}
\begin{chunk}{ug13.ht}
\begin{page}{ugDomainsPuttingPage}{13.13.7. Putting It All Together}
\beginscroll

To create the database facility, you put all these constructors
into one file.\footnote{You could use separate files, but we
are putting them all together because, organizationally, that is
the logical thing to do.}
At the top of the file put \spadcmd{)abbrev} commands, giving the
constructor abbreviations you created.

\beginImportant
  
\noindent
{\tt 1.\ \ \ )abbrev\ domain\ \ ICARD\ \ \ IndexCard}\newline
{\tt 2.\ \ \ )abbrev\ domain\ \ QEQUAT\ \ QueryEquation}\newline
{\tt 3.\ \ \ )abbrev\ domain\ \ MTHING\ \ MergeThing}\newline
{\tt 4.\ \ \ )abbrev\ domain\ \ DLIST\ \ \ DataList}\newline
{\tt 5.\ \ \ )abbrev\ domain\ \ DBASE\ \ \ Database}\newline
{\tt 6.\ \ \ )abbrev\ package\ OPQUERY\ OperationsQuery}\newline
\endImportant

With all this in {\bf alql.spad}, for example, compile it using
\begin{verbatim}
)compile alql
\end{verbatim}
and then load each of the constructors:
\begin{verbatim}
)load ICARD QEQUAT MTHING DLIST DBASE OPQUERY
\end{verbatim}
You are ready to try some sample queries.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugDomainsExamplesPage}{ug13.ht}{Example Queries}
\begin{chunk}{ug13.ht}
\begin{page}{ugDomainsExamplesPage}{13.13.8. Example Queries}
\beginscroll

Our first set of queries give some statistics on constructors in
the current Axiom system.

\xtc{
How many constructors does Axiom have?
}{
\spadpaste{ks := getDatabase "k"\bound{q1}}
}
\xtc{
Break this down into the number of categories, domains, and packages.
}{
\spadpaste{[ks.(kind=k) for k in ["c","d","p"]]\bound{q3}\free{q1}}
}
\xtc{
What are all the domain constructors that take no parameters?
}{
\spadpaste{elt(ks.(kind="d").(nargs="0"),name)\bound{q4}\free{q1}}
}
\xtc{
How many constructors have ``Matrix'' in their name?
}{
\spadpaste{mk := ks.(name="*Matrix*")\bound{q5}\free{q1}}
}
\xtc{
What are the names of those that are domains?
}{
\spadpaste{elt(mk.(kind="d"),name)\bound{q6}\free{q5}}
}
\xtc{
How many operations are there in the library?
}{
\spadpaste{o := getDatabase "o"\bound{o1}}
}
\xtc{
Break this down into categories, domains, and packages.
}{
\spadpaste{[o.(kind=k) for k in ["c","d","p"]]\free{o1}}
}

The query language is helpful in getting information about a
particular operation you might like to apply.
While this information can be obtained with
\Browse{}, the use of the query database gives you data that you
can manipulate in the workspace.

\xtc{
How many operations have ``eigen'' in the name?
}{
\spadpaste{eigens := o.(name="*eigen*")\bound{eigens}\free{o1}}
}
\xtc{
What are their names?
}{
\spadpaste{elt(eigens,name)\free{eigens}}
}
\xtc{
Where do they come from?
}{
\spadpaste{elt(elt(elt(eigens,origin),sort),unique) \free{eigens}}
}

The operations \axiomOp{+} and \axiomOp{-} are useful for
constructing small databases and combining them.
However, remember that the only matching you can do is string
matching.
Thus a pattern such as {\tt "*Matrix*"} on the type field
matches
any type containing \axiomType{Matrix}, \axiomType{MatrixCategory},
\axiomType{SquareMatrix}, and so on.

\xtc{
How many operations mention ``Matrix'' in their type?
}{
\spadpaste{tm := o.(type="*Matrix*")\bound{x10}\free{o1}}
}
\xtc{
How many operations come from constructors with ``Matrix'' in
their name?
}{
\spadpaste{fm := o.(origin="*Matrix*")\bound{x11}\free{o1}}
}
\xtc{
How many operations are in \axiom{fm} but not in \axiom{tm}?
}{
\spadpaste{fm-tm \bound{x12}\free{x10 x11}}
}
\xtc{
Display the operations that both mention ``Matrix'' in their type
and come from a constructor having ``Matrix'' in their name.
}{
\spadpaste{fullDisplay(fm-\%) \bound{x13}\free{x12}}
}
\xtc{
How many operations involve matrices?
}{
\spadpaste{m := tm+fm \bound{x14}\free{x10 x11}}
}
\xtc{
Display 4 of them.
}{
\spadpaste{fullDisplay(m, 202, 205) \free{x14}}
}
\xtc{
How many distinct names of operations involving matrices are there?
}{
\spadpaste{elt(elt(elt(m,name),unique),count) \free{x14}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugDomainsExamplesPagePatch1}
\begin{paste}{ugDomainsExamplesPageFull1}{ugDomainsExamplesPageEmpty1}
\pastebutton{ugDomainsExamplesPageFull1}{\hidepaste}
\tab{5}\spadcommand{ks := getDatabase "k"\bound{q1 }}
\indentrel{3}\begin{verbatim}
   (1)  1067
                               Type: Database IndexCard
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPageEmpty1}
\begin{paste}{ugDomainsExamplesPageEmpty1}{ugDomainsExamplesPagePatch1}
\pastebutton{ugDomainsExamplesPageEmpty1}{\showpaste}
\tab{5}\spadcommand{ks := getDatabase "k"\bound{q1 }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPagePatch2}
\begin{paste}{ugDomainsExamplesPageFull2}{ugDomainsExamplesPageEmpty2}
\pastebutton{ugDomainsExamplesPageFull2}{\hidepaste}
\tab{5}\spadcommand{[ks.(kind=k) for k in ["c","d","p"]]\bound{q3 }\free{q1 }}
\indentrel{3}\begin{verbatim}
   (2)  [205,393,469]
                          Type: List Database IndexCard
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPageEmpty2}
\begin{paste}{ugDomainsExamplesPageEmpty2}{ugDomainsExamplesPagePatch2}
\pastebutton{ugDomainsExamplesPageEmpty2}{\showpaste}
\tab{5}\spadcommand{[ks.(kind=k) for k in ["c","d","p"]]\bound{q3 }\free{q1 }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPagePatch3}
\begin{paste}{ugDomainsExamplesPageFull3}{ugDomainsExamplesPageEmpty3}
\pastebutton{ugDomainsExamplesPageFull3}{\hidepaste}
\tab{5}\spadcommand{elt(ks.(kind="d").(nargs="0"),name)\bound{q4 }\free{q1 }}
\indentrel{3}\begin{verbatim}
   (3)
   ["AlgebraicNumber", "AnonymousFunction", "Any",
    "AttributeButtons", "BasicFunctions",
    "BasicOperator", "BinaryExpansion", "BinaryFile",
    "Bits", "Boolean", "CardinalNumber",
    "CharacterClass", "Character", "Color", "Commutator",
    "DecimalExpansion", "DoubleFloat", "DrawOption",
    "Exit", "ExtAlgBasis", "FileName", "Float",
    "FortranCode", "FortranScalarType",
    "FortranTemplate", "FortranType", "GraphImage",
    "HexadecimalExpansion", "IVBaseColor", "IVBasicNode",
    "IVCoordinate3", "IVCoordinate4", "IVFaceSet",
    "IVField", "IVGroup", "IVIndexedLineSet",
    "IVNodeConnection", "IVNodeObject", "IVPointSet",
    "IVQuadMesh", "IVSeparator", "IVSimpleInnerNode",
    "IVUtilities", "IVValue", "IndexCard",
    "InnerAlgebraicNumber", "InputForm", "Integer",
    "IntegrationFunctionsTable", "InventorDataSink",
    "InventorRenderPackage", "InventorViewPort",
    "Library", "MachineComplex", "MachineFloat",
    "MachineInteger",
    "NagDiscreteFourierTransformInterfacePackage",
    "NagEigenInterfacePackage",
    "NagOptimisationInterfacePackage",
    "NagQuadratureInterfacePackage", "NagResultChecks",
    "NagSpecialFunctionsInterfacePackage",
    "NonNegativeInteger", "None",
    "NumericalIntegrationProblem", "NumericalODEProblem",
    "NumericalOptimizationProblem",
    "NumericalPDEProblem", "ODEIntensityFunctionsTable",
    "OrdSetInts", "OutputForm", "Palette", "Partition",
    "Pi", "PlaneAlgebraicCurvePlot", "Plot3D", "Plot",
    "PositiveInteger", "QueryEquation", "RenderTools",
    "Result", "RomanNumeral", "RoutinesTable",
    "SExpression", "ScriptFormulaFormat",
    "SingleInteger", "SingletonAsOrderedSet", "String",
    "SubSpaceComponentProperty", "Switch", "SymbolTable",
    "Symbol", "TexFormat", "TextFile", "TheSymbolTable",
    "ThreeDimensionalViewport", "Timer",
    "TwoDimensionalViewport", "Void",
    "d01TransformFunctionType", "d01ajfAnnaType",
    "d01akfAnnaType", "d01alfAnnaType", "d01amfAnnaType",
    "d01anfAnnaType", "d01apfAnnaType", "d01aqfAnnaType",
    "d01asfAnnaType", "d01fcfAnnaType", "d01gbfAnnaType",
    "d02bbfAnnaType", "d02bhfAnnaType", "d02cjfAnnaType",
    "d02ejfAnnaType", "d03eefAnnaType", "d03fafAnnaType",
    "e04dgfAnnaType", "e04fdfAnnaType", "e04gcfAnnaType",
    "e04jafAnnaType", "e04mbfAnnaType", "e04nafAnnaType",
    "e04ucfAnnaType"]
                                  Type: DataList String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPageEmpty3}
\begin{paste}{ugDomainsExamplesPageEmpty3}{ugDomainsExamplesPagePatch3}
\pastebutton{ugDomainsExamplesPageEmpty3}{\showpaste}
\tab{5}\spadcommand{elt(ks.(kind="d").(nargs="0"),name)\bound{q4 }\free{q1 }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPagePatch4}
\begin{paste}{ugDomainsExamplesPageFull4}{ugDomainsExamplesPageEmpty4}
\pastebutton{ugDomainsExamplesPageFull4}{\hidepaste}
\tab{5}\spadcommand{mk := ks.(name="*Matrix*")\bound{q5 }\free{q1 }}
\indentrel{3}\begin{verbatim}
   (4)  26
                               Type: Database IndexCard
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPageEmpty4}
\begin{paste}{ugDomainsExamplesPageEmpty4}{ugDomainsExamplesPagePatch4}
\pastebutton{ugDomainsExamplesPageEmpty4}{\showpaste}
\tab{5}\spadcommand{mk := ks.(name="*Matrix*")\bound{q5 }\free{q1 }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPagePatch5}
\begin{paste}{ugDomainsExamplesPageFull5}{ugDomainsExamplesPageEmpty5}
\pastebutton{ugDomainsExamplesPageFull5}{\hidepaste}
\tab{5}\spadcommand{elt(mk.(kind="d"),name)\bound{q6 }\free{q5 }}
\indentrel{3}\begin{verbatim}
   (5)
   ["DenavitHartenbergMatrix",
    "DirectProductMatrixModule", "IndexedMatrix",
    "LieSquareMatrix", "Matrix", "RectangularMatrix",
    "SquareMatrix", "ThreeDimensionalMatrix"]
                                  Type: DataList String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPageEmpty5}
\begin{paste}{ugDomainsExamplesPageEmpty5}{ugDomainsExamplesPagePatch5}
\pastebutton{ugDomainsExamplesPageEmpty5}{\showpaste}
\tab{5}\spadcommand{elt(mk.(kind="d"),name)\bound{q6 }\free{q5 }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPagePatch6}
\begin{paste}{ugDomainsExamplesPageFull6}{ugDomainsExamplesPageEmpty6}
\pastebutton{ugDomainsExamplesPageFull6}{\hidepaste}
\tab{5}\spadcommand{o := getDatabase "o"\bound{o1 }}
\indentrel{3}\begin{verbatim}
   (6)  6315
                               Type: Database IndexCard
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPageEmpty6}
\begin{paste}{ugDomainsExamplesPageEmpty6}{ugDomainsExamplesPagePatch6}
\pastebutton{ugDomainsExamplesPageEmpty6}{\showpaste}
\tab{5}\spadcommand{o := getDatabase "o"\bound{o1 }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPagePatch7}
\begin{paste}{ugDomainsExamplesPageFull7}{ugDomainsExamplesPageEmpty7}
\pastebutton{ugDomainsExamplesPageFull7}{\hidepaste}
\tab{5}\spadcommand{[o.(kind=k) for k in ["c","d","p"]]\free{o1 }}
\indentrel{3}\begin{verbatim}
   (7)  [1646,2040,2629]
                          Type: List Database IndexCard
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPageEmpty7}
\begin{paste}{ugDomainsExamplesPageEmpty7}{ugDomainsExamplesPagePatch7}
\pastebutton{ugDomainsExamplesPageEmpty7}{\showpaste}
\tab{5}\spadcommand{[o.(kind=k) for k in ["c","d","p"]]\free{o1 }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPagePatch8}
\begin{paste}{ugDomainsExamplesPageFull8}{ugDomainsExamplesPageEmpty8}
\pastebutton{ugDomainsExamplesPageFull8}{\hidepaste}
\tab{5}\spadcommand{eigens := o.(name="*eigen*")\bound{eigens }\free{o1 }}
\indentrel{3}\begin{verbatim}
   (8)  4
                               Type: Database IndexCard
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPageEmpty8}
\begin{paste}{ugDomainsExamplesPageEmpty8}{ugDomainsExamplesPagePatch8}
\pastebutton{ugDomainsExamplesPageEmpty8}{\showpaste}
\tab{5}\spadcommand{eigens := o.(name="*eigen*")\bound{eigens }\free{o1 }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPagePatch9}
\begin{paste}{ugDomainsExamplesPageFull9}{ugDomainsExamplesPageEmpty9}
\pastebutton{ugDomainsExamplesPageFull9}{\hidepaste}
\tab{5}\spadcommand{elt(eigens,name)\free{eigens }}
\indentrel{3}\begin{verbatim}
   (9)
   ["eigenMatrix", "eigenvalues", "eigenvector",
    "eigenvectors"]
                                  Type: DataList String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPageEmpty9}
\begin{paste}{ugDomainsExamplesPageEmpty9}{ugDomainsExamplesPagePatch9}
\pastebutton{ugDomainsExamplesPageEmpty9}{\showpaste}
\tab{5}\spadcommand{elt(eigens,name)\free{eigens }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPagePatch10}
\begin{paste}{ugDomainsExamplesPageFull10}{ugDomainsExamplesPageEmpty10}
\pastebutton{ugDomainsExamplesPageFull10}{\hidepaste}
\tab{5}\spadcommand{elt(elt(elt(eigens,origin),sort),unique)\free{eigens }}
\indentrel{3}\begin{verbatim}
   (10)  ["EigenPackage","RadicalEigenPackage"]
                                  Type: DataList String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPageEmpty10}
\begin{paste}{ugDomainsExamplesPageEmpty10}{ugDomainsExamplesPagePatch10}
\pastebutton{ugDomainsExamplesPageEmpty10}{\showpaste}
\tab{5}\spadcommand{elt(elt(elt(eigens,origin),sort),unique)\free{eigens }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPagePatch11}
\begin{paste}{ugDomainsExamplesPageFull11}{ugDomainsExamplesPageEmpty11}
\pastebutton{ugDomainsExamplesPageFull11}{\hidepaste}
\tab{5}\spadcommand{tm := o.(type="*Matrix*")\bound{x10 }\free{o1 }}
\indentrel{3}\begin{verbatim}
   (11)  353
                               Type: Database IndexCard
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPageEmpty11}
\begin{paste}{ugDomainsExamplesPageEmpty11}{ugDomainsExamplesPagePatch11}
\pastebutton{ugDomainsExamplesPageEmpty11}{\showpaste}
\tab{5}\spadcommand{tm := o.(type="*Matrix*")\bound{x10 }\free{o1 }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPagePatch12}
\begin{paste}{ugDomainsExamplesPageFull12}{ugDomainsExamplesPageEmpty12}
\pastebutton{ugDomainsExamplesPageFull12}{\hidepaste}
\tab{5}\spadcommand{fm := o.(origin="*Matrix*")\bound{x11 }\free{o1 }}
\indentrel{3}\begin{verbatim}
   (12)  192
                               Type: Database IndexCard
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPageEmpty12}
\begin{paste}{ugDomainsExamplesPageEmpty12}{ugDomainsExamplesPagePatch12}
\pastebutton{ugDomainsExamplesPageEmpty12}{\showpaste}
\tab{5}\spadcommand{fm := o.(origin="*Matrix*")\bound{x11 }\free{o1 }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPagePatch13}
\begin{paste}{ugDomainsExamplesPageFull13}{ugDomainsExamplesPageEmpty13}
\pastebutton{ugDomainsExamplesPageFull13}{\hidepaste}
\tab{5}\spadcommand{fm-tm\bound{x12 }\free{x10 x11 }}
\indentrel{3}\begin{verbatim}
   (13)  146
                               Type: Database IndexCard
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPageEmpty13}
\begin{paste}{ugDomainsExamplesPageEmpty13}{ugDomainsExamplesPagePatch13}
\pastebutton{ugDomainsExamplesPageEmpty13}{\showpaste}
\tab{5}\spadcommand{fm-tm\bound{x12 }\free{x10 x11 }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPagePatch14}
\begin{paste}{ugDomainsExamplesPageFull14}{ugDomainsExamplesPageEmpty14}
\pastebutton{ugDomainsExamplesPageFull14}{\hidepaste}
\tab{5}\spadcommand{fullDisplay(fm-\%)\bound{x13 }\free{x12 }}
\indentrel{3}\begin{verbatim}
   ** : (Matrix(R),NonNegativeInteger)->Matrix(R)
      from StorageEfficientMatrixOperations(R) (unexposed)
   clearDenominator : (Matrix(Q))->Matrix(R)
      from MatrixCommonDenominator(R,Q)
   coerceP
      : (Vector(Matrix(R)))->Vector(Matrix(Polynomial(R)))
      from CoerceVectorMatrixPackage(R) (unexposed)
   coerce
      :
      (Vector(Matrix(R)))->Vector(Matrix(Fraction(Polynom
      ial(R))))
      from CoerceVectorMatrixPackage(R) (unexposed)
   coerce : (_$)->Matrix(R)
      from RectangularMatrix(m,n,R) (unexposed)
   coerce : (_$)->Matrix(R)
      from SquareMatrix(ndim,R) (unexposed)
   coerce : (Matrix(MachineFloat))->_$
      from FortranMatrixCategory
   commonDenominator : (Matrix(Q))->R
      from MatrixCommonDenominator(R,Q)
   copy! : (Matrix(R),Matrix(R))->Matrix(R)
      from StorageEfficientMatrixOperations(R) (unexposed)
   f01brf
      :
      (Integer,Integer,Integer,Integer,DoubleFloat,Boolea
      n,Boolean,List(Boolean),Matrix(DoubleFloat),Matrix(
      Integer),Matrix(Integer),Integer)->Result
      from NagMatrixOperationsPackage
   f01bsf
      :
      (Integer,Integer,Integer,Matrix(Integer),Matrix(Int
      eger),Matrix(Integer),Matrix(Integer),Boolean,Doubl
      eFloat,Boolean,Matrix(Integer),Matrix(DoubleFloat),
      Integer)->Result
      from NagMatrixOperationsPackage
   f01maf
      :
      (Integer,Integer,Integer,Integer,List(Boolean),Matr
      ix(DoubleFloat),Matrix(Integer),Matrix(Integer),Dou
      bleFloat,DoubleFloat,Integer)->Result
      from NagMatrixOperationsPackage
   f01mcf
      :
      (Integer,Matrix(DoubleFloat),Integer,Matrix(Integer
      ),Integer)->Result
      from NagMatrixOperationsPackage
   f01qcf
      :
      (Integer,Integer,Integer,Matrix(DoubleFloat),Intege
      r)->Result
      from NagMatrixOperationsPackage
   f01qdf
      :
      (String,String,Integer,Integer,Matrix(DoubleFloat),
      Integer,Matrix(DoubleFloat),Integer,Integer,Matrix(
      DoubleFloat),Integer)->Result
      from NagMatrixOperationsPackage
   f01qef
      :
      (String,Integer,Integer,Integer,Integer,Matrix(Doub
      leFloat),Matrix(DoubleFloat),Integer)->Result
      from NagMatrixOperationsPackage
   f01rcf
      :
      (Integer,Integer,Integer,Matrix(Complex(DoubleFloat
      )),Integer)->Result
      from NagMatrixOperationsPackage
   f01rdf
      :
      (String,String,Integer,Integer,Matrix(Complex(Doubl
      eFloat)),Integer,Matrix(Complex(DoubleFloat)),Integ
      er,Integer,Matrix(Complex(DoubleFloat)),Integer)->R
      esult
      from NagMatrixOperationsPackage
   f01ref
      :
      (String,Integer,Integer,Integer,Integer,Matrix(Comp
      lex(DoubleFloat)),Matrix(Complex(DoubleFloat)),Inte
      ger)->Result
      from NagMatrixOperationsPackage
   hasSolution? : (Matrix(F),Vector(F))->Boolean
      from LinearSystemMatrixPackage1(F)
   leftScalarTimes! : (Matrix(R),R,Matrix(R))->Matrix(R)
      from StorageEfficientMatrixOperations(R) (unexposed)
   minus! : (Matrix(R),Matrix(R))->Matrix(R)
      from StorageEfficientMatrixOperations(R) (unexposed)
   minus! : (Matrix(R),Matrix(R),Matrix(R))->Matrix(R)
      from StorageEfficientMatrixOperations(R) (unexposed)
   particularSolution
      : (Matrix(F),Vector(F))->Union(Vector(F),"failed")
      from LinearSystemMatrixPackage1(F)
   plus! : (Matrix(R),Matrix(R),Matrix(R))->Matrix(R)
      from StorageEfficientMatrixOperations(R) (unexposed)
   power!
      :
      (Matrix(R),Matrix(R),Matrix(R),Matrix(R),NonNegativ
      eInteger)->Matrix(R)
      from StorageEfficientMatrixOperations(R) (unexposed)
   rank : (Matrix(F),Vector(F))->NonNegativeInteger
      from LinearSystemMatrixPackage1(F)
   rectangularMatrix : (Matrix(R))->_$
      from RectangularMatrix(m,n,R) (unexposed)
   retractIfCan
      : (Matrix(Expression(Float)))->Union(_$,"failed")
      from FortranMatrixFunctionCategory
   retractIfCan
      : (Matrix(Expression(Integer)))->Union(_$,"failed")
      from FortranMatrixFunctionCategory
   retractIfCan
      :
      (Matrix(Fraction(Polynomial(Float))))->Union(_$,"fa
      iled")
      from FortranMatrixFunctionCategory
   retractIfCan
      :
      (Matrix(Fraction(Polynomial(Integer))))->Union(_$,"
      failed")
      from FortranMatrixFunctionCategory
   retractIfCan
      : (Matrix(Polynomial(Float)))->Union(_$,"failed")
      from FortranMatrixFunctionCategory
   retractIfCan
      : (Matrix(Polynomial(Integer)))->Union(_$,"failed")
      from FortranMatrixFunctionCategory
   retract : (Matrix(Expression(Float)))->_$
      from FortranMatrixFunctionCategory
   retract : (Matrix(Expression(Integer)))->_$
      from FortranMatrixFunctionCategory
   retract : (Matrix(Fraction(Polynomial(Float))))->_$
      from FortranMatrixFunctionCategory
   retract : (Matrix(Fraction(Polynomial(Integer))))->_$
      from FortranMatrixFunctionCategory
   retract : (Matrix(Polynomial(Float)))->_$
      from FortranMatrixFunctionCategory
   retract : (Matrix(Polynomial(Integer)))->_$
      from FortranMatrixFunctionCategory
   rightScalarTimes! : (Matrix(R),Matrix(R),R)->Matrix(R)
      from StorageEfficientMatrixOperations(R) (unexposed)
   solve
      :
      (Matrix(F),List(Vector(F)))->List(Record(particular
      :Union(Vector(F),"failed"),basis:List(Vector(F))))
      from LinearSystemMatrixPackage1(F)
   solve
      :
      (Matrix(F),Vector(F))->Record(particular:Union(Vect
      or(F),"failed"),basis:List(Vector(F)))
      from LinearSystemMatrixPackage1(F)
   splitDenominator
      : (Matrix(Q))->Record(num:Matrix(R),den:R)
      from MatrixCommonDenominator(R,Q)
   squareMatrix : (Matrix(R))->_$
      from SquareMatrix(ndim,R) (unexposed)
   times! : (Matrix(R),Matrix(R),Matrix(R))->Matrix(R)
      from StorageEfficientMatrixOperations(R) (unexposed)
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPageEmpty14}
\begin{paste}{ugDomainsExamplesPageEmpty14}{ugDomainsExamplesPagePatch14}
\pastebutton{ugDomainsExamplesPageEmpty14}{\showpaste}
\tab{5}\spadcommand{fullDisplay(fm-\%)\bound{x13 }\free{x12 }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPagePatch15}
\begin{paste}{ugDomainsExamplesPageFull15}{ugDomainsExamplesPageEmpty15}
\pastebutton{ugDomainsExamplesPageFull15}{\hidepaste}
\tab{5}\spadcommand{m := tm+fm\bound{x14 }\free{x10 x11 }}
\indentrel{3}\begin{verbatim}
   (15)  499
                               Type: Database IndexCard
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPageEmpty15}
\begin{paste}{ugDomainsExamplesPageEmpty15}{ugDomainsExamplesPagePatch15}
\pastebutton{ugDomainsExamplesPageEmpty15}{\showpaste}
\tab{5}\spadcommand{m := tm+fm\bound{x14 }\free{x10 x11 }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPagePatch16}
\begin{paste}{ugDomainsExamplesPageFull16}{ugDomainsExamplesPageEmpty16}
\pastebutton{ugDomainsExamplesPageFull16}{\hidepaste}
\tab{5}\spadcommand{fullDisplay(m, 202, 205)\free{x14 }}
\indentrel{3}\begin{verbatim}
   elt : (_$,List(Integer),List(Integer))->_$
      from MatrixCategory(R,Row,Col)
   elt : (_$,Integer,Integer,R)->R
      from RectangularMatrixCategory(m,n,R,Row,Col)
   elt
      :
      (_$,NonNegativeInteger,NonNegativeInteger,NonNegati
      veInteger)->R
      from ThreeDimensionalMatrix(R)
   eval
      :
      (Matrix(Expression(DoubleFloat)),List(Symbol),Vecto
      r(Expression(DoubleFloat)))->Matrix(Expression(Doub
      leFloat))
      from d02AgentsPackage
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPageEmpty16}
\begin{paste}{ugDomainsExamplesPageEmpty16}{ugDomainsExamplesPagePatch16}
\pastebutton{ugDomainsExamplesPageEmpty16}{\showpaste}
\tab{5}\spadcommand{fullDisplay(m, 202, 205)\free{x14 }}
\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPagePatch17}
\begin{paste}{ugDomainsExamplesPageFull17}{ugDomainsExamplesPageEmpty17}
\pastebutton{ugDomainsExamplesPageFull17}{\hidepaste}
\tab{5}\spadcommand{elt(elt(elt(m,name),unique),count)\free{x14 }}
\indentrel{3}\begin{verbatim}
   (17)  317
                                  Type: PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugDomainsExamplesPageEmpty17}
\begin{paste}{ugDomainsExamplesPageEmpty17}{ugDomainsExamplesPagePatch17}
\pastebutton{ugDomainsExamplesPageEmpty17}{\showpaste}
\tab{5}\spadcommand{elt(elt(elt(m,name),unique),count)\free{x14 }}
\end{paste}\end{patch}

\end{chunk}
\chapter{Users Guide Chapter 14 (ug14.ht)}
\pagetitle{ugBrowsePage}{ug14.ht}{Browse}
\pageto{notitle}{ugBrowseStartPage}
\pageto{notitle}{ugBrowseDomainPage}
\pageto{notitle}{ugBrowseMiscellaneousFeaturesPage}
\begin{chunk}{ug14.ht}
\begin{page}{ugBrowsePage}{14. Browse}
\beginscroll

This chapter discusses the \Browse{}
component of Hyperdoc.
We suggest you invoke Axiom and work through this
chapter, section by section, following our examples to gain some
familiarity with \Browse{}.

\beginmenu
    \menudownlink{{14.1. The Front Page: Searching the Library}}
{ugBrowseStartPage}
    \menudownlink{{14.2. The Constructor Page}}{ugBrowseDomainPage}
    \menudownlink{{14.3. Miscellaneous Features of Browse}}
{ugBrowseMiscellaneousFeaturesPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugBrowseStartPage}{ug14.ht}
{The Front Page: Searching the Library}
\pageto{notitle}{ugBrowseCapitalizationConventionPage}
\pageto{notitle}{ugBrowseDomainPage}
\pageto{notitle}{ugBrowseViewsOfConstructorsPage}
\pageto{notitle}{ugBrowseViewsOfOperationsPage}
\begin{chunk}{ug14.ht}
\begin{page}{ugBrowseStartPage}
{14.1. The Front Page: Searching the Library}
\beginscroll
To enter \Browse{}, click on {\bf Browse} on the top level page
of Hyperdoc to get the {\it front page} of \Browse{}.
%
%324pt is 4.5",180pt is 2.5",432pt is 6"=textwidth,54=(432-324)/2
%ps files are 4.5"x2.5" except source 4.5"x2.5"
%

To use this page, you first enter a \spadgloss{search string} into
the input area at the top, then click on one of the buttons below.
We show the use of each of the buttons by example.

\subsubsection{Constructors}

First enter the search string {\tt Matrix} into the input area and
click on {\bf Constructors}.  What you get is the {\it constructor
page} for \axiomType{Matrix}.  We show and describe this page in
detail in \downlink{``The Constructor Page''}{ugBrowseDomainPage} in
Section 14.2\ignore{ugBrowseDomain}.  By convention,
Axiom does a case-insensitive search for a match.  Thus {\tt matrix}
is just as good as {\tt Matrix}, has the same effect as {\tt MaTrix},
and so on.  We recommend that you generally use small letters for
names however.  A search string with only capital letters has a
special meaning (see
\downlink{``Capitalization Convention''}
{ugBrowseCapitalizationConventionPage}
in Section 14.3.3\ignore{ugBrowseCapitalizationConvention}).


Click on \UpBitmap{} to return to the \Browse{} front page.

Use the symbol ``{\tt *}'' in search strings as a \spadgloss{wild
card}.
A wild card matches any substring, including the empty string.
For example, enter the search string {\tt *matrix*} into the input
area and click on {\bf Constructors}.\footnote{To get only
categories, domains, or packages, rather than all constructors,
you can click on the corresponding button to the right of {\bf
Constructors}.}
What you get is a table of all constructors whose names contain
the string ``{\tt matrix}.''

All constructors containing the string are listed, whether
\spadglossSee{exposed}{expose} or \spadglossSee{unexposed}{expose}.
You can hide the names of the unexposed constructors by clicking on
the {\it *=}{\bf unexposed} button in the {\it Views} panel at the
bottom of the window.  (The button will change to {\bf exposed} {\it
only}.)

One of the names in this table is \axiomType{Matrix}.  Click on
\axiomType{Matrix}.  What you get is again the constructor page for
\axiomType{Matrix}.  As you see, \Browse{} gives you a large network
of information in which there are many ways to reach the same pages.

Again click on the \UpBitmap{} to return to the table of constructors
whose names contain {\tt matrix}.  Below the table is a {\it Views}
panel.  This panel contains buttons that let you view constructors in
different ways.  To learn about views of constructors, skip to
\downlink{``Views Of Constructors''}{ugBrowseViewsOfConstructorsPage}
in Section 14.2.3\ignore{ugBrowseViewsOfConstructors}.

Click on \UpBitmap{} to return to the \Browse{} front page.

\subsubsection{Operations}

Enter {\tt *matrix} into the input area and click on {\bf Operations}.
This time you get a table of {\it operations} whose names end with
{\tt matrix} or {\tt Matrix}.


If you select an operation name, you go to a page describing all the
operations in Axiom of that name.  At the bottom of an operation page
is another kind of {\it Views} panel, one for operation pages.  To
learn more about these views, skip to
\downlink{``Views of Operations''}{ugBrowseViewsOfOperationsPage}
in Section 14.3.2\ignore{ugBrowseViewsOfOperations}.

Click on \UpBitmap{} to return to the \Browse{} front page.

\subsubsection{Attributes}

This button gives you a table of attribute names that match the
search string. Enter the search string {\tt *} and click on
{\bf Attributes} to get a list
of all system attributes.

Click on \UpBitmap{} to return to the \Browse{} front page.

Again there is a {\it Views} panel at the bottom with buttons that let
you view the attributes in different ways.

\subsubsection{General}

This button does a general search for all constructor, operation, and
attribute names matching the search string.  Enter the search string
\allowbreak {\tt *matrix*} into the input area.  Click on {\bf
General} to find all constructs that have {\tt matrix} as a part of
their name.


The summary gives you all the names under a heading when the number of
entries is less than 10. 

Click on \UpBitmap{} to return to the \Browse{} front page.

\subsubsection{Documentation}

Again enter the search key {\tt *matrix*} and this time click on
{\bf Documentation}.
This search matches any constructor, operation, or attribute
name whose documentation contains a substring matching {\tt
matrix}.


Click on \UpBitmap{} to return to the \Browse{} front page.

\subsubsection{Complete}

This search combines both {\bf General} and {\bf Documentation}.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugBrowseDomainPage}{ug14.ht}{The Constructor Page}
\begin{chunk}{ug14.ht}
\begin{page}{ugBrowseDomainPage}{14.2. The Constructor Page}
\beginscroll

In this section we look in detail at a constructor page for domain
\axiomType{Matrix}.
Enter {\tt matrix} into the input area on the main \Browse{} page
and click on {\bf Constructors}.



The header part tells you that \axiomType{Matrix} has abbreviation
\axiomType{MATRIX} and one argument called {\tt R} that must be a
domain of category \axiomType{Ring}.
Just what domains can be arguments of \axiomType{Matrix}?
To find this out, click on the {\tt R} on the second line of the
heading.
What you get is a table of all acceptable domain parameter values
of {\tt R}, or a table of \spadgloss{rings} in Axiom.


Click on \UpBitmap{} to return to the constructor page for
\axiomType{Matrix}.
\texht{\newpage}{}

If you have access to the source code of Axiom, the third
line of the heading gives you the name of the source file
containing the definition of \axiomType{Matrix}.
Click on it to pop up an editor window containing the source code
of \axiomType{Matrix}.


We recommend that you leave the editor window up while working
through this chapter as you occasionally may want to refer to it.
\texht{\newpage}{}

\beginmenu
\menudownlink{{14.2.1. Constructor Page Buttons}}
{ugBrowseDomainButtonsPage}
\menudownlink{{14.2.2. Cross Reference}}
{ugBrowseCrossReferencePage}
\menudownlink{{14.2.3. Views Of Constructors}}
{ugBrowseViewsOfConstructorsPage}
\menudownlink{{14.2.4. Giving Parameters to Constructors}}
{ugBrowseGivingParametersPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugBrowseDomainButtonsPage}{ug14.ht}{Constructor Page Buttons}
\pageto{notitle}{ugBrowseViewsOfOperationsPage}
\begin{chunk}{ug14.ht}
\begin{page}{ugBrowseDomainButtonsPage}{14.2.1. Constructor Page Buttons}
\beginscroll

We examine each button on this page in order.

\labelSpace{2pc}

\subsubsection{Description}

Click here to bring up a page with a brief description of
constructor \axiomType{Matrix}.
If you have access to system source code, note that these comments
can be found directly over the constructor definition.


\subsubsection{Operations}

Click here to get a table of operations exported by
\axiomType{Matrix}.
You may wish to widen the window to have multiple columns as
below.


If you click on an operation name, you bring up a description page for
the operations.  For a detailed description of these pages, skip to
\downlink{``Views of Operations''}{ugBrowseViewsOfOperationsPage}
in Section 14.3.2\ignore{ugBrowseViewsOfOperations}.

\subsubsection{Attributes}

Click here to get a table of the two attributes exported by
\axiomType{Matrix}:
\spadatt{\texht{fi\-nite\-Ag\-gre\-gate}{finiteAggregate}} and 
\spadatt{shallowlyMutable}.
These are two computational properties that result from
\axiomType{Matrix} being regarded as a data structure.

\subsubsection{Examples}

Click here to get an {\it examples page} with examples of operations to
create and manipulate matrices.

Read through this section.
Try selecting the various buttons.
Notice that if you click on an operation name, such as
\spadfunFrom{new}{Matrix}, you bring up a description page for that
operation from \axiomType{Matrix}.

Example pages have several examples of Axiom commands.
Each example has an active button to its left.
Click on it!
A pre-computed answer is pasted into the page immediately following the
command.
If you click on the button a second time, the answer disappears.
This button thus acts as a toggle:
``now you see it; now you don't.''

Note also that the Axiom commands themselves are active.
If you want to see Axiom execute the command, then click on it!
A new Axiom window appears on your screen and the command is
executed.

\httex{At the end of the page is generally a menu of buttons that lead
you to further sections.
Select one of these topics to explore its contents.}{}

\subsubsection{Exports}

Click here to see a page describing the exports of \axiomType{Matrix}
exactly as described by the source code.


As you see, \axiomType{Matrix} declares that it exports all the operations
and attributes exported by category
\axiomType{MatrixCategory(R, Row, Col)}.
In addition, two operations, \axiomFun{diagonalMatrix} and
\axiomFun{inverse}, are explicitly exported.

To learn a little about the structure of Axiom, we suggest you do
the following exercise.
Otherwise, click on \UpButton{} and go on to the next section.
\axiomType{Matrix} explicitly exports only two operations.
The other operations are thus exports of \axiomType{MatrixCategory}.
In general, operations are usually not explicitly exported by a domain.
Typically they are \spadglossSee{inherited}{inherit} from several
different categories.
Let's find out from where the operations of \axiomType{Matrix} come.

\indent{4}
\beginitems
\item[1. ] Click on {\bf MatrixCategory}, then on {\bf Exports}.
Here you see that {\bf MatrixCategory} explicitly exports many matrix
operations.
Also, it inherits its operations from
\axiomType{TwoDimensionalArrayCategory}.

\item[2. ] Click on {\bf TwoDimensionalArrayCategory}, then on 
{\bf Exports}.  Here you see explicit operations dealing with rows 
and columns.  In addition, it inherits operations from
\axiomType{HomogeneousAggregate}.

%\item Click on {\bf HomogeneousAggregate}, then on {\bf Exports}.
%And so on.
%If you continue doing this, eventually you will

\item[3. ] Click on \UpBitmap{} and then
click on {\bf Object}, then on {\bf Exports}, where you see
there are no exports.

\item[4. ] Click on \UpBitmap{} repeatedly to return to the constructor 
page for \axiomType{Matrix}.

\enditems
\indent{0}

\subsubsection{Related Operations}

Click here bringing up a table of operations that are exported by
\spadglossSee{packages}{package} but not by \axiomType{Matrix} itself.


To see a table of such packages, use the {\bf Relatives} button on the
{\bf Cross Reference} page described next.


\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugBrowseCrossReferencePage}{ug14.ht}{Cross Reference}
\begin{chunk}{ug14.ht}
\begin{page}{ugBrowseCrossReferencePage}{14.2.2. Cross Reference}
\beginscroll
Click on the {\bf Cross Reference} button on the main constructor page
for \axiomType{Matrix}.
This gives you a page having various cross reference information stored
under the respective buttons.


\subsubsection{Parents}

The parents of a domain are the same as the categories mentioned under
the {\bf Exports} button on the first page.
Domain \axiomType{Matrix} has only one parent but in general a domain can
have any number.

\subsubsection{Ancestors}

The \spadglossSee{ancestors}{ancestor} of a constructor consist of its
parents, the parents of its parents, and so on.  Did you perform the
exercise in the last section under {\bf Exports}?  If so, you see here
all the categories you found while ascending the {\bf Exports} chain
for \axiomType{Matrix}.

\subsubsection{Relatives}

The \spadglossSee{relatives}{relative} of a domain constructor are package
constructors that provide operations in addition to those
\spadglossSee{exported}{export} by the domain.

Try this exercise.
\indent{4}
\beginitems
\item[1. ] Click on {\bf Relatives}, bringing up a list of
\spadglossSee{packages}{package}.

\item[2. ] Click on {\bf LinearSystemMatrixPackage} bringing up its
constructor page.\footnote{You may want to widen your Hyperdoc
window to make what follows more legible.}

\item[3. ] Click on {\bf Operations}.
Here you see \axiomFun{rank}, an operation also exported by
\axiomType{Matrix} itself.

\item[4. ] Click on {\bf rank}.
This \spadfunFrom{rank}{LinearSystemMatrixPackage} has two arguments and
thus is different from the \spadfunFrom{rank}{Matrix} from
\axiomType{Matrix}.

\item[5. ] Click on \UpBitmap{} to return to the list of operations for 
the package \axiomType{LinearSystemMatrixPackage}.

\item[6. ] Click on {\bf solve} to bring up a
\spadfunFrom{solve}{LinearSystemMatrixPackage} for linear systems of
equations.

\item[7. ] Click on \UpBitmap{} several times to return to the cross
reference page for \axiomType{Matrix}.
\enditems
\indent{0}

\subsubsection{Dependents}

The \spadglossSee{dependents}{dependent} of a constructor are those
\spadglossSee{domains}{domain} or \spadglossSee{packages}{package}
that mention that constructor either as an argument or in its 
\spadglossSee{exports}{export}.

If you click on {\bf Dependents} two entries may surprise you:
\axiomType{RectangularMatrix} and \axiomType{SquareMatrix}.
This happens because \axiomType{Matrix}, as it turns out, appears in
signatures of operations exported by these domains.

\subsubsection{Lineage}

The term \spadgloss{lineage} refers to the {\it search order} for
functions.
If you are an expert user or curious about how the Axiom system
works, try the following exercise.
Otherwise, you best skip this button and go on to {\bf Clients}.

Clicking on {\bf Lineage} gives you a
list of domain constructors:
\axiomType{InnerIndexedTwoDimensionalArray},
\aliascon{MatrixCategory\&}{MATCAT-},
\aliascon{TwoDimensionalArrayCategory\&}{ARR2CAT-},
\aliascon{HomogeneousAggregate\&}{HOAGG-},
\aliascon{Aggregate\&}{AGG-}.
What are these constructors and how are they used?

We explain by an example.  Suppose you create a matrix using the
interpreter, then ask for its \axiomFun{rank}.  Axiom must then find a
function implementing the \axiomFun{rank} operation for matrices.  The
first place Axiom looks for \axiomFun{rank} is in the
\axiomType{Matrix} domain.

If not there, the lineage of \axiomType{Matrix} tells Axiom where else
to look.  Associated with the matrix domain are five other lineage
domains.  Their order is important.  Axiom first searches the first
one, \axiomType{InnerIndexedTwoDimensionalArray}.  If not there, it
searches the second \aliascon{MatrixCategory\&}{MATCAT-}.  And so on.

Where do these {\it lineage constructors} come from?
The source code for \axiomType{Matrix} contains this syntax for the
\spadgloss{function body} of
\axiomType{Matrix}:\footnote{\axiomType{InnerIndexedTwoDimensionalArray}
is a special domain implemented for matrix-like domains to provide
efficient implementations of \twodim{} arrays.
For example, domains of category \axiomType{TwoDimensionalArrayCategory}
can have any integer as their \spad{minIndex}.
Matrices and other members of this special ``inner'' array have their
\spad{minIndex} defined as \spad{1}.}
\begin{verbatim}
InnerIndexedTwoDimensionalArray(R,mnRow,mnCol,Row,Col)
   add ...
\end{verbatim}
where the ``{\tt ...}'' denotes all the code that follows.
In English, this means:
``The functions for matrices are defined as those from
\axiomType{InnerIndexedTwoDimensionalArray} domain augmented by those
defined in `{\tt ...}','' where the latter take precedence.

This explains \axiomType{InnerIndexedTwoDimensionalArray}.
The other names, those with names ending with an ampersand \axiomSyntax{\&} are
\spadglossSee{default packages}{default package}
for categories to which \axiomType{Matrix} belongs.
Default packages are ordered by the notion of ``closest ancestor.''

\subsubsection{Clients}

A client of \axiomType{Matrix} is any constructor that uses
\axiomType{Matrix} in its implementation.
For example, \axiomType{Complex} is a client of \axiomType{Matrix}; it
exports several operations that take matrices as arguments or return
matrices as values.\footnote{A constructor is a client of
\axiomType{Matrix} if it handles any matrix.
For example, a constructor having internal (unexported) operations
dealing with matrices is also a client.}

\subsubsection{Benefactors}

A \spadgloss{benefactor} of \axiomType{Matrix} is any constructor that
\axiomType{Matrix} uses in its implementation.
This information, like that for clients, is gathered from run-time
structures.\footnote{The benefactors exclude constructors such as
\axiomType{PrimitiveArray} whose operations macro-expand and so vanish
from sight!}

Cross reference pages for categories have some different buttons on
them.
Starting with the constructor page of \axiomType{Matrix}, click on
\axiomType{Ring} producing its constructor page.
Click on {\bf Cross Reference},
producing the cross-reference page for \axiomType{Ring}.
Here are buttons {\bf Parents} and {\bf Ancestors} similar to the notion
for domains, except for categories the relationship between parent and
child is defined through \spadgloss{category extension}.

\subsubsection{Children}

Category hierarchies go both ways.
There are children as well as parents.
A child can have any number of parents, but always at least one.
Every category is therefore a descendant of exactly one category:
\axiomType{Object}.

\subsubsection{Descendants}

These are children, children of children, and so on.

Category hierarchies are complicated by the fact that categories take
parameters.
Where a parameterized category fits into a hierarchy {\it may} depend on
values of its parameters.
In general, the set of categories in Axiom forms a {\it directed
acyclic graph}, that is, a graph with directed arcs and no cycles.

\subsubsection{Domains}

This produces a table of all domain constructors that can possibly be
rings (members of category \axiomType{Ring}).
Some domains are unconditional rings.
Others are rings for some parameters and not for others.
To find out which, select the {\bf conditions} button in the views
panel.
For example, \axiomType{DirectProduct(n, R)} is a ring if {\tt R} is a
ring.



\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugBrowseViewsOfConstructorsPage}{ug14.ht}{Views Of Constructors}
\begin{chunk}{ug14.ht}
\begin{page}{ugBrowseViewsOfConstructorsPage}{14.2.3. Views Of Constructors}
\beginscroll

Below every constructor table page is a {\it Views} panel.
As an example, click on {\bf Cross Reference} from
the constructor page of \axiomType{Matrix},
then on {\bf Benefactors} to produce a
short table of constructor names.

The {\it Views} panel is at the bottom of the page.
Two items, {\it names} and {\it conditions,} are in italics.
Others are active buttons.
The active buttons are those that give you useful alternative views
on this table of constructors.
Once you select a view, you notice that the button turns
off (becomes italicized) so that you cannot reselect it.

\subsubsection{names}

This view gives you a table of names.
Selecting any of these names brings up the constructor page for that
constructor.

\subsubsection{abbrs}

This view gives you a table of abbreviations, in the same order as the
original constructor names.
nAbbreviations are in capitals and are limited to 7 characters.
They can be used interchangeably with constructor names in input areas.

\subsubsection{kinds}

This view organizes constructor names into
the three kinds: categories, domains and packages.

\subsubsection{files}

This view gives a table of file names for the source
code of the constructors in alphabetic order after removing
duplicates.

\subsubsection{parameters}

This view presents constructors with the arguments.
This view of the benefactors of \axiomType{Matrix} shows that
\axiomType{Matrix} uses as many as five different \axiomType{List} domains
in its implementation.

\subsubsection{filter}

This button is used to refine the list of names or abbreviations.
Starting with the {\it names} view, enter {\tt m*} into the input area
and click on {\bf filter}.
You then get a shorter table with only the names beginning with {\tt m}.

\subsubsection{documentation}

This gives you documentation for each of the constructors.

\subsubsection{conditions}

This page organizes the constructors according to predicates.  The
view is not available for your example page since all constructors are
unconditional.  For a table with conditions, return to the {\bf Cross
Reference} page for \axiomType{Matrix}, click on {\bf Ancestors}, then
on {\bf conditions} in the view panel.  This page shows you that
\axiomType{CoercibleTo(OutputForm)} and \axiomType{SetCategory} are
ancestors of \axiomType{Matrix(R)} only if {\tt R} belongs to category
\axiomType{SetCategory}.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugBrowseGivingParametersPage}{ug14.ht}
{Giving Parameters to Constructors}
\begin{chunk}{ug14.ht}
\begin{page}{ugBrowseGivingParametersPage}
{14.2.4. Giving Parameters to Constructors}
\beginscroll
%*********************************************************************

Notice the input area at the bottom of the constructor page.  If you
leave this blank, then the information you get is for the domain
constructor \axiomType{Matrix(R)}, that is, \axiomType{Matrix} for an
arbitrary underlying domain {\tt R}.

In general, however, the exports and other information {\it do} usually
depend on the actual value of {\tt R}.
For example, \axiomType{Matrix} exports the \axiomFun{inverse} operation
only if the domain {\tt R} is a \axiomType{Field}.
To see this, try this from the main constructor page:

\indent{4}
\beginitems
\item[1. ] Enter {\tt Integer} into the input area at the bottom of
the page.

\item[2. ] Click on {\bf Operations}, producing a table of operations.
Note the number of operation names that appear at the top of the
page.

\item[3. ] Click on \UpBitmap{} to return to the constructor page.

\item[4. ] Use the
\texht{\fbox{\bf Delete}}{{\bf Delete}}
or
\texht{\fbox{\bf Backspace}}{{\bf Backspace}}
keys to erase {\tt Integer} from the input area.

\item[5. ] Click on {\bf Operations} to produce a new table of operations.
Look at the number of operations you get.
This number is greater than what you had before.
Find, for example, the operation \axiomFun{inverse}.

\item[6. ] Click on {\bf inverse} to produce a page describing the
operation \axiomFun{inverse}.  At the bottom of the description, you
notice that the {\bf Conditions} line says ``{\tt R} has
\axiomType{Field}.''  This operation is {\it not} exported by
\axiomType{Matrix(Integer)} since \axiomType{Integer} is not a
\spadgloss{field}.

Try putting the name of a domain such as \axiomType{Fraction Integer}
(which is a field) into the input area, then clicking on {\bf Operations}.
As you see, the operation \axiomFun{inverse} is exported.
\enditems
\indent{0}

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugBrowseMiscellaneousFeaturesPage}{ug14.ht}
{Miscellaneous Features of Browse}
\begin{chunk}{ug14.ht}
\begin{page}{ugBrowseMiscellaneousFeaturesPage}
{14.3. Miscellaneous Features of Browse}
\beginscroll
\labelSpace{4pc}
\beginmenu
\menudownlink{{14.3.1. The Description Page for Operations}}
{ugBrowseDescriptionPagePage}
\menudownlink{{14.3.2. Views of Operations}}
{ugBrowseViewsOfOperationsPage}
\menudownlink{{14.3.3. Capitalization Convention}}
{ugBrowseCapitalizationConventionPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugBrowseDescriptionPagePage}{ug14.ht}
{The Description Page for Operations}
\begin{chunk}{ug14.ht}
\begin{page}{ugBrowseDescriptionPagePage}
{14.3.1. The Description Page for Operations}
\beginscroll
From the constructor page of \axiomType{Matrix},
click on {\bf Operations} to bring up the table of operations
for \axiomType{Matrix}.

Find the operation {\bf inverse} in the table and click on it.
This takes you to a page showing the documentation for this operation.


Here is the significance of the headings you see.

\subsubsection{Arguments}

This lists each of the arguments of the operation in turn,
paraphrasing the \spadgloss{signature} of the operation.  As for
signatures, a \axiomSyntax{\$} is used to designate {\em this domain},
that is, \axiomType{Matrix(R)}.

\subsubsection{Returns}

This describes the return value for the operation, analogous to the {\bf
Arguments} part.

\subsubsection{Origin}

This tells you which domain or category explicitly exports the
operation.
In this example, the domain itself is the {\it Origin}.


\subsubsection{Conditions}

This tells you that the operation is exported by 
\axiomType{Matrix(R)} only if
``{\tt R} has \axiomType{Field},'' that is, ``{\tt R} is a member of
category \axiomType{Field}.''
When no {\bf Conditions} part is given, the operation is exported for
all values of {\tt R}.

\subsubsection{Description}

Here are the \axiomSyntax{++} comments
that appear in the source code of its {\it Origin}, here 
\axiomType{Matrix}.
You find these comments in the source code for \axiomType{Matrix}.


Click on \UpBitmap{} to return to the table of operations.
Click on {\bf map}.
Here you find three different operations named \axiomFun{map}.
This should not surprise you.
Operations are identified by name and \spadgloss{signature}.
There are three operations named \axiomFun{map}, each with
different signatures.
What you see is the {\it descriptions} view of the operations.
If you like, select the button in the heading of one of these
descriptions to get {\it only} that operation.

\subsubsection{Where}

This part qualifies domain parameters mentioned in the arguments to the
operation.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugBrowseViewsOfOperationsPage}{ug14.ht}{Views of Operations}
\begin{chunk}{ug14.ht}
\begin{page}{ugBrowseViewsOfOperationsPage}{14.3.2. Views of Operations}
\beginscroll

We suggest that you go to the constructor page for \axiomType{Matrix}
and click on {\bf Operations} to bring up a table of operations
with a {\it Views} panel at the bottom.

\subsubsection{names}

This view lists the names of the operations.
Unlike constructors, however, there may be several operations with the
same name.
The heading for the page tells you the number of unique names and the
number of distinct operations when these numbers are different.

\subsubsection{filter}

As for constructors, you can use this button to cut down the list of
operations you are looking at.
Enter, for example, {\tt m*} into the input area to the right of {\bf
filter} then click on {\bf filter}.
As usual, any logical expression is permitted.
For example, use
\begin{verbatim}
*! or *?
\end{verbatim}
to get a list of destructive operations and predicates.

\subsubsection{documentation}

This gives you the most information:
a detailed description of all the operations in the form you have seen
before.
Every other button summarizes these operations in some form.

\subsubsection{signatures}

This views the operations by showing their signatures.

\subsubsection{parameters}

This views the operations by their distinct syntactic forms with
parameters.

\subsubsection{origins}

This organizes the operations according to the constructor that
explicitly exports them.

\subsubsection{conditions}

This view organizes the operations into conditional and unconditional
operations.

\subsubsection{usage}

This button is only available if your user-level is set to {\it
development}.
The {\bf usage} button produces a table of constructors that reference this
operation.\footnote{Axiom requires an especially long time to
produce this table, so anticipate this when requesting this
information.}

\subsubsection{implementation}

This button is only available if your user-level is set to {\it
development}.
If you enter values for all domain parameters on the constructor page,
then the {\bf implementation} button appears in place of the {\bf
conditions} button.
This button tells you what domains or packages actually implement the
various operations.\footnote{This button often takes a long time; expect
a delay while you wait for an answer.}

With your user-level set to {\it development}, we suggest you try this
exercise.
Return to the main constructor page for \axiomType{Matrix}, then enter
{\tt Integer} into the input area at the bottom as the value of {\tt R}.
Then click on {\bf Operations} to produce a table of operations.
Note that the {\bf conditions} part of the {\it Views} table is
replaced by {\bf implementation}.
Click on {\bf implementation}.
After some delay, you get a page describing what implements each of
the matrix operations, organized by the various domains and packages.


\subsubsection{generalize}

This button only appears for an operation page of a constructor
involving a unique operation name.

From an operations page for \axiomType{Matrix}, select any
operation name, say {\bf rank}.
In the views panel, the {\bf filter} button is  replaced by
{\bf generalize}.
Click on it!
%% Replaced {\bf threshold} with 10 below.  MGR 1995oct31
What you get is a description of all Axiom operations
named \axiomFun{rank}.\footnote{If there were more than 10
operations of the name, you get instead a page
with a {\it Views} panel at the bottom and the message to {\bf
Select a view below}.
To get the descriptions of all these operations as mentioned
above, select the {\bf description} button.}

\subsubsection{all domains}

This button only appears on an operation page resulting from a
search from the front page of \Browse{} or from selecting
{\bf generalize} from an operation page for a constructor.

Note that the {\bf filter} button in the {\it Views} panel is
replaced by {\bf all domains}.
Click on it to produce a table of {\it all} domains or packages that
export a \axiomFun{rank} operation.


We note that this table specifically refers to all the \axiomFun{rank}
operations shown in the preceding page.
Return to the descriptions of all the \axiomFun{rank} operations and
select one of them by clicking on the button in its heading.
Select {\bf all domains}.
As you see, you have a smaller table of constructors.
When there is only one constructor, you get the
constructor page for that constructor.
\texht{\newpage}{}

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugBrowseCapitalizationConventionPage}{ug14.ht}
{Capitalization Convention}
\begin{chunk}{ug14.ht}
\begin{page}{ugBrowseCapitalizationConventionPage}
{14.3.3. Capitalization Convention}
\beginscroll

When entering search keys for constructors, you can use capital
letters to search for abbreviations.
For example, enter {\tt UTS} into the input area and click on {\bf
Constructors}.
Up comes a page describing \axiomType{UnivariateTaylorSeries}
whose abbreviation is \axiomType{UTS}.

Constructor abbreviations always have three or more capital
letters.
For short constructor names (six letters or less), abbreviations
are not generally helpful as their abbreviation is typically the
constructor name in capitals.
For example, the abbreviation for \axiomType{Matrix} is
\axiomType{MATRIX}.

Abbreviations can also contain numbers.
For example, \axiomType{POLY2} is the abbreviation for constructor
\axiomType{PolynomialFunctions2}.
For default packages, the abbreviation is the same as the
abbreviation for the corresponding category with the ``\&''
replaced by ``-''.
For example, for the category default package
\aliascon{MatrixCategory\&}{MATCAT-} the abbreviation is
\axiomType{MATCAT-} since the corresponding category
\axiomType{MatrixCategory} has abbreviation \axiomType{MATCAT}.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\chapter{Users Guide Chapter 15 (ug15.ht)}
\pagetitle{ugWhatsNewPage}{ug15.ht}{What's New in Axiom Version 2.0}
\begin{chunk}{ug15.ht}
\begin{page}{ugWhatsNewPage}{15. What's New in Axiom Version 2.0}
\beginscroll

Many things have changed in this new version of Axiom and
we describe many of the more important topics here.

\beginmenu
\menudownlink{{15.1. Important Things to Read First}}
{ugWhatsNewImportantPage}
\menudownlink{{15.3. The NAG Library Link}}{nagLinkIntroPage}
\menudownlink{{15.4. Interactive Front-end and Language}}
{ugWhatsNewLanguagePage}
\menudownlink{{15.5. Library}}{ugWhatsNewLibraryPage}
\menudownlink{{15.6. \HyperName}}{ugWhatsNewHyperDocPage}
\menudownlink{{15.7. Documentation}}{ugWhatsNewDocumentationPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugWhatsNewImportantPage}{ug15.ht}
{Important Things to Read First}
\begin{chunk}{ug15.ht}
\begin{page}{ugWhatsNewImportantPage}
{15.1. Important Things to Read First}
\beginscroll

If you have any private {\tt .spad} files (that is, library files
which were not shipped with Axiom) you will need to
recompile them.  For example, if you wrote the file {\tt
regress.spad} then you should issue {\tt )compile regress.spad}
before trying to use it.

The internal representation of \axiomType{Union}  has changed. 
This means that \texht{\linebreak}{} Axiom data saved 
with Release 1.x may not
be readable by this Release. If you cannot recreate the saved data      
by recomputing in Release 2.0, please contact NAG for assistance.       

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{nagLinkIntroPage}{ug15.ht}{The NAG Library Link}
\pageto{notitle}{htxl1}
\pageto{notitle}{nagDocumentationPage}
\pageto{notitle}{nagLinkUsagePage}
\pageto{notitle}{aspSectionPage}
\pageto{notitle}{generalFortranPage}
\pageto{notitle}{nagTechnicalPage}
\begin{chunk}{ug15.ht}
\begin{page}{nagLinkIntroPage}{15.3. The NAG Library Link}
\beginscroll

The \naglib{} link allows you to call NAG Fortran
routines from within Axiom, passing Axiom objects as parameters
and getting them back as results.

The \naglib{} and, consequently, the link are divided into {\em
chapters}, which cover different areas of numerical analysis.  The
statistical and sorting {\em chapters} of the Library, however, are
not included in the link and various support and utility routines
(mainly the F06 and X {\em chapters}) have been omitted.

Each {\em chapter} has a short (at most three-letter) name; for
example, the {\em chapter} devoted to the solution of ordinary
differential equations is called D02.  When using the link via the
\downlink{Hyperdoc interface}{htxl1}, you will be presented with a
complete menu of these {\em chapters}. The names of individual
routines within each {\em chapter} are formed by adding three letters
to the {\em chapter} name, so for example the routine for solving ODEs
by Adams method is called
\axiomFunFrom{d02cjf}{NagOrdinaryDifferentialEquationsPackage}.

\beginmenu
    \menudownlink{{15.3.1. Interpreting NAG Documentation}}
{nagDocumentationPage}
    \menudownlink{{15.3.2. Using the Link}}{nagLinkUsagePage}
    \menudownlink{{15.3.3. Providing values for Argument Subprograms}}
{aspSectionPage}
    \menudownlink{{15.3.4. General Fortran-generation utilities in Axiom}}
{generalFortranPage}
    \menudownlink{{15.3.5. Some technical information}}{nagTechnicalPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{nagDocumentationPage}{ug15.ht}{Interpreting NAG Documentation}
\pageto{notitle}{manpageXXintro}
\pageto{notitle}{manpageXXonline}
\pageto{notitle}{FoundationLibraryDocPage}
\pageto{notitle}{aspSectionPage}
\begin{chunk}{ug15.ht}
\begin{page}{nagDocumentationPage}{15.3.1. Interpreting NAG Documentation}
\beginscroll

Information about using the \naglib{} in general, and about using
individual routines in particular, can be accessed via Hyperdoc.
This documentation refers to the Fortran routines directly; the
purpose of this subsection is to explain how this corresponds to the
Axiom routines.

For general information about the \naglib{} users should consult
\downlink{Essential Introduction to the NAG Foundation Library}
{manpageXXintro}.
The documentation is in ASCII format, and a description of the conventions
used to represent mathematical symbols is given in
\downlink{Introduction to NAG On-Line Documentation}{manpageXXonline}.
Advice about choosing a routine from a particular {\em chapter} can 
be found in the \downlink{Chapter Documents}{FoundationLibraryDocPage}.

\subsubsection{Correspondence Between Fortran and Axiom types}

The NAG documentation refers to the Fortran types of objects; in
general, the correspondence to Axiom types is as follows.
\indent{4}
\beginitems
\item[-] Fortran INTEGER corresponds to Axiom \axiomType{Integer}.
\item[-] Fortran DOUBLE PRECISION corresponds to Axiom 
\axiomType{DoubleFloat}.
\item[-] Fortran COMPLEX corresponds to Axiom 
\axiomType{Complex DoubleFloat}.
\item[-] Fortran LOGICAL corresponds to Axiom \axiomType{Boolean}.
\item[-] Fortran CHARACTER*(*) corresponds to Axiom \axiomType{String}.
\enditems
\indent{0}
(Exceptionally, for NAG EXTERNAL parameters -- ASPs in link parlance
-- REAL and COMPLEX correspond to \axiomType{MachineFloat} and 
\axiomType{MachineComplex},
respectively; see 
\downlink{``Providing values for Argument Subprograms''}
{aspSectionPage} in Section 15.3.3\ignore{aspSection}.)

The correspondence for aggregates is as follows.
\indent{4}
\beginitems
\item[-] A one-dimensional Fortran array corresponds to an Axiom 
\texht{\linebreak}{}
      \axiomType{Matrix} with one column.
\item[-] A two-dimensional Fortran ARRAY corresponds to an Axiom 
\texht{\linebreak}{}
      \axiomType{Matrix}.
\item[-] A three-dimensional Fortran ARRAY corresponds to an Axiom 
\texht{\linebreak}{}
      \axiomType{ThreeDimensionalMatrix}.
\enditems
\indent{0}
Higher-dimensional arrays are not currently needed for the \naglib{}.

Arguments which are Fortran FUNCTIONs or SUBROUTINEs correspond to
special ASP domains in Axiom. See
\downlink{``Providing values for Argument Subprograms''}
{aspSectionPage} in Section 15.3.3\ignore{aspSection}.

\subsubsection{Classification of NAG parameters}

NAG parameters are classified as belonging to one (or more) of the
following categories: {\tt Input}, {\tt Output}, {\tt Workspace} or
{\tt External} procedure.  Within {\tt External} procedures a similar
classification is used, and parameters may also be {\tt Dummies}, or
{\tt User Workspace} (data structures not used by the NAG routine but
provided for the convenience of the user).

When calling a NAG routine via the link the user only provides values
for {\tt Input} and {\tt External} parameters.

The order of the parameters is, in general, different from  the order
specified in the \naglib{} documentation. The Browser description
for each routine helps in determining the correspondence. As a rule of
thumb, {\tt Input} parameters come first followed by {\tt Input/Output}
parameters. The {\tt External} parameters are always found at the end.


\subsubsection{IFAIL}

NAG routines often return diagnostic information through a parameter
called \axiom{ifail}.  With a few exceptions, the principle is that on
input \axiom{ifail} takes one of the values $-1,0,1$.  This determines
how the routine behaves when it encounters an error:
\indent{4}
\beginitems
\item[-] a value of 1 causes the NAG routine to return without printing 
an error message;
\item[-] a value of 0 causes the NAG routine to print an error message 
and abort;
\item[-] a value of -1 causes the NAG routine to return and print an 
error message.
\enditems
\indent{0}

The user is STRONGLY ADVISED to set \axiom{ifail} to \texht{$-1$}{-1}
when using the link.  If \axiom{ifail} has been set to \texht{$1$}{1}
or \texht{$-1$}{-1} on input, then its value on output will determine
the possible cause of any error.  A value of \texht{$0$}{0} indicates
successful completion, otherwise it provides an index into a table of
diagnostics provided as part of the routine documentation (accessible
via \Browse{}).

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{nagLinkUsagePage}{ug15.ht}{Using the Link}
\pageto{notitle}{htxl1}
\begin{chunk}{ug15.ht}
\begin{page}{nagLinkUsagePage}{15.3.2. Using the Link}
\beginscroll

The easiest way to use the link is via the
\downlink{Hyperdoc interface}{htxl1}.
You will be presented with a set of fill-in forms where
you can specify the parameters for each call.  Initially, the forms
contain example values, demonstrating the use of each routine (these,
in fact, correspond to the standard NAG example program for the
routine in question).  For some parameters, these values can provide
reasonable defaults; others, of course, represent data.  When you
change a parameter which controls the size of an array, the data in
that array are reset to a ``neutral'' value -- usually zero.

When you are satisfied with the values entered, clicking on the
``Continue'' button will display the Axiom command needed to
run the chosen NAG routine with these values.  Clicking on the
``Do It'' button will then cause Axiom to execute this command
and return the result in the parent Axiom session, as described
below.  Note that, for some routines, multiple HyperDoc ``pages'' are
required, due to the structure of the data.  For these, returning to
an earlier page causes HyperDoc to reset the later pages (this is a
general feature of HyperDoc); in such a case, the simplest way to
repeat a call, varying a parameter on an earlier page, is probably to
modify the call displayed in the parent session.

An alternative approach is to call NAG routines directly in your
normal Axiom session (that is, using the Axiom
interpreter).  Such calls return an
object of type \axiomType{Result}.  As not
all parameters in the underlying NAG routine are required in the
Axiom call (and the parameter ordering may be different), before
calling a NAG routine you should consult the description of the
Axiom operation in the Browser.  (The quickest route to this
is to type the routine name, in lower case, into the Browser's
input area, then click on {\tt Operations}.)  The parameter names
used coincide with NAG's, although they will appear here in lower
case.  Of course, it is also possible to become familiar with the
Axiom form of a routine by first using it through the
\downlink{Hyperdoc interface}{htxl1}.

\xtc{
As an example of this mode of working, we can find a zero
of a function, lying between 3 and 4, as follows:
}{
\spadpaste{answer:=c05adf(3.0,4.0,1.0e-5,0.0,-1,sin(X)::ASP1(F))
\bound{answer} }
}
\xtc{
By default, \axiomType{Result} only displays the type of returned values,
since the amount of information returned can be quite large.  Individual
components can be examined as follows:
}{
\spadpaste{answer . x\free{answer}}
}
\xtc{
}{
\spadpaste{answer . ifail\free{answer}}
}
\xtc{
In order to avoid conflict with names defined in the workspace, you
can also get the values by using the \axiomType{String} type (the
interpreter automatically coerces them to \axiomType{Symbol})
}{
\spadpaste{answer "x"\free{answer}}
}


It is possible to have Axiom display the values of scalar or array
results automatically.  For more details, see the commands  
\axiomFunFrom{showScalarValues}{Result}
and \axiomFunFrom{showArrayValues}{Result}.

\xtc{
There is also a {\bf .input} file for each NAG routine, containing
Axiom interpreter commands to set up and run the standard NAG
example for that routine.
}{
\spadpaste{)read c05adf.input}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{nagLinkUsagePagePatch1}
\begin{paste}{nagLinkUsagePageFull1}{nagLinkUsagePageEmpty1}
\pastebutton{nagLinkUsagePageFull1}{\hidepaste}
\tab{5}\spadcommand{answer:=c05adf(3.0,4.0,1.0e-5,0.0,-1,sin(X)::ASP1(F))\bound{answer }}
\indentrel{3}\begin{verbatim}
   (1)  [ifail: Integer,x: DoubleFloat]
                                           Type: Result
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{nagLinkUsagePageEmpty1}
\begin{paste}{nagLinkUsagePageEmpty1}{nagLinkUsagePagePatch1}
\pastebutton{nagLinkUsagePageEmpty1}{\showpaste}
\tab{5}\spadcommand{answer:=c05adf(3.0,4.0,1.0e-5,0.0,-1,sin(X)::ASP1(F))\bound{answer }}
\end{paste}\end{patch}

\begin{patch}{nagLinkUsagePagePatch2}
\begin{paste}{nagLinkUsagePageFull2}{nagLinkUsagePageEmpty2}
\pastebutton{nagLinkUsagePageFull2}{\hidepaste}
\tab{5}\spadcommand{answer . x\free{answer }}
\indentrel{3}\begin{verbatim}
   (2)  3.14159265545896
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{nagLinkUsagePageEmpty2}
\begin{paste}{nagLinkUsagePageEmpty2}{nagLinkUsagePagePatch2}
\pastebutton{nagLinkUsagePageEmpty2}{\showpaste}
\tab{5}\spadcommand{answer . x\free{answer }}
\end{paste}\end{patch}

\begin{patch}{nagLinkUsagePagePatch3}
\begin{paste}{nagLinkUsagePageFull3}{nagLinkUsagePageEmpty3}
\pastebutton{nagLinkUsagePageFull3}{\hidepaste}
\tab{5}\spadcommand{answer . ifail\free{answer }}
\indentrel{3}\begin{verbatim}
   (3)  0
                                          Type: Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{nagLinkUsagePageEmpty3}
\begin{paste}{nagLinkUsagePageEmpty3}{nagLinkUsagePagePatch3}
\pastebutton{nagLinkUsagePageEmpty3}{\showpaste}
\tab{5}\spadcommand{answer . ifail\free{answer }}
\end{paste}\end{patch}

\begin{patch}{nagLinkUsagePagePatch4}
\begin{paste}{nagLinkUsagePageFull4}{nagLinkUsagePageEmpty4}
\pastebutton{nagLinkUsagePageFull4}{\hidepaste}
\tab{5}\spadcommand{answer "x"\free{answer }}
\indentrel{3}\begin{verbatim}
   (4)  3.14159265545896
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{nagLinkUsagePageEmpty4}
\begin{paste}{nagLinkUsagePageEmpty4}{nagLinkUsagePagePatch4}
\pastebutton{nagLinkUsagePageEmpty4}{\showpaste}
\tab{5}\spadcommand{answer "x"\free{answer }}
\end{paste}\end{patch}

\begin{patch}{nagLinkUsagePagePatch5}
\begin{paste}{nagLinkUsagePageFull5}{nagLinkUsagePageEmpty5}
\pastebutton{nagLinkUsagePageFull5}{\hidepaste}
\tab{5}\spadcommand{)read c05adf.input}
\indentrel{3}\begin{verbatim}
   (1)  true
                                          Type: Boolean
   (2)  true
                                          Type: Boolean
   (3)  F
                                           Type: Asp1 F
   (4)  0.0
                                      Type: DoubleFloat
   (5)  1.0
                                      Type: DoubleFloat
   (6)  1.0e-05
                                      Type: DoubleFloat
   (7)  0.0
                                      Type: DoubleFloat
   (8)  [ifail: 0,x: 0.567143306604963]
                                           Type: Result
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{nagLinkUsagePageEmpty5}
\begin{paste}{nagLinkUsagePageEmpty5}{nagLinkUsagePagePatch5}
\pastebutton{nagLinkUsagePageEmpty5}{\showpaste}
\tab{5}\spadcommand{)read c05adf.input}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{aspSectionPage}{ug15.ht}
{Providing values for Argument Subprograms}
\pageto{notitle}{generalFortranPage}
\begin{chunk}{ug15.ht}
\begin{page}{aspSectionPage}
{15.3.3. Providing values for Argument Subprograms}
\beginscroll

There are a number of ways in which users can provide values for argument
subprograms (ASPs).  At the top level the user will see that NAG routines
require
an object from the \axiomType{Union} of a \axiomType{Filename} and an ASP.
\xtc{
For example \axiomFun{c05adf} requires an object of type 
\texht{\linebreak}{} \axiomType{Union}(fn: 
\axiomType{FileName},fp: \axiomType{Asp1 F})
}{
\spadpaste{)display operation c05adf}
}

The user thus has a choice of providing the name of a file containing
Fortran source code, or of somehow generating the ASP within Axiom.
If a filename is specified, it is searched for in the {\it local} 
machine, i.e., the machine that Axiom is running on.

\subsubsection{Providing ASPs via \axiomType{FortranExpression}}

The \axiomType{FortranExpression} domain is used to represent
expressions which can be translated into Fortran under certain
circumstances.  It is very similar to \axiomType{Expression} except
that only operators which exist in Fortran can be used, and only
certain variables can occur.  For example the instantiation
\axiomType{FortranExpression([X],[M],MachineFloat)} is the domain of
expressions containing the scalar \axiom{X} and the array \axiom{M}.
\xtc{
This allows us to create expressions like:
}{
\spadpaste{f : FortranExpression([X],[M],MachineFloat) := sin(X)+M[3,1]}
}
\xtc{
but not
}{
\spadpaste{f : FortranExpression([X],[M],MachineFloat) := sin(M)+Y}
}

Those ASPs which represent expressions usually export a
\axiomFun{coerce} from an appropriate instantiation of
\axiomType{FortranExpression} (or perhaps \axiomType{Vector
FortranExpression} etc.).  For convenience there are also retractions
from appropriate instantiations of \axiomType{Expression},
\axiomType{Polynomial} and \axiomType{Fraction Polynomial}.

\subsubsection{Providing ASPs via \axiomType{FortranCode}}

\texht{\exptypeindex{FortranCode}}{} \axiomType{FortranCode} allows us
to build arbitrarily complex ASPs via a kind of pseudo-code.  It is
described fully in
\downlink{``General Fortran-generation utilities in Axiom''}
{generalFortranPage} in Section 15.3.4\ignore{generalFortran}.

Every ASP exports two \axiomFun{coerce} functions: one from
\axiomType{FortranCode} and one from \axiomType{List FortranCode}.
There is also a \axiomFun{coerce} from \texht{\linebreak}{}
\axiomType{Record( localSymbols: SymbolTable, code: List FortranCode)}
which is used for passing extra symbol information about the ASP.

\xtc{
So for example, to integrate the function abs(x) we could use the
built-in \axiomFun{abs} function.  But suppose we want to get back to
basics and define it directly, then we could do the following:
}{
\spadpaste{d01ajf(-1.0, 1.0, 0.0, 1.0e-5, 800, 200, -1, cond(LT(X,0), 
assign(F,-X), assign(F,X))) result }
}

The \axiomFunFrom{cond}{FortranCode} operation creates a conditional
clause and the \axiomFunFrom{assign}{FortranCode} an assignment
statement.

\subsubsection{Providing ASPs via \axiomType{FileName}}

Suppose we have created the file ``asp.f'' as follows:
\begin{verbatim}
      DOUBLE PRECISION FUNCTION F(X)
      DOUBLE PRECISION X
      F=4.0D0/(X*X+1.0D0)
      RETURN
      END
\end{verbatim}
and wish to pass it to the NAG
routine \axiomFun{d01ajf} which performs one-dimensional quadrature.
We can do this as follows:
\begin{verbatim}
d01ajf(0.0 ,1.0, 0.0, 1.0e-5, 800, 200, -1, "asp.f")
\end{verbatim}

\endscroll
\autobuttons
\end{page}

\begin{patch}{aspSectionPagePatch1}
\begin{paste}{aspSectionPageFull1}{aspSectionPageEmpty1}
\pastebutton{aspSectionPageFull1}{\hidepaste}
\tab{5}\spadcommand{)display operation c05adf}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{aspSectionPageEmpty1}
\begin{paste}{aspSectionPageEmpty1}{aspSectionPagePatch1}
\pastebutton{aspSectionPageEmpty1}{\showpaste}
\tab{5}\spadcommand{)display operation c05adf}
\end{paste}\end{patch}

\begin{patch}{aspSectionPagePatch2}
\begin{paste}{aspSectionPageFull2}{aspSectionPageEmpty2}
\pastebutton{aspSectionPageFull2}{\hidepaste}
\tab{5}\spadcommand{f : FortranExpression([X],[M],MachineFloat) := sin(X)+M[3,1]}
\indentrel{3}\begin{verbatim}
   (1)  sin(X) + M
                  3,1
          Type: FortranExpression([X],[M],MachineFloat)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{aspSectionPageEmpty2}
\begin{paste}{aspSectionPageEmpty2}{aspSectionPagePatch2}
\pastebutton{aspSectionPageEmpty2}{\showpaste}
\tab{5}\spadcommand{f : FortranExpression([X],[M],MachineFloat) := sin(X)+M[3,1]}
\end{paste}\end{patch}

\begin{patch}{aspSectionPagePatch3}
\begin{paste}{aspSectionPageFull3}{aspSectionPageEmpty3}
\pastebutton{aspSectionPageFull3}{\hidepaste}
\tab{5}\spadcommand{f : FortranExpression([X],[M],MachineFloat) := sin(M)+Y}
\indentrel{3}\begin{verbatim}
   sin(M) + Y
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{aspSectionPageEmpty3}
\begin{paste}{aspSectionPageEmpty3}{aspSectionPagePatch3}
\pastebutton{aspSectionPageEmpty3}{\showpaste}
\tab{5}\spadcommand{f : FortranExpression([X],[M],MachineFloat) := sin(M)+Y}
\end{paste}\end{patch}

\begin{patch}{aspSectionPagePatch4}
\begin{paste}{aspSectionPageFull4}{aspSectionPageEmpty4}
\pastebutton{aspSectionPageFull4}{\hidepaste}
\tab{5}\spadcommand{d01ajf(-1.0, 1.0, 0.0, 1.0e-5, 800, 200, -1, cond(LT(X,0), assign(F,-X), assign(F,X))) result}
\indentrel{3}\begin{verbatim}
   (2)  1.0
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{aspSectionPageEmpty4}
\begin{paste}{aspSectionPageEmpty4}{aspSectionPagePatch4}
\pastebutton{aspSectionPageEmpty4}{\showpaste}
\tab{5}\spadcommand{d01ajf(-1.0, 1.0, 0.0, 1.0e-5, 800, 200, -1, cond(LT(X,0), assign(F,-X), assign(F,X))) result}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{generalFortranPage}{ug15.ht}
{General Fortran-generation utilities in Axiom}
\begin{chunk}{ug15.ht}
\begin{page}{generalFortranPage}
{15.3.4. General Fortran-generation utilities in Axiom}
\beginscroll

This section describes more advanced facilities which are available to
users who wish to generate Fortran code from within Axiom.  There are
facilities to manipulate templates, store type information, and
generate code fragments or complete programs.

\subsubsection{Template Manipulation}

A template is a skeletal program which is ``fleshed out'' with data when
it is processed.  It is a sequence of {\em active} and {\em passive} parts:
active parts are sequences of Axiom commands which are processed as if they
had been typed into the interpreter; passive parts are simply echoed
verbatim on the Fortran output stream.

Suppose, for example, that we have the following template, stored in
the file ``test.tem'':
\begin{verbatim}
-- A simple template
beginVerbatim
      DOUBLE PRECISION FUNCTION F(X)
      DOUBLE PRECISION X
endVerbatim
outputAsFortran("F",f)
beginVerbatim
      RETURN
      END
endVerbatim
\end{verbatim}
The passive parts lie between the two tokens {\tt beginVerbatim} and
\texht{\linebreak}{} {\tt endVerbatim}.  There are two active
statements: one which is simply an Axiom ( \texht{\verb+--+}{\-\-})
comment, and one which produces an assignment to the current value of
{\tt f}.  We could use it as follows:
\begin{verbatim}
(4) ->f := 4.0/(1+X**2)

           4
   (4)   ------
          2
         X  + 1
                       
(5) ->processTemplate "test.tem"
      DOUBLE PRECISION FUNCTION F(X)
      DOUBLE PRECISION X
      F=4.0D0/(X*X+1.0D0)
      RETURN 
      END

   (5)  "CONSOLE"
\end{verbatim}

(A more reliable method of specifying the filename will be introduced
below.)  Note that the Fortran assignment {\tt F=4.0D0/(X*X+1.0D0)}
automatically converted 4.0 and 1 into DOUBLE PRECISION numbers; in
general, the Axiom Fortran generation facility will convert
anything which should be a floating point object into either
a Fortran REAL or DOUBLE PRECISION object.
\xtc{
Which alternative is used is determined by the command
}{
\spadpaste{)set fortran precision}
}

It is sometimes useful to end a template before the file itself ends
(e.g. to allow the template to be tested incrementally or so that a
piece of text describing how the template works can be included).  It
is of course possible to ``comment-out'' the remainder of the file.
Alternatively, the single token {\tt endInput} as part of an active
portion of the template will cause processing to be ended prematurely
at that point.

The \axiomFun{processTemplate} command comes in two flavours.  In the
first case, illustrated above, it takes one argument of domain
\axiomType{FileName}, the name of the template to be processed, and
writes its output on the current Fortran output stream.  In general, a
filename can be generated from {\em directory}, {\em name} and {\em
extension} components, using the operation \axiomFun{filename}, as in
\begin{verbatim}
processTemplate filename("","test","tem")
\end{verbatim}
There is an alternative version of \axiomFun{processTemplate}, which
takes two arguments (both of domain \axiomType{FileName}).  In this
case the first argument is the name of the template to be processed,
and the second is the file in which to write the results.  Both
versions return the location of the generated Fortran code as their
result ({\tt "CONSOLE"} in the above example).

It is sometimes useful to be able to mix active and passive parts of a
line or statement.  For example you might want to generate a Fortran
Comment describing your data set.  For this kind of application we
provide three functions as follows:
\texht
{
\begin{tabular}{p{1.8in}p{2.6in}}
\axiomFun{fortranLiteral} & writes a string on the Fortran output 
stream \\
 & \\
\axiomFun{fortranCarriageReturn} & writes a carriage return on the 
Fortran output stream \\
& \\
\axiomFun{fortranLiteralLine} & writes a string followed by a return
on the Fortran output stream \\
\end{tabular}
}
{
\newline
\axiomFun{fortranLiteral}\tab{25}writes a string on the Fortran 
output stream\newline
\axiomFun{fortranCarriageReturn}\tab{25}writes a carriage return 
on the Fortran output stream\newline
\axiomFun{fortranLiteralLine}\tab{25}writes a string followed by 
a return on the Fortran output stream\newline
}
\xtc{
So we could create our comment as follows:
}{
\spadpaste{m := matrix [[1,2,3],[4,5,6]]\bound{m}}
}
\xtc{
}{
\spadpaste{fortranLiteralLine concat 
["C\ \ \ \ \ \ The\ Matrix\ has\ ", nrows(m)::String, "\ rows\ 
and\ ", ncols(m)::String, "\ columns"]\free{m}}
}
\xtc{
or, alternatively:
}{
\spadpaste{fortranLiteral "C\ \ \ \ \ \ The\ Matrix\ has\ "}
}
\xtc{
}{
\spadpaste{fortranLiteral(nrows(m)::String)}
}
\xtc{
}{
\spadpaste{fortranLiteral "\ rows\ and\ "}
}
\xtc{
}{
\spadpaste{fortranLiteral(ncols(m)::String)\free{m}}
}
\xtc{
}{
\spadpaste{fortranLiteral "\ columns"}
}
\xtc{
}{
\spadpaste{fortranCarriageReturn()}
}

We should stress that these functions, together with the
\axiomFun{outputAsFortran} function are the {\em only} sure ways of
getting output to appear on the Fortran output stream.  Attempts to
use Axiom commands such as \axiomFun{output} or \axiomFunX{writeline}
may appear to give the required result when displayed on the console,
but will give the wrong result when Fortran and algebraic output are
sent to differing locations.  On the other hand, these functions can
be used to send helpful messages to the user, without interfering with
the generated Fortran.

\subsubsection{Manipulating the Fortran Output Stream}
\texht{\exptypeindex{FortranOutputStackPackage}}{}

Sometimes it is useful to manipulate the Fortran output stream in a
program, possibly without being aware of its current value.  The main
use of this is for gathering type declarations (see ``Fortran Types''
below) but it can be useful in other contexts as well.  Thus we
provide a set of commands to manipulate a stack of (open) output
streams.  Only one stream can be written to at any given time.  The
stack is never empty---its initial value is the console or the current
value of the Fortran output stream, and can be determined using
\xtc{
}{
\spadpaste{topFortranOutputStack()}
}
(see below).
The commands available to manipulate the stack are:
\texht{
\begin{tabular}{ll}
\axiomFun{clearFortranOutputStack} & resets the stack to the console \\
 & \\
\axiomFun{pushFortranOutputStack} & pushes a 
\axiomType{FileName} onto the stack \\
 & \\
\axiomFun{popFortranOutputStack} & pops the stack \\
 & \\
\axiomFun{showFortranOutputStack} & returns the current stack \\
 & \\
\axiomFun{topFortranOutputStack} & returns the top element of the stack \\
\end{tabular}
}
{
\newline
\axiomFun{clearFortranOutputStack}\tab{25}resets the stack\newline
\axiomFun{pushFortranOutputStack}\tab{25}pushes a 
\axiomType{FileName} onto the stack\newline
\axiomFun{popFortranOutputStack}\tab{25}pops the stack\newline
\axiomFun{showFortranOutputStack}\tab{25}returns the current stack\newline
\axiomFun{topFortranOutputStack}\tab{25}returns the 
top element of the stack\newline
}
These commands are all part of \axiomType{FortranOutputStackPackage}.

\subsubsection{Fortran Types}

When generating code it is important to keep track of the Fortran
types of the objects which we are generating.  This is useful for a
number of reasons, not least to ensure that we are actually generating
legal Fortran code.  The current type system is built up in several
layers, and we shall describe each in turn.

\subsubsection{FortranScalarType}
\texht{\exptypeindex{FortranScalarType}}{}

This domain represents the simple Fortran datatypes: REAL, 
DOUBLE PRECISION, COMPLEX, LOGICAL, INTEGER, and CHARACTER.
It is possible to \axiomFun{coerce} a \axiomType{String} or 
\axiomType{Symbol} into the domain, test whether two objects are 
equal, and also apply the predicate functions 
\axiomFunFrom{real?}{FortranScalarType} etc.

\subsubsection{FortranType}
\texht{\exptypeindex{FortranType}}{}

This domain represents ``full'' types: i.e., datatype plus array
dimensions (where appropriate) plus whether or not the parameter is an
external subprogram.  It is possible to \axiomFun{coerce} an object of
\axiomType{FortranScalarType} into the domain or \axiomFun{construct}
one from an element of \axiomType{FortranScalarType}, a list of
\axiomType{Polynomial Integer}s (which can of course be simple
integers or symbols) representing its dimensions, and a
\axiomType{Boolean} declaring whether it is external or not.  The list
of dimensions must be empty if the \axiomType{Boolean} is {\tt true}.
The functions \axiomFun{scalarTypeOf}, \axiomFun{dimensionsOf} and
\axiomFun{external?} return the appropriate parts, and it is possible
to get the various basic Fortran Types via functions like
\axiomFun{fortranReal}.
\xtc{
For example:
}{
\spadpaste{type:=construct(real,[i,10],false)$FortranType}
}
\xtc{
or
}{
\spadpaste{type:=[real,[i,10],false]$FortranType\bound{type}}
}
\xtc{
}{
\spadpaste{scalarTypeOf type\free{type}}
}
\xtc{
}{
\spadpaste{dimensionsOf type\free{type}}
}
\xtc{
}{
\spadpaste{external?  type\free{type}}
}
\xtc{
}{
\spadpaste{fortranLogical()}
}
\xtc{
}{
\spadpaste{construct(integer,[],true)$FortranType}
}

\subsubsection{SymbolTable}
\texht{\exptypeindex{SymbolTable}}{}

This domain creates and manipulates a symbol table for generated
Fortran code.  This is used by \axiomType{FortranProgram} to represent
the types of objects in a subprogram.  The commands available are:
\texht{
\begin{tabular}{ll}
\axiomFun{empty} & creates a new \axiomType{SymbolTable} \\
 & \\
\axiomFunX{declare} & creates a new entry in a table \\
 & \\
\axiomFun{fortranTypeOf} & returns the type of an object in a table \\
 & \\
\axiomFun{parametersOf} & returns a list of all the symbols in the table \\
 & \\
\axiomFun{typeList} & returns a list of all objects of a given type \\
 & \\
\axiomFun{typeLists} & 
returns a list of lists of all objects sorted by type \\
 & \\
\axiomFun{externalList} & returns a list of all {\tt EXTERNAL} objects \\
 & \\
\axiomFun{printTypes} & produces Fortran type declarations from a table\\
\end{tabular}
}
{
\newline
\axiomFun{empty}\tab{25}creates a new \axiomType{SymbolTable}\newline
\axiomFunX{declare}\tab{25}creates a new entry in a table \newline
\axiomFun{fortranTypeOf}
\tab{25}returns the type of an object in a table \newline
\axiomFun{parametersOf}
\tab{25}returns a list of all the symbols in the table \newline
\axiomFun{typeList}
\tab{25}returns a list of all objects of a given type \newline
\axiomFun{typeLists}
\tab{25}returns a list of lists of all objects sorted by type \newline
\axiomFun{externalList}
\tab{25}returns a list of all {\tt EXTERNAL} objects \newline
\axiomFun{printTypes}
\tab{25}produces Fortran type declarations from a table\newline
}
\xtc{
}{
\spadpaste{symbols := empty()$SymbolTable\bound{symbols}}
}
\xtc{
}{
\spadpaste{declare!(X,fortranReal(),symbols)\free{symbols}}
}
\xtc{
}{
\spadpaste{declare!(M,construct(real,[i,j],false)$FortranType,symbols)
\free{symbols}}
}
\xtc{
}{
\spadpaste{declare!([i,j],fortranInteger(),symbols)\free{symbols}}
}
\xtc{
}{
\spadpaste{symbols\free{symbols}}
}
\xtc{
}{
\spadpaste{fortranTypeOf(i,symbols)\free{symbols}}
}
\xtc{
}{
\spadpaste{typeList(real,symbols)\free{symbols}}
}
\xtc{
}{
\spadpaste{printTypes symbols\free{symbols}}
}

\subsubsection{TheSymbolTable}
\texht{\exptypeindex{TheSymbolTable}}{}

This domain creates and manipulates one global symbol table to be
used, for example, during template processing. It is also used when
linking to external Fortran routines. The information stored for each
subprogram (and the main program segment, where relevant) is:
\indent{4}
\beginitems
\item[-] its name;
\item[-] its return type;
\item[-] its argument list;
\item[-] and its argument types.
\enditems
\indent{0}
Initially, any information provided is deemed to be for the main program
segment.
\xtc{
Issuing the following command indicates that from now on all information
refers to the subprogram \axiom{F}.
}{
\spadpaste{newSubProgram F}
}
\xtc{
It is possible to return to processing the main program segment by issuing
the command:
}{
\spadpaste{endSubProgram()}
}
The following commands exist:
\texht{
\begin{tabular}{p{1.6in}p{2.8in}}
\axiomFunX{returnType} 
& declares the return type of the current subprogram \\
 & \\
\axiomFun{returnTypeOf} 
& returns the return type of a subprogram \\
 & \\
\axiomFunX{argumentList} 
&  declares the argument list of the current subprogram \\
 & \\
\axiomFun{argumentListOf} 
&  returns the argument list of a subprogram \\
 & \\
\axiomFunX{declare} 
& provides type declarations for parameters of the current subprogram \\
 & \\
\axiomFun{symbolTableOf} 
& returns the symbol table  of a subprogram \\
 & \\
\axiomFun{printHeader} 
& produces the Fortran header for the current subprogram \\
\end{tabular}
}
{
\newline
\axiomFunX{returnType}
\tab{25}declares the return type of the current subprogram \newline
\axiomFun{returnTypeOf}
\tab{25}returns the return type of a subprogram \newline
\axiomFunX{argumentList}
\tab{25}declares the argument list of the current subprogram \newline
\axiomFun{argumentListOf}
\tab{25}returns the argument list of a subprogram \newline
\axiomFunX{declare}
\tab{25}provides type declarations for parameters of the 
current subprogram \newline
\axiomFun{symbolTableOf}\tab{25}returns the symbol table  
of a subprogram \newline
\axiomFun{printHeader}\tab{25}produce the Fortran header 
for the current subprogram \newline
}
In addition there are versions of these commands which are
parameterised by the name of a subprogram, and others parameterised by
both the name of a subprogram and by an instance of
\axiomType{TheSymbolTable}.
\xtc{
}{
\spadpaste{newSubProgram F \bound{forPleasure}}
}
\xtc{
}{
\spadpaste{argumentList!(F,[X])\free{forPleasure}}
}
\xtc{
}{
\spadpaste{returnType!(F,real)\free{forPleasure}}
}
\xtc{
}{
\spadpaste{declare!(X,fortranReal(),F)\free{forPleasure}}
}
\xtc{
}{
\spadpaste{printHeader F\free{forPleasure}}
}

\subsubsection{Advanced Fortran Code Generation}

This section describes facilities for representing Fortran statements, and
building up complete subprograms from them.

\subsubsection{Switch}
\texht{\exptypeindex{Switch}}{}

This domain is used to represent statements like {\tt x < y}.  Although
these can be represented directly in Axiom, it is a little cumbersome,
since Axiom evaluates the last statement, for example, to \axiom{true}
(since \axiom{x} is  lexicographically less than \axiom{y}).

Instead we have a set of operations, 
such as \axiomFun{LT} to represent \axiom{<},
to let us build such statements.  The available constructors are:
\texht{
\centerline{{\begin{tabular}{ll}}}
\centerline{{\axiomFun{LT} & $<$ }}
\centerline{{\axiomFun{GT} & $>$ }}
\centerline{{\axiomFun{LE} & $\leq$ }}
\centerline{{\axiomFun{GE} & $\geq$ }}
\centerline{{\axiomFun{EQ} & $=$ }}
\centerline{{\axiomFun{AND} & $and$}}
\centerline{{\axiomFun{OR} & $or$ }}
\centerline{{\axiomFun{NOT} & $not$ }}
\centerline{{\end{tabular}}}
}
{
\newline
\axiomFun{LT}\tab{25}\texht{$<$}{<} \newline
\axiomFun{GT}\tab{25}\texht{$>$}{>} \newline
\axiomFun{LE}\tab{25}\texht{$\leq$}{<=} \newline
\axiomFun{GE}\tab{25}\texht{$\geq$}{>=} \newline
\axiomFun{EQ}\tab{25}\texht{$=$}{=} \newline
\axiomFun{AND}\tab{25}\texht{$and$}{{\tt and}}\newline
\axiomFun{OR}\tab{25}\texht{$or$}{{\tt or}} \newline
\axiomFun{NOT}\tab{25}\texht{$not$}{{\tt not}} \newline
}
\xtc{
So for example:
}{
\spadpaste{LT(x,y)}
}

\subsubsection{FortranCode}

This domain represents code segments or operations: currently assignments,
conditionals, blocks, comments, gotos, continues, various kinds of loops,
and return statements.
\xtc{
For example we can create quite a complicated conditional statement using
assignments, and then turn it into Fortran code:
}{
\spadpaste{
c := cond(LT(X,Y),assign(F,X),cond(GT(Y,Z),assign(F,Y),assign(F,Z)))
\bound{c}}
}
\xtc{
}{
\spadpaste{printCode c\free{c}}
}

The Fortran code is printed
on the current Fortran output stream.

\subsubsection{FortranProgram}
\texht{\exptypeindex{FortranProgram}}{}

This domain is used to construct complete Fortran subprograms out of
elements of \axiomType{FortranCode}.  It is parameterised by the name
of the target subprogram (a \axiomType{Symbol}), its return type (from
\axiomType{Union}(\axiomType{FortranScalarType},``void'')), its
arguments (from \axiomType{List Symbol}), and its symbol table (from
\axiomType{SymbolTable}).  One can \axiomFun{coerce} elements of
either \axiomType{FortranCode} or \axiomType{Expression} into it.

\xtc{
First of all we create a symbol table:
}{
\spadpaste{symbols := empty()$SymbolTable\bound{symbols}}
}
\xtc{
Now put some type declarations into it:
}{
\spadpaste{declare!([X,Y],fortranReal(),symbols)\free{symbols}}
}
\xtc{
Then (for convenience)
we set up the particular instantiation of \axiomType{FortranProgram}
}{
\spadpaste{FP := FortranProgram(F,real,[X,Y],symbols)\free{symbols}
\bound{FP}}
}
\xtc{
Create an object of type \axiomType{Expression(Integer)}:
}{
\spadpaste{asp := X*sin(Y)\bound{asp}}
}
\xtc{
Now \axiomFun{coerce} it into \axiomType{FP}, and print its Fortran form:
}{
\spadpaste{outputAsFortran(asp::FP)\free{FP asp}}
}

We can generate a \axiomType{FortranProgram} using \axiom{FortranCode}.  
For example:
\xtc{
Augment our symbol table:
}{
\spadpaste{declare!(Z,fortranReal(),symbols)\free{symbols}\bound{Z}}
}
\xtc{
and transform the conditional expression we prepared earlier:
}{
\spadpaste{outputAsFortran([c,returns()]::FP) \free{FP c Z}}
}

\endscroll
\autobuttons
\end{page}

\begin{patch}{generalFortranPagePatch1}
\begin{paste}{generalFortranPageFull1}{generalFortranPageEmpty1}
\pastebutton{generalFortranPageFull1}{\hidepaste}
\tab{5}\spadcommand{)set fortran precision}
\indentrel{3}\begin{verbatim}
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty1}
\begin{paste}{generalFortranPageEmpty1}{generalFortranPagePatch1}
\pastebutton{generalFortranPageEmpty1}{\showpaste}
\tab{5}\spadcommand{)set fortran precision}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch2}
\begin{paste}{generalFortranPageFull2}{generalFortranPageEmpty2}
\pastebutton{generalFortranPageFull2}{\hidepaste}
\tab{5}\spadcommand{m := matrix [[1,2,3],[4,5,6]]\bound{m }}
\indentrel{3}\begin{verbatim}
        Ú1  2  3¿
   (1)  ³       ³
        À4  5  6Ù
                                   Type: Matrix Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty2}
\begin{paste}{generalFortranPageEmpty2}{generalFortranPagePatch2}
\pastebutton{generalFortranPageEmpty2}{\showpaste}
\tab{5}\spadcommand{m := matrix [[1,2,3],[4,5,6]]\bound{m }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch3}
\begin{paste}{generalFortranPageFull3}{generalFortranPageEmpty3}
\pastebutton{generalFortranPageFull3}{\hidepaste}
\tab{5}\spadcommand{fortranLiteralLine concat ["C      The Matrix has ", nrows(m)::String, " rows and ", ncols(m)::String, " columns"]\free{m }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty3}
\begin{paste}{generalFortranPageEmpty3}{generalFortranPagePatch3}
\pastebutton{generalFortranPageEmpty3}{\showpaste}
\tab{5}\spadcommand{fortranLiteralLine concat ["C      The Matrix has ", nrows(m)::String, " rows and ", ncols(m)::String, " columns"]\free{m }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch4}
\begin{paste}{generalFortranPageFull4}{generalFortranPageEmpty4}
\pastebutton{generalFortranPageFull4}{\hidepaste}
\tab{5}\spadcommand{fortranLiteral "C      The Matrix has "}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty4}
\begin{paste}{generalFortranPageEmpty4}{generalFortranPagePatch4}
\pastebutton{generalFortranPageEmpty4}{\showpaste}
\tab{5}\spadcommand{fortranLiteral "C      The Matrix has "}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch5}
\begin{paste}{generalFortranPageFull5}{generalFortranPageEmpty5}
\pastebutton{generalFortranPageFull5}{\hidepaste}
\tab{5}\spadcommand{fortranLiteral(nrows(m)::String)}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty5}
\begin{paste}{generalFortranPageEmpty5}{generalFortranPagePatch5}
\pastebutton{generalFortranPageEmpty5}{\showpaste}
\tab{5}\spadcommand{fortranLiteral(nrows(m)::String)}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch6}
\begin{paste}{generalFortranPageFull6}{generalFortranPageEmpty6}
\pastebutton{generalFortranPageFull6}{\hidepaste}
\tab{5}\spadcommand{fortranLiteral " rows and "}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty6}
\begin{paste}{generalFortranPageEmpty6}{generalFortranPagePatch6}
\pastebutton{generalFortranPageEmpty6}{\showpaste}
\tab{5}\spadcommand{fortranLiteral " rows and "}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch7}
\begin{paste}{generalFortranPageFull7}{generalFortranPageEmpty7}
\pastebutton{generalFortranPageFull7}{\hidepaste}
\tab{5}\spadcommand{fortranLiteral(ncols(m)::String)\free{m }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty7}
\begin{paste}{generalFortranPageEmpty7}{generalFortranPagePatch7}
\pastebutton{generalFortranPageEmpty7}{\showpaste}
\tab{5}\spadcommand{fortranLiteral(ncols(m)::String)\free{m }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch8}
\begin{paste}{generalFortranPageFull8}{generalFortranPageEmpty8}
\pastebutton{generalFortranPageFull8}{\hidepaste}
\tab{5}\spadcommand{fortranLiteral " columns"}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty8}
\begin{paste}{generalFortranPageEmpty8}{generalFortranPagePatch8}
\pastebutton{generalFortranPageEmpty8}{\showpaste}
\tab{5}\spadcommand{fortranLiteral " columns"}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch9}
\begin{paste}{generalFortranPageFull9}{generalFortranPageEmpty9}
\pastebutton{generalFortranPageFull9}{\hidepaste}
\tab{5}\spadcommand{fortranCarriageReturn()}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty9}
\begin{paste}{generalFortranPageEmpty9}{generalFortranPagePatch9}
\pastebutton{generalFortranPageEmpty9}{\showpaste}
\tab{5}\spadcommand{fortranCarriageReturn()}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch10}
\begin{paste}{generalFortranPageFull10}{generalFortranPageEmpty10}
\pastebutton{generalFortranPageFull10}{\hidepaste}
\tab{5}\spadcommand{topFortranOutputStack()}
\indentrel{3}\begin{verbatim}
   (9)  "CONSOLE"
                                           Type: String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty10}
\begin{paste}{generalFortranPageEmpty10}{generalFortranPagePatch10}
\pastebutton{generalFortranPageEmpty10}{\showpaste}
\tab{5}\spadcommand{topFortranOutputStack()}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch11}
\begin{paste}{generalFortranPageFull11}{generalFortranPageEmpty11}
\pastebutton{generalFortranPageFull11}{\hidepaste}
\tab{5}\spadcommand{type:=construct(real,[i,10],false)$FortranType}
\indentrel{3}\begin{verbatim}
   (10)  REAL
             (i,10)
                                      Type: FortranType
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty11}
\begin{paste}{generalFortranPageEmpty11}{generalFortranPagePatch11}
\pastebutton{generalFortranPageEmpty11}{\showpaste}
\tab{5}\spadcommand{type:=construct(real,[i,10],false)$FortranType}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch12}
\begin{paste}{generalFortranPageFull12}{generalFortranPageEmpty12}
\pastebutton{generalFortranPageFull12}{\hidepaste}
\tab{5}\spadcommand{type:=[real,[i,10],false]$FortranType\bound{type }}
\indentrel{3}\begin{verbatim}
   (11)  REAL
             (i,10)
                                      Type: FortranType
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty12}
\begin{paste}{generalFortranPageEmpty12}{generalFortranPagePatch12}
\pastebutton{generalFortranPageEmpty12}{\showpaste}
\tab{5}\spadcommand{type:=[real,[i,10],false]$FortranType\bound{type }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch13}
\begin{paste}{generalFortranPageFull13}{generalFortranPageEmpty13}
\pastebutton{generalFortranPageFull13}{\hidepaste}
\tab{5}\spadcommand{scalarTypeOf type\free{type }}
\indentrel{3}\begin{verbatim}
   (12)  REAL
                Type: Union(fst: FortranScalarType,...)
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty13}
\begin{paste}{generalFortranPageEmpty13}{generalFortranPagePatch13}
\pastebutton{generalFortranPageEmpty13}{\showpaste}
\tab{5}\spadcommand{scalarTypeOf type\free{type }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch14}
\begin{paste}{generalFortranPageFull14}{generalFortranPageEmpty14}
\pastebutton{generalFortranPageFull14}{\hidepaste}
\tab{5}\spadcommand{dimensionsOf type\free{type }}
\indentrel{3}\begin{verbatim}
   (13)  [i,10]
                          Type: List Polynomial Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty14}
\begin{paste}{generalFortranPageEmpty14}{generalFortranPagePatch14}
\pastebutton{generalFortranPageEmpty14}{\showpaste}
\tab{5}\spadcommand{dimensionsOf type\free{type }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch15}
\begin{paste}{generalFortranPageFull15}{generalFortranPageEmpty15}
\pastebutton{generalFortranPageFull15}{\hidepaste}
\tab{5}\spadcommand{external? type\free{type }}
\indentrel{3}\begin{verbatim}
   (14)  false
                                          Type: Boolean
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty15}
\begin{paste}{generalFortranPageEmpty15}{generalFortranPagePatch15}
\pastebutton{generalFortranPageEmpty15}{\showpaste}
\tab{5}\spadcommand{external? type\free{type }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch16}
\begin{paste}{generalFortranPageFull16}{generalFortranPageEmpty16}
\pastebutton{generalFortranPageFull16}{\hidepaste}
\tab{5}\spadcommand{fortranLogical()}
\indentrel{3}\begin{verbatim}
   (15)  LOGICAL
                                      Type: FortranType
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty16}
\begin{paste}{generalFortranPageEmpty16}{generalFortranPagePatch16}
\pastebutton{generalFortranPageEmpty16}{\showpaste}
\tab{5}\spadcommand{fortranLogical()}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch17}
\begin{paste}{generalFortranPageFull17}{generalFortranPageEmpty17}
\pastebutton{generalFortranPageFull17}{\hidepaste}
\tab{5}\spadcommand{construct(integer,[],true)$FortranType}
\indentrel{3}\begin{verbatim}
   (16)  EXTERNAL INTEGER
                                      Type: FortranType
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty17}
\begin{paste}{generalFortranPageEmpty17}{generalFortranPagePatch17}
\pastebutton{generalFortranPageEmpty17}{\showpaste}
\tab{5}\spadcommand{construct(integer,[],true)$FortranType}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch18}
\begin{paste}{generalFortranPageFull18}{generalFortranPageEmpty18}
\pastebutton{generalFortranPageFull18}{\hidepaste}
\tab{5}\spadcommand{symbols := empty()$SymbolTable\bound{symbols }}
\indentrel{3}\begin{verbatim}
   (17)  table()
                                      Type: SymbolTable
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty18}
\begin{paste}{generalFortranPageEmpty18}{generalFortranPagePatch18}
\pastebutton{generalFortranPageEmpty18}{\showpaste}
\tab{5}\spadcommand{symbols := empty()$SymbolTable\bound{symbols }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch19}
\begin{paste}{generalFortranPageFull19}{generalFortranPageEmpty19}
\pastebutton{generalFortranPageFull19}{\hidepaste}
\tab{5}\spadcommand{declare!(X,fortranReal(),symbols)\free{symbols }}
\indentrel{3}\begin{verbatim}
   (18)  REAL
                                      Type: FortranType
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty19}
\begin{paste}{generalFortranPageEmpty19}{generalFortranPagePatch19}
\pastebutton{generalFortranPageEmpty19}{\showpaste}
\tab{5}\spadcommand{declare!(X,fortranReal(),symbols)\free{symbols }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch20}
\begin{paste}{generalFortranPageFull20}{generalFortranPageEmpty20}
\pastebutton{generalFortranPageFull20}{\hidepaste}
\tab{5}\spadcommand{declare!(M,construct(real,[i,j],false)$FortranType,symbols)\free{symbols }}
\indentrel{3}\begin{verbatim}
   (19)  REAL
             (i,j)
                                      Type: FortranType
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty20}
\begin{paste}{generalFortranPageEmpty20}{generalFortranPagePatch20}
\pastebutton{generalFortranPageEmpty20}{\showpaste}
\tab{5}\spadcommand{declare!(M,construct(real,[i,j],false)$FortranType,symbols)\free{symbols }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch21}
\begin{paste}{generalFortranPageFull21}{generalFortranPageEmpty21}
\pastebutton{generalFortranPageFull21}{\hidepaste}
\tab{5}\spadcommand{declare!([i,j],fortranInteger(),symbols)\free{symbols }}
\indentrel{3}\begin{verbatim}
   (20)  INTEGER
                                      Type: FortranType
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty21}
\begin{paste}{generalFortranPageEmpty21}{generalFortranPagePatch21}
\pastebutton{generalFortranPageEmpty21}{\showpaste}
\tab{5}\spadcommand{declare!([i,j],fortranInteger(),symbols)\free{symbols }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch22}
\begin{paste}{generalFortranPageFull22}{generalFortranPageEmpty22}
\pastebutton{generalFortranPageFull22}{\hidepaste}
\tab{5}\spadcommand{symbols\free{symbols }}
\indentrel{3}\begin{verbatim}
   (21)
   table(X= REAL,M= REAL     ,i= INTEGER,j= INTEGER)
                        (i,j)
                                      Type: SymbolTable
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty22}
\begin{paste}{generalFortranPageEmpty22}{generalFortranPagePatch22}
\pastebutton{generalFortranPageEmpty22}{\showpaste}
\tab{5}\spadcommand{symbols\free{symbols }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch23}
\begin{paste}{generalFortranPageFull23}{generalFortranPageEmpty23}
\pastebutton{generalFortranPageFull23}{\hidepaste}
\tab{5}\spadcommand{fortranTypeOf(i,symbols)\free{symbols }}
\indentrel{3}\begin{verbatim}
   (22)  INTEGER
                                      Type: FortranType
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty23}
\begin{paste}{generalFortranPageEmpty23}{generalFortranPagePatch23}
\pastebutton{generalFortranPageEmpty23}{\showpaste}
\tab{5}\spadcommand{fortranTypeOf(i,symbols)\free{symbols }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch24}
\begin{paste}{generalFortranPageFull24}{generalFortranPageEmpty24}
\pastebutton{generalFortranPageFull24}{\hidepaste}
\tab{5}\spadcommand{typeList(real,symbols)\free{symbols }}
\indentrel{3}\begin{verbatim}
   (23)  [X,[M,i,j]]
Type: List Union(name: Symbol,bounds: List Union(S: Symbol,P: Polynomial Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty24}
\begin{paste}{generalFortranPageEmpty24}{generalFortranPagePatch24}
\pastebutton{generalFortranPageEmpty24}{\showpaste}
\tab{5}\spadcommand{typeList(real,symbols)\free{symbols }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch25}
\begin{paste}{generalFortranPageFull25}{generalFortranPageEmpty25}
\pastebutton{generalFortranPageFull25}{\hidepaste}
\tab{5}\spadcommand{printTypes symbols\free{symbols }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty25}
\begin{paste}{generalFortranPageEmpty25}{generalFortranPagePatch25}
\pastebutton{generalFortranPageEmpty25}{\showpaste}
\tab{5}\spadcommand{printTypes symbols\free{symbols }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch26}
\begin{paste}{generalFortranPageFull26}{generalFortranPageEmpty26}
\pastebutton{generalFortranPageFull26}{\hidepaste}
\tab{5}\spadcommand{newSubProgram F}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty26}
\begin{paste}{generalFortranPageEmpty26}{generalFortranPagePatch26}
\pastebutton{generalFortranPageEmpty26}{\showpaste}
\tab{5}\spadcommand{newSubProgram F}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch27}
\begin{paste}{generalFortranPageFull27}{generalFortranPageEmpty27}
\pastebutton{generalFortranPageFull27}{\hidepaste}
\tab{5}\spadcommand{endSubProgram()}
\indentrel{3}\begin{verbatim}
   (26)  MAIN
                                           Type: Symbol
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty27}
\begin{paste}{generalFortranPageEmpty27}{generalFortranPagePatch27}
\pastebutton{generalFortranPageEmpty27}{\showpaste}
\tab{5}\spadcommand{endSubProgram()}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch28}
\begin{paste}{generalFortranPageFull28}{generalFortranPageEmpty28}
\pastebutton{generalFortranPageFull28}{\hidepaste}
\tab{5}\spadcommand{newSubProgram F\bound{forPleasure }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty28}
\begin{paste}{generalFortranPageEmpty28}{generalFortranPagePatch28}
\pastebutton{generalFortranPageEmpty28}{\showpaste}
\tab{5}\spadcommand{newSubProgram F\bound{forPleasure }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch29}
\begin{paste}{generalFortranPageFull29}{generalFortranPageEmpty29}
\pastebutton{generalFortranPageFull29}{\hidepaste}
\tab{5}\spadcommand{argumentList!(F,[X])\free{forPleasure }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty29}
\begin{paste}{generalFortranPageEmpty29}{generalFortranPagePatch29}
\pastebutton{generalFortranPageEmpty29}{\showpaste}
\tab{5}\spadcommand{argumentList!(F,[X])\free{forPleasure }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch30}
\begin{paste}{generalFortranPageFull30}{generalFortranPageEmpty30}
\pastebutton{generalFortranPageFull30}{\hidepaste}
\tab{5}\spadcommand{returnType!(F,real)\free{forPleasure }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty30}
\begin{paste}{generalFortranPageEmpty30}{generalFortranPagePatch30}
\pastebutton{generalFortranPageEmpty30}{\showpaste}
\tab{5}\spadcommand{returnType!(F,real)\free{forPleasure }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch31}
\begin{paste}{generalFortranPageFull31}{generalFortranPageEmpty31}
\pastebutton{generalFortranPageFull31}{\hidepaste}
\tab{5}\spadcommand{declare!(X,fortranReal(),F)\free{forPleasure }}
\indentrel{3}\begin{verbatim}
   (30)  REAL
                                      Type: FortranType
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty31}
\begin{paste}{generalFortranPageEmpty31}{generalFortranPagePatch31}
\pastebutton{generalFortranPageEmpty31}{\showpaste}
\tab{5}\spadcommand{declare!(X,fortranReal(),F)\free{forPleasure }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch32}
\begin{paste}{generalFortranPageFull32}{generalFortranPageEmpty32}
\pastebutton{generalFortranPageFull32}{\hidepaste}
\tab{5}\spadcommand{printHeader F\free{forPleasure }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty32}
\begin{paste}{generalFortranPageEmpty32}{generalFortranPagePatch32}
\pastebutton{generalFortranPageEmpty32}{\showpaste}
\tab{5}\spadcommand{printHeader F\free{forPleasure }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch33}
\begin{paste}{generalFortranPageFull33}{generalFortranPageEmpty33}
\pastebutton{generalFortranPageFull33}{\hidepaste}
\tab{5}\spadcommand{LT(x,y)}
\indentrel{3}\begin{verbatim}
   (32)  x < y
                                           Type: Switch
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty33}
\begin{paste}{generalFortranPageEmpty33}{generalFortranPagePatch33}
\pastebutton{generalFortranPageEmpty33}{\showpaste}
\tab{5}\spadcommand{LT(x,y)}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch34}
\begin{paste}{generalFortranPageFull34}{generalFortranPageEmpty34}
\pastebutton{generalFortranPageFull34}{\hidepaste}
\tab{5}\spadcommand{c := cond(LT(X,Y),assign(F,X),cond(GT(Y,Z),assign(F,Y),assign(F,Z)))\bound{c }}
\indentrel{3}\begin{verbatim}
   (33)  conditional
                                      Type: FortranCode
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty34}
\begin{paste}{generalFortranPageEmpty34}{generalFortranPagePatch34}
\pastebutton{generalFortranPageEmpty34}{\showpaste}
\tab{5}\spadcommand{c := cond(LT(X,Y),assign(F,X),cond(GT(Y,Z),assign(F,Y),assign(F,Z)))\bound{c }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch35}
\begin{paste}{generalFortranPageFull35}{generalFortranPageEmpty35}
\pastebutton{generalFortranPageFull35}{\hidepaste}
\tab{5}\spadcommand{printCode c\free{c }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty35}
\begin{paste}{generalFortranPageEmpty35}{generalFortranPagePatch35}
\pastebutton{generalFortranPageEmpty35}{\showpaste}
\tab{5}\spadcommand{printCode c\free{c }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch36}
\begin{paste}{generalFortranPageFull36}{generalFortranPageEmpty36}
\pastebutton{generalFortranPageFull36}{\hidepaste}
\tab{5}\spadcommand{symbols := empty()$SymbolTable\bound{symbols }}
\indentrel{3}\begin{verbatim}
   (35)  table()
                                      Type: SymbolTable
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty36}
\begin{paste}{generalFortranPageEmpty36}{generalFortranPagePatch36}
\pastebutton{generalFortranPageEmpty36}{\showpaste}
\tab{5}\spadcommand{symbols := empty()$SymbolTable\bound{symbols }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch37}
\begin{paste}{generalFortranPageFull37}{generalFortranPageEmpty37}
\pastebutton{generalFortranPageFull37}{\hidepaste}
\tab{5}\spadcommand{declare!([X,Y],fortranReal(),symbols)\free{symbols }}
\indentrel{3}\begin{verbatim}
   (36)  REAL
                                      Type: FortranType
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty37}
\begin{paste}{generalFortranPageEmpty37}{generalFortranPagePatch37}
\pastebutton{generalFortranPageEmpty37}{\showpaste}
\tab{5}\spadcommand{declare!([X,Y],fortranReal(),symbols)\free{symbols }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch38}
\begin{paste}{generalFortranPageFull38}{generalFortranPageEmpty38}
\pastebutton{generalFortranPageFull38}{\hidepaste}
\tab{5}\spadcommand{FP := FortranProgram(F,real,[X,Y],symbols)\free{symbols }\bound{FP }}
\indentrel{3}\begin{verbatim}
   (37)  FortranProgram(F,REAL,[X,Y],table(...,...))
                                           Type: Domain
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty38}
\begin{paste}{generalFortranPageEmpty38}{generalFortranPagePatch38}
\pastebutton{generalFortranPageEmpty38}{\showpaste}
\tab{5}\spadcommand{FP := FortranProgram(F,real,[X,Y],symbols)\free{symbols }\bound{FP }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch39}
\begin{paste}{generalFortranPageFull39}{generalFortranPageEmpty39}
\pastebutton{generalFortranPageFull39}{\hidepaste}
\tab{5}\spadcommand{asp := X*sin(Y)\bound{asp }}
\indentrel{3}\begin{verbatim}
   (38)  X sin(Y)
                               Type: Expression Integer
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty39}
\begin{paste}{generalFortranPageEmpty39}{generalFortranPagePatch39}
\pastebutton{generalFortranPageEmpty39}{\showpaste}
\tab{5}\spadcommand{asp := X*sin(Y)\bound{asp }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch40}
\begin{paste}{generalFortranPageFull40}{generalFortranPageEmpty40}
\pastebutton{generalFortranPageFull40}{\hidepaste}
\tab{5}\spadcommand{outputAsFortran(asp::FP)\free{FP asp }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty40}
\begin{paste}{generalFortranPageEmpty40}{generalFortranPagePatch40}
\pastebutton{generalFortranPageEmpty40}{\showpaste}
\tab{5}\spadcommand{outputAsFortran(asp::FP)\free{FP asp }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch41}
\begin{paste}{generalFortranPageFull41}{generalFortranPageEmpty41}
\pastebutton{generalFortranPageFull41}{\hidepaste}
\tab{5}\spadcommand{declare!(Z,fortranReal(),symbols)\free{symbols }\bound{Z }}
\indentrel{3}\begin{verbatim}
   (40)  REAL
                                      Type: FortranType
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty41}
\begin{paste}{generalFortranPageEmpty41}{generalFortranPagePatch41}
\pastebutton{generalFortranPageEmpty41}{\showpaste}
\tab{5}\spadcommand{declare!(Z,fortranReal(),symbols)\free{symbols }\bound{Z }}
\end{paste}\end{patch}

\begin{patch}{generalFortranPagePatch42}
\begin{paste}{generalFortranPageFull42}{generalFortranPageEmpty42}
\pastebutton{generalFortranPageFull42}{\hidepaste}
\tab{5}\spadcommand{outputAsFortran([c,returns()]::FP)\free{FP c Z }}
\indentrel{3}\begin{verbatim}
                                             Type: Void
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{generalFortranPageEmpty42}
\begin{paste}{generalFortranPageEmpty42}{generalFortranPagePatch42}
\pastebutton{generalFortranPageEmpty42}{\showpaste}
\tab{5}\spadcommand{outputAsFortran([c,returns()]::FP)\free{FP c Z }}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{nagTechnicalPage}{ug15.ht}{Some technical information}
\begin{chunk}{ug15.ht}
\begin{page}{nagTechnicalPage}{15.3.5. Some technical information}
\beginscroll

The model adopted for the link is a server-client configuration --
Axiom acting as a client via a local agent (a process called {\tt
nagman}). The server side is implemented by the {\tt nagd} daemon
process which may run on a different host.  The {\tt nagman} local
agent is started by default whenever you start Axiom. The {\tt nagd}
server must be started separately.  Instructions for installing and
running the server are supplied in the NAG documentation.  Use the
\spadcmd{)set naglink host} system command to point your local agent
to a server in your network.

On the Axiom side, one sees a set of {\em packages}
(ask \Browse{} for {\em Nag*}) for each chapter, each exporting
operations with the same name as a routine in the \naglib{}.
The arguments and return value of each operation belong to
standard Axiom types.

The {\tt man} pages for the \naglib{} are accessible via the description
of each operation in \Browse{} (among other places).

In the implementation of each operation, the set of inputs is passed
to the local agent {\tt nagman}, which makes a Remote Procedure Call
(RPC) to the remote {\tt nagd} daemon process.  The local agent
receives the RPC results and forwards them to the Axiom workspace
where they are interpreted appropriately.

How are Fortran subroutines turned into RPC calls?  For each Fortran
routine in the \naglib{}, a C main() routine is supplied.  Its job is
to assemble the RPC input (numeric) data stream into the appropriate
Fortran data structures for the routine, call the Fortran routine from
C and serialize the results into an RPC output data stream.

Many \naglib{} routines accept ASPs (Argument Subprogram Parameters).
These specify user-supplied Fortran routines (e.g. a routine to
supply values of a function is required for numerical integration).
How are they handled? There are new facilities in Axiom to help.
A set of Axiom domains has been provided to turn values in standard
 Axiom types (such as Expression Integer) into the appropriate
piece of Fortran for each case (a filename pointing to Fortran source
for the ASP can always be supplied instead).
Ask \Browse{} for {\em Asp*} to see these domains. The Fortran fragments
are included in the outgoing RPC stream, but {\tt nagd} intercepts them,
compiles them, and links them with the main() C program before executing
the resulting program on the numeric part of the RPC stream.


\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugWhatsNewLanguagePage}{ug15.ht}
{Interactive Front-end and Language}
\pageto{notitle}{ugLangLoopsBreakPage}
\pageto{notitle}{ugLangBlocksPage}
\begin{chunk}{ug15.ht}
\begin{page}{ugWhatsNewLanguagePage}
{15.4. Interactive Front-end and Language}
\beginscroll

The \axiom{leave} keyword has been replaced by the \axiom{break}
keyword for compatibility with the new Axiom extension language.  See
section \downlink{``break in Loops''}{ugLangLoopsBreakPage} in
Section 5.4.3\ignore{ugLangLoopsBreak} for more
information.

Curly braces are no longer used to create sets. Instead, use
\axiomFun{set} followed by a bracketed expression. For example,
\xtc{
}{
\spadpaste{set [1,2,3,4]}
}

Curly braces are now used to enclose a block (see section
\downlink{``Blocks''}{ugLangBlocksPage} in Section
5.2\ignore{ugLangBlocks} for more information). For
compatibility, a block can still be enclosed by parentheses as well.

New coercions to and from type \axiomType{Expression} have been
added. For example, it is now possible to map a polynomial
represented as an expression to an appropriate polynomial type.

Various messages have been added or rewritten for clarity.

\endscroll
\autobuttons
\end{page}

\begin{patch}{ugWhatsNewLanguagePagePatch1}
\begin{paste}{ugWhatsNewLanguagePageFull1}{ugWhatsNewLanguagePageEmpty1}
\pastebutton{ugWhatsNewLanguagePageFull1}{\hidepaste}
\tab{5}\spadcommand{set [1,2,3,4]}
\indentrel{3}\begin{verbatim}
   (1)  {1,2,3,4}
                              Type: Set PositiveInteger
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{ugWhatsNewLanguagePageEmpty1}
\begin{paste}{ugWhatsNewLanguagePageEmpty1}{ugWhatsNewLanguagePagePatch1}
\pastebutton{ugWhatsNewLanguagePageEmpty1}{\showpaste}
\tab{5}\spadcommand{set [1,2,3,4]}
\end{paste}\end{patch}

\end{chunk}
\pagetitle{ugWhatsNewLibraryPage}{ug15.ht}{Library}
\pageto{notitle}{FullPartialFracExpansionXmpPage}
\begin{chunk}{ug15.ht}
\begin{page}{ugWhatsNewLibraryPage}{15.5. Library}
\beginscroll

The \axiomType{FullPartialFracExpansion}
domain has been added. This domain computes factor-free full
partial fraction expansions.
See section
\downlink{`FullPartialFracExpansion'}
{FullPartialFracExpansionXmpPage}
\ignore{FullPartialFracExpansion}
for examples.

We have implemented the Bertrand/Cantor algorithm for integrals of
hyperelliptic functions. This brings a major speedup for some
classes of algebraic integrals.

We have implemented a new (direct) algorithm for integrating
trigonometric functions. This brings a speedup and an improvement in
the answer quality.

The {\sf SmallFloat} domain has been renamed
\axiomType{DoubleFloat} and {\sf SmallInteger} has been renamed
\axiomType{SingleInteger}. The new abbreviations as
\axiomType{DFLOAT} and \axiomType{SINT}, respectively.
We have defined the macro {\sf SF}, the old abbreviation for {\sf
SmallFloat}, to expand to \axiomType{DoubleFloat} and modified
the documentation and input file examples to use the new names
and abbreviations. You should do the same in any private Axiom
files you have.

There are many new categories, domains and packages related to the
NAG Library Link facility. See the file

\unixcommand{\env{AXIOM}/../../src/algebra/exposed.lsp}
{xterm\ -e\ vi\ +"/naglink"\ \env{AXIOM}/../../src/algebra/exposed.lsp}

for a list of constructors in the {\bf naglink} Axiom exposure group.

We have made improvements to the differential equation solvers
and there is a new facility for solving systems of first-order 
linear differential equations.
In particular, an important fix was made to the solver for
inhomogeneous linear ordinary differential equations that
corrected the calculation of particular solutions.
We also made improvements to the polynomial
and transcendental equation solvers including the
ability to solve some classes of systems of transcendental
equations.

The efficiency of power series have been improved and left and right
expansions of \spad{tan(f(x))} at \spad{x =} a pole of \spad{f(x)}
can now be computed.
A number of power series bugs were fixed and the 
\axiomType{GeneralUnivariatePowerSeries}
domain was added.
The power series variable can appear in the coefficients and when this
happens, you cannot differentiate or integrate the series.
Differentiation and integration with respect to other variables is
supported.

A domain was added for representing asymptotic expansions of a
function at an exponential singularity.

For limits, the main new feature is the exponential expansion domain
used to treat certain exponential singularities.  Previously, such
singularities were treated in an {\it ad hoc} way and only a few cases
were covered.  Now Axiom can do things like

\begin{verbatim}
limit( (x+1)**(x+1)/x**x - x**x/(x-1)**(x-1), x = %plusInfinity)
\end{verbatim}

in a systematic way.  It only does one level of nesting, though.  In
other words, we can handle \spad{exp(} some function with a pole
\spad{)}, but not \texht{\linebreak}{} \spad{exp(exp(} some function
with a pole \spad{)).}

The computation of integral bases has been improved through careful
use of Hermite row reduction. A P-adic algorithm for function fields
of algebraic curves in finite characteristic has also been developed.

Miscellaneous: There is improved conversion of definite and indefinite
integrals to \axiomType{InputForm}; binomial coefficients are
displayed in a new way; some new simplifications of radicals have been
implemented; the operation \spadfun{complexForm} for converting to
rectangular coordinates has been added; symmetric product operations
have been added to \axiomType{LinearOrdinaryDifferentialOperator}.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugWhatsNewHyperDocPage}{ug15.ht}{\HyperName}
\pageto{notitle}{ugHyperKeysPage}
\begin{chunk}{ug15.ht}
\begin{page}{ugWhatsNewHyperDocPage}{15.6. \HyperName}
\beginscroll

The buttons on the titlebar and scrollbar have been replaced
with ones which have a 3D effect. You can change the foreground and
background colors of these ``controls'' by including and modifying
the following lines in your {\bf .Xdefaults} file.
\begin{verbatim}
Axiom.hyperdoc.ControlBackground: White
Axiom.hyperdoc.ControlForeground: Black
\end{verbatim}

For various reasons, Hyperdoc sometimes displays a
secondary window. You can control the size and placement of this
window by including and modifying
the following line in your {\bf .Xdefaults} file.
%
\begin{verbatim}
Axiom.hyperdoc.FormGeometry: =950x450+100+0
\end{verbatim}
%
This setting is a standard X Window System geometry specification:
you are requesting a window 950 pixels wide by 450 deep and placed in
the upper left corner.

Some key definitions have been changed to conform more closely with
the CUA guidelines. Press \texht{F9}{\downlink{F9}{ugHyperKeysPage}}
to see the current definitions.

Input boxes (for example, in the Browser) now accept paste-ins from
the X Window System. Use the second button to paste in something
you have previously copied or cut. An example of how you can use this
is that you can paste the type from an Axiom computation
into the main Browser input box.


\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugWhatsNewDocumentationPage}{ug15.ht}{Documentation}
\pageto{notitle}{ugGraphTwoDbuildPage}
\pageto{notitle}{ugGraphTwoDappendPage}
\pageto{notitle}{ugIntroCallFunPage}
\pageto{notitle}{ugUserRulesPage}
\begin{chunk}{ug15.ht}
\begin{page}{ugWhatsNewDocumentationPage}{15.7. Documentation}
\beginscroll
\texht{
We describe here a few additions to the on-line
version of the Axiom book which you can read with
HyperDoc.
}{}

A section has been added to the graphics chapter, describing how to
build \twodim{} graphs from lists of points. An example is given
showing how to read the points from a file.  See section
\downlink{``Building Two-Dimensional Graphs''}
{ugGraphTwoDbuildPage} in Section
7.1.9\ignore{ugGraphTwoDbuild} for details.

A further section has been added to that same chapter, describing how
to add a \twodim{} graph to a viewport which already contains other
graphs.  See section
\downlink{``Appending a Graph to a Viewport 
Window Containing a Graph''}{ugGraphTwoDappendPage} in
Section 7.1.10\ignore{ugGraphTwoDappend} for
details.

Chapter 3 
and the on-line Hyperdoc help have been unified.

An explanation of operation names ending in ``?'' and ``!'' has been
added to the first chapter.  See the end of the section
\downlink{``Calling Functions''}{ugIntroCallFunPage} in Section
1.3.6\ignore{ugIntroCallFun} for details.

An expanded explanation of using predicates has been added to the
sixth chapter. See the example involving \userfun{evenRule} in the
middle of the section
\downlink{``Rules and Pattern Matching''}{ugUserRulesPage} in Section
6.21\ignore{ugUserRules} for details.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\chapter{Users Guide Chapter 16 (ug16.ht)}
\begin{chunk}{ug16.ht}
\newcommand{\lanb}{{\tt [}}
\newcommand{\ranb}{{\tt ]}}
\newcommand{\vertline}{\texht{$|$}{{\tt |}}}

\end{chunk}
\pagetitle{ugSysCmdPage}{ug16.ht}{Axiom System Commands}
\pagepic{ps/v71ugsyscmdpage.eps}{ugsyscmdpage}{0.50}
\pagefrom{Reference}{TopReferencePage}
\pageto{Introduction}{ugSysCmdOverviewPage}
\pageto{)abbreviation}{ugSysCmdabbreviationPage}
\pageto{)boot}{ugSysCmdbootPage}
\pageto{)cd}{ugSysCmdcdPage} 
\pageto{)close}{ugSysCmdclosePage} 
\pageto{)clear}{ugSysCmdclearPage} 
\pageto{)compile}{ugSysCmdcompilePage} 
\pageto{)display}{ugSysCmddisplayPage} 
\pageto{)edit}{ugSysCmdeditPage} 
\pageto{)fin}{ugSysCmdfinPage} 
\pageto{)frame}{ugSysCmdframePage} 
\pageto{)help}{ugSysCmdhelpPage} 
\pageto{)history}{ugSysCmdhistoryPage} 
\pageto{)library}{ugSysCmdlibraryPage} 
\pageto{)lisp}{ugSysCmdlispPage} 
\pageto{)load}{ugSysCmdloadPage} 
\pageto{)ltrace}{ugSysCmdltracePage} 
\pageto{)pquit}{ugSysCmdpquitPage} 
\pageto{)quit}{ugSysCmdquitPage} 
\pageto{)read}{ugSysCmdreadPage} 
\pageto{)set}{ugSysCmdsetPage} 
\pageto{)show}{ugSysCmdshowPage} 
\pageto{)spool}{ugSysCmdspoolPage} 
\pageto{)synonym}{ugSysCmdsynonymPage} 
\pageto{)system}{ugSysCmdsystemPage} 
\pageto{)trace}{ugSysCmdtracePage} 
\pageto{)undo}{ugSysCmdundoPage} 
\pageto{)what}{ugSysCmdwhatPage} 
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdPage}{B. Axiom System Commands}
\beginscroll

\texht{\bgroup\baselineskip 10pt\ixpt{}\def\Isize{\SIsize}}{}

This chapter describes system commands, the command-line
facilities used to control the Axiom environment.
The first section is an introduction and discusses the common
syntax of the commands available.

\table{
  { \downlink{\menuitemstyle{A.1. Introduction}}{ugSysCmdOverviewPage} }
  { \downlink{\menuitemstyle{A.2. )abbreviation}}
{ugSysCmdabbreviationPage} }
  { \downlink{\menuitemstyle{A.3. )boot}}{ugSysCmdbootPage} }
  { \downlink{\menuitemstyle{A.4. )cd}}{ugSysCmdcdPage} }
  { \downlink{\menuitemstyle{A.5. )close}}{ugSysCmdclosePage} }
  { \downlink{\menuitemstyle{A.6. )clear}}{ugSysCmdclearPage} }
  { \downlink{\menuitemstyle{A.7. )compile}}{ugSysCmdcompilePage} }
  { \downlink{\menuitemstyle{A.8. )display}}{ugSysCmddisplayPage} }
  { \downlink{\menuitemstyle{A.9. )edit}}{ugSysCmdeditPage} }
  { \downlink{\menuitemstyle{A.10. )fin}}{ugSysCmdfinPage} }
  { \downlink{\menuitemstyle{A.11. )frame}}{ugSysCmdframePage} }
  { \downlink{\menuitemstyle{A.12. )help}}{ugSysCmdhelpPage} }
  { \downlink{\menuitemstyle{A.13. )history}}{ugSysCmdhistoryPage} }
  { \downlink{\menuitemstyle{A.14. )library}}{ugSysCmdlibraryPage} }
  { \downlink{\menuitemstyle{A.15. )lisp}}{ugSysCmdlispPage} }
  { \downlink{\menuitemstyle{A.16. )load}}{ugSysCmdloadPage} }
  { \downlink{\menuitemstyle{A.17. )ltrace}}{ugSysCmdltracePage} }
  { \downlink{\menuitemstyle{A.18. )pquit}}{ugSysCmdpquitPage} }
  { \downlink{\menuitemstyle{A.19. )quit}}{ugSysCmdquitPage} }
  { \downlink{\menuitemstyle{A.20. )read}}{ugSysCmdreadPage} }
  { \downlink{\menuitemstyle{A.21. )set}}{ugSysCmdsetPage} }
  { \downlink{\menuitemstyle{A.22. )show}}{ugSysCmdshowPage} }
  { \downlink{\menuitemstyle{A.23. )spool}}{ugSysCmdspoolPage} }
  { \downlink{\menuitemstyle{A.24. )synonym}}{ugSysCmdsynonymPage} }
  { \downlink{\menuitemstyle{A.25. )system}}{ugSysCmdsystemPage} }
  { \downlink{\menuitemstyle{A.26. )trace}}{ugSysCmdtracePage} }
  { \downlink{\menuitemstyle{A.27. )undo}}{ugSysCmdundoPage} }
  { \downlink{\menuitemstyle{A.28. )what}}{ugSysCmdwhatPage} }
}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdOverviewPage}{ug16.ht}{Introduction}
\pageto{notitle}{ugSysCmdsetPage}
\pageto{notitle}{ugSysCmdcompilePage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdOverviewPage}{B.1. Introduction}
\beginscroll

System commands are used to perform Axiom environment management.
Among the commands are those that display what has been defined or
computed, set up multiple logical Axiom environments (frames), clear
definitions, read files of expressions and commands, show what
functions are available, and terminate Axiom.

Some commands are restricted: the commands
\begin{verbatim}
)set userlevel interpreter
)set userlevel compiler
)set userlevel development
\end{verbatim}
set the user-access level to the three possible choices.  All commands
are available at {\tt development} level and the fewest are available
at {\tt interpreter} level.  The default user-level is {\tt
interpreter}.  In addition to the \spadcmd{)set} command (discussed in
\downlink{``)set''}{ugSysCmdsetPage} in Section
B.21\ignore{ugSysCmdset}) you can use the Hyperdoc
settings facility to change the {\it user-level.}  \texht{}{Click on
\lispmemolink{Settings}{(|htSystemVariables|)} here to immediately go
to the settings facility.}

Each command listing begins with one or more syntax pattern
descriptions plus examples of related commands.  The syntax
descriptions are intended to be easy to read and do not necessarily
represent the most compact way of specifying all possible arguments
and options; the descriptions may occasionally be redundant.

All system commands begin with a right parenthesis which should be in
the first available column of the input line (that is, immediately
after the input prompt, if any).  System commands may be issued
directly to Axiom or be included in {\bf .input} files.

A system command {\it argument} is a word that directly follows the
command name and is not followed or preceded by a right parenthesis.
A system command {\it option} follows the system command and is
directly preceded by a right parenthesis.  Options may have arguments:
they directly follow the option.  This example may make it easier to
remember what is an option and what is an argument:

\centerline{{{\tt )syscmd {\it arg1 arg2} )opt1 
{\it opt1arg1 opt1arg2} )opt2 {\it opt2arg1} ...}}}

In the system command descriptions, optional arguments and options are
enclosed in brackets (``\lanb'' and ``\ranb'').  If an argument or
option name is in italics, it is meant to be a variable and must have
some actual value substituted for it when the system command call is
made.  For example, the syntax pattern description

\noindent
{\tt )read} {\it fileName} {\tt \lanb{})quietly\ranb{}}

\noindent
would imply that you must provide an actual file name for
{\it fileName} but need not use the {\tt )quietly} option.
Thus
\begin{verbatim}
)read matrix.input
\end{verbatim}
is a valid instance of the above pattern.

System command names and options may be abbreviated and may be in
upper or lower case.
The case of actual arguments may be significant, depending on the
particular situation (such as in file names).
System command names and options may be abbreviated to the minimum
number of starting letters so that the name or option is unique.
Thus
\begin{verbatim}
)s Integer
\end{verbatim}
is not a valid abbreviation for the {\tt )set} command,
because both {\tt )set} and {\tt )show}
begin with the letter ``s''.
Typically, two or three letters are sufficient for disambiguating names.
In our descriptions of the commands, we have used no abbreviations for
either command names or options.

In some syntax descriptions we use a vertical line ``\vertline'' to
indicate that you must specify one of the listed choices.  For
example, in \begin{verbatim} )set output fortran on | off
\end{verbatim} only {\tt on} and {\tt off} are acceptable words for
following {\tt boot}.  We also sometimes use ``...'' to indicate that
additional arguments or options of the listed form are allowed.
Finally, in the syntax descriptions we may also list the syntax of
related commands.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdabbreviationPage}{ug16.ht}{)abbreviation}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdabbreviationPage}{B.2. )abbreviation}
\beginscroll


\par\noindent{\bf User Level Required:} compiler

\par\noindent{\bf Command Syntax:}
\begin{items}
\item {\tt )abbreviation query  \lanb{}{\it nameOrAbbrev}\ranb{}}
\item {\tt )abbreviation category  {\it abbrev  fullname} \lanb{}
)quiet\ranb{}}
\item {\tt )abbreviation domain  {\it abbrev  fullname}   \lanb{}
)quiet\ranb{}}
\item {\tt )abbreviation package  {\it abbrev  fullname}  \lanb{}
)quiet\ranb{}}
\item {\tt )abbreviation remove  {\it nameOrAbbrev}}
\end{items}

\par\noindent{\bf Command Description:}

This command is used to query, set and remove abbreviations for category,
domain and package constructors.
Every constructor must have a unique abbreviation.
This abbreviation is part of the name of the subdirectory
under which the components of the compiled constructor are
stored.
Furthermore, by issuing this command you
let the system know what file to load automatically if you use a new
constructor.
Abbreviations must start with a letter and then be followed by
up to seven letters or digits.
Any letters appearing in the abbreviation must be in uppercase.

When used with the {\tt query} argument,
this command may be used to list the name
associated with a  particular abbreviation or the  abbreviation for a
constructor.
If no abbreviation or name is given, the names and corresponding
abbreviations for {\it all} constructors are listed.

The following shows the abbreviation for the constructor \spadtype{List}:
\begin{verbatim}
)abbreviation query List
\end{verbatim}
The following shows the constructor name corresponding to the
abbreviation \spadtype{NNI}:
\begin{verbatim}
)abbreviation query NNI
\end{verbatim}
The following lists all constructor names and their abbreviations.
\begin{verbatim}
)abbreviation query
\end{verbatim}

To add an abbreviation for a constructor, use this command with
{\tt category}, {\tt domain} or {\tt package}.
The following add abbreviations to the system for a
category, domain and package, respectively:
\begin{verbatim}
)abbreviation domain   SET Set
)abbreviation category COMPCAT  ComplexCategory
)abbreviation package  LIST2MAP ListToMap
\end{verbatim}
If the {\tt )quiet} option is used,
no output is displayed from this command.
You would normally only define an abbreviation in a library source file.
If this command is issued for a constructor that has already been loaded, the
constructor will be reloaded next time it is referenced.  In particular, you
can use this command to force the automatic reloading of constructors.

To remove an abbreviation, the {\tt remove} argument is used.
This is usually
only used to correct a previous command that set an abbreviation for a
constructor name.
If, in fact, the abbreviation does exist, you are prompted
for confirmation of the removal request.
Either of the following commands
will remove the abbreviation \spadtype{VECTOR2} and the
constructor name \spadtype{VectorFunctions2} from the system:
\begin{verbatim}
)abbreviation remove VECTOR2
)abbreviation remove VectorFunctions2
\end{verbatim}

\par\noindent{\bf Also See:}
\downlink{``)compile''}{ugSysCmdcompilePage} in section B.7

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdbootPage}{ug16.ht}{)boot}
\pageto{notitle}{ugSysCmdfinPage}
\pageto{notitle}{ugSysCmdlispPage}
\pageto{notitle}{ugSysCmdsetPage}
\pageto{notitle}{ugSysCmdsystemPage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdbootPage}{B.3. )boot}
\beginscroll


\par\noindent{\bf User Level Required:} development

\par\noindent{\bf Command Syntax:}
\begin{items}
\item {\tt )boot} {\it bootExpression}
\end{items}

\par\noindent{\bf Command Description:}

This command is used by Axiom system developers to execute
expressions written in the BOOT language.
For example,
\begin{verbatim}
)boot times3(x) == 3*x
\end{verbatim}
creates and compiles the \Lisp{} function ``times3''
obtained by translating the BOOT code.

\par\noindent{\bf Also See:}
\downlink{``)fin''}{ugSysCmdfinPage} in section B.10
\downlink{``)lisp''}{ugSysCmdlispPage} in section B.15
\downlink{``)set''}{ugSysCmdsetPage} in section B.21
\downlink{``)system''}{ugSysCmdsystemPage} in section B.25

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdcdPage}{ug16.ht}{)cd}
\pageto{notitle}{ugSysCmdcompilePage}
\pageto{notitle}{ugSysCmdeditPage}
\pageto{notitle}{ugSysCmdhistoryPage}
\pageto{notitle}{ugSysCmdlibraryPage}
\pageto{notitle}{ugSysCmdreadPage}
\pageto{notitle}{ugSysCmdspoolPage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdcdPage}{B.4. )cd}
\beginscroll


\par\noindent{\bf User Level Required:} interpreter

\par\noindent{\bf Command Syntax:}
\begin{items}
\item {\tt )cd} {\it directory}
\end{items}

\par\noindent{\bf Command Description:}

This command sets the Axiom working current directory.
The current directory is used for looking for
input files (for {\tt )read}),
Axiom library source files (for {\tt )compile}),
saved history environment files (for {\tt )history )restore}),
compiled Axiom library files (for \spadcmd{)library}), and
files to edit (for {\tt )edit}).
It is also used for writing
spool files (via {\tt )spool}),
writing history input files (via {\tt )history )write}) and
history environment files (via {\tt )history )save}),and
compiled Axiom library files (via {\tt )compile}).

If issued with no argument, this command sets the Axiom
current directory to your home directory.
If an argument is used, it must be a valid directory name.
Except for the ``{\tt )}'' at the beginning of the command,
this has the same syntax as the operating system {\tt cd} command.

\par\noindent{\bf Also See:}
\downlink{``)compile''}{ugSysCmdcompilePage} in section B.7
\downlink{``)edit''}{ugSysCmdeditPage} in section B.9
\downlink{``)history''}{ugSysCmdhistoryPage} in section B.13
\downlink{``)library''}{ugSysCmdlibraryPage} in section B.14
\downlink{``)read''}{ugSysCmdreadPage} in section B.20
\downlink{``)spool''}{ugSysCmdspoolPage} in section B.32

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdclosePage}{ug16.ht}{)close}
\pageto{notitle}{ugSysCmdquitPage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdclosePage}{B.5. )close}
\beginscroll


\par\noindent{\bf User Level Required:} interpreter

\par\noindent{\bf Command Syntax:}
\begin{items}
\item{\tt )close}
\item{\tt )close )quietly}
\end{items}
\par\noindent{\bf Command Description:}

This command is used to close down interpreter client processes.  Such
processes are started by Hyperdoc to run Axiom examples when you click
on their text. When you have finished examining or modifying the
example and you do not want the extra window around anymore, issue
\begin{verbatim}
)close
\end{verbatim}
to the Axiom prompt in the window.

If you try to close down the last remaining interpreter client
process, Axiom will offer to close down the entire Axiom
session and return you to the operating system by displaying something
like
\begin{verbatim}
   This is the last Axiom session. Do you want to kill Axiom?
\end{verbatim}
Type "y" (followed by the Return key) if this is what you had in mind.
Type "n" (followed by the Return key) to cancel the command.

You can use the {\tt )quietly} option to force Axiom to
close down the interpreter client process without closing down
the entire Axiom session.

\par\noindent{\bf Also See:}
\downlink{``)quit''}{ugSysCmdquitPage} in section B.19

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdclearPage}{ug16.ht}{)clear}
\pageto{notitle}{ugSysCmddisplayPage}
\pageto{notitle}{ugSysCmdhistoryPage}
\pageto{notitle}{ugSysCmdundoPage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdclearPage}{B.6. )clear}
\beginscroll


\par\noindent{\bf User Level Required:} interpreter

\par\noindent{\bf Command Syntax:}
\begin{items}
\item{\tt )clear all}
\item{\tt )clear completely}
\item{\tt )clear properties all}
\item{\tt )clear properties}  {\it obj1 \lanb{}obj2 ...\ranb{}}
\item{\tt )clear value      all}
\item{\tt )clear value}     {\it obj1 \lanb{}obj2 ...\ranb{}}
\item{\tt )clear mode       all}
\item{\tt )clear mode}      {\it obj1 \lanb{}obj2 ...\ranb{}}
\end{items}
\par\noindent{\bf Command Description:}

This command is used to remove function and variable declarations,
definitions and values from the workspace.  To empty the entire
workspace and reset the step counter to 1, issue
\begin{verbatim}
)clear all
\end{verbatim}
To remove everything in the workspace but not reset the step counter, 
issue
\begin{verbatim}
)clear properties all
\end{verbatim}
To remove everything about the object {\tt x}, issue
\begin{verbatim}
)clear properties x
\end{verbatim}
To remove everything about the objects {\tt x, y} and {\tt f}, issue
\begin{verbatim}
)clear properties x y f
\end{verbatim}

The word {\tt properties} may be abbreviated to the single letter
``{\tt p}''.
\begin{verbatim}
)clear p all
)clear p x
)clear p x y f
\end{verbatim}
All definitions of functions and values of variables may be removed 
by either
\begin{verbatim}
)clear value all
)clear v all
\end{verbatim}
This retains whatever declarations the objects had.  To remove 
definitions and
values for the specific objects {\tt x, y} and {\tt f}, issue
\begin{verbatim}
)clear value x y f
)clear v x y f
\end{verbatim}
To remove  the declarations  of everything while  leaving the  
definitions and
values, issue
\begin{verbatim}
)clear mode  all
)clear m all
\end{verbatim}
To remove declarations for the specific objects {\tt x, y} and 
{\tt f}, issue
\begin{verbatim}
)clear mode x y f
)clear m x y f
\end{verbatim}
The {\tt )display names} and {\tt )display properties} commands  
may be used
to see what is currently in the workspace.

The command
\begin{verbatim}
)clear completely
\end{verbatim}
does everything that {\tt )clear all} does, and also clears the internal
system function and constructor caches.

\par\noindent{\bf Also See:}
\downlink{``)display''}{ugSysCmddisplayPage} in section B.8
\downlink{``)history''}{ugSysCmdhistoryPage} in section B.13
\downlink{``)undo''}{ugSysCmdundoPage} in section B.27

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdcompilePage}{ug16.ht}{)compile}
\pageto{notitle}{ugSysCmdcdPage}
\pageto{notitle}{ugSysCmdtracePage}
\pageto{notitle}{ugSysCmdabbreviationPage}
\pageto{notitle}{ugSysCmdeditPage}
\pageto{notitle}{ugSysCmdlibraryPage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdcompilePage}{B.7. )compile}
\beginscroll


\par\noindent{\bf User Level Required:} compiler

\par\noindent{\bf Command Syntax:}

\begin{items}
\item {\tt )compile}
\item {\tt )compile {\it fileName}}
\item {\tt )compile {\it fileName}.spad}
\item {\tt )compile {\it directory/fileName}.spad}
\item {\tt )compile {\it fileName} )quiet}
\item {\tt )compile {\it fileName} )noquiet}
\item {\tt )compile {\it fileName} )break}
\item {\tt )compile {\it fileName} )nobreak}
\item {\tt )compile {\it fileName} )library}
\item {\tt )compile {\it fileName} )nolibrary}
\item {\tt )compile {\it fileName} )vartrace}
\item {\tt )compile {\it fileName} )constructor} {\it nameOrAbbrev}
\end{items}

\par\noindent{\bf Command Description:}

You use this command to invoke the Axiom library compiler.  This
compiles files with file extension {\tt .spad} with the Axiom system
compiler. The command first looks in the standard system directories
for files with extension {\tt .spad}.
 
Should you not want the {\tt )library} command automatically invoked, 
call {\tt )compile} with the {\tt )nolibrary} option. For example,
\begin{verbatim} 
)compile mycode )nolibrary
\end{verbatim} 
By default, the {\tt )library} system command exposes all domains and 
categories it processes. This means that the Axiom intepreter will consider 
those domains and categories when it is trying to resolve a reference to a 
function.
Sometimes domains and categories should not be exposed. For example, a domain
may just be used privately by another domain and may not be meant for
top-level use. The {\tt )library} command should still be used, though, so 
that the code will be loaded on demand. In this case, you should use the 
{\tt )nolibrary} option on {\tt )compile} and the {\tt )noexpose} option in 
the {\tt )library} command. For
example,
\begin{verbatim} 
)compile mycode.spad )nolibrary
)library mycode )noexpose
\end{verbatim} 
Once you have established your own collection of compiled code, you may find
it handy to use the )dir option on the )library command. This causes )library
to process all compiled code in the specified directory. For example,
\begin{verbatim} 
)library )dir /u/jones/quantum
\end{verbatim} 
You must give an explicit directory after )dir, even if you want all compiled
code in the current working directory processed.
\begin{verbatim} 
)library )dir .
\end{verbatim} 
You can compile category, domain, and package constructors contained in files
with file extension {\tt .spad}. You can compile individual constructors or 
every constructor in a file.
 
The full filename is remembered between invocations of this command and 
{\tt )edit} commands. The sequence of commands
\begin{verbatim} 
)compile matrix.spad
)edit
)compile
\end{verbatim} 
will call the compiler, edit, and then call the compiler again on the file
matrix.spad. If you do not specify a directory, the working current directory
(see description of command )cd ) is searched for the file. If the file is
not found, the standard system directories are searched.
 
If you do not give any options, all constructors within a file are compiled.
Each constructor should have an {\tt )abbreviation} command in the file in 
which it is defined. We suggest that you place the {\tt )abbreviation} 
commands at the top of the file in the order in which the constructors are 
defined. The list of commands serves as a table of contents for the file.
 
The {\tt )library} option causes directories containing the compiled code 
for each constructor to be created in the working current directory. The 
name of such a directory consists of the constructor abbreviation and the 
{\tt .nrlib} file extension. For example, the directory containing the 
compiled code for the {\tt MATRIX} constructor is called {\bf MATRIX.nrlib}. 
The {\tt )nolibrary} option says that such files should not be created. 
 
The {\tt )vartrace} option causes the compiler to generate extra code for the
constructor to support conditional tracing of variable assignments. 
Without this option, this code is suppressed
and one cannot use the )vars option for the trace command.
 
The {\tt )constructor} option is used to specify a particular constructor to
compile. All other constructors in the file are ignored. The constructor name
or abbreviation follows {\tt )constructor}. Thus either

\begin{verbatim} 
)compile matrix.spad )constructor RectangularMatrix
\end{verbatim}
or
\begin{verbatim} 
)compile matrix.spad )constructor RMATRIX
\end{verbatim}
compiles the {\tt RectangularMatrix} constructor defined in {\bf matrix.spad}.
 
The {\tt )break} and {\tt )nobreak} options determine what the compiler does
when it encounters an error. {\tt )break} is the default and it indicates that
processing should stop at the first error. The value of the {\tt )set break}
variable then controls what happens.
 
\par\noindent{\bf Also See:}
\downlink{``)abbreviation''}{ugSysCmdabbreviationPage} in section B.2
\downlink{``)edit''}{ugSysCmdeditPage} in section B.9
\downlink{``)library''}{ugSysCmdlibraryPage} in section B.14

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmddisplayPage}{ug16.ht}{)display}
\pageto{notitle}{ugSysCmdclearPage}
\pageto{notitle}{ugSysCmdhistoryPage}
\pageto{notitle}{ugSysCmdsetPage}
\pageto{notitle}{ugSysCmdshowPage}
\pageto{notitle}{ugSysCmdwhatPage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmddisplayPage}{B.8. )display}
\beginscroll


\par\noindent{\bf User Level Required:} interpreter

\par\noindent{\bf Command Syntax:}
\begin{items}
\item {\tt )display all}
\item {\tt )display properties}
\item {\tt )display properties all}
\item {\tt )display properties} {\it \lanb{}obj1 \lanb{}obj2 ...
\ranb{}\ranb{}}
\item {\tt )display value all}
\item {\tt )display value} {\it \lanb{}obj1 \lanb{}obj2 ...\ranb{}\ranb{}}
\item {\tt )display mode all}
\item {\tt )display mode} {\it \lanb{}obj1 \lanb{}obj2 ...\ranb{}\ranb{}}
\item {\tt )display names}
\item {\tt )display operations} {\it opName}
\end{items}
\par\noindent{\bf Command Description:}

This command is  used to display the contents of  the workspace and
signatures of functions  with a  given  name.\footnote{A
\spadgloss{signature} gives the argument and return types of a
function.}

The command
\begin{verbatim}
)display names
\end{verbatim}
lists the names of all user-defined objects in the workspace.  This is
useful if you do not wish to see everything about the objects and need
only be reminded of their names.

The commands
\begin{verbatim}
)display all
)display properties
)display properties all
\end{verbatim}
all do the same thing: show the values and types and declared modes of
all variables in the workspace.  If you have defined functions, their
signatures and definitions will also be displayed.

To show all information about a  particular variable or user functions,
for example, something named {\tt d}, issue
\begin{verbatim}
)display properties d
\end{verbatim}
To just show the value (and the type) of {\tt d}, issue
\begin{verbatim}
)display value d
\end{verbatim}
To just show the declared mode of {\tt d}, issue
\begin{verbatim}
)display mode d
\end{verbatim}

All modemaps for a given operation may be displayed by using {\tt
)display operations}.  A \spadgloss{modemap} is a collection of
information about a particular reference to an operation.  This
includes the types of the arguments and the return value, the location
of the implementation and any conditions on the types.  The modemap
may contain patterns.  The following displays the modemaps for the
operation \spadfunFrom{complex}{ComplexCategory}:
\begin{verbatim}
)d op complex
\end{verbatim}

\par\noindent{\bf Also See:}
\downlink{``)clear''}{ugSysCmdclearPage} in section B.6
\downlink{``)history''}{ugSysCmdhistoryPage} in section B.13
\downlink{``)set''}{ugSysCmdsetPage} in section B.21
\downlink{``)show''}{ugSysCmdshowPage} in section B.22
\downlink{``)what''}{ugSysCmdwhatPage} in section B.28

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdeditPage}{ug16.ht}{)edit}
\pageto{notitle}{ugSysCmdsystemPage}
\pageto{notitle}{ugSysCmdcompilePage}
\pageto{notitle}{ugSysCmdreadPage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdeditPage}{B.9. )edit}
\beginscroll


\par\noindent{\bf User Level Required:} interpreter

\par\noindent{\bf Command Syntax:}
\begin{items}
\item{\tt )edit} \lanb{}{\it filename}\ranb{}
\end{items}
\par\noindent{\bf Command Description:}

This command is  used to edit files.
It works in conjunction  with the {\tt )read}
and {\tt )compile} commands to remember the name
of the file on which you are working.
By specifying the name fully, you  can edit any file you wish.
Thus
\begin{verbatim}
)edit /u/julius/matrix.input
\end{verbatim}
will place  you in an editor looking at the  file
{\tt /u/julius/matrix.input}.
By default, the editor is {\tt vi},
but if you have an EDITOR shell environment variable defined, that editor
will be used.
When Axiom is running under the X Window System,
it will try to open a separate {\tt xterm} running your editor if
it thinks one is necessary.
For example, under the Korn shell, if you issue
\begin{verbatim}
export EDITOR=emacs
\end{verbatim}
then the emacs
editor will be used by \spadcmd{)edit}.

If you do not specify a file name, the last file you edited,
read or compiled will be used.
If there is no ``last file'' you will be placed in the editor editing
an empty unnamed file.

It is possible to use the {\tt )system} command to edit a file directly.
For example,
\begin{verbatim}
)system emacs /etc/rc.tcpip
\end{verbatim}
calls {\tt emacs} to edit the file.

\par\noindent{\bf Also See:}
\downlink{``)system''}{ugSysCmdsystemPage} in section B.25
\downlink{``)compile''}{ugSysCmdcompilePage} in section B.7
\downlink{``)read''}{ugSysCmdreadPage} in section B.20

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdfinPage}{ug16.ht}{)fin}
\pageto{notitle}{ugSysCmdpquitPage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdfinPage}{B.10. )fin}
\beginscroll


\par\noindent{\bf User Level Required:} development

\par\noindent{\bf Command Syntax:}
\begin{items}
\item {\tt )fin}
\end{items}
\par\noindent{\bf Command Description:}

This command is used by Axiom
developers to leave the Axiom system and return
to the underlying \Lisp{} system.
To return to Axiom, issue the
``{\tt (\vertline{}spad\vertline{})}''
function call to \Lisp{}.

\par\noindent{\bf Also See:}
\downlink{``)pquit''}{ugSysCmdpquitPage} in section B.18

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdframePage}{ug16.ht}{)frame}
\pageto{notitle}{ugSysCmdhistoryPage}
\pageto{notitle}{ugSysCmdsetPage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdframePage}{B.11. )frame}
\beginscroll


\par\noindent{\bf User Level Required:} interpreter

\par\noindent{\bf Command Syntax:}
\begin{items}
\item{\tt )frame  new  {\it frameName}}
\item{\tt )frame  drop  {\it \lanb{}frameName\ranb{}}}
\item{\tt )frame  next}
\item{\tt )frame  last}
\item{\tt )frame  names}
\item{\tt )frame  import {\it frameName} 
{\it \lanb{}objectName1 \lanb{}objectName2 ...\ranb{}\ranb{}}}
\item{\tt )set message frame on \vertline{} off}
\item{\tt )set message prompt frame}
\end{items}

\par\noindent{\bf Command Description:}

A {\it frame} can be thought of as a logical session within the
physical session that you get when you start the system.  You can
have as many frames as you want, within the limits of your computer's
storage, paging space, and so on.
Each frame has its own {\it step number}, {\it environment} and {\it
history.}  You can have a variable named {\tt a} in one frame and it
will have nothing to do with anything that might be called {\tt a} in
any other frame.

Some frames are created by the Hyperdoc program and these can
have pretty strange names, since they are generated automatically.
To find out the names
of all frames, issue
\begin{verbatim}
)frame names
\end{verbatim}
It will indicate the name of the current frame.

You create a new frame
``{\bf quark}'' by issuing
\begin{verbatim}
)frame new quark
\end{verbatim}
The history facility can be turned on by issuing either
{\tt )set history on} or {\tt )history )on}.
If the history facility is on and you are saving history information
in a file rather than in the Axiom environment
then a history file with filename {\bf quark.axh} will
be created as you enter commands.
If you wish to go back to what
you were doing in the
``{\bf initial}'' frame, use
\begin{verbatim}
)frame next
\end{verbatim}
or
\begin{verbatim}
)frame last
\end{verbatim}
to cycle through the ring of available frames to get back to
``{\bf initial}''.

If you want to throw
away a frame (say ``{\bf quark}''), issue
\begin{verbatim}
)frame drop quark
\end{verbatim}
If you omit the name, the current frame is dropped.

If you do use frames with the history facility on and writing to a file,
you may want to delete some of the older history files.
These are directories, so you may want to issue a command like
{\tt rm -r quark.axh} to the operating system.

You can bring things from another frame by using
{\tt )frame import}.
For example, to bring the {\tt f} and {\tt g} from the frame ``{\bf quark}''
to the current frame, issue
\begin{verbatim}
)frame import quark f g
\end{verbatim}
If you want everything from the frame ``{\bf quark}'', issue
\begin{verbatim}
)frame import quark
\end{verbatim}
You will be asked to verify that you really want everything.

There are two {\tt )set} flags
to make it easier to tell where you are.
\begin{verbatim}
)set message frame on | off
\end{verbatim}
will print more messages about frames when it is set on.
By default, it is off.
\begin{verbatim}
)set message prompt frame
\end{verbatim}
will give a prompt
that looks like
\begin{verbatim}
initial (1) ->
\end{verbatim}
when you start up. In this case, the frame name and step make up the
prompt.

\par\noindent{\bf Also See:}
\downlink{``)history''}{ugSysCmdhistoryPage} in section B.13
\downlink{``)set''}{ugSysCmdsetPage} in section B.21

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdhelpPage}{ug16.ht}{)help}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdhelpPage}{B.12. )help}
\beginscroll


\par\noindent{\bf User Level Required:} interpreter

\par\noindent{\bf Command Syntax:}
\begin{items}
\item{\tt )help}
\item{\tt )help} {\it commandName}
\end{items}

\par\noindent{\bf Command Description:}

This command displays help information about system commands.
If you issue
\begin{verbatim}
)help
\end{verbatim}
then this very text will be shown.
You can also give the name or abbreviation of a system command
to display information about it.
For example,
\begin{verbatim}
)help clear
\end{verbatim}
will display the description of the {\tt )clear} system command.

All this material is available in the Axiom User Guide
and in Hyperdoc.
In Hyperdoc, choose the {\bf Commands} item from the
{\bf Reference} menu.



\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdhistoryPage}{ug16.ht}{)history}
\pageto{notitle}{ugSysCmdframePage}
\pageto{notitle}{ugSysCmdcdPage}
\pageto{notitle}{ugSysCmdreadPage}
\pageto{notitle}{ugSysCmdsetPage}
\pageto{notitle}{ugSysCmdundoPage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdhistoryPage}{B.13. )history}
\beginscroll


\par\noindent{\bf User Level Required:} interpreter

\par\noindent{\bf Command Syntax:}
\begin{items}
\item{\tt )history )on}
\item{\tt )history )off}
\item{\tt )history )write} {\it historyInputFileName}
\item{\tt )history )show \lanb{}{\it n}\ranb{} \lanb{}both\ranb{}}
\item{\tt )history )save} {\it savedHistoryName}
\item{\tt )history )restore} \lanb{}{\it savedHistoryName}\ranb{}
\item{\tt )history )reset}
\item{\tt )history )change} {\it n}
\item{\tt )history )memory}
\item{\tt )history )file}
\item{\tt \%}
\item{\tt \%\%({\it n})}
\item{\tt )set history on \vertline{} off}
\end{items}

\par\noindent{\bf Command Description:}

The {\it history} facility within Axiom allows you to restore your
environment to that of another session and recall previous
computational results.
Additional commands allow you to review previous
input lines and to create an {\bf .input} file of the lines typed to
Axiom.

Axiom saves your input and output if the history facility is
turned on (which is the default).
This information is saved if either of
\begin{verbatim}
)set history on
)history )on
\end{verbatim}
has been issued.
Issuing either
\begin{verbatim}
)set history off
)history )off
\end{verbatim}
will discontinue the recording of information.

Whether the facility is disabled or not, the value of \spadSyntax{\%}
in Axiom always refers to the result of the last computation.  If you
have not yet entered anything, \spadSyntax{\%} evaluates to an object
of type \spadtype{Variable('\%)}.  The function \spadSyntax{\%\%} may
be used to refer to other previous results if the history facility is
enabled.  In that case, {\tt \%\%(n)} is the output from step {\tt n}
if {\tt n > 0}.  If {\tt n < 0}, the step is computed relative to the
current step.  Thus {\tt \%\%(-1)} is also the previous step, {\tt
\%\%(-2)}, is the step before that, and so on.  If an invalid step
number is given, Axiom will signal an error.

The {\it environment} information can either be saved in a file or
entirely in memory (the default).  Each frame
(\downlink{``)frame''}{ugSysCmdframePage} in Section
B.11\ignore{ugSysCmdframe}) has its own history
database.  When it is kept in a file, some of it may also be kept in
memory for efficiency.  When the information is saved in a file, the
name of the file is of the form {\bf FRAME.axh} where ``{\bf FRAME}''
is the name of the current frame.  The history file is placed in the
current working directory (see
\downlink{``)cd''}{ugSysCmdcdPage} in Section
B.4\ignore{ugSysCmdcd}).  Note that these history
database files are not text files (in fact, they are directories
themselves), and so are not in human-readable format.

The options to the {\tt )history} command are as follows:

\indent{0}
\beginitems
\item[{\tt )change} {\it n}]
will set the number of steps that are saved in memory to {\it n}.
This option only has effect when the history data is maintained in a
file.
If you have issued {\tt )history )memory} (or not changed the default)
there is no need to use {\tt )history )change}.

\item[{\tt )on}]
will start the recording of information.
If the workspace is not empty, you will be asked to confirm this
request.
If you do so, the workspace will be cleared and history data will begin
being saved.
You can also turn the facility on by issuing {\tt )set history on}.

\item[{\tt )off}]
will stop the recording of information.
The {\tt )history )show} command will not work after issuing this
command.
Note that this command may be issued to save time, as there is some
performance penalty paid for saving the environment data.
You can also turn the facility off by issuing {\tt )set history off}.

\item[{\tt )file}]
indicates that history data should be saved in an external file on disk.

\item[{\tt )memory}]
indicates that all history data should be kept in memory rather than
saved in a file.
Note that if you are computing with very large objects it may not be
practical to kept this data in memory.

\item[{\tt )reset}]
will flush the internal list of the most recent workspace calculations
so that the data structures may be garbage collected by the underlying
\Lisp{} system.
Like {\tt )history )change}, this option only has real effect when
history data is being saved in a file.

\item[{\tt )restore} \lanb{}{\it savedHistoryName}\ranb{}]
completely clears the environment and restores it to a saved session, if
possible.
The {\tt )save} option below allows you to save a session to a file
with a given name. If you had issued
{\tt )history )save jacobi}
the command
{\tt )history )restore jacobi}
would clear the current workspace and load the contents of the named
saved session. If no saved session name is specified, the system looks
for a file called {\bf last.axh}.

\item[{\tt )save} {\it savedHistoryName}]
is used to save  a snapshot of the environment in a file.
This file is placed in the current working directory
(see \downlink{``)cd''}{ugSysCmdcdPage} 
in Section B.4\ignore{ugSysCmdcd}).
Use {\tt )history )restore} to restore the environment to the state
preserved in the file.
This option also creates an input file containing all the lines of input
since you created the workspace frame (for example, by starting your
Axiom session) or last did a \spadcmd{)clear all} or
\spadcmd{)clear completely}.

\item[{\tt )show} \lanb{}{\it n}\ranb{} \lanb{}{\tt both}\ranb{}]
can show previous input lines and output results.
{\tt )show} will display up to twenty of the last input lines
(fewer if you haven't typed in twenty lines).
{\tt )show} {\it n} will display up to {\it n} of the last input lines.
{\tt )show both} will display up to five of the last input lines and
output results.
{\tt )show} {\it n} {\tt both} will display up to {\it n} of the last
input lines and output results.

\item[{\tt )write} {\it historyInputFile}]
creates an {\bf .input} file with the input lines typed since the start
of the session/frame or the last {\tt )clear all} or {\tt )clear
completely}.
If {\it historyInputFileName} does not 
contain a period (``.'') in the filename,
{\bf .input} is appended to it.
For example,
{\tt )history )write chaos}
and
{\tt )history )write chaos.input}
both write the input lines to a file called {\bf chaos.input} in your
current working directory.
If you issued one or more {\tt )undo} commands,
{\tt )history )write}
eliminates all
input lines backtracked over as a result of {\tt )undo}.
You can edit this file and then use {\tt )read} to have Axiom process
the contents.
\enditems
\indent{0}

\par\noindent{\bf Also See:}
\downlink{``)frame''}{ugSysCmdframePage} in section B.11
\downlink{``)read''}{ugSysCmdreadPage} in section B.20
\downlink{``)set''}{ugSysCmdsetPage} in section B.21
\downlink{``)undo''}{ugSysCmdundoPage} in section B.27

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdlibraryPage}{ug16.ht}{)library}
\pageto{notitle}{ugSysCmdcdPage}
\pageto{notitle}{ugSysCmdcompilePage}
\pageto{notitle}{ugSysCmdframePage}
\pageto{notitle}{ugSysCmdsetPage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdlibraryPage}{B.14. )library}
\beginscroll


\par\noindent{\bf User Level Required:} interpreter

\par\noindent{\bf Command Syntax:}
\begin{items}
\item{\tt )library {\it libName1  \lanb{}libName2 ...\ranb{}}}
\item{\tt )library )dir {\it dirName}}
\item{\tt )library )only {\it objName1  \lanb{}objlib2 ...\ranb{}}}
\item{\tt )library )noexpose}
\end{items}

\par\noindent{\bf Command Description:}

This command replaces the {\tt )load} system command that
was available in Axiom releases before version 2.0.
The \spadcmd{)library} command makes available to Axiom the compiled
objects in the libraries listed.

For example, if you {\tt )compile dopler.as} in your home
directory, issue {\tt )library dopler} to have Axiom look
at the library, determine the category and domain constructors present,
update the internal database with various properties of the
constructors, and arrange for the constructors to be
automatically loaded when needed.
If the {\tt )noexpose} option has not been given, the
constructors will be exposed (that is, available) in the current
frame.

If you compiled a file with the old system compiler, you will
have an {\it nrlib} present, for example, {\it DOPLER.nrlib,}
where {\tt DOPLER} is a constructor abbreviation.
The command {\tt )library DOPLER} will then do the analysis and
database updates as above.

To tell the system about all libraries in a directory, use
{\tt )library )dir dirName} where {\tt dirName} is an explicit
directory.
You may specify ``.'' as the directory, which means the current
directory from which you started the system or the one you set
via the \spadcmd{)cd} command. The directory name is required.

You may only want to tell the system about particular
constructors within a library. In this case, use the {\tt )only}
option. The command {\tt )library dopler )only Test1} will only
cause the {\sf Test1} constructor to be analyzed, autoloaded,
etc..

Finally, each constructor in a library are usually automatically
exposed when the \spadcmd{)library} command is used. Use the {\tt
)noexpose} option if you not want them exposed. At a later time you
can use {\tt )set expose add constructor} to expose any hidden
constructors.

{\bf Note for Axiom beta testers:} At various times this
command was called {\tt )local} and {\tt )with} before the name
{\tt )library} became the official name.

\par\noindent{\bf Also See:}
\downlink{``)cd''}{ugSysCmdcdPage} in section B.4
\downlink{``)compile''}{ugSysCmdcompilePage} in section B.7
\downlink{``)frame''}{ugSysCmdframePage} in section B.11
\downlink{``)set''}{ugSysCmdsetPage} in section B.21

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdlispPage}{ug16.ht}{)lisp}
\pageto{notitle}{ugSysCmdsystemPage}
\pageto{notitle}{ugSysCmdbootPage}
\pageto{notitle}{ugSysCmdfinPage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdlispPage}{B.15. )lisp}
\beginscroll


\par\noindent{\bf User Level Required:} development

\par\noindent{\bf Command Syntax:}
\begin{items}
\item {\tt )lisp} {\it\lanb{}lispExpression\ranb{}}
\end{items}

\par\noindent{\bf Command Description:}

This command is used by Axiom system developers to have single
expressions evaluated by the \Lisp{} system on which Axiom is built.
The {\it lispExpression} is read by the \Lisp{} reader and evaluated.
If this expression is not complete (unbalanced parentheses, say), the
reader will wait until a complete expression is entered.

Since this command is only useful for evaluating single expressions,
the {\tt )fin} command may be used to drop out of Axiom into \Lisp{}.

\par\noindent{\bf Also See:}
\downlink{``)system''}{ugSysCmdsystemPage} in section B.25
\downlink{``)boot''}{ugSysCmdbootPage} in section B.3
\downlink{``)fin''}{ugSysCmdfinPage} in section B.10

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdloadPage}{ug16.ht}{)load}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdloadPage}{B.16. )load}
\beginscroll


\par\noindent{\bf User Level Required:} interpreter

\par\noindent{\bf Command Description:}

This command is obsolete. Use \spadcmd{)library} instead.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdltracePage}{ug16.ht}{)ltrace}
\pageto{notitle}{ugSysCmdbootPage}
\pageto{notitle}{ugSysCmdlispPage}
\pageto{notitle}{ugSysCmdtracePage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdltracePage}{B.17. )ltrace}
\beginscroll


\par\noindent{\bf User Level Required:} development

\par\noindent{\bf Command Syntax:}

This command has the same arguments as options as the
\spadcmd{)trace} command.

\par\noindent{\bf Command Description:}

This command is used by Axiom system developers to trace
\Lisp{} or
BOOT functions.
It is not supported for general use.

\par\noindent{\bf Also See:}
\downlink{``)boot''}{ugSysCmdbootPage} in section B.3
\downlink{``)lisp''}{ugSysCmdlispPage} in section B.15
\downlink{``)trace''}{ugSysCmdtracePage} in section B.26

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdpquitPage}{ug16.ht}{)pquit}
\pageto{notitle}{ugSysCmdfinPage}
\pageto{notitle}{ugSysCmdhistoryPage}
\pageto{notitle}{ugSysCmdclosePage}
\pageto{notitle}{ugSysCmdquitPage}
\pageto{notitle}{ugSysCmdsystemPage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdpquitPage}{B.18. )pquit}
\beginscroll


\par\noindent{\bf User Level Required:} interpreter

\par\noindent{\bf Command Syntax:}
\begin{items}
\item{\tt )pquit}
\end{items}

\par\noindent{\bf Command Description:}

This command is used to terminate Axiom  and return to the
operating system.
Other than by redoing all your computations or by
using the {\tt )history )restore}
command to try to restore your working environment,
you cannot return to Axiom in the same state.

{\tt )pquit} differs from the {\tt )quit} in that it always asks for
confirmation that you want to terminate Axiom (the ``p'' is for
``protected'').
When you enter the {\tt )pquit} command, Axiom responds
%
\centerline{{Please enter {\bf y} or {\bf yes} 
if you really want to leave the interactive }}
\centerline{{environment and return to the operating system:}}
%
If you respond with {\tt y} or {\tt yes}, you will see the message
%
\centerline{{You are now leaving the Axiom interactive environment. }}
\centerline{{Issue the command {\bf axiom} to 
the operating system to start a new session.}}
%
and Axiom will terminate and return you to the operating
system (or the environment from which you invoked the system).
If you responded with something other than {\tt y} or {\tt yes}, then
the message
%
\centerline{{You have chosen to remain in the 
Axiom interactive environment.}}
%
will be displayed and, indeed, Axiom would still be running.

\par\noindent{\bf Also See:}
\downlink{``)fin''}{ugSysCmdfinPage} in section B.10
\downlink{``)history''}{ugSysCmdhistoryPage} in section B.13
\downlink{``)close''}{ugSysCmdclosePage} in section B.5
\downlink{``)quit''}{ugSysCmdquitPage} in section B.19
\downlink{``)system''}{ugSysCmdsystemPage} in section B.25

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdquitPage}{ug16.ht}{)quit}
\pageto{notitle}{ugSysCmdfinPage}
\pageto{notitle}{ugSysCmdhistoryPage}
\pageto{notitle}{ugSysCmdclosePage}
\pageto{notitle}{ugSysCmdpquitPage}
\pageto{notitle}{ugSysCmdsystemPage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdquitPage}{B.19. )quit}
\beginscroll


\par\noindent{\bf User Level Required:} interpreter

\par\noindent{\bf Command Syntax:}
\begin{items}
\item{\tt )quit}
\item{\tt )set quit protected \vertline{} unprotected}
\end{items}

\par\noindent{\bf Command Description:}

This command is used to terminate Axiom  and return to the
operating system.
Other than by redoing all your computations or by
using the {\tt )history )restore}
command to try to restore your working environment,
you cannot return to Axiom in the same state.

{\tt )quit} differs from the {\tt )pquit} in that it asks for
confirmation only if the command
\begin{verbatim}
)set quit protected
\end{verbatim}
has been issued.
Otherwise, {\tt )quit} will make Axiom terminate and return you
to the operating system (or the environment from which you invoked the
system).

The default setting is {\tt )set quit protected} so that {\tt )quit}
and {\tt )pquit} behave in the same way.
If you do issue
\begin{verbatim}
)set quit unprotected
\end{verbatim}
we
suggest that you do not (somehow) assign {\tt )quit} to be
executed when you press, say, a function key.

\par\noindent{\bf Also See:}
\downlink{``)fin''}{ugSysCmdfinPage} in section B.10
\downlink{``)history''}{ugSysCmdhistoryPage} in section B.13
\downlink{``)close''}{ugSysCmdclosePage} in section B.5
\downlink{``)quit''}{ugSysCmdpquitPage} in section B.19
\downlink{``)system''}{ugSysCmdsystemPage} in section B.25

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdreadPage}{ug16.ht}{)read}
\pageto{notitle}{ugInOutInPage}
\pageto{notitle}{ugSysCmdcompilePage}
\pageto{notitle}{ugSysCmdeditPage}
\pageto{notitle}{ugSysCmdhistoryPage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdreadPage}{B.20. )read}
\beginscroll


\par\noindent{\bf User Level Required:} interpreter

\par\noindent{\bf Command Syntax:}
\begin{items}
\item {\tt )read} {\it \lanb{}fileName\ranb{}}
\item {\tt )read} {\it \lanb{}fileName\ranb{}} 
\lanb{}{\tt )quiet}\ranb{} \lanb{}{\tt )ifthere}\ranb{}
\end{items}
\par\noindent{\bf Command Description:}

This command is used to read {\bf .input} files into Axiom.
The command
\begin{verbatim}
)read matrix.input
\end{verbatim}
will read the contents of the file {\bf matrix.input} into Axiom.  The
``.input'' file extension is optional.  See
\downlink{``Input Files and Output Styles''}{ugInOutInPage} in Section 4
\ignore{ugInOutIn} for more information about {\bf
.input} files.

This command remembers the previous file you edited, read or compiled.
If you do not specify a file name, the previous file will be read.

The {\tt )ifthere} option checks to see whether the {\bf .input} file
exists.  If it does not, the {\tt )read} command does nothing.  If you
do not use this option and the file does not exist, you are asked to
give the name of an existing {\bf .input} file.

The {\tt )quiet} option suppresses output while the file is being read.

\par\noindent{\bf Also See:}
\downlink{``)compile''}{ugSysCmdcompilePage} in section B.7
\downlink{``)edit''}{ugSysCmdeditPage} in section B.9
\downlink{``)history''}{ugSysCmdhistoryPage}  section B.13

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdsetPage}{ug16.ht}{)set}
\pageto{notitle}{ugSysCmdquitPage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdsetPage}{B.21. )set}
\beginscroll


\par\noindent{\bf User Level Required:} interpreter

\par\noindent{\bf Command Syntax:}
\begin{items}
\item {\tt )set}
\item {\tt )set} {\it label1 \lanb{}... labelN\ranb{}}
\item {\tt )set} {\it label1 \lanb{}... labelN\ranb{} newValue}
\end{items}
\par\noindent{\bf Command Description:}

The {\tt )set} command is used to view or set system variables that
control what messages are displayed, the type of output desired, the
status of the history facility, the way Axiom user functions are
cached, and so on.
Since this collection is very large, we will not discuss them here.
Rather, we will show how the facility is used.
We urge you to explore the {\tt )set} options to familiarize yourself
with how you can modify your Axiom working environment.
There is a Hyperdoc version of this same facility available from the
main Hyperdoc menu.
\texht{}{Click \lispmemolink{here}{(|htSystemVariables|)} to go to it.}

The {\tt )set} command is command-driven with a menu display.
It is tree-structured.
To see all top-level nodes, issue {\tt )set} by itself.
\begin{verbatim}
)set
\end{verbatim}
Variables with values have them displayed near the right margin.
Subtrees of selections have ``{\tt ...}''
displayed in the value field.
For example, there are many kinds of messages, so issue
{\tt )set message} to see the choices.
\begin{verbatim}
)set message
\end{verbatim}
The current setting  for the variable that displays
whether computation times
are displayed is visible in the menu displayed by the last command.
To see more information, issue
\begin{verbatim}
)set message time
\end{verbatim}
This shows that time printing is on now.
To turn it off, issue
\begin{verbatim}
)set message time off
\end{verbatim}

As noted above, not all settings have so many qualifiers.
For example, to change the {\tt )quit} command to being unprotected
(that is, you will not be prompted for verification), you need only issue
\begin{verbatim}
)set quit unprotected
\end{verbatim}

\par\noindent{\bf Also See:}
\downlink{``)quit''}{ugSysCmdquitPage} in section B.19

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdshowPage}{ug16.ht}{)show}
\pageto{notitle}{ugSysCmddisplayPage}
\pageto{notitle}{ugSysCmdsetPage}
\pageto{notitle}{ugSysCmdwhatPage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdshowPage}{B.22. )show}
\beginscroll


\par\noindent{\bf User Level Required:} interpreter

\par\noindent{\bf Command Syntax:}
\begin{items}
\item{\tt )show {\it nameOrAbbrev}}
\item{\tt )show {\it nameOrAbbrev} )operations}
\item{\tt )show {\it nameOrAbbrev} )attributes}
\end{items}

\par\noindent{\bf Command Description:}
This command displays information about Axiom
domain, package and category {\it constructors}.
If no options are given, the {\tt )operations} option is assumed.
For example,
\begin{verbatim}
)show POLY
)show POLY )operations
)show Polynomial
)show Polynomial )operations
\end{verbatim}
each display basic information about the
\spadtype{Polynomial} domain constructor and then provide a
listing of operations.
Since \spadtype{Polynomial} requires a \spadtype{Ring} (for example,
\spadtype{Integer}) as argument, the above commands all refer
to a unspecified ring {\tt R}.
In the list of operations, \spadSyntax{\$} means
\spadtype{Polynomial(R)}.

The basic information displayed includes the {\it signature}
of the constructor (the name and arguments), the constructor
{\it abbreviation}, the {\it exposure status} of the constructor, and the
name of the {\it library source file} for the constructor.

If operation information about a specific domain is wanted,
the full or abbreviated domain name may be used.
For example,
\begin{verbatim}
)show POLY INT
)show POLY INT )operations
)show Polynomial Integer
)show Polynomial Integer )operations
\end{verbatim}
are among  the combinations that will
display the operations exported  by the
domain \spadtype{Polynomial(Integer)} (as opposed to the general
{\it domain constructor} \spadtype{Polynomial}).
Attributes may be listed by using the {\tt )attributes} option.

\par\noindent{\bf Also See:}
\downlink{``)display''}{ugSysCmddisplayPage} in section B.8
\downlink{``)set''}{ugSysCmdsetPage} in section B.21
\downlink{``)what''}{ugSysCmdwhatPage} in section B.28

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdspoolPage}{ug16.ht}{)spool}
\pageto{notitle}{ugSysCmdcdPage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdspoolPage}{B.23. )spool}
\beginscroll


\par\noindent{\bf User Level Required:} interpreter

\par\noindent{\bf Command Syntax:}
\begin{items}
\item{\tt )spool} \lanb{}{\it fileName}\ranb{}
\item{\tt )spool}
\end{items}

\par\noindent{\bf Command Description:}

This command is used to save {\it (spool)} all Axiom input and output
into a file, called a {\it spool file.}
You can only have one spool file active at a time.
To start spool, issue this command with a filename. For example,
\begin{verbatim}
)spool integrate.out
\end{verbatim}
To stop spooling, issue {\tt )spool} with no filename.

If the filename is qualified with a directory, then the output will be
placed in that directory.  If no directory information is given, the
spool file will be placed in the {\it current directory.}  The current
directory is the directory from which you started Axiom or is the
directory you specified using the {\tt )cd} command.

\par\noindent{\bf Also See:}
\downlink{``)cd''}{ugSysCmdcdPage} in section B.4
\ugSysCmdcdNumber

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdsynonymPage}{ug16.ht}{)synonym}
\pageto{notitle}{ugSysCmdsetPage}
\pageto{notitle}{ugSysCmdwhatPage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdsynonymPage}{B.24. )synonym}
\beginscroll


\par\noindent{\bf User Level Required:} interpreter

\par\noindent{\bf Command Syntax:}
\begin{items}
\item{\tt )synonym}
\item{\tt )synonym} {\it synonym fullCommand}
\item{\tt )what synonyms}
\end{items}

\par\noindent{\bf Command Description:}

This command is used to create short synonyms for system command
expressions.  For example, the following synonyms might simplify
commands you often use.
\begin{verbatim}
)synonym save         history )save
)synonym restore      history )restore
)synonym mail         system mail
)synonym ls           system ls
)synonym fortran      set output fortran
\end{verbatim}
Once defined, synonyms can be
used in place of the longer  command expressions.
Thus
\begin{verbatim}
)fortran on
\end{verbatim}
is the same as the longer
\begin{verbatim}
)set fortran output on
\end{verbatim}
To list all defined synonyms, issue either of
\begin{verbatim}
)synonyms
)what synonyms
\end{verbatim}
To list, say, all synonyms that contain the substring
``{\tt ap}'', issue
\begin{verbatim}
)what synonyms ap
\end{verbatim}

\par\noindent{\bf Also See:}
\downlink{``)set''}{ugSysCmdsetPage} in section B.21
\downlink{``)what''}{ugSysCmdwhatPage} in section B.28

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdsystemPage}{ug16.ht}{)system}
\pageto{notitle}{ugSysCmdbootPage}
\pageto{notitle}{ugSysCmdfinPage}
\pageto{notitle}{ugSysCmdlispPage}
\pageto{notitle}{ugSysCmdpquitPage}
\pageto{notitle}{ugSysCmdquitPage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdsystemPage}{B.25. )system}
\beginscroll

\par\noindent{\bf User Level Required:} interpreter

\par\noindent{\bf Command Syntax:}
\begin{items}
\item{\tt )system} {\it cmdExpression}
\end{items}

\par\noindent{\bf Command Description:}

This command may be used to issue commands to the operating system
while remaining in Axiom.  The {\it cmdExpression} is passed to the
operating system for execution.

To get an operating system shell, issue, for example,
\spadcmd{)system sh}.
When you enter the key combination,
\texht{\fbox{\bf Ctrl}--\fbox{\bf D}}{{\bf Ctrl-D}}
(pressing and holding the
\texht{\fbox{\bf Ctrl}}{{\bf Ctrl}} key and then pressing the
\texht{\fbox{\bf D}}{{\bf D}} key)
the shell will terminate and you will return to Axiom.
We do not recommend this way of creating a shell because
\Lisp{} may field some interrupts instead of the shell.
If possible, use a shell running in another window.

If you execute programs that misbehave you may not be able to return
to Axiom.  If this happens, you may have no other choice than to
restart Axiom and restore the environment via {\tt )history )restore},
if possible.

\par\noindent{\bf Also See:}
\downlink{``)boot''}{ugSysCmdbootPage} in section B.3
\downlink{``)fin''}{ugSysCmdfinPage} in section B.10
\downlink{``)lisp''}{ugSysCmdlispPage} in section B.15
\downlink{``)quit''}{ugSysCmdpquitPage} in section B.18
\downlink{``)quit''}{ugSysCmdquitPage} in section B.19

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdtracePage}{ug16.ht}{)trace}
\pageto{notitle}{ugSysCmdcompilePage}
\pageto{notitle}{ugSysCmdbootPage}
\pageto{notitle}{ugSysCmdlispPage}
\pageto{notitle}{ugSysCmdltracePage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdtracePage}{B.26. )trace}
\beginscroll


\par\noindent{\bf User Level Required:} interpreter

\par\noindent{\bf Command Syntax:}
\begin{items}
\item{\tt )trace}
\item{\tt )trace )off}

\item{\tt )trace} {\it function \lanb{}options\ranb{}}
\item{\tt )trace} {\it constructor \lanb{}options\ranb{}}
\item{\tt )trace} {\it domainOrPackage \lanb{}options\ranb{}}
\end{items}
%
where options can be one or more of
%
\begin{items}
\item{\tt )after} {\it S-expression}
\item{\tt )before} {\it S-expression}
\item{\tt )break after}
\item{\tt )break before}
\item{\tt )cond} {\it S-expression}
\item{\tt )count}
\item{\tt )count} {\it n}
\item{\tt )depth} {\it n}
\item{\tt )local} {\it op1 \lanb{}... opN\ranb{}}
\item{\tt )nonquietly}
\item{\tt )nt}
\item{\tt )off}
\item{\tt )only} {\it listOfDataToDisplay}
\item{\tt )ops}
\item{\tt )ops} {\it op1 \lanb{}... opN \ranb{}}
\item{\tt )restore}
\item{\tt )stats}
\item{\tt )stats reset}
\item{\tt )timer}
\item{\tt )varbreak}
\item{\tt )varbreak} {\it var1 \lanb{}... varN \ranb{}}
\item{\tt )vars}
\item{\tt )vars} {\it var1 \lanb{}... varN \ranb{}}
\item{\tt )within} {\it executingFunction}
\end{items}

\par\noindent{\bf Command Description:}

This command is used to trace the execution of functions that make
up the Axiom system, functions defined by users,
and functions from the system library.
Almost all options are available for each type of function but
exceptions will be noted below.

To list all functions, constructors, domains and packages that are
traced, simply issue
\begin{verbatim}
)trace
\end{verbatim}
To untrace everything that is traced, issue
\begin{verbatim}
)trace )off
\end{verbatim}
When a function is traced, the default system action is to display
the arguments to the function and the return value when the
function is exited.
Note that if a function is left via an action such as a {\tt THROW}, no
return value will be displayed.
Also, optimization of tail recursion may decrease the number of
times a function is actually invoked and so may cause less trace
information to be displayed.
Other information can be displayed or collected when a function is
traced and this is controlled by the various options.
Most options will be of interest only to Axiom system
developers.
If a domain or package is traced, the default action is to trace
all functions exported.

Individual interpreter, lisp or boot
functions can be traced by listing their names after
{\tt )trace}.
Any options that are present must follow the functions to be
traced.
\begin{verbatim}
)trace f
\end{verbatim}
traces the function {\tt f}.
To untrace {\tt f}, issue
\begin{verbatim}
)trace f )off
\end{verbatim}
Note that if a function name contains a special character, it will
be necessary to escape the character with an underscore
%
\begin{verbatim}
)trace _/D_,1
\end{verbatim}

To trace all domains or packages that are or will be created from a
particular constructor, give the constructor name or abbreviation
after {\tt )trace}.

\begin{verbatim}
)trace MATRIX
)trace List Integer
\end{verbatim}

The first command traces all domains currently instantiated with
\spadtype{Matrix}.  If additional domains are instantiated with this
constructor (for example, if you have used \spadtype{Matrix(Integer)}
and \spadtype{Matrix(Float)}), they will be automatically traced.  The
second command traces \spadtype{List(Integer)}.  It is possible to
trace individual functions in a domain or package.  See the {\tt )ops}
option below.

The following are the general options for the {\tt )trace}
command.

%!! system command parser doesn't treat general s-expressions correctly,
%!! I recommand not documenting )after )before and )cond
\indent{0}
\beginitems
%\item[{\tt )after} {\it S-expression}]
%causes the given \Lisp{} {\it S-expression} to be
%executed after exiting the traced function.

%\item[{\tt )before} {\it S-expression}]
%causes the given \Lisp{} {\it S-expression} to be
%executed before entering the traced function.

\item[{\tt )break after}]
causes a \Lisp{} break loop to be entered after
exiting the traced function.

\item[{\tt )break before}]
causes a \Lisp{} break loop to be entered before
entering the traced function.

\item[{\tt )break}]
is the same as \spadcmd{)break before}.

%\item[{\tt )cond} {\it S-expression}]
%causes trace information to be shown only if the given
%\Lisp{} {\it S-expression} evaluates to non-NIL.  For
%example, the following command causes the system function
%{\tt resolveTT} to be traced but to have the information
%displayed only if the value of the variable
%{\tt \$reportBottomUpFlag} is non-NIL.
%\begin{verbatim}
%)trace resolveTT )cond \_\$reportBottomUpFlag}
%\end{verbatim}

\item[{\tt )count}]
causes the system to keep a count of the number of times the
traced function is entered.  The total can be displayed with
{\tt )trace )stats} and cleared with {\tt )trace )stats reset}.

\item[{\tt )count} {\it n}]
causes information about the traced function to be displayed for
the first {\it n} executions.  After the \eth{\it n} execution, the
function is untraced.

\item[{\tt )depth} {\it n}]
causes trace information to be shown for only {\it n} levels of
recursion of the traced function.  The command
\begin{verbatim}
)trace fib )depth 10
\end{verbatim}
will cause the display of only 10 levels of trace information for
the recursive execution of a user function \userfun{fib}.

\item[{\tt )math}]
causes the function arguments and return value to be displayed in the
Axiom monospace two-dimensional math format.

\item[{\tt )nonquietly}]
causes the display of additional messages when a function is
traced.

\item[{\tt )nt}]
This suppresses all normal trace information.  This option is
useful if the {\tt )count} or {\tt )timer} options are used and
you are interested in the statistics but not the function calling
information.

\item[{\tt )off}]
causes untracing of all or specific functions.  Without an
argument, all functions, constructors, domains and packages are
untraced.  Otherwise, the given functions and other objects
are untraced.  To
immediately retrace the untraced functions, issue {\tt )trace
)restore}.

\item[{\tt )only} {\it listOfDataToDisplay}]
causes only specific trace information to be shown.  The items are
listed by using the following abbreviations:
\indent{0}
\beginitems
\item[a]        display all arguments
\item[v]        display return value
\item[1]        display first argument
\item[2]        display second argument
\item[15]       display the 15th argument, and so on
\enditems
\indent{0}
\enditems
\indent{0}
\indent{0}
\beginitems

\item[{\tt )restore}]
causes the last untraced functions to be retraced.  If additional
options are present, they are added to those previously in effect.

\item[{\tt )stats}]
causes the display of statistics collected by the use of the
{\tt )count} and {\tt )timer} options.

\item[{\tt )stats reset}]
resets to 0 the statistics collected by the use of the
{\tt )count} and {\tt )timer} options.

\item[{\tt )timer}]
causes the system to keep a count of execution times for the
traced function.  The total can be displayed with {\tt )trace
)stats} and cleared with {\tt )trace )stats reset}.

%!! only for lisp, boot, may not work in any case, recommend removing
%\item[{\tt )varbreak}]
%causes a \Lisp{} break loop to be entered after
%the assignment to any variable in the traced function.

\item[{\tt )varbreak} {\it var1 \lanb{}... varN\ranb{}}]
causes a \Lisp{} break loop to be entered after
the assignment to any of the listed variables in the traced
function.

\item[{\tt )vars}]
causes the display of the value of any variable after it is assigned
in the traced function.  Note that library code must have been
compiled (see
\downlink{``)compile''}{ugSysCmdcompilePage} in Section
B.7\ignore{ugSysCmdcompile}) using the {\tt
)vartrace} option in order to support this option.

\item[{\tt )vars} {\it var1 \lanb{}... varN\ranb{}}]
causes the display of the value of any of the specified variables
after they are assigned in the traced function.  Note that library
code must have been compiled (see
\downlink{``)compile''}{ugSysCmdcompilePage} in Section
B.7\ignore{ugSysCmdcompile}) using the {\tt
)vartrace} option in order to support this option.

\item[{\tt )within} {\it executingFunction}]
causes the display of trace information only if the traced
function is called when the given {\it executingFunction} is running.
\enditems
\indent{0}

The following are the options for tracing constructors, domains
and packages.

\indent{0}
\beginitems
\item[{\tt )local} {\it \lanb{}op1 \lanb{}... opN\ranb{}\ranb{}}]
causes local functions of the constructor to be traced.  Note that
to untrace an individual local function, you must use the fully
qualified internal name, using the escape character
\spadSyntax{\_} before the semicolon.
\begin{verbatim}
)trace FRAC )local
)trace FRAC_;cancelGcd )off
\end{verbatim}

\item[{\tt )ops} {\it op1 \lanb{}... opN\ranb{}}]
By default, all operations from a domain or package are traced
when the domain or package is traced.  This option allows you to
specify that only particular operations should be traced.  The
command
%
\begin{verbatim}
)trace Integer )ops min max _+ _-
\end{verbatim}
%
traces four operations from the domain \spadtype{Integer}.  Since
{\tt +} and {\tt -} are special
characters, it is necessary
to escape them with an underscore.
\enditems
\indent{0}

\par\noindent{\bf Also See:}
\downlink{``)boot''}{ugSysCmdbootPage} in section B.3
\downlink{``)lisp''}{ugSysCmdlispPage} in section B.15
\downlink{``)trace''}{ugSysCmdltracePage} in section B.26

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdundoPage}{ug16.ht}{)undo}
\pageto{notitle}{ugSysCmdhistoryPage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdundoPage}{B.27. )undo}
\beginscroll


\par\noindent{\bf User Level Required:} interpreter

\par\noindent{\bf Command Syntax:}
\begin{items}
\item{\tt )undo}
\item{\tt )undo} {\it integer}
\item{\tt )undo} {\it integer \lanb{}option\ranb{}}
\item{\tt )undo} {\tt )redo}
\end{items}
%
where {\it option} is one of
%
\begin{items}
\item{\tt )after}
\item{\tt )before}
\end{items}

\par\noindent{\bf Command Description:}

This command is used to
restore the state of the user environment to an earlier
point in the interactive session.
The argument of an {\tt )undo} is an integer which must designate some
step number in the interactive session.

\begin{verbatim}
)undo n
)undo n )after
\end{verbatim}
These commands return the state of the interactive
environment to that immediately after step {\tt n}.
If {\tt n} is a positive number, then {\tt n} refers to step nummber
{\tt n}. If {\tt n} is a negative number, it refers to the \eth{\tt n}
previous command (that is, undoes the effects of the last \smath{-n}
commands).

A {\tt )clear all} resets the {\tt )undo} facility.
Otherwise, an {\tt )undo} undoes the effect of {\tt )clear} with
options {\tt properties}, {\tt value}, and {\tt mode}, and
that of a previous {\tt undo}.
If any such system commands are given between steps \smath{n} and
\smath{n + 1} (\smath{n > 0}), their effect is undone
for {\tt )undo m} for any \texht{\smath{0 < m \leq n}.}{0 < m <= n}.

The command {\tt )undo} is equivalent to {\tt )undo -1} (it undoes
the effect of the previous user expression).
The command {\tt )undo 0} undoes any of the above system commands
issued since the last user expression.

\begin{verbatim}
)undo n )before
\end{verbatim}
This command returns the state of the interactive
environment to that immediately before step {\tt n}.
Any {\tt )undo} or {\tt )clear} system commands
given before step {\tt n} will not be undone.

\begin{verbatim}
)undo )redo
\end{verbatim}
This command reads the file {\tt redo.input}.
created by the last {\tt )undo} command.
This file consists of all user input lines, excluding those
backtracked over due to a previous {\tt )undo}.

\par\noindent{\bf Also See:}
\downlink{``)history''}{ugSysCmdhistoryPage} in section B.13
The command {\tt )history )write} will eliminate the ``undone'' command
lines of your program.

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugSysCmdwhatPage}{ug16.ht}{)what}
\pageto{notitle}{ugSysCmddisplayPage}
\pageto{notitle}{ugSysCmdsetPage}
\pageto{notitle}{ugSysCmdshowPage}
\begin{chunk}{ug16.ht}
\begin{page}{ugSysCmdwhatPage}{B.28. )what}
\beginscroll


\par\noindent{\bf User Level Required:} interpreter

\par\noindent{\bf Command Syntax:}
\begin{items}
\item{\tt )what categories} {\it pattern1} \lanb{}
{\it pattern2 ...\ranb{}}
\item{\tt )what commands  } {\it pattern1} \lanb{}
{\it pattern2 ...\ranb{}}
\item{\tt )what domains   } {\it pattern1} \lanb{}
{\it pattern2 ...\ranb{}}
\item{\tt )what operations} {\it pattern1} \lanb{}
{\it pattern2 ...\ranb{}}
\item{\tt )what packages  } {\it pattern1} \lanb{}
{\it pattern2 ...\ranb{}}
\item{\tt )what synonym   } {\it pattern1} \lanb{}
{\it pattern2 ...\ranb{}}
\item{\tt )what things    } {\it pattern1} \lanb{}
{\it pattern2 ...\ranb{}}
\item{\tt )apropos        } {\it pattern1} \lanb{}
{\it pattern2 ...\ranb{}}
\end{items}

\par\noindent{\bf Command Description:}

This command is used to display lists of things in the system.  The
patterns are all strings and, if present, restrict the contents of the
lists.  Only those items that contain one or more of the strings as
substrings are displayed.  For example,
\begin{verbatim}
)what synonym
\end{verbatim}
displays all command synonyms,
\begin{verbatim}
)what synonym ver
\end{verbatim}
displays all command synonyms containing the substring ``{\tt ver}'',
\begin{verbatim}
)what synonym ver pr
\end{verbatim}
displays all command synonyms
containing the substring  ``{\tt ver}'' or  the substring
``{\tt pr}''.
Output similar to the following will be displayed
\begin{verbatim}
---------------- System Command Synonyms -----------------

user-defined synonyms satisfying patterns:
      ver pr

  )apr ........................... )what things
  )apropos ....................... )what things
  )prompt ........................ )set message prompt
  )version ....................... )lisp *yearweek*
\end{verbatim}

Several other things can be listed with the {\tt )what} command:

\indent{0}
\beginitems
\item[{\tt categories}] displays a list of category constructors.
\item[{\tt commands}]  displays a list of  system commands available  
at your user-level.
Your user-level
is set via the  {\tt )set userlevel} command.
To get a description of a particular command, such as ``{\tt )what}'', 
issue {\tt )help what}.
\item[{\tt domains}]   displays a list of domain constructors.
\item[{\tt operations}] displays a list of operations in  the system 
library. It  is recommended that you  qualify this command with one or
more patterns, as there are thousands of operations available.  For
example, say you are looking for functions that involve computation of
eigenvalues.  To find their names, try {\tt )what operations eig}.
A rather large list of operations  is loaded into the workspace when
this command  is first issued.  This  list will be deleted  when you
clear the workspace  via {\tt )clear all} or {\tt )clear completely}.
It will be re-created if it is needed again.
\item[{\tt packages}]  displays a list of package constructors.
\item[{\tt synonym}]  lists system command synonyms.
\item[{\tt things}]    displays all  of the  above types for  items 
containing the pattern strings as  substrings.
The command synonym  {\tt )apropos} is equivalent to
{\tt )what things}.
\enditems
\indent{0}

\par\noindent{\bf Also See:}
\downlink{``)display''}{ugSysCmddisplayPage} in section B.8
\downlink{``)set''}{ugSysCmdsetPage} in section B.21
\downlink{``)show''}{ugSysCmdshowPage} in section B.22

\texht{\egroup}{}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\chapter{Users Guide Chapter 21 (ug21.ht)}
\pagetitle{ugAppGraphicsPage}{ug21.ht}{Programs for Axiom Images}
\begin{chunk}{ug21.ht}
\begin{page}{ugAppGraphicsPage}{G. Programs for Axiom Images}
\beginscroll
%
This appendix contains the Axiom programs used to generate
the images in the \Gallery{} color insert of this book.
All these input files are included
with the Axiom system.
To produce the images
on page 6 of the \Gallery{} insert, for example, issue the command:
\begin{verbatim}
)read images6
\end{verbatim}

These images were produced on an IBM RS/6000 model 530 with a
standard color graphics adapter.  The smooth shaded images
were made from X Window System screen dumps.
The remaining images were produced with Axiom-generated
PostScript output.  The images were reproduced from slides made on an Agfa
ChromaScript PostScript interpreter with a Matrix Instruments QCR camera.

\beginmenu
    \menudownlink{{F.1. images1.input}}{ugFimagesOnePage}
    \menudownlink{{F.2. images2.input}}{ugFimagesTwoPage}
    \menudownlink{{F.3. images3.input}}{ugFimagesThreePage}
    \menudownlink{{F.4. images5.input}}{ugFimagesFivePage}
    \menudownlink{{F.5. images6.input}}{ugFimagesSixPage}
    \menudownlink{{F.6. images7.input}}{ugFimagesSevenPage}
    \menudownlink{{F.7. images8.input}}{ugFimagesEightPage}
    \menudownlink{{F.8. conformal.input}}{ugFconformalPage}
    \menudownlink{{F.9. tknot.input}}{ugFtknotPage}
    \menudownlink{{F.10. ntube.input}}{ugFntubePage}
    \menudownlink{{F.11. dhtri.input}}{ugFdhtriPage}
    \menudownlink{{F.12. tetra.input}}{ugFtetraPage}
    \menudownlink{{F.13. antoine.input}}{ugFantoinePage}
    \menudownlink{{F.14. scherk.input}}{ugFscherkPage}
\endmenu
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugFimagesOnePage}{ug21.ht}{images1.input}
\begin{chunk}{ug21.ht}
\begin{page}{ugFimagesOnePage}{G.1. images1.input}
\beginscroll

\labelSpace{3pc}

  
\noindent
{\tt 1.\ \ \ )read\ tknot}\newline
{\tt 2.\ \ \ }\newline
{\tt 3.\ \ \ torusKnot(15,17,\ 0.1,\ 6,\ 700)}\newline
  
\noindent

\newpage
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugFimagesTwoPage}{ug21.ht}{images2.input}
\begin{chunk}{ug21.ht}
\begin{page}{ugFimagesTwoPage}{G.2. images2.input}
\beginscroll

These images illustrate how Newton's method converges when computing
the complex cube roots of 2.  Each point in the \smath{(x,y)}-plane
represents the complex number \smath{x + iy,} which is given as a
starting point for Newton's method.  The poles in these images
represent bad starting values.  The flat areas are the regions of
convergence to the three roots.

  
\noindent
{\tt 1.\ \ \ )read\ newton}\newline
{\tt 2.\ \ \ )read\ vectors}\newline
{\tt 3.\ \ \ f\ :=\ newtonStep(x**3\ -\ 2)}\newline
{\tt 4.\ \ \ }\newline
  
\noindent

The function \texht{$f^n$}{f**n} computes $n$ steps of Newton's method.

  
\noindent
{\tt 1.\ \ \ clipValue\ :=\ 4}\newline
{\tt 2.\ \ \ drawComplexVectorField(f**3,\ -3..3,\ -3..3)}\newline
{\tt 3.\ \ \ drawComplex(f**3,\ -3..3,\ -3..3)}\newline
{\tt 4.\ \ \ drawComplex(f**4,\ -3..3,\ -3..3)}\newline
  
\noindent

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugFimagesThreePage}{ug21.ht}{images3.input}
\begin{chunk}{ug21.ht}
\begin{page}{ugFimagesThreePage}{G.3. images3.input}
\beginscroll

  
\noindent
{\tt 1.\ \ \ )r\ tknot}\newline
{\tt 2.\ \ \ for\ i\ in\ 0..4\ repeat\ 
torusKnot(2,\ 2\ +\ i/4,\ 0.5,\ 25,\ 250)}\newline
  
\noindent

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugFimagesFivePage}{ug21.ht}{images5.input}
\begin{chunk}{ug21.ht}
\begin{page}{ugFimagesFivePage}{G.4. images5.input}
\beginscroll

The parameterization of the Etruscan Venus is due to George Frances.

  
\noindent
{\tt 1.\ \ \ venus(a,r,steps)\ ==}\newline
{\tt 2.\ \ \ \ \ surf\ :=\ 
(u:DFLOAT,\ v:DFLOAT):\ Point\ DFLOAT\ +->}\newline
{\tt 3.\ \ \ \ \ \ \ cv\ :=\ cos(v)}\newline
{\tt 4.\ \ \ \ \ \ \ sv\ :=\ sin(v)}\newline
{\tt 5.\ \ \ \ \ \ \ cu\ :=\ cos(u)}\newline
{\tt 6.\ \ \ \ \ \ \ su\ :=\ sin(u)}\newline
{\tt 7.\ \ \ \ \ \ \ x\ :=\ r\ *\ cos(2*u)\ *\ cv\ +\ sv\ *\ cu}\newline
{\tt 8.\ \ \ \ \ \ \ y\ :=\ r\ *\ sin(2*u)\ *\ cv\ -\ sv\ *\ su}\newline
{\tt 9.\ \ \ \ \ \ \ z\ :=\ a\ *\ cv}\newline
{\tt 10.\ \ \ \ \ \ point\ [x,y,z]}\newline
{\tt 11.\ \ \ \ 
draw(surf,\ 0..\%pi,\ -\%pi..\%pi,\ var1Steps==steps,}\newline
{\tt 12.\ \ \ \ \ \ \ \ \ 
var2Steps==steps,\ title\ ==\ "Etruscan\ Venus")}\newline
{\tt 13.\ \ }\newline
{\tt 14.\ \ venus(5/2,\ 13/10,\ 50)}\newline
  
\noindent

The Figure-8 Klein Bottle
parameterization is from
``Differential Geometry and Computer Graphics'' by Thomas Banchoff,
in {\it Perspectives in Mathematics,} Anniversary of Oberwolfasch 1984,
Birkh\"{a}user-Verlag, Basel, pp. 43-60.

  
\noindent
{\tt 1.\ \ \ klein(x,y)\ ==}\newline
{\tt 2.\ \ \ \ \ cx\ :=\ cos(x)}\newline
{\tt 3.\ \ \ \ \ cy\ :=\ cos(y)}\newline
{\tt 4.\ \ \ \ \ sx\ :=\ sin(x)}\newline
{\tt 5.\ \ \ \ \ sy\ :=\ sin(y)}\newline
{\tt 6.\ \ \ \ \ sx2\ :=\ sin(x/2)}\newline
{\tt 7.\ \ \ \ \ cx2\ :=\ cos(x/2)}\newline
{\tt 8.\ \ \ \ \ sq2\ :=\ sqrt(2.0@DFLOAT)}\newline
{\tt 9.\ \ \ \ \ 
point\ [cx\ *\ (cx2\ *\ (sq2\ +\ cy)\ +\ (sx2\ *\ sy\ *\ cy)),\ \_}
\newline
{\tt 10.\ \ \ \ \ \ \ \ \ \ \ 
sx\ *\ (cx2\ *\ (sq2\ +\ cy)\ +\ (sx2\ *\ sy\ *\ cy)),\ \_}\newline
{\tt 11.\ \ \ \ \ \ \ \ \ \ \ 
-sx2\ *\ (sq2\ +\ cy)\ +\ cx2\ *\ sy\ *\ cy]}\newline
{\tt 12.\ \ }\newline
{\tt 13.\ \ draw(klein,\ 0..4*\%pi,\ 0..2*\%pi,\ var1Steps==50,}\newline
{\tt 14.\ \ \ \ \ \ \ 
var2Steps==50,title=="Figure\ Eight\ Klein\ Bottle")}\newline
  
\noindent

The next two images are examples of generalized tubes.

  
\noindent
{\tt 15.\ \ )read\ ntube}\newline
{\tt 16.\ \ rotateBy(p,\ theta)\ ==}\newline
{\tt 17.\ \ \ \ c\ :=\ cos(theta)}\newline
{\tt 18.\ \ \ \ s\ :=\ sin(theta)}\newline
{\tt 19.\ \ \ \ point\ [p.1*c\ -\ p.2*s,\ p.1*s\ +\ p.2*c]}\newline
{\tt 20.\ \ }\newline
{\tt 21.\ \ bcircle\ t\ ==\ }\newline
{\tt 22.\ \ \ \ point\ [3*cos\ t,\ 3*sin\ t,\ 0]}\newline
{\tt 23.\ \ \ }\newline
{\tt 24.\ \ twist(u,\ t)\ ==}\newline
{\tt 25.\ \ \ \ theta\ :=\ 4*t}\newline
{\tt 26.\ \ \ \ p\ :=\ point\ [sin\ u,\ cos(u)/2]}\newline
{\tt 27.\ \ \ \ rotateBy(p,\ theta)}\newline
{\tt 28.\ \ \ }\newline
{\tt 29.\ \ ntubeDrawOpt(bcircle,\ twist,\ 0..2*\%pi,\ 0..2*\%pi,}
\newline
{\tt 30.\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 
var1Steps\ ==\ 70,\ var2Steps\ ==\ 250)}\newline
{\tt 31.\ \ }\newline
{\tt 32.\ \ twist2(u,\ t)\ ==}\newline
{\tt 33.\ \ \ \ theta\ :=\ t}\newline
{\tt 34.\ \ \ \ p\ :=\ point\ [sin\ u,\ cos(u)]}\newline
{\tt 35.\ \ \ \ rotateBy(p,\ theta)}\newline
{\tt 36.\ \ }\newline
{\tt 37.\ \ cf(u,v)\ ==\ sin(21*u)}\newline
{\tt 38.\ \ }\newline
{\tt 39.\ \ ntubeDrawOpt(bcircle,\ twist2,\ 0..2*\%pi,\ 0..2*\%pi,}
\newline
{\tt 40.\ \ \ \ colorFunction\ ==\ cf,\ var1Steps\ ==\ 168,}\newline
{\tt 41.\ \ \ \ var2Steps\ ==\ 126)}\newline
  
\noindent

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugFimagesSixPage}{ug21.ht}{images6.input}
\begin{chunk}{ug21.ht}
\begin{page}{ugFimagesSixPage}{G.5. images6.input}
\beginscroll

\labelSpace{3pc}
  
\noindent
{\tt 1.\ \ \ gam(x,y)\ ==\ }\newline
{\tt 2.\ \ \ \ \ g\ :=\ Gamma\ complex(x,y)}\newline
{\tt 3.\ \ \ \ \ 
point\ [x,y,max(min(real\ g,\ 4),\ -4),\ argument\ g]}\newline
{\tt 4.\ \ \ }\newline
{\tt 5.\ \ \ }\newline
{\tt 6.\ \ \ draw(gam,\ -\%pi..\%pi,\ -\%pi..\%pi,\ }\newline
{\tt 7.\ \ \ \ \ \ \ \ title\ ==\ "Gamma(x\ +\ \%i*y)",\ \_}\newline
{\tt 8.\ \ \ \ \ \ \ \ var1Steps\ ==\ 100,\ var2Steps\ ==\ 100)}\newline
{\tt 9.\ \ \ }\newline
{\tt 10.\ \ b(x,y)\ ==\ Beta(x,y)}\newline
{\tt 11.\ \ }\newline
{\tt 12.\ \ draw(b,\ -3.1..3,\ -3.1\ ..\ 3,\ title\ ==\ "Beta(x,y)")}
\newline
{\tt 13.\ \ }\newline
{\tt 14.\ \ atf(x,y)\ ==\ }\newline
{\tt 15.\ \ \ \ a\ :=\ atan\ complex(x,y)}\newline
{\tt 16.\ \ \ \ point\ [x,y,real\ a,\ argument\ a]}\newline
{\tt 17.\ \ }\newline
{\tt 18.\ \ draw(atf,\ -3.0..\%pi,\ -3.0..\%pi)}\newline
  
\noindent


\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugFimagesSevenPage}{ug21.ht}{images7.input}
\begin{chunk}{ug21.ht}
\begin{page}{ugFimagesSevenPage}{G.6. images7.input}
\beginscroll

First we look at the conformal
map \texht{$z \mapsto z + 1/z$}{z +-> z + 1/z}.
\labelSpace{2pc}
  
\noindent
{\tt 1.\ \ \ )read\ conformal}\newline
{\tt 2.\ \ \ }\newline
{\tt 3.\ \ \ }\newline
{\tt 4.\ \ \ f\ z\ ==\ z}\newline
{\tt 5.\ \ \ }\newline
{\tt 6.\ \ \ conformalDraw(f,\ -2..2,\ -2..2,\ 9,\ 9,\ "cartesian")}
\newline
{\tt 7.\ \ \ }\newline
{\tt 8.\ \ \ f\ z\ ==\ z\ +\ 1/z}\newline
{\tt 9.\ \ \ \ }\newline
{\tt 10.\ \ conformalDraw(f,\ -2..2,\ -2..2,\ 9,\ 9,\ "cartesian")}
\newline
  
\noindent

The map \texht{$z \mapsto -(z+1)/(z-1)$}{z +-> -(z+1)/(z-1)} maps
the unit disk to the right half-plane, as shown
on the Riemann sphere.

  
\noindent
{\tt 1.\ \ \ f\ z\ ==\ z}\newline
{\tt 2.\ \ \ }\newline
{\tt 3.\ \ \ riemannConformalDraw(f,0.1..0.99,0..2*\%pi,7,11,"polar")}
\newline
{\tt 4.\ \ \ }\newline
{\tt 5.\ \ \ f\ z\ ==\ -(z+1)/(z-1)}\newline
{\tt 6.\ \ \ }\newline
{\tt 7.\ \ \ riemannConformalDraw(f,0.1..0.99,0..2*\%pi,7,11,"polar")}
\newline
{\tt 8.\ \ \ }\newline
{\tt 9.\ \ \ riemannSphereDraw(-4..4,\ -4..4,\ 7,\ 7,\ "cartesian")}
\newline
  
\noindent

\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugFimagesEightPage}{ug21.ht}{images8.input}
\begin{chunk}{ug21.ht}
\begin{page}{ugFimagesEightPage}{G.7. images8.input}
\beginscroll

\labelSpace{1pc}
  
\noindent
{\tt 1.\ \ \ )read\ dhtri}\newline
{\tt 2.\ \ \ )read\ tetra}\newline
{\tt 3.\ \ \ drawPyramid\ 4}\newline
{\tt 4.\ \ \ }\newline
{\tt 5.\ \ \ )read\ antoine}\newline
{\tt 6.\ \ \ drawRings\ 2}\newline
{\tt 7.\ \ \ }\newline
{\tt 8.\ \ \ )read\ scherk}\newline
{\tt 9.\ \ \ drawScherk(3,3)}\newline
{\tt 10.\ \ }\newline
{\tt 11.\ \ )read\ ribbonsnew}\newline
{\tt 12.\ \ drawRibbons([x**i\ for\ i\ in\ 1..5],\ x=-1..1,\ y=0..2)}\newline
  
\noindent


%\input{gallery/conformal.htex}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugFconformalPage}{ug21.ht}{conformal.input}
\begin{chunk}{ug21.ht}
\begin{page}{ugFconformalPage}{G.8. conformal.input}
\beginscroll
%
The functions in this section draw conformal maps both on the
plane and on the Riemann sphere.

%-- Compile, don't interpret functions.
%\xmpLine{)set fun comp on}{}
  
\noindent
{\tt 1.\ \ \ C\ :=\ Complex\ DoubleFloat}\newline
{\tt 2.\ \ \ S\ :=\ Segment\ DoubleFloat}\newline
{\tt 3.\ \ \ R3\ :=\ Point\ DFLOAT}\newline
{\tt 4.\ \ \ \ }\newline
  
\noindent

\userfun{conformalDraw}{\it (f, rRange, tRange, rSteps, tSteps,
coord)} draws the image of the coordinate grid under {\it f} in the
complex plane.  The grid may be given in either polar or Cartesian
coordinates.  Argument {\it f} is the function to draw; {\it rRange}
is the range of the radius (in polar) or real (in Cartesian); 
{\it tRange} is the range of \texht{$\theta$}{\theta} (in polar) or
imaginary (in Cartesian); {\it tSteps, rSteps}, are the number of
intervals in the {\it r} and \texht{$\theta$}{\theta} directions; and
{\it coord} is the coordinate system to use (either {\tt "polar"} or
{\tt "cartesian"}).

  
\noindent
{\tt 1.\ \ \ 
conformalDraw:\ (C\ ->\ C,\ S,\ S,\ PI,\ PI,\ String)\ ->\ VIEW3D}\newline
{\tt 2.\ \ \ 
conformalDraw(f,rRange,tRange,rSteps,tSteps,coord)\ ==}\newline
{\tt 3.\ \ \ \ \ transformC\ :=}\newline
{\tt 4.\ \ \ \ \ \ \ coord\ =\ "polar"\ =>\ polar2Complex}\newline
{\tt 5.\ \ \ \ \ \ \ cartesian2Complex}\newline
{\tt 6.\ \ \ \ \ cm\ :=\ makeConformalMap(f,\ transformC)}\newline
{\tt 7.\ \ \ \ \ sp\ :=\ createThreeSpace()}\newline
{\tt 8.\ \ \ \ \ 
adaptGrid(sp,\ cm,\ rRange,\ tRange,\ rSteps,\ tSteps)}\newline
{\tt 9.\ \ \ \ \ makeViewport3D(sp,\ "Conformal\ Map")}\newline
  
\noindent

\userfun{riemannConformalDraw}{\it (f, rRange, tRange, rSteps, tSteps,
coord)} draws the image of the coordinate grid under {\it f} on the
Riemann sphere.  The grid may be given in either polar or Cartesian
coordinates.  Its arguments are the same as those for
\userfun{conformalDraw}.
  
\noindent
{\tt 10.\ \ riemannConformalDraw:(C->C,S,S,PI,PI,String)->VIEW3D}\newline
{\tt 11.\ \ riemannConformalDraw(f,\ rRange,\ tRange,}\newline
{\tt 12.\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 
rSteps,\ tSteps,\ coord)\ ==}\newline
{\tt 13.\ \ \ \ transformC\ :=}\newline
{\tt 14.\ \ \ \ \ \ coord\ =\ "polar"\ =>\ polar2Complex}\newline
{\tt 15.\ \ \ \ \ \ cartesian2Complex}\newline
{\tt 16.\ \ \ \ sp\ :=\ createThreeSpace()}\newline
{\tt 17.\ \ \ \ cm\ :=\ makeRiemannConformalMap(f,\ transformC)}\newline
{\tt 18.\ \ \ \ 
adaptGrid(sp,\ cm,\ rRange,\ tRange,\ rSteps,\ tSteps)}\newline
{\tt 19.\ \ \ \ 
curve(sp,[point\ [0,0,2.0@DFLOAT,0],point\ [0,0,2.0@DFLOAT,0]])}\newline
{\tt 20.\ \ \ \ 
makeViewport3D(sp,"Map\ on\ the\ Riemann\ Sphere")}\newline
{\tt 21.\ \ }\newline
{\tt 22.\ \ 
adaptGrid(sp,\ f,\ uRange,\ vRange,\ \ uSteps,\ vSteps)\ ==}\newline
{\tt 23.\ \ \ \ delU\ :=\ (hi(uRange)\ -\ lo(uRange))/uSteps}\newline
{\tt 24.\ \ \ \ delV\ :=\ (hi(vRange)\ -\ lo(vRange))/vSteps}\newline
{\tt 25.\ \ \ \ uSteps\ :=\ uSteps\ +\ 1;\ vSteps\ :=\ vSteps\ +\ 1}\newline
{\tt 26.\ \ \ \ u\ :=\ lo\ uRange}\newline
{\tt 27.\ \ \ \ for\ i\ in\ 1..uSteps\ repeat}\newline
{\tt 28.\ \ \ \ \ \ c\ :=\ curryLeft(f,u)}\newline
{\tt 29.\ \ \ \ \ \ cf\ :=\ (t:DFLOAT):DFLOAT\ +->\ 0}\newline
{\tt 30.\ \ \ \ \ \ 
makeObject(c,vRange::SEG\ Float,colorFunction==cf,}\newline
{\tt 31.\ \ \ \ \ \ \ \ 
space\ ==\ sp,\ tubeRadius\ ==\ .02,\ tubePoints\ ==\ 6)}\newline
{\tt 32.\ \ \ \ \ \ u\ :=\ u\ +\ delU}\newline
{\tt 33.\ \ \ \ v\ :=\ lo\ vRange}\newline
{\tt 34.\ \ \ \ for\ i\ in\ 1..vSteps\ repeat}\newline
{\tt 35.\ \ \ \ \ \ c\ :=\ curryRight(f,v)}\newline
{\tt 36.\ \ \ \ \ \ cf\ :=\ (t:DFLOAT):DFLOAT\ +->\ 1}\newline
{\tt 37.\ \ \ \ \ \ 
makeObject(c,uRange::SEG\ Float,colorFunction==cf,}\newline
{\tt 38.\ \ \ \ \ \ \ \ 
space\ ==\ sp,\ tubeRadius\ ==\ .02,\ tubePoints\ ==\ 6)}\newline
{\tt 39.\ \ \ \ \ \ v\ :=\ v\ +\ delV}\newline
{\tt 40.\ \ \ \ void()}\newline
{\tt 41.\ \ }\newline
{\tt 42.\ \ riemannTransform(z)\ ==}\newline
{\tt 43.\ \ \ \ r\ :=\ sqrt\ norm\ z}\newline
{\tt 44.\ \ \ \ cosTheta\ :=\ (real\ z)/r}\newline
{\tt 45.\ \ \ \ sinTheta\ :=\ (imag\ z)/r}\newline
{\tt 46.\ \ \ \ cp\ :=\ 4*r/(4+r**2)}\newline
{\tt 47.\ \ \ \ sp\ :=\ sqrt(1-cp*cp)}\newline
{\tt 48.\ \ \ \ if\ r>2\ then\ sp\ :=\ -sp}\newline
{\tt 49.\ \ \ \ point\ [cosTheta*cp,\ sinTheta*cp,\ -sp\ +\ 1]}\newline
{\tt 50.\ \ \ }\newline
{\tt 51.\ \ cartesian2Complex(r:DFLOAT,\ i:DFLOAT):C\ ==}\newline
{\tt 52.\ \ \ \ complex(r,\ i)}\newline
{\tt 53.\ \ }\newline
{\tt 54.\ \ polar2Complex(r:DFLOAT,\ th:DFLOAT):C\ ==\ }\newline
{\tt 55.\ \ \ \ complex(r*cos(th),\ r*sin(th))}\newline
{\tt 56.\ \ }\newline
{\tt 57.\ \ makeConformalMap(f,\ transformC)\ ==}\newline
{\tt 58.\ \ \ \ (u:DFLOAT,v:DFLOAT):R3\ +->\ }\newline
{\tt 59.\ \ \ \ \ \ z\ :=\ f\ transformC(u,\ v)}\newline
{\tt 60.\ \ \ \ \ \ point\ [real\ z,\ imag\ z,\ 0.0@DFLOAT]}\newline
{\tt 61.\ \ \ }\newline
{\tt 62.\ \ makeRiemannConformalMap(f,\ transformC)\ ==}\newline
{\tt 63.\ \ \ \ (u:DFLOAT,\ v:DFLOAT):R3\ +->}\newline
{\tt 64.\ \ \ \ \ \ riemannTransform\ f\ transformC(u,\ v)}\newline
{\tt 65.\ \ }\newline
{\tt 66.\ \ 
riemannSphereDraw:\ (S,\ S,\ PI,\ PI,\ String)\ ->\ VIEW3D}\newline
{\tt 67.\ \ 
riemannSphereDraw(rRange,tRange,rSteps,tSteps,coord)\ ==}\newline
{\tt 68.\ \ \ \ transformC\ :=}\newline
{\tt 69.\ \ \ \ \ \ coord\ =\ "polar"\ =>\ polar2Complex}\newline
{\tt 70.\ \ \ \ \ \ cartesian2Complex}\newline
{\tt 71.\ \ \ \ grid\ :=\ (u:DFLOAT,\ v:DFLOAT):\ R3\ +->\ }\newline
{\tt 72.\ \ \ \ \ \ z1\ :=\ transformC(u,\ v)}\newline
{\tt 73.\ \ \ \ \ \ point\ [real\ z1,\ imag\ z1,\ 0]}\newline
{\tt 74.\ \ \ \ sp\ :=\ createThreeSpace()}\newline
{\tt 75.\ \ \ \ 
adaptGrid(sp,\ grid,\ rRange,\ tRange,\ rSteps,\ tSteps)}\newline
{\tt 76.\ \ \ \ 
connectingLines(sp,grid,rRange,tRange,rSteps,tSteps)}\newline
{\tt 77.\ \ \ \ 
makeObject(riemannSphere,0..2*\%pi,0..\%pi,space==sp)}\newline
{\tt 78.\ \ \ \ f\ :=\ (z:C):C\ +->\ z}\newline
{\tt 79.\ \ \ \ 
cm\ :=\ makeRiemannConformalMap(f,\ transformC)}\newline
{\tt 80.\ \ \ \ 
adaptGrid(sp,\ cm,\ rRange,\ tRange,\ rSteps,\ tSteps)}\newline
{\tt 81.\ \ \ \ makeViewport3D(sp,\ "Riemann\ Sphere")}\newline
{\tt 82.\ \ \ }\newline
{\tt 83.\ \ 
connectingLines(sp,f,uRange,vRange,uSteps,vSteps)\ ==}\newline
{\tt 84.\ \ \ \ delU\ :=\ (hi(uRange)\ -\ lo(uRange))/uSteps}\newline
{\tt 85.\ \ \ \ delV\ :=\ (hi(vRange)\ -\ lo(vRange))/vSteps}\newline
{\tt 86.\ \ \ \ 
uSteps\ :=\ uSteps\ +\ 1;\ vSteps\ :=\ vSteps\ +\ 1}\newline
{\tt 87.\ \ \ \ u\ :=\ lo\ uRange}\newline
{\tt 88.\ \ \ \ for\ i\ in\ 1..uSteps\ repeat}\newline
{\tt 89.\ \ \ \ \ \ v\ :=\ lo\ vRange}\newline
{\tt 90.\ \ \ \ \ \ for\ j\ in\ 1..vSteps\ repeat}\newline
{\tt 91.\ \ \ \ \ \ \ \ p1\ :=\ f(u,v)}\newline
{\tt 92.\ \ \ \ \ \ \ \ 
p2\ :=\ riemannTransform\ complex(p1.1,\ p1.2)}\newline
{\tt 93.\ \ \ \ \ \ \ \ fun\ :=\ lineFromTo(p1,p2)}\newline
{\tt 94.\ \ \ \ \ \ \ \ cf\ :=\ (t:DFLOAT):DFLOAT\ +->\ 3}\newline
{\tt 95.\ \ \ \ \ \ \ \ 
makeObject(fun,\ 0..1,space==sp,tubePoints==4,}\newline
{\tt 96.\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 
tubeRadius==0.01,colorFunction==cf)}\newline
{\tt 97.\ \ \ \ \ \ \ \ v\ :=\ v\ +\ delV}\newline
{\tt 98.\ \ \ \ \ \ u\ :=\ u\ +\ delU}\newline
{\tt 99.\ \ \ \ void()}\newline
{\tt 100.\ \ }\newline
{\tt 101.\ riemannSphere(u,v)\ ==\ }\newline
{\tt 102.\ \ \ sv\ :=\ sin(v)}\newline
{\tt 103.\ \ \ 
0.99@DFLOAT*(point\ [cos(u)*sv,sin(u)*sv,cos(v),0.0@DFLOAT])+}\newline
{\tt 104.\ \ \ \ \ 
point\ [0.0@DFLOAT,\ 0.0@DFLOAT,\ 1.0@DFLOAT,\ 4.0@DFLOAT]}\newline
{\tt 105.\ \ }\newline
{\tt 106.\ lineFromTo(p1,\ p2)\ ==}\newline
{\tt 107.\ \ \ d\ :=\ p2\ -\ p1}\newline
{\tt 108.\ \ \ (t:DFLOAT):Point\ DFLOAT\ +->}\newline
{\tt 109.\ \ \ \ \ p1\ +\ t*d}\newline
  
\noindent

%\input{gallery/tknot.htex}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugFtknotPage}{ug21.ht}{tknot.input}
\begin{chunk}{ug21.ht}
\begin{page}{ugFtknotPage}{G.9. tknot.input}
\beginscroll
%
Create a $(p,q)$ torus-knot with radius $r$ around the curve.
The formula was derived by Larry Lambe.

  
\noindent
{\tt 1.\ \ \ )read\ ntube}\newline
{\tt 2.\ \ \ 
torusKnot:\ (DFLOAT,\ DFLOAT,\ DFLOAT,\ PI,\ PI)\ ->\ VIEW3D}\newline
{\tt 3.\ \ \ torusKnot(p,\ q\ ,r,\ uSteps,\ tSteps)\ ==}\newline
{\tt 4.\ \ \ \ \ knot\ :=\ (t:DFLOAT):Point\ DFLOAT\ +->\ }\newline
{\tt 5.\ \ \ \ \ \ \ fac\ :=\ 4/(2.2@DFLOAT-sin(q*t))}\newline
{\tt 6.\ \ \ \ \ \ \ 
fac\ *\ point\ [cos(p*t),\ sin(p*t),\ cos(q*t)]}\newline
{\tt 7.\ \ \ \ \ 
circle\ :=\ (u:DFLOAT,\ t:DFLOAT):\ Point\ DFLOAT\ +->}\newline
{\tt 8.\ \ \ \ \ \ \ r\ *\ point\ [cos\ u,\ sin\ u]}\newline
{\tt 9.\ \ \ \ \ 
ntubeDrawOpt(knot,\ circle,\ 0..2*\%pi,\ 0..2*\%pi,}\newline
{\tt 10.\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 
var1Steps\ ==\ uSteps,\ var2Steps\ ==\ tSteps)}\newline
{\tt 11.\ \ }\newline
  
\noindent

%\input{gallery/ntube.htex}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugFntubePage}{ug21.ht}{ntube.input}
\pageto{notitle}{ugFimagesFivePage}
\begin{chunk}{ug21.ht}
\begin{page}{ugFntubePage}{G.10. ntube.input}
\beginscroll

The functions in this file create generalized tubes (also known as
generalized cylinders).  These functions draw a 2-d curve in the
normal planes around a 3-d curve.

  
\noindent
{\tt 1.\ \ \ R3\ :=\ Point\ DFLOAT}\newline
{\tt 2.\ \ \ R2\ :=\ Point\ DFLOAT}\newline
{\tt 3.\ \ \ S\ :=\ Segment\ Float}\newline
{\tt 4.\ \ \ }\newline
{\tt 5.\ \ \ ThreeCurve\ :=\ DFLOAT\ ->\ R3}\newline
{\tt 6.\ \ \ TwoCurve\ :=\ (DFLOAT,\ DFLOAT)\ ->\ R2}\newline
{\tt 7.\ \ \ Surface\ :=\ (DFLOAT,\ DFLOAT)\ ->\ R3}\newline
{\tt 8.\ \ \ }\newline
{\tt 9.\ \ \ FrenetFrame\ :=\ }\newline
{\tt 10.\ \ \ \ \ 
Record(value:R3,tangent:R3,normal:R3,binormal:R3)}\newline
{\tt 11.\ \ frame:\ FrenetFrame}\newline
{\tt 12.\ \ }\newline
  
\noindent

\userfun{ntubeDraw}{\it (spaceCurve, planeCurve,} 
$u_0 .. u_1,$ $t_0 .. t_1)$ draws 
{\it planeCurve} in the normal planes of {\it
spaceCurve.}  The parameter $u_0 .. u_1$ specifies the parameter range
for {\it planeCurve} and $t_0 .. t_1$ specifies the parameter range
for {\it spaceCurve}.  Additionally, the plane curve function takes a
second parameter: the current parameter of {\it spaceCurve}.  This
allows the plane curve to change shape as it goes around the space
curve.

  
\noindent
{\tt 1.\ \ \ 
ntubeDraw:\ (ThreeCurve,TwoCurve,S,S)\ ->\ VIEW3D}\newline
{\tt 2.\ \ \ 
ntubeDraw(spaceCurve,planeCurve,uRange,tRange)\ ==}\newline
{\tt 3.\ \ \ \ \ 
ntubeDrawOpt(spaceCurve,\ planeCurve,\ uRange,\ \_}\newline
{\tt 4.\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 
tRange,\ []\$List\ DROPT)}\newline
{\tt 5.\ \ \ \ }\newline
{\tt 6.\ \ \ 
ntubeDrawOpt:\ (ThreeCurve,TwoCurve,S,S,List\ DROPT)}\newline
{\tt 7.\ \ \ \ \ \ \ ->\ VIEW3D}\newline
{\tt 8.\ \ \ 
ntubeDrawOpt(spaceCurve,planeCurve,uRange,tRange,l)\ ==}\newline
{\tt 9.\ \ \ \ \ \ \ \ \ \ \ \ \ }\newline
{\tt 10.\ \ \ \ 
delT:DFLOAT\ :=\ (hi(tRange)\ -\ lo(tRange))/10000}\newline
{\tt 11.\ \ \ \ oldT:DFLOAT\ :=\ lo(tRange)\ -\ 1}\newline
{\tt 12.\ \ \ \ 
fun\ :=\ ngeneralTube(spaceCurve,planeCurve,delT,oldT)}\newline
{\tt 13.\ \ \ \ draw(fun,\ uRange,\ tRange,\ l)}\newline
{\tt 14.\ \ }\newline
  
\noindent

\userfun{nfrenetFrame}{\it (c, t, delT)}
numerically computes the Frenet frame
about the curve {\it c} at {\it t}.
Parameter {\it delT} is a small number used to
compute derivatives.
  
\noindent
{\tt 15.\ \ nfrenetFrame(c,\ t,\ delT)\ ==}\newline
{\tt 16.\ \ \ \ f0\ :=\ c(t)}\newline
{\tt 17.\ \ \ \ f1\ :=\ c(t+delT)}\newline
{\tt 18.\ \ \ \ t0\ :=\ f1\ -\ f0}\newline
{\tt 19.\ \ \ \ 
n0\ :=\ f1\ +\ f0\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ }\newline
{\tt 20.\ \ \ \ b\ :=\ cross(t0,\ n0)}\newline
{\tt 21.\ \ \ \ n\ :=\ cross(b,t0)}\newline
{\tt 22.\ \ \ \ ln\ :=\ length\ n}\newline
{\tt 23.\ \ \ \ lb\ :=\ length\ b}\newline
{\tt 24.\ \ \ \ ln\ =\ 0\ or\ lb\ =\ 0\ =>}\newline
{\tt 25.\ \ \ \ \ \ \ \ 
error\ "Frenet\ Frame\ not\ well\ defined"}\newline
{\tt 26.\ \ \ \ n\ :=\ (1/ln)*n}\newline
{\tt 27.\ \ \ \ b\ :=\ (1/lb)*b}\newline
{\tt 28.\ \ \ \ [f0,\ t0,\ n,\ b]\$FrenetFrame}\newline
  
\noindent

\userfun{ngeneralTube}{\it (spaceCurve, planeCurve,}{\it  delT, oltT)}
creates a function that can be passed to the system axiomFun{draw} command.
The function is a parameterized surface for the general tube
around {\it spaceCurve}.  {\it delT} is a small number used to compute
derivatives. {\it oldT} is used to hold the current value of the
{\it t} parameter for {\it spaceCurve.}  This is an efficiency measure
to ensure that frames are only computed once for each value of {\it t}.
  
\noindent
{\tt 29.\ \ 
ngeneralTube:\ (ThreeCurve,\ TwoCurve,\ DFLOAT,\ DFLOAT)\ ->\ Surface}
\newline
{\tt 30.\ \ 
ngeneralTube(spaceCurve,\ planeCurve,\ delT,\ oldT)\ ==}\newline
{\tt 31.\ \ \ \ free\ frame}\newline
{\tt 32.\ \ \ \ (v:DFLOAT,\ t:\ DFLOAT):\ R3\ +->}\newline
{\tt 33.\ \ \ \ \ \ if\ (t\ \texht{$\sim$}{~}=\ oldT)\ then}\newline
{\tt 34.\ \ \ \ \ \ \ \ 
frame\ :=\ nfrenetFrame(spaceCurve,\ t,\ delT)}\newline
{\tt 35.\ \ \ \ \ \ \ \ oldT\ :=\ t}\newline
{\tt 36.\ \ \ \ \ \ p\ :=\ planeCurve(v,\ t)}\newline
{\tt 37.\ \ \ \ \ \ frame.value\ +\ p.1*frame.normal\ +\ p.2*frame.binormal}\newline
  
\noindent

%\input{gallery/dhtri.htex}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugFdhtriPage}{ug21.ht}{dhtri.input}
\begin{chunk}{ug21.ht}
\begin{page}{ugFdhtriPage}{G.11. dhtri.input}
\beginscroll
%
Create affine transformations (DH matrices) that transform
a given triangle into another.

  
\noindent
{\tt 1.\ \ \ tri2tri:\ (List\ Point\ DFLOAT,
\ List\ Point\ DFLOAT)\ ->\ DHMATRIX(DFLOAT)}\newline
{\tt 2.\ \ \ tri2tri(t1,\ t2)\ ==}\newline
{\tt 3.\ \ \ \ \ n1\ :=\ triangleNormal(t1)}\newline
{\tt 4.\ \ \ \ \ n2\ :=\ triangleNormal(t2)}\newline
{\tt 5.\ \ \ \ \ tet2tet(concat(t1,\ n1),\ concat(t2,\ n2))}\newline
{\tt 6.\ \ \ \ }\newline
{\tt 7.\ \ \ tet2tet:\ (List\ Point\ DFLOAT,
\ List\ Point\ DFLOAT)\ ->\ DHMATRIX(DFLOAT)}\newline
{\tt 8.\ \ \ tet2tet(t1,\ t2)\ ==}\newline
{\tt 9.\ \ \ \ \ m1\ :=\ makeColumnMatrix\ t1}\newline
{\tt 10.\ \ \ \ m2\ :=\ makeColumnMatrix\ t2}\newline
{\tt 11.\ \ \ \ m2\ *\ inverse(m1)}\newline
{\tt 12.\ \ \ }\newline
{\tt 13.\ \ makeColumnMatrix(t)\ ==}\newline
{\tt 14.\ \ \ \ m\ :=\ new(4,4,0)\$DHMATRIX(DFLOAT)}\newline
{\tt 15.\ \ \ \ for\ x\ in\ t\ for\ i\ in\ 1..repeat}\newline
{\tt 16.\ \ \ \ \ \ for\ j\ in\ 1..3\ repeat}\newline
{\tt 17.\ \ \ \ \ \ \ \ m(j,i)\ :=\ x.j}\newline
{\tt 18.\ \ \ \ \ \ m(4,i)\ :=\ 1}\newline
{\tt 19.\ \ \ \ m}\newline
{\tt 20.\ \ \ }\newline
{\tt 21.\ \ triangleNormal(t)\ ==}\newline
{\tt 22.\ \ \ \ a\ :=\ triangleArea\ t}\newline
{\tt 23.\ \ \ \ p1\ :=\ t.2\ -\ t.1}\newline
{\tt 24.\ \ \ \ p2\ :=\ t.3\ -\ t.2}\newline
{\tt 25.\ \ \ \ c\ :=\ cross(p1,\ p2)}\newline
{\tt 26.\ \ \ \ len\ :=\ length(c)}\newline
{\tt 27.\ \ \ \ len\ =\ 0\ =>\ error\ "degenerate\ triangle!"}\newline
{\tt 28.\ \ \ \ c\ :=\ (1/len)*c}\newline
{\tt 29.\ \ \ \ t.1\ +\ sqrt(a)\ *\ c}\newline
{\tt 30.\ \ \ }\newline
{\tt 31.\ \ triangleArea\ t\ ==}\newline
{\tt 32.\ \ \ \ a\ :=\ length(t.2\ -\ t.1)}\newline
{\tt 33.\ \ \ \ b\ :=\ length(t.3\ -\ t.2)}\newline
{\tt 34.\ \ \ \ c\ :=\ length(t.1\ -\ t.3)}\newline
{\tt 35.\ \ \ \ s\ :=\ (a+b+c)/2}\newline
{\tt 36.\ \ \ \ sqrt(s*(s-a)*(s-b)*(s-c))}\newline
  
\noindent


\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugFtetraPage}{ug21.ht}{tetra.input}
\begin{chunk}{ug21.ht}
\begin{page}{ugFtetraPage}{G.12. tetra.input}
\beginscroll
%
%\input{gallery/tetra.htex}
%\outdent{Sierpinsky's Tetrahedron}

\labelSpace{3pc}

  
\noindent
{\tt 1.\ \ \ )set\ expose\ add\ con\ DenavitHartenbergMatrix}\newline
{\tt 2.\ \ \ }\newline
{\tt 3.\ \ \ x1:DFLOAT\ :=\ sqrt(2.0@DFLOAT/3.0@DFLOAT)}\newline
{\tt 4.\ \ \ x2:DFLOAT\ :=\ sqrt(3.0@DFLOAT)/6}\newline
{\tt 5.\ \ \ }\newline
{\tt 6.\ \ \ p1\ :=\ point\ [-0.5@DFLOAT,\ -x2,\ 0.0@DFLOAT]}\newline
{\tt 7.\ \ \ p2\ :=\ point\ [0.5@DFLOAT,\ -x2,\ 0.0@DFLOAT]}\newline
{\tt 8.\ \ \ p3\ :=\ point\ [0.0@DFLOAT,\ 2*x2,\ 0.0@DFLOAT]}\newline
{\tt 9.\ \ \ p4\ :=\ point\ [0.0@DFLOAT,\ 0.0@DFLOAT,\ x1]}\newline
{\tt 10.\ \ \ }\newline
{\tt 11.\ \ baseTriangle\ \ :=\ [p2,\ p1,\ p3]}\newline
{\tt 12.\ \ }\newline
{\tt 13.\ \ mt\ \ :=\ 
[0.5@DFLOAT*(p2+p1),\ 0.5@DFLOAT*(p1+p3),\ 0.5@DFLOAT*(p3+p2)]}\newline
{\tt 14.\ \ }\newline
{\tt 15.\ \ bt1\ :=\ [mt.1,\ p1,\ mt.2]}\newline
{\tt 16.\ \ bt2\ :=\ [p2,\ mt.1,\ mt.3]}\newline
{\tt 17.\ \ bt3\ :=\ [mt.2,\ p3,\ mt.3]}\newline
{\tt 18.\ \ bt4\ :=\ 
[0.5@DFLOAT*(p2+p4),\ 0.5@DFLOAT*(p1+p4),\ 0.5@DFLOAT*(p3+p4)]}\newline
{\tt 19.\ \ }\newline
{\tt 20.\ \ tt1\ :=\ tri2tri(baseTriangle,\ bt1)}\newline
{\tt 21.\ \ tt2\ :=\ tri2tri(baseTriangle,\ bt2)}\newline
{\tt 22.\ \ tt3\ :=\ tri2tri(baseTriangle,\ bt3)}\newline
{\tt 23.\ \ tt4\ :=\ tri2tri(baseTriangle,\ bt4)}\newline
{\tt 24.\ \ }\newline
{\tt 25.\ \ drawPyramid(n)\ ==}\newline
{\tt 26.\ \ \ \ s\ :=\ createThreeSpace()}\newline
{\tt 27.\ \ \ \ dh\ :=\ rotatex(0.0@DFLOAT)}\newline
{\tt 28.\ \ \ \ drawPyramidInner(s,\ n,\ dh)}\newline
{\tt 29.\ \ \ \ makeViewport3D(s,\ "Sierpinsky\ Tetrahedron")}\newline
{\tt 30.\ \ }\newline
{\tt 31.\ \ drawPyramidInner(s,\ n,\ dh)\ ==}\newline
{\tt 32.\ \ \ \ n\ =\ 0\ =>\ makeTetrahedron(s,\ dh,\ n)}\newline
{\tt 33.\ \ \ \ drawPyramidInner(s,\ n-1,\ dh\ *\ tt1)}\newline
{\tt 34.\ \ \ \ drawPyramidInner(s,\ n-1,\ dh\ *\ tt2)}\newline
{\tt 35.\ \ \ \ drawPyramidInner(s,\ n-1,\ dh\ *\ tt3)}\newline
{\tt 36.\ \ \ \ drawPyramidInner(s,\ n-1,\ dh\ *\ tt4)}\newline
{\tt 37.\ \ }\newline
{\tt 38.\ \ makeTetrahedron(sp,\ dh,\ color)\ ==}\newline
{\tt 39.\ \ \ \ w1\ :=\ dh*p1}\newline
{\tt 40.\ \ \ \ w2\ :=\ dh*p2}\newline
{\tt 41.\ \ \ \ w3\ :=\ dh*p3}\newline
{\tt 42.\ \ \ \ w4\ :=\ dh*p4}\newline
{\tt 43.\ \ \ \ polygon(sp,\ [w1,\ w2,\ w4])}\newline
{\tt 44.\ \ \ \ polygon(sp,\ [w1,\ w3,\ w4])}\newline
{\tt 45.\ \ \ \ polygon(sp,\ [w2,\ w3,\ w4])}\newline
{\tt 46.\ \ \ \ void()}\newline
  
\noindent


%\input{gallery/antoine.htex}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugFantoinePage}{ug21.ht}{antoine.input}
\begin{chunk}{ug21.ht}
\begin{page}{ugFantoinePage}{G.13. antoine.input}
\beginscroll
%
Draw Antoine's Necklace.
Thank you to Matthew Grayson at IBM's T.J Watson Research Center for the idea.

  
\noindent
{\tt 1.\ \ \ )set\ expose\ add\ con\ DenavitHartenbergMatrix}\newline
{\tt 2.\ \ \ }\newline
{\tt 3.\ \ \ torusRot:\ DHMATRIX(DFLOAT)}\newline
{\tt 4.\ \ \ }\newline
{\tt 5.\ \ \ }\newline
{\tt 6.\ \ \ drawRings(n)\ ==}\newline
{\tt 7.\ \ \ \ \ s\ :=\ createThreeSpace()}\newline
{\tt 8.\ \ \ \ \ dh:DHMATRIX(DFLOAT)\ :=\ identity()}\newline
{\tt 9.\ \ \ \ \ drawRingsInner(s,\ n,\ dh)}\newline
{\tt 10.\ \ \ \ makeViewport3D(s,\ "Antoine's\ Necklace")}\newline
{\tt 11.\ \ }\newline
  
\noindent

In order to draw Antoine rings, we take one ring, scale it down to a
smaller size, rotate it around its central axis, translate it to the
edge of the larger ring and rotate it around the edge to a point
corresponding to its count (there are 10 positions around the edge of
the larger ring). For each of these new rings we recursively perform
the operations, each ring becoming 10 smaller rings. Notice how the
\axiomType{DHMATRIX} operations are used to build up the proper matrix
composing all these transformations.

  
\noindent
{\tt 1.\ \ \ drawRingsInner(s,\ n,\ dh)\ ==}\newline
{\tt 2.\ \ \ \ \ n\ =\ 0\ =>}\newline
{\tt 3.\ \ \ \ \ \ \ drawRing(s,\ dh)}\newline
{\tt 4.\ \ \ \ \ \ \ void()}\newline
{\tt 5.\ \ \ \ \ t\ :=\ 0.0@DFLOAT}\newline
{\tt 6.\ \ \ \ \ p\ :=\ 0.0@DFLOAT}\newline
{\tt 7.\ \ \ \ \ tr\ :=\ 1.0@DFLOAT}\newline
{\tt 8.\ \ \ \ \ inc\ :=\ 0.1@DFLOAT}\newline
{\tt 9.\ \ \ \ \ for\ i\ in\ 1..10\ repeat}\newline
{\tt 10.\ \ \ \ \ \ tr\ :=\ tr\ +\ inc}\newline
{\tt 11.\ \ \ \ \ \ inc\ :=\ -inc}\newline
{\tt 12.\ \ \ \ \ \ 
dh'\ :=\ dh*rotatez(t)*translate(tr,0.0@DFLOAT,0.0@DFLOAT)*}\newline
{\tt 13.\ \ \ \ \ \ \ \ \ \ \ \ \ 
rotatey(p)*scale(0.35@DFLOAT,\ 0.48@DFLOAT,\ 0.4@DFLOAT)}\newline
{\tt 14.\ \ \ \ \ \ drawRingsInner(s,\ n-1,\ dh')}\newline
{\tt 15.\ \ \ \ \ \ t\ :=\ t\ +\ 36.0@DFLOAT}\newline
{\tt 16.\ \ \ \ \ \ p\ :=\ p\ +\ 90.0@DFLOAT}\newline
{\tt 17.\ \ \ \ void()}\newline
{\tt 18.\ \ }\newline
{\tt 19.\ \ drawRing(s,\ dh)\ ==}\newline
{\tt 20.\ \ \ \ free\ torusRot}\newline
{\tt 21.\ \ \ \ torusRot\ :=\ dh}\newline
{\tt 22.\ \ \ \ 
makeObject(torus,\ 0..2*\%pi,\ 0..2*\%pi,\ var1Steps\ ==\ 6,}\newline
{\tt 23.\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 
space\ ==\ s,\ var2Steps\ ==\ 15)}\newline
{\tt 24.\ \ }\newline
{\tt 25.\ \ torus(u\ ,v)\ ==}\newline
{\tt 26.\ \ \ \ cu\ :=\ cos(u)/6}\newline
{\tt 27.\ \ \ \ 
torusRot*point\ [(1+cu)*cos(v),(1+cu)*sin(v),(sin\ u)/6]}\newline
  
\noindent

%\input{gallery/scherk.htex}
\endscroll
\autobuttons
\end{page}

\end{chunk}
\pagetitle{ugFscherkPage}{ug21.ht}{scherk.input}
\begin{chunk}{ug21.ht}
\begin{page}{ugFscherkPage}{G.14. scherk.input}
\beginscroll
%

Scherk's minimal surface, defined by:
\texht{$e^z \cos(x) = \cos(y)$}{\axiom{exp(z) * cos(x) = cos(y)}}.
See: {\it A Comprehensive Introduction to Differential Geometry,} Vol. 3,
by Michael Spivak, Publish Or Perish, Berkeley, 1979, pp. 249-252.

  
\noindent
{\tt 1.\ \ \ (xOffset,\ yOffset):DFLOAT}\newline
{\tt 2.\ \ \ \ }\newline
{\tt 3.\ \ \ }\newline
{\tt 4.\ \ \ drawScherk(m,n)\ ==}\newline
{\tt 5.\ \ \ \ \ free\ xOffset,\ yOffset}\newline
{\tt 6.\ \ \ \ \ space\ :=\ createThreeSpace()}\newline
{\tt 7.\ \ \ \ \ for\ i\ in\ 0..m-1\ repeat}\newline
{\tt 8.\ \ \ \ \ \ \ xOffset\ :=\ i*\%pi}\newline
{\tt 9.\ \ \ \ \ \ \ for\ j\ in\ 0\ ..\ n-1\ repeat}\newline
{\tt 10.\ \ \ \ \ \ \ \ rem(i+j,\ 2)\ =\ 0\ =>\ 'iter}\newline
{\tt 11.\ \ \ \ \ \ \ \ yOffset\ :=\ j*\%pi}\newline
{\tt 12.\ \ \ \ \ \ \ \ drawOneScherk(space)}\newline
{\tt 13.\ \ \ \ 
makeViewport3D(space,\ "Scherk's\ Minimal\ Surface")}\newline
{\tt 14.\ \ }\newline
{\tt 15.\ \ scherk1(u,v)\ ==}\newline
{\tt 16.\ \ \ \ x\ :=\ cos(u)/exp(v)}\newline
{\tt 17.\ \ \ \ 
point\ [xOffset\ +\ acos(x),\ yOffset\ +\ u,\ v,\ abs(v)]}\newline
{\tt 18.\ \ \ }\newline
{\tt 19.\ \ scherk2(u,v)\ ==}\newline
{\tt 20.\ \ \ \ x\ :=\ cos(u)/exp(v)}\newline
{\tt 21.\ \ \ \ 
point\ [xOffset\ -\ acos(x),\ yOffset\ +\ u,\ v,\ abs(v)]}\newline
{\tt 22.\ \ \ }\newline
{\tt 23.\ \ scherk3(u,v)\ ==\ }\newline
{\tt 24.\ \ \ \ x\ :=\ exp(v)\ *\ cos(u)}\newline
{\tt 25.\ \ \ \ 
point\ [xOffset\ +\ u,\ yOffset\ +\ acos(x),\ v,\ abs(v)]}\newline
{\tt 26.\ \ \ }\newline
{\tt 27.\ \ scherk4(u,v)\ ==\ }\newline
{\tt 28.\ \ \ \ x\ :=\ exp(v)\ *\ cos(u)}\newline
{\tt 29.\ \ \ \ 
point\ [xOffset\ +\ u,\ yOffset\ -\ acos(x),\ v,\ abs(v)]}\newline
{\tt 30.\ \ \ }\newline
{\tt 31.\ \ drawOneScherk(s)\ ==}\newline
{\tt 32.\ \ \ \ 
makeObject(scherk1,-\%pi/2..\%pi/2,0..\%pi/2,space==s,}\newline
{\tt 33.\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 
var1Steps\ ==\ 28,\ var2Steps\ ==\ 28)}\newline
{\tt 34.\ \ \ \ 
makeObject(scherk2,-\%pi/2..\%pi/2,0..\%pi/2,space==s,}\newline
{\tt 35.\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 
var1Steps\ ==\ 28,\ var2Steps\ ==\ 28)}\newline
{\tt 36.\ \ \ \ 
makeObject(scherk3,-\%pi/2..\%pi/2,-\%pi/2..0,space==s,}\newline
{\tt 37.\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 
var1Steps\ ==\ 28,\ var2Steps\ ==\ 28)}\newline
{\tt 38.\ \ \ \ 
makeObject(scherk4,-\%pi/2..\%pi/2,-\%pi/2..0,space==s,}\newline
{\tt 39.\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 
var1Steps\ ==\ 28,\ var2Steps\ ==\ 28)}\newline
{\tt 40.\ \ \ \ void()}\newline
  
\noindent
\endscroll
\autobuttons
\end{page}

\end{chunk}
\chapter{Hypertex Language Pages}
\pagetitle{Hyperdoc}{hyperdoc.ht}{Creating Hyperdoc Pages}
\pageto{notitle}{ViewportPage}
\pageto{notitle}{BitMaps}
\pageto{notitle}{CPHelp}
\begin{chunk}{hyperdoc.ht}
\begin{page}{Hyperdoc}{Creating Hyperdoc Pages}

\beginscroll
This document tells how to create \HyperName pages.
To start with, it is rather meager but it will grow with time.
\beginmenu
\menulink{Viewports}{ViewportPage} Including live graphics in documents.
\menulink{Gadjets}{BitMaps} Bitmaps for use in macros.
\menulink{Control Panel Bits}{CPHelp} Development page for help 
facility for viewports. yuck.
%\menulink{Test Pages}{TestPage} Some test pages left by J.M.
%\menulink{Paste Pages}{PastePage} Examples of how to use paste in areas.
\endmenu

\endscroll
\autobuttons
\end{page}

\end{chunk}
\section{htxadvpage1.ht}
\pagetitle{HTXAdvPage1}{htxadvpage1.ht}{Input Areas}
\pageto{notitle}{HTXAdvPage2}
\begin{chunk}{htxadvpage1.ht}
\begin{page}{HTXAdvPage1}{Input areas}
\centerline{\fbox{{\tt \thispage}}}\newline
\begin{scroll}

You have probably seen input areas in other Hyperdoc
pages. They provide {\it dynamic link} capabilities.
Instead of having a choice between certain actions,
they allow you to specify an action on--the--fly.
To use them, you need the following commands:
\beginImportant
\newline
{\tt \\inputstring\{{\it label}\}\{{\it length}\}\{{\it default value}\}}
\newline
{\tt \\stringvalue\{{\it label}\}}
\endImportant

The first command puts up an input area of the {\it length}
specified. The {\it default value} is placed in it.
The first argument, {\it label} gives a name to the
contents of the input area.
You can refer to those contents by using
the second command. Never place a {\tt \\stringvalue} command
in an "exposed" part of the page. It is only meant
to be used as an argument to an {\it action}.
Here are some examples.





\beginImportant
\begin{paste}{HTXAdvPage1xPaste1}{HTXAdvPage1xPatch1}
\pastebutton{HTXAdvPage1xPaste1}{Interpret}
\newline
{\tt Page name \\tab\{16\} }
{\tt \\inputstring\{pagetogo\}\{30\}\{RootPage\}}\newline
{\tt \\newline}\newline
{\tt \\downlink\{GO!\}\{\\stringvalue\{pagetogo\}\}}\newline
\end{paste}
\endImportant

\beginImportant
\begin{paste}{HTXAdvPage1xPaste2}{HTXAdvPage1xPatch2}
\pastebutton{HTXAdvPage1xPaste2}{Interpret}
\newline
{\tt File to edit \\tab\{16\}}\newline
{\tt \\inputstring\{filetoedit\}\{30\}\{/etc/passwd\}}\newline
{\tt \\newline}\newline
{\tt \\unixcommand\{Ready!\}\{xterm  -e vi \\stringvalue\{filetoedit\}\}}
\end{paste}
\endImportant


\end{scroll}
\beginmenu
\menulink{Next Page --- Radio boxes}{HTXAdvPage2}
\endmenu

\end{page}

\end{chunk}
\pagetitle{HTXAdvPage1xPatch1}{htxadvpage1.ht}{HTXAdvPage1xPatch1 patch}
\begin{chunk}{htxadvpage1.ht}
\begin{patch}{HTXAdvPage1xPatch1}
\begin{paste}{HTXAdvPage1xPaste1A}{HTXAdvPage1xPatch1A}
\pastebutton{HTXAdvPage1xPaste1A}{Source}
\newline
Page name \tab{16}
\inputstring{pagetogo}{30}{RootPage}
\newline
\downlink{GO!}{\stringvalue{pagetogo}}
\end{paste}
\end{patch}

\end{chunk}
\pagetitle{HTXAdvPage1xPatch1A}{htxadvpage1.ht}{HTXAdvPage1xPatch1A patch}
\begin{chunk}{htxadvpage1.ht}
\begin{patch}{HTXAdvPage1xPatch1A}
\begin{paste}{HTXAdvPage1xPaste1B}{HTXAdvPage1xPatch1}
\pastebutton{HTXAdvPage1xPaste1B}{Interpret}
\newline
{\tt Page name \\tab\{16\} }
{\tt \\inputstring\{pagetogo\}\{30\}\{RootPage\}}\newline
{\tt \\newline}\newline
{\tt \\downlink\{GO!\}\{\\stringvalue\{pagetogo\}\}}\newline
\end{paste}
\end{patch}

\end{chunk}
\pagetitle{HTXAdvPage1xPatch2}{htxadvpage1.ht}{HTXAdvPage1xPatch2 patch}
\begin{chunk}{htxadvpage1.ht}
\begin{patch}{HTXAdvPage1xPatch2}
\begin{paste}{HTXAdvPage1xPaste2A}{HTXAdvPage1xPatch2A}
\pastebutton{HTXAdvPage1xPaste2A}{Source}
\newline
File to edit \tab{16}
\inputstring{filetoedit}{30}{/etc/passwd}
\newline
\unixcommand{Ready!}{xterm  -e vi \stringvalue{filetoedit}}
\end{paste}
\end{patch}

\end{chunk}
\pagetitle{HTXAdvPage1xPatch2A}{htxadvpage1.ht}{HTXAdvPage1xPatch2A patch}
\begin{chunk}{htxadvpage1.ht}
\begin{patch}{HTXAdvPage1xPatch2A}
\begin{paste}{HTXAdvPage1xPaste2B}{HTXAdvPage1xPatch2}
\pastebutton{HTXAdvPage1xPaste2B}{Interpret}
\newline
{\tt File to edit \\tab\{16\}}\newline
{\tt \\inputstring\{filetoedit\}\{30\}\{/etc/passwd\}}\newline
{\tt \\newline}\newline
{\tt \\unixcommand\{Ready!\}\{xterm  -e vi \\stringvalue\{filetoedit\}\}}
\end{paste}
\end{patch}

\end{chunk}
\section{htxadvpage2.ht}
\pagetitle{HTXAdvPage2}{htxadvpage2.ht}{Radio buttons}
\pageto{notitle}{HTXAdvPage3}
\begin{chunk}{htxadvpage2.ht}
\begin{page}{HTXAdvPage2}{Radio buttons}
\centerline{\fbox{{\tt \thispage}}}\newline
\begin{scroll}


If you just want to make a multiple-choice
type selection, why not use the {\it radio buttons}.

You need to use bitmaps for the active areas (the buttons) but
Hyperdoc will keep track of the currently activated button.
You can use this boolean information somewhere else on your page.
The commands to use are:
\beginImportant
\newline
{\tt \\radioboxes\{{\it group name}\}\{{\it bitmap file1}\}
\{{\it bitmap file0}\}}
\newline
{\tt \\radiobox[{\it initial state}]\{{\it label}\}
\{{\it group name}\}}
\newline
{\tt \\boxvalue\{{\it label}\}}
\endImportant

The {\tt \\radioboxes} command sets up a group of {\tt \\radiobox}
buttons. The {\it group name} is a label for the group. The filenames
for the bitmaps are specified in {\it bitmap file1} and 
{\it bitmap file0}.  
The first one should denote an activated button and the
second a de-activated one.

To display each button in a group, use {\tt \\radiobox}.  The 
{\it initial state} should be either {\tt 1} or {\tt 0} depending on
whether the button should first be displayed as activated or not.  The
second {\it label} argument defines the name by which the current
state of the button can be referred to.  The third argument specifies
which group this button belongs to.

The {\tt \\boxvalue} command can then be used in various
actions. The value of it will
be either {\tt t} or {\tt nil}.

In the example below, we use the {\tt \\htbmfile} macro
defined in {\bf util.ht} so that we do not have to write
the full bitmap file pathnames.

This is how we set up the group. The {\tt \\radioboxes} command 
does not display anything.
Note that these commands cannot be included in a {\it patch}.
This is why we display this time the source and the result
at the same time.
\beginImportant
\newline
{\tt \\radioboxes\{group\}
\{\\htbmfile\{pick\}\}\{\\htbmfile\{unpick\}\}}\newline
{\tt \\newline \\table\{}\newline
{\tt \{\\radiobox[1]\{b1\}\{group\}\}}\newline
{\tt \{\\radiobox[0]\{b2\}\{group\}\}}\newline
{\tt \{\\radiobox[0]\{b3\}\{group\}\}\}}\newline
{\tt \\newline}\newline
{\tt \\lispcommand\{lisp\}\{(pprint (list}\newline
{\tt \\boxvalue\{b1\} \\boxvalue\{b2\} \\boxvalue\{b3\}))\}}\newline
{\tt \\newline}\newline
{\tt \\unixcommand\{unix\}\{echo '\\boxvalue\{b1\}}\newline
{\tt \\boxvalue\{b2\} \\boxvalue\{b3\}'\}}
\endImportant
\radioboxes{group}{\htbmfile{pick}}{\htbmfile{unpick}}
\table{
{\radiobox[1]{b1}{group}}
{\radiobox[0]{b2}{group}}
{\radiobox[0]{b3}{group}}}
\newline
\lispcommand{lisp}{(pprint (list
\boxvalue{b1} \boxvalue{b2} \boxvalue{b3}))}
\newline
\unixcommand{unix}{echo '\boxvalue{b1}
\boxvalue{b2} \boxvalue{b3}'}
\endImportant




You can only set one radio button at a time. If you want
a non--exclusive selection, try {\tt \\inputbox}.
The syntax for this command is
\beginImportant
\newline
{\tt \\inputbox[{\it initial state}]
\{{\it label}\}\{{\it bitmap file1}\}\{{\it bitmap file0}\}}
\endImportant

There is no group command for these.
\beginImportant
\newline
{\tt \\table\{}\newline
{\tt \{\\inputbox[1]\{c1\}
\{\\htbmfile\{pick\}\}\{\\htbmfile\{unpick\}\}\}}\newline
{\tt \{\\inputbox\{c2\}
\{\\htbmfile\{pick\}\}\{\\htbmfile\{unpick\}\}\}}\newline
{\tt \{\\inputbox[1]\{c3\}
\{\\htbmfile\{pick\}\}\{\\htbmfile\{unpick\}\}\}\}}\newline
{\tt \\newline}\newline
{\tt \\lispcommand\{lisp\}\{(pprint (list}\newline
{\tt \\boxvalue\{c1\} \\boxvalue\{c2\} \\boxvalue\{c3\}))\}}\newline
{\tt \\newline}\newline
{\tt \\unixcommand\{unix\}\{echo }\newline
{\tt '\\boxvalue\{c1\} \\boxvalue\{c2\} \\boxvalue\{c3\}'\}}\newline
\endImportant
\table{
{\inputbox[1]{c1}{\htbmfile{pick}}{\htbmfile{unpick}}}
{\inputbox{c2}{\htbmfile{pick}}{\htbmfile{unpick}}}
{\inputbox[1]{c3}{\htbmfile{pick}}{\htbmfile{unpick}}}}
\newline
\lispcommand{lisp}{(pprint (list
\boxvalue{c1} \boxvalue{c2} \boxvalue{c3}))}
\newline
\unixcommand{unix}{echo
'\boxvalue{c1} \boxvalue{c2} \boxvalue{c3}'}
\endImportant


Note that the {\it initial state} is an
optional argument. If omitted
the button will initially
be deactivated.

\end{scroll}
\beginmenu
\menulink{Next Page --- Macros}{HTXAdvPage3}
\endmenu

\end{page}

\end{chunk}
\section{htxadvpage3.ht}
\pagetitle{HTXAdvPage3}{htxadvpage3.ht}{Macros}
\pageto{notitle}{HTXAdvPage4}
\begin{chunk}{htxadvpage3.ht}
\begin{page}{HTXAdvPage3}{Macros}
\centerline{\fbox{{\tt \thispage}}}\newline
\begin{scroll}


Sometimes you may find yourself having to
write
almost the same piece of Hyperdoc
text many times. Thankfully, there is a command to ease
the work.
It is the {\tt \\newcommand} command and provides
a macro facility for Hyperdoc.
In this way, you can give a short name to a sequence of Hyperdoc
text and use that name to include the sequence in your pages.
The way this works is the following
\beginImportant
\newline
\centerline{{\tt \\newcommand\{\\{\it name}\}
[{\it number of arguments}]\{{\it Hyperdoc text}\}}}
\endImportant
and here is an example from {\bf util.ht}
\beginImportant
\newline
{\tt \\newcommand\{\\axiomSig\}[2]
\{\\axiomType\{\#1\} \{\\tt ->\} \\axiomType\{\#2\}\}}
\newline
{\tt \\newcommand\{\\axiomType\}[1]
\{\\lispdownlink\{\#1\}\{(|spadType| '|\#1|)\}\}}
\endImportant

You see that a macro's definition can invoke another.
Don't create a circular definition though!
Notice how the arguments of the macro are used
in the definition. The {\tt \#{\it n}} construct
is the place--holder of the {\it n}'th argument.

To use the macro, just treat it as an ordinary command.
For instance
\beginImportant
\newline
{\tt \\axiomSig\{Integer\}\{List Integer\}}
\endImportant
displays and acts like this
\beginImportant
\newline
\axiomSig{Integer}{List Integer}
\endImportant

The best way to familiarise yourself to
macros is to study the macros defined in
\centerline{{\bf util.ht}}
It is highly probable that a good many of them
will prove useful to you.
Clever use of macros will allow you to
create Hyperdoc text that can be
formatted by other programs (such as TeX).
The Axiom User Guide was written
in such a way as to make translation in
Hyperdoc form and TeX form a mechanical process.

\end{scroll}
\beginmenu
\menulink{Next Page --- Patch and Paste}{HTXAdvPage4}
\endmenu

\end{page}

\end{chunk}
\section{htxadvpage4.ht}
\pagetitle{HTXAdvPage4}{htxadvpage4.ht}{Patch and Paste}
\pageto{notitle}{HTXAdvPage5}
\begin{chunk}{htxadvpage4.ht}
\begin{page}{HTXAdvPage4}{Patch and Paste}
\centerline{\fbox{{\tt \thispage}}}\newline
\begin{scroll}


A powerful Hyperdoc feature is
the ability to {\it replace}
part of a displayed page with another part
when an active area is clicked. The group commands
{\it patch} and {\it paste} offer this facility.
A {\it paste} region can appear anywhere
within a page or a {\it patch}. A {\it patch} region must be defined
outside a page definition.

We need a few  objects to define the {\it paste}
region. These are a {\it name} with which to
refer to it, some way of specifying what it
is to be replaced by and a {\it trigger} for the
replacement. A {\it patch} is how we specify the
second of these objects.
The {\it patch} is generally a sequence of Hyperdoc
text.

If we want to have the option of returning to the original
(or ,indeed, proceeding to a {\it third} alternative)
we clearly must include a {\it paste} in the {\it patch}.

Let us start with a simple example. We wish to
have the word {\tt initial} somewhere on the page replaced by the
word {\tt final} at a click of a button.
Let us first define the {\it patch}. It will just contain
the word {\tt final}. Here is a definition of a
patch called {\tt patch1} (note that
the actual definition must be outside this page's definition).
\beginImportant
\newline
{\tt \\begin\{patch\}\{patch1\}} \newline
{\tt final}\newline
{\tt \\end\{patch\}}
\endImportant
We now define a {\it paste} region exactly where we
want the word {\tt initial} to appear.
\beginImportant
\newline
{\tt \\begin\{paste\}\{paste1\}\{patch1\}}\newline
{\tt initial}\newline
{\tt \\end\{paste\}}
\centerline{{\it results in}}
\begin{paste}{paste1}{patch1}
initial
\end{paste}
\endImportant
We have specified first the name of the {\it paste} region
which is {\tt paste1} and then the name of the
replacement {\it patch} which is {\tt patch1}.
Something is missing -- the trigger.
To include a trigger we write
\beginImportant
\newline
{\tt \\pastebutton\{paste1\}\{trigger\}
\centerline{{\it results in}}
\pastebutton{paste1}{trigger}
\endImportant
This new command {\tt \\pastebutton} displays the second argument
as an active area. The first argument specifies the {\it paste}
region it refers to. Clicking on {\tt trigger} above will
replace the word {\tt initial} with the word {\tt final}.

We can, if we like, include the {\tt \\pastebutton} in the {\it paste}
region.
Let us improve on the situation by providing a way
of going back to the original word {\tt initial} on the page.
The {\it patch} must itself include a {\it paste}.
What will the replacement {\it patch} for this new {\it paste}
be ? Well, we  have to define a second {\it patch}
that contains all the stuff in the original {\it paste}
region. Here is the updated {\it patch} for the first replacement.
The {\tt \\MenuDotBitmap} macro is defined in {\bf util.ht}.
It displays a button bitmap.
This time we put the {\tt \\pastebutton}
inside the {\it paste}.
\beginImportant
\newline
{\tt \\begin\{patch\}\{Patch1\}}\newline
{\tt \\begin\{paste\}\{Paste2\}\{Patch2\}}\newline
{\tt \\pastebutton\{Paste2\}\{\\MenuDotBitmap\}}\newline
{\tt final}\newline
{\tt \\end\{paste\}}\newline
{\tt \\end\{patch\}}\newline
\endImportant
and the new {\tt Patch2} {\it patch}
\beginImportant
\newline
{\tt \\begin\{patch\}\{Patch2\}}\newline
{\tt \\begin\{paste\}\{Paste3\}\{Patch1\}}\newline
{\tt \\pastebutton\{Paste3\}\{\\MenuDotBitmap\}}\newline
{\tt initial}\newline
{\tt \\end\{paste\}}\newline
{\tt \\end\{patch\}}\newline
\endImportant

Remember that these {\it patch} definitons must
occur outside a {\tt \\begin\{page\} - \\end\{page\}} group.
What is left now is to define the starting {\it paste}
region.
\beginImportant
\newline
{\tt \\begin\{paste\}\{Paste1\}\{Patch1\}}\newline
{\tt \\pastebutton\{Paste1\}\{\\MenuDotBitmap\}}\newline
{\tt initial}\newline
{\tt \\end\{paste\}}
\centerline{{\it results in}}
\begin{paste}{Paste1}{Patch1}
\pastebutton{Paste1}{\MenuDotBitmap}
initial
\end{paste}
\endImportant

Clicking on the button above next to {\tt initial}
will replace the {\tt Paste1} region with
{\tt Patch1}. That {\it patch}
also contains a {\it paste} region ({\tt Paste2}).
Clicking on {\it its} button will put up
{\tt Patch2} which has a {\it paste} region ({\tt Paste3}).
Clicking on {\it its} button will put up {\tt Patch1}
again. In that way, we close the chain of replacements.




\end{scroll}
\beginmenu
\menulink{Next Page --- Axiom paste-ins}{HTXAdvPage5}
\endmenu

\end{page}

\end{chunk}
\subsection{patch1 patch}
\label{patch1}
\index{patch!patch1!htxadvpage4.ht}
\index{htxadvpage4.ht!patch!patch1}
\index{patch1!htxadvpage4.ht!patch}
\begin{chunk}{htxadvpage4.ht}
\begin{patch}{patch1}
final
\end{patch}

\end{chunk}
\subsection{Patch1 patch}
\label{Patch1}
\index{patch!Patch1!htxadvpage4.ht}
\index{htxadvpage4.ht!patch!Patch1}
\index{Patch1!htxadvpage4.ht!patch}
\begin{chunk}{htxadvpage4.ht}
\begin{patch}{Patch1}
\begin{paste}{Paste2}{Patch2}
\pastebutton{Paste2}{\MenuDotBitmap}
final
\end{paste}
\end{patch}

\end{chunk}
\subsection{Patch2 patch}
\label{Patch2}
\index{patch!Patch2!htxadvpage4.ht}
\index{htxadvpage4.ht!patch!Patch2}
\index{Patch2!htxadvpage4.ht!patch}
\begin{chunk}{htxadvpage4.ht}
\begin{patch}{Patch2}
\begin{paste}{Paste3}{Patch1}
\pastebutton{Paste3}{\MenuDotBitmap}
initial
\end{paste}
\end{patch}

\end{chunk}
\section{htxadvpage5.ht}
\pagetitle{HTXAdvPage5}{htxadvpage5.ht}{Axiom paste-ins}
\pageto{notitle}{HTXAdvPage6}
\begin{chunk}{htxadvpage5.ht}
\begin{page}{HTXAdvPage5}{Axiom paste-ins}
\centerline{\fbox{{\tt \thispage}}}\newline
\begin{scroll}

The {\it paste} and {\it patch} facility 
(see \downlink{previous page}{HTXAdvPage4})
is used to display (or hide) the Axiom output
of an Axiom command ({\tt\\axiomcommand})
included in a
Hyperdoc page.

A mechanism has been set up to {\it automatically} generate
these paste-ins. It amounts to replacing an
{\tt \\axiomcommand} by a {\tt \\pastecommand} in the
Hyperdoc page.

In the case of a \axiomOp{draw} Axiom command
, where the result is to create an interactive viewport,
the appropriate command to use is {\tt \\pastegraph}.
The effect of this is to include (as the output)
the Axiom generated {\it image} of the graph
as an active area. Clicking on it will put up an
interactive viewport.
The {\tt \\pastegraph} command should be used only when
the result of the associated Axiom operation is
to {\it create} an interactive viewport. It is {\it not} necessarily
appropriate for all commands whose result
is a \axiomType{Two{}Dimensional{}Viewport} or 
\axiomType{Three{}Dimensional{}Viewport}.
The {\tt \\pastecommand} and {\tt \\pastegraph}
are  macros defined in {\bf util.ht}.



There is no automatic paste-in generation facility
for Axiom piles (the {\tt \\begin\{axiomsrc\}} command).


The automatic paste-in generation mechanism works by invoking Axiom
with a particular option.  Hyperdoc is also started automatically. It
reads the {\tt \\pastecommand} and {\tt \\pastegraph} commands in all
pages in a specified {\bf somefile.ht} and passes them to Axiom for
evaluation. Hyperdoc captures the output and writes it out (to a file
called {\bf somefile.pht}) as the body of some {\it patch}
definitions. The commands encountered are written to a file 
{\bf somefile.input} which you can {\tt )read} from an Axiom session.  
It also creates directories for the graphics images encountered. Those
files and directories will be written under the {\it current}
directory.  The idea is that you then include the {\it patch}
definitions in {\bf somefile.pht} in your local database using {\bf
htadd}.


You can try this feature now. Edit a file called, say, {\bf trypaste.ht}
in a directory, say {\bf /tmp}. Put the following Hyperdoc text
in it.
\beginImportant
\newline
{\tt \\begin\{page\}\{TryPaste\}\{Trying out paste-in generation\}}\newline
{\tt \\begin\{scroll\}}\newline
{\tt \\pastecommand\{f z == z**2 \\bound\{f\}\}}\newline
{\tt \\pastegraph\{draw(f,-1..1) \\free\{f\}\}}\newline
{\tt \\pastecommand\{x:= f 3 \\free\{f\}\}}\newline
{\tt \\end\{scroll\}}\newline
{\tt \\end\{page\}}\newline
\endImportant

From the directory that contains the {\bf trypaste.ht},
issue
\centerline{
{\tt htadd -l ./trypaste.ht}
}
You will get the
{\bf ht.db} database file.
Set the environment variable {\tt HTPATH} so that
it points first to your directory and then the system directory.
In the {\bf /bin/csh}, you might use
\centerline{
{\tt setenv HTPATH /tmp:\$AXIOM/doc}
}
Make sure that no {\bf trypaste.input} or {\bf trypaste.pht}
files exist in the directory.
Then issue
\centerline{
{\tt axiom -paste trypaste.ht}
}
 and wait for
Axiom to finish.

There is a modification you will wish to make to
the {\bf trypaste.pht} file.
This is because the generated Hyperdoc text will assume that
the {\it viewport} data will be located in the
{\it system} directory.
\centerline{{\bf \env{AXIOM}/doc/viewports}}
You may want to place your images in a different directory,
say, {\bf /u/sugar/viewports}.
If so, then change all occurences of
\beginImportant
\newline
{\tt \\env\{AXIOM\}/doc/viewports/}
\centerline{{\it by}}
{\tt /u/sugar/viewports/}
\endImportant
in the file {\bf trypaste.pht}. The last step
is to include the {\it patch} definitions
in {\bf trypaste.pht} to your local database.
Issue
\centerline{
{\tt htadd -l ./trypaste.pht}
}
to update the database. If you have provided
a link to your pages from the {\tt RootPage}
via the {\tt \\localinfo} macro, you should now
be able to start Axiom or Hyperdoc
and see the computed Axiom output whenever you
click on the buttons to the left of each command.



\end{scroll}
\beginmenu
\menulink{Next Page --- Miscellaneous}{HTXAdvPage6}
\endmenu

\end{page}

\end{chunk}
\section{htxadvpage6.ht}
\pagetitle{HTXAdvPage6}{htxadvpage6.ht}{Miscellaneous}
\pageto{notitle}{HTXAdvTopPage}
\begin{chunk}{htxadvpage6.ht}
\begin{page}{HTXAdvPage6}{Miscellaneous}
\centerline{\fbox{{\tt \thispage}}}\newline
\begin{scroll}


We present here a few commands that may be of some use
to you.
You may want to know certain parameters so that you can pass
them to one of the action {\tt \\command}s.

The {\tt \\thispage} command shows the name of the
current page.

\beginImportant
\begin{paste}{HTXAdvPage6xPaste1}{HTXAdvPage6xPatch1}
\pastebutton{HTXAdvPage6xPaste1}{Interpret}
\newline
{\tt \\thispage}\newline
{\tt \\newline}\newline
{\tt \\lispcommand\{Lisp\}\{(pprint "\\thispage")\}}\newline
\end{paste}
\endImportant


The {\tt \\windowid} command shows the X Windows
{\it WindowID} of the current window.

\beginImportant
\begin{paste}{HTXAdvPage6xPaste2}{HTXAdvPage6xPatch2}
\pastebutton{HTXAdvPage6xPaste2}{Interpret}
\newline
{\tt \\windowid}\newline
{\tt \\newline}\newline
{\tt \\lispcommand\{Lisp\}\{(pprint \\windowid)\}}\newline
\end{paste}
\endImportant

% \examplenumber not documented

The {\tt \\env} command gets the value of an environment
variable. It is an error to use {\tt \\env} with an undefined
environment variable.

\beginImportant
\begin{paste}{HTXAdvPage6xPaste3}{HTXAdvPage6xPatch3}
\pastebutton{HTXAdvPage6xPaste3}{Interpret}
\newline
{\tt \\env\{AXIOM\}}
\end{paste}
\endImportant


The {\tt \\nolines} command, if included somewhere
in the page, eliminates the horizontal lines that
delimit the header and footer regions.


% \beep not documented

%\returnbutton{homebutton}{ReturnPage}

%\upbutton{upbutton}{UpPage}


\end{scroll}
\beginmenu
\menulink{Back to Menu}{HTXAdvTopPage}
\endmenu

\end{page}

\end{chunk}
\subsection{HTXAdvPage6xPatch1 patch}
\label{HTXAdvPage6xPatch1}
\index{patch!HTXAdvPage6xPatch1!htxadvpage6.ht}
\index{htxadvpage6.ht!patch!HTXAdvPage6xPatch1}
\index{HTXAdvPage6xPatch1!htxadvpage6.ht!patch}
\begin{chunk}{htxadvpage6.ht}
\begin{patch}{HTXAdvPage6xPatch1}
\begin{paste}{HTXAdvPage6xPaste1A}{HTXAdvPage6xPatch1A}
\pastebutton{HTXAdvPage6xPaste1A}{Source}
\newline
\thispage
\newline
\lispcommand{Lisp}{(pprint "\thispage")}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXAdvPage6xPatch1A patch}
\label{HTXAdvPage6xPatch1A}
\index{patch!HTXAdvPage6xPatch1A!htxadvpage6.ht}
\index{htxadvpage6.ht!patch!HTXAdvPage6xPatch1A}
\index{HTXAdvPage6xPatch1A!htxadvpage6.ht!patch}
\begin{chunk}{htxadvpage6.ht}
\begin{patch}{HTXAdvPage6xPatch1A}
\begin{paste}{HTXAdvPage6xPaste1B}{HTXAdvPage6xPatch1}
\pastebutton{HTXAdvPage6xPaste1B}{Interpret}
\newline
{\tt \\thispage}\newline
{\tt \\newline}\newline
{\tt \\lispcommand\{Lisp\}\{(pprint "\\thispage")\}}\newline
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXAdvPage6xPatch2 patch}
\label{HTXAdvPage6xPatch2}
\index{patch!HTXAdvPage6xPatch2!htxadvpage6.ht}
\index{htxadvpage6.ht!patch!HTXAdvPage6xPatch2}
\index{HTXAdvPage6xPatch2!htxadvpage6.ht!patch}
\begin{chunk}{htxadvpage6.ht}
\begin{patch}{HTXAdvPage6xPatch2}
\begin{paste}{HTXAdvPage6xPaste2A}{HTXAdvPage6xPatch2A}
\pastebutton{HTXAdvPage6xPaste2A}{Source}
\newline
\windowid
\newline
\lispcommand{Lisp}{(pprint \windowid)}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXAdvPage6xPatch2A patch}
\label{HTXAdvPage6xPatch2A}
\index{patch!HTXAdvPage6xPatch2A!htxadvpage6.ht}
\index{htxadvpage6.ht!patch!HTXAdvPage6xPatch2A}
\index{HTXAdvPage6xPatch2A!htxadvpage6.ht!patch}
\begin{chunk}{htxadvpage6.ht}
\begin{patch}{HTXAdvPage6xPatch2A}
\begin{paste}{HTXAdvPage6xPaste2B}{HTXAdvPage6xPatch2}
\pastebutton{HTXAdvPage6xPaste2B}{Interpret}
\newline
{\tt \\windowid}\newline
{\tt \\newline}\newline
{\tt \\lispcommand\{Lisp\}\{(pprint \\windowid)\}}\newline
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXAdvPage6xPatch3 patch}
\label{HTXAdvPage6xPatch3}
\index{patch!HTXAdvPage6xPatch3!htxadvpage6.ht}
\index{htxadvpage6.ht!patch!HTXAdvPage6xPatch3}
\index{HTXAdvPage6xPatch3!htxadvpage6.ht!patch}
\begin{chunk}{htxadvpage6.ht}
\begin{patch}{HTXAdvPage6xPatch3}
\begin{paste}{HTXAdvPage6xPaste3A}{HTXAdvPage6xPatch3A}
\pastebutton{HTXAdvPage6xPaste3A}{Source}
\newline
\env{AXIOM}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXAdvPage6xPatch3A patch}
\label{HTXAdvPage6xPatch3A}
\index{patch!HTXAdvPage6xPatch3A!htxadvpage6.ht}
\index{htxadvpage6.ht!patch!HTXAdvPage6xPatch3A}
\index{HTXAdvPage6xPatch3A!htxadvpage6.ht!patch}
\begin{chunk}{htxadvpage6.ht}
\begin{patch}{HTXAdvPage6xPatch3A}
\begin{paste}{HTXAdvPage6xPaste3B}{HTXAdvPage6xPatch3}
\pastebutton{HTXAdvPage6xPaste3B}{Interpret}
\newline
{\tt \\env\{AXIOM\}}\newline
\end{paste}
\end{patch}

\end{chunk}
\section{htxadvtoppage.ht}
\pagetitle{HTXAdvTopPage}{htxadvtoppage.ht}{Advanced features in Hyperdoc}
\pageto{notitle}{HTXAdvPage1}
\pageto{notitle}{HTXAdvPage2}
\pageto{notitle}{HTXAdvPage3}
\pageto{notitle}{HTXAdvPage4}
\pageto{notitle}{HTXAdvPage5}
\pageto{notitle}{HTXAdvPage6}
\begin{chunk}{htxadvtoppage.ht}
\begin{page}{HTXAdvTopPage}{Advanced features in Hyperdoc}
\centerline{\fbox{{\tt \thispage}}}\newline
\beginscroll
\beginmenu
\menudownlink{Creating input areas}{HTXAdvPage1}
\menudownlink{Creating radio boxes}{HTXAdvPage2}
\menudownlink{Define new macros     }{HTXAdvPage3}
\menudownlink{Using patch and paste}{HTXAdvPage4}
\menudownlink{Generate paste-ins for Axiom commands}{HTXAdvPage5}
\menudownlink{Miscellaneous}{HTXAdvPage6}
\endmenu
\endscroll
\end{page}

\end{chunk}
\section{htxformatpage1.ht}
\pagetitle{HTXFormatPage1}{htxformatpage1.ht}{Using the special characters}
\pageto{notitle}{HTXFormatPage2}
\begin{chunk}{htxformatpage1.ht}
\begin{page}{HTXFormatPage1}{Using the special characters}
\centerline{\fbox{{\tt \thispage}}}\newline
\begin{scroll}

You can display the special characters ({\tt \$ \\ \{ \{ \[ \] \% \#})
by simply inserting the backslash {\tt \\} character just before any 
one of them. So,
\beginImportant
\begin{paste}{HTXFormatPage1xPaste1}{HTXFormatPage1xPatch1}
\pastebutton{HTXFormatPage1xPaste1}{Interpret}
\newline
{\tt the characters \\\$, \\\\, \\\{, \\\}, \\\[, \\\], \\\%, \\\# }
\end{paste}
\endImportant


The {\tt \%} character is used in Hyperdoc as a comment marker.
If it is encountered on any line (without being preceded by the {\tt \\}
 character,
of course), Hyperdoc will ignore all remaining characters on that line.
\beginImportant
\begin{paste}{HTXFormatPage1xPaste2}{HTXFormatPage1xPatch2}
\pastebutton{HTXFormatPage1xPaste2}{Interpret}
\newline
{\tt  the latest figures indicate \% GET THE LATEST FIGURES}\newline
{\tt a steady rise}\indent{0}
\end{paste}
\endImportant

Earlier versions of Hyperdoc merged the words "indicate" and "a"
into one word in the example above. This no longer occurs.

\end{scroll}
\beginmenu
\menulink{Next -- Formatting without commands}{HTXFormatPage2}
\endmenu

\end{page}

\end{chunk}
\subsection{HTXFormatPage1xPatch1 patch}
\label{HTXFormatPage1xPatch1}
\index{patch!HTXFormatPage1xPatch1!htxformatpage1.ht}
\index{htxformatpage1.ht!patch!HTXFormatPage1xPatch1}
\index{HTXFormatPage1xPatch1!htxformatpage1.ht!patch}
\begin{chunk}{htxformatpage1.ht}
\begin{patch}{HTXFormatPage1xPatch1}
\begin{paste}{HTXFormatPage1xPaste1A}{HTXFormatPage1xPatch1A}
\pastebutton{HTXFormatPage1xPaste1A}{Source}
\newline
the characters \$, \\, \{, \}, \[, \],  \%, \#
\end{paste}
\end{patch}
\begin{patch}{HTXFormatPage1xPatch1A}
\begin{paste}{HTXFormatPage1xPaste1B}{HTXFormatPage1xPatch1}
\pastebutton{HTXFormatPage1xPaste1B}{Interpret}
\newline
{\tt the characters \\\$, \\\\, \\\{, \\\}, \\\[, \\\], \\\%, \\\# }
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage1xPatch2 patch}
\label{HTXFormatPage1xPatch2}
\index{patch!HTXFormatPage1xPatch2!htxformatpage1.ht}
\index{htxformatpage1.ht!patch!HTXFormatPage1xPatch2}
\index{HTXFormatPage1xPatch2!htxformatpage1.ht!patch}
\begin{chunk}{htxformatpage1.ht}
\begin{patch}{HTXFormatPage1xPatch2}
\begin{paste}{HTXFormatPage1xPaste2A}{HTXFormatPage1xPatch2A}
\pastebutton{HTXFormatPage1xPaste2A}{Source}
\newline
the latest figures indicate % GET THE LATEST FIGURES
a steady rise
\end{paste}
\end{patch}
\begin{patch}{HTXFormatPage1xPatch2A}
\begin{paste}{HTXFormatPage1xPaste2B}{HTXFormatPage1xPatch2}
\pastebutton{HTXFormatPage1xPaste2B}{Interpret}
\newline
{\tt  the latest figures indicate \% GET THE LATEST FIGURES}\newline
{\tt a steady rise}\indent{0}
\end{paste}
\end{patch}

\end{chunk}
\section{htxformatpage2.ht}
\pagetitle{HTXFormatPage2}{htxformatpage2.ht}{Formatting without commands}
\begin{chunk}{htxformatpage2.ht}
\begin{page}{HTXFormatPage2}{Formatting without commands}
\centerline{\fbox{{\tt \thispage}}}\newline
\begin{scroll}

Hyperdoc will interpret normal text in a {\em source file}
according to the following rules. \newline
\menuitemstyle{\indentrel{4}
Spaces mark the ends of words. The number of spaces between
words is {\em not} significant, that is, you cannot control word spacing
by inserting or removing extra space characters.
\indentrel{-4}}
\beginImportant
\begin{paste}{HTXFormatPage2xxPaste1}{HTXFormatPage2xPatch1}
\pastebutton{HTXFormatPage2xxPaste1}{Interpret}
\begin{verbatim}
word    spacing is       not  important
\end{verbatim}
\end{paste}
\endImportant
\menuitemstyle{\indentrel{4}
End-of-line  characters are not significant.
You can break up lines in the source file as you like. The end-of-line
will be interpreted as a space. 
Take advantage of this feature to improve the readability of the
source file.
\indentrel{-4}}
\beginImportant
\begin{paste}{HTXFormatPage2xxPaste2}{HTXFormatPage2xPatch2}
\pastebutton{HTXFormatPage2xxPaste2}{Interpret}
\begin{verbatim}
This is
one
sentence.
\end{verbatim}
\end{paste}
\endImportant
\menuitemstyle{\indentrel{4}
A blank line marks the end of a paragraph. 
Leaving more blank lines that necessary has no effect.
\indentrel{-4}}
\beginImportant
\begin{paste}{HTXFormatPage2xxPaste3}{HTXFormatPage2xPatch3}
\pastebutton{HTXFormatPage2xxPaste3}{Interpret}
\begin{verbatim}
some end.% A COMMENT


Start a paragraph

Start another paragraph.
\end{verbatim}
\end{paste}
\endImportant
\menuitemstyle{\indentrel{4}
The two-character combination {\tt \{\}} can be used to indicate
possible breaking of long words. It does not affect the formatting
in any other way.
\indentrel{-4}}
\beginImportant
\begin{paste}{HTXFormatPage2xxPaste4}{HTXFormatPage2xPatch4}
\pastebutton{HTXFormatPage2xxPaste4}{Interpret}
\begin{verbatim}
Generalized{}Multivariate{}Factorize
One{}Dimensional{}Array{}Aggregate
Elementary{}Function{}Definite{}Integration
Elementary{}Functions{}Univariate{}Puiseux{}Series
Finite{}Field{}Cyclic{}Group{}Extension{}ByPolynomial
\end{verbatim}
\end{paste}
\endImportant




\end{scroll}
\beginmenu
\menulink{Next -- Using different fonts}{HTXFormatPage3}
\endmenu

\end{page}

\end{chunk}
\subsection{HTXFormatPage2xPatch1 patch}
\label{HTXFormatPage2xPatch1}
\index{patch!HTXFormatPage2xPatch1!htxformatpage2.ht}
\index{htxformatpage2.ht!patch!HTXFormatPage2xPatch1}
\index{HTXFormatPage2xPatch1!htxformatpage2.ht!patch}
\begin{chunk}{htxformatpage2.ht}
\begin{patch}{HTXFormatPage2xPatch1}
\begin{paste}{HTXFormatPage2xxPaste1A}{HTXFormatPage2xPatch1A}
\pastebutton{HTXFormatPage2xxPaste1A}{Source}
\newline
word    spacing is       not  important
\end{paste}
\end{patch}
\begin{patch}{HTXFormatPage2xPatch1A}
\begin{paste}{HTXFormatPage2xxPaste1B}{HTXFormatPage2xPatch1}
\pastebutton{HTXFormatPage2xxPaste1B}{Interpret}
\begin{verbatim}
word    spacing is       not  important
\end{verbatim}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage2xPatch2 patch}
\label{HTXFormatPage2xPatch2}
\index{patch!HTXFormatPage2xPatch2!htxformatpage2.ht}
\index{htxformatpage2.ht!patch!HTXFormatPage2xPatch2}
\index{HTXFormatPage2xPatch2!htxformatpage2.ht!patch}
\begin{chunk}{htxformatpage2.ht}
\begin{patch}{HTXFormatPage2xPatch2}
\begin{paste}{HTXFormatPage2xxPaste2A}{HTXFormatPage2xPatch2A}
\pastebutton{HTXFormatPage2xxPaste2A}{Source}
\newline
This is
one
sentence.
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage2xPatch2A patch}
\label{HTXFormatPage2xPatch2A}
\index{patch!HTXFormatPage2xPatch2A!htxformatpage2.ht}
\index{htxformatpage2.ht!patch!HTXFormatPage2xPatch2A}
\index{HTXFormatPage2xPatch2A!htxformatpage2.ht!patch}
\begin{chunk}{htxformatpage2.ht}
\begin{patch}{HTXFormatPage2xPatch2A}
\begin{paste}{HTXFormatPage2xxPaste2B}{HTXFormatPage2xPatch2}
\pastebutton{HTXFormatPage2xxPaste2B}{Interpret}
\begin{verbatim}
This is
one
sentence.
\end{verbatim}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage2xPatch3 patch}
\label{HTXFormatPage2xPatch3}
\index{patch!HTXFormatPage2xPatch3!htxformatpage2.ht}
\index{htxformatpage2.ht!patch!HTXFormatPage2xPatch3}
\index{HTXFormatPage2xPatch3!htxformatpage2.ht!patch}
\begin{chunk}{htxformatpage2.ht}
\begin{patch}{HTXFormatPage2xPatch3}
\begin{paste}{HTXFormatPage2xxPaste3A}{HTXFormatPage2xPatch3A}
\pastebutton{HTXFormatPage2xxPaste3A}{Source}
\newline
some end.% A COMMENT


Start a paragraph.

Start another paragraph.
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage2xPatch3A patch}
\label{HTXFormatPage2xPatch3A}
\index{patch!HTXFormatPage2xPatch3A!htxformatpage2.ht}
\index{htxformatpage2.ht!patch!HTXFormatPage2xPatch3A}
\index{HTXFormatPage2xPatch3A!htxformatpage2.ht!patch}
\begin{chunk}{htxformatpage2.ht}
\begin{patch}{HTXFormatPage2xPatch3A}
\begin{paste}{HTXFormatPage2xxPaste3B}{HTXFormatPage2xPatch3}
\pastebutton{HTXFormatPage2xxPaste3B}{Interpret}
\begin{verbatim}
some end.% A COMMENT


Start a paragraph

Start another paragraph.
\end{verbatim}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage2xPatch4 patch}
\label{HTXFormatPage2xPatch4}
\index{patch!HTXFormatPage2xPatch4!htxformatpage2.ht}
\index{htxformatpage2.ht!patch!HTXFormatPage2xPatch4}
\index{HTXFormatPage2xPatch4!htxformatpage2.ht!patch}
\begin{chunk}{htxformatpage2.ht}
\begin{patch}{HTXFormatPage2xPatch4}
\begin{paste}{HTXFormatPage2xxPaste4A}{HTXFormatPage2xPatch4A}
\pastebutton{HTXFormatPage2xxPaste4A}{Source}
\newline
Generalized{}Multivariate{}Factorize
One{}Dimensional{}Array{}Aggregate
Elementary{}Function{}Definite{}Integration
Elementary{}Functions{}Univariate{}Puiseux{}Series
Finite{}Field{}Cyclic{}Group{}Extension{}ByPolynomial
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage2xPatch4A patch}
\label{HTXFormatPage2xPatch4A}
\index{patch!HTXFormatPage2xPatch4A!htxformatpage2.ht}
\index{htxformatpage2.ht!patch!HTXFormatPage2xPatch4A}
\index{HTXFormatPage2xPatch4A!htxformatpage2.ht!patch}
\begin{chunk}{htxformatpage2.ht}
\begin{patch}{HTXFormatPage2xPatch4A}
\begin{paste}{HTXFormatPage2xxPaste4B}{HTXFormatPage2xPatch4}
\pastebutton{HTXFormatPage2xxPaste4B}{Interpret}
\begin{verbatim}
Generalized{}Multivariate{}Factorize
One{}Dimensional{}Array{}Aggregate
Elementary{}Function{}Definite{}Integration
Elementary{}Functions{}Univariate{}Puiseux{}Series
Finite{}Field{}Cyclic{}Group{}Extension{}ByPolynomial
\end{verbatim}
\end{paste}
\end{patch}

\end{chunk}
\section{htxformatpage3.ht}
\pagetitle{HTXFormatPage3}{htxformatpage3.ht}{Using different fonts}
\begin{chunk}{htxformatpage3.ht}
\begin{page}{HTXFormatPage3}{Using different fonts}
\centerline{\fbox{{\tt \thispage}}}\newline
\begin{scroll}

You can use various fonts for the text. Hyperdoc makes
four {\em logical} fonts available to you: a {\em roman} font, an
{\em emphasised} font, a {\em bold} font and a
{\em typewriter} font. The actual font that corresponds to
each logical font is determined by the end user via a
defaults file. The colour for each of these fonts can also
be specified.

Normal text is displayed with the roman font.
If you want to emphasize some text, use the {\tt \\em}
command in the following way.
\beginImportant
\begin{paste}{HTXFormatPage3xPaste1}{HTXFormatPage3xPatch1}
\pastebutton{HTXFormatPage3xPaste1}{Interpret}
\newline
{\tt this is \{\\em emphasised\} text}
\end{paste}
\endImportant

Note the use of the braces to enclose command and "arguments".
All font commands are specified in the same way. The {\tt \\em} command
will in fact {\em switch} between roman and emphasised
font every time it is used.
\beginImportant
\begin{paste}{HTXFormatPage3xPaste2}{HTXFormatPage3xPatch2}
\pastebutton{HTXFormatPage3xPaste2}{Interpret}
\newline
{\tt \{\\em this is \{\\em emphasised\} text\}}
\end{paste}
\endImportant

If you want to be sure that the emphasized font will be used, specify
the {\tt \\it} command. Similarly, you can explicitly select the roman
font with the {\tt \\rm} command.
\beginImportant
\begin{paste}{HTXFormatPage3xPaste3}{HTXFormatPage3xPatch3}
\pastebutton{HTXFormatPage3xPaste3}{Interpret}
\newline
{\tt \{\\em this is \{\\it emphasised\} text and this is \{\\rm roman\}\}}
\end{paste}
\endImportant


The bold font is selected with the {\tt \\bf} command and the typewriter
font with the {\tt \\tt} command. All these commands can be applied to
individual characters, words, sentences etc.
\beginImportant
\begin{paste}{HTXFormatPage3xPaste4}{HTXFormatPage3xPatch4}
\pastebutton{HTXFormatPage3xPaste4}{Interpret}
\newline
{\tt \{\\bf U\}\{\\tt g\}\{\\it l\}\{\\rm y\}}
\end{paste}
\endImportant


Currently, Hyperdoc does not adjust its internal spacing rules
to each font individually. This means that, for consistent results,
users are encouraged to specify (in the defaults file)
"character-cell" fonts that are not
too small or too large for Hyperdoc. Here is the correspondence
between the above font commands and the defaults names:\newline
\menuitemstyle{RmFont \tab{26} {\tt \\rm} or {\tt \\em} }\newline
\menuitemstyle{BoldFont \tab{26} {\tt \\bf} }\newline
\menuitemstyle{EmphasizeFont \tab{26} {\tt \\it} or {\tt \\em} }\newline
\menuitemstyle{Ttfont \tab{26} {\tt \\tt} }\newline

Hyperdoc uses two more logical fonts that can be specified by
the end user : AxiomFont and ActiveFont. However, you cannot
explicitly use these fonts in your text. The ActiveFont is automatically
used for active area text and the AxiomFont is reserved for
active Axiom commands.




\end{scroll}
\beginmenu
\menulink{Next -- Indentation}{HTXFormatPage4}
\endmenu

\end{page}

\end{chunk}
\subsection{HTXFormatPage3xPatch1 patch}
\label{HTXFormatPage3xPatch1}
\index{patch!HTXFormatPage3xPatch1!htxformatpage3.ht}
\index{htxformatpage3.ht!patch!HTXFormatPage3xPatch1}
\index{HTXFormatPage3xPatch1!htxformatpage3.ht!patch}
\begin{chunk}{htxformatpage3.ht}
\begin{patch}{HTXFormatPage3xPatch1}
\begin{paste}{HTXFormatPage3xPaste1A}{HTXFormatPage3xPatch1A}
\pastebutton{HTXFormatPage3xPaste1A}{Source}
\newline
this is {\em emphasised} text
\end{paste}
\end{patch}
\begin{patch}{HTXFormatPage3xPatch1A}
\begin{paste}{HTXFormatPage3xPaste1B}{HTXFormatPage3xPatch1}
\pastebutton{HTXFormatPage3xPaste1B}{Interpret}
\newline
{\tt this is \{\\em emphasised\} text}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage3xPatch2 patch}
\label{HTXFormatPage3xPatch2}
\index{patch!HTXFormatPage3xPatch2!htxformatpage3.ht}
\index{htxformatpage3.ht!patch!HTXFormatPage3xPatch2}
\index{HTXFormatPage3xPatch2!htxformatpage3.ht!patch}
\begin{chunk}{htxformatpage3.ht}
\begin{patch}{HTXFormatPage3xPatch2}
\begin{paste}{HTXFormatPage3xPaste2A}{HTXFormatPage3xPatch2A}
\pastebutton{HTXFormatPage3xPaste2A}{Source}
\newline
{\em this is {\em emphasised} text}
\end{paste}
\end{patch}
\begin{patch}{HTXFormatPage3xPatch2A}
\begin{paste}{HTXFormatPage3xPaste2B}{HTXFormatPage3xPatch2}
\pastebutton{HTXFormatPage3xPaste2B}{Interpret}
\newline
{\tt \{\\em this is \{\\em emphasised\} text\}}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage3xPatch3 patch}
\label{HTXFormatPage3xPatch3}
\index{patch!HTXFormatPage3xPatch3!htxformatpage3.ht}
\index{htxformatpage3.ht!patch!HTXFormatPage3xPatch3}
\index{HTXFormatPage3xPatch3!htxformatpage3.ht!patch}
\begin{chunk}{htxformatpage3.ht}
\begin{patch}{HTXFormatPage3xPatch3}
\begin{paste}{HTXFormatPage3xPaste3A}{HTXFormatPage3xPatch3A}
\pastebutton{HTXFormatPage3xPaste3A}{Source}
\newline
{\em this is {\it emphasised} text and this is {\rm roman}}
\end{paste}
\end{patch}
\begin{patch}{HTXFormatPage3xPatch3A}
\begin{paste}{HTXFormatPage3xPaste3B}{HTXFormatPage3xPatch3}
\pastebutton{HTXFormatPage3xPaste3B}{Interpret}
\newline
{\tt \{\\em this is \{\\it emphasised\} text 
and this is \{\\rm roman\}\}}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage3xPatch4 patch}
\label{HTXFormatPage3xPatch4}
\index{patch!HTXFormatPage3xPatch4!htxformatpage3.ht}
\index{htxformatpage3.ht!patch!HTXFormatPage3xPatch4}
\index{HTXFormatPage3xPatch4!htxformatpage3.ht!patch}
\begin{chunk}{htxformatpage3.ht}
\begin{patch}{HTXFormatPage3xPatch4}
\begin{paste}{HTXFormatPage3xPaste4A}{HTXFormatPage3xPatch4A}
\pastebutton{HTXFormatPage3xPaste4A}{Source}
\newline
{\bf U}{\tt g}{\it l}{\rm y}
\end{paste}
\end{patch}
\begin{patch}{HTXFormatPage3xPatch4A}
\begin{paste}{HTXFormatPage3xPaste4B}{HTXFormatPage3xPatch4}
\pastebutton{HTXFormatPage3xPaste4B}{Interpret}
\newline
{\tt \{\\bf U\}\{\\tt g\}\{\\it l\}\{\\rm y\}}
\end{paste}
\end{patch}

\end{chunk}
\section{htxformatpage4.ht}
\pagetitle{HTXFormatPage4}{htexformatpage4.ht}{Indentation}
\begin{chunk}{htxformatpage4.ht}
\begin{page}{HTXFormatPage4}{Indentation}
\centerline{\fbox{{\tt \thispage}}}\newline
\begin{scroll}

You can control the indentation of lines of text in Hyperdoc with
some useful commands.
Use the command {\tt \\par} to force a new paragraph if you don't want
to use the blank-line rule. The first line of a new paragraph
will normally be indented by a standard small amount. If you
just want to start on a new line, use the {\tt \\newline}
command.
\beginImportant
\begin{paste}{HTXFormatPage4xPaste1}{HTXFormatPage4xPatch1}
\pastebutton{HTXFormatPage4xPaste1}{Interpret}
\newline
{\tt let us start a new line \\newline here }
\end{paste}
\endImportant

The  command {\tt \\indent\{{\it value}\}} will
set the left-page-margin {\it value} characters
to the right of the standard left-page-margin.
The initial (standard) state of a page can be reset by the
{\tt \\indent\{0\}} command.
The first lines of paragraphs will be indented
by the {\it extra} standard  amount. The {\tt \\indent\{{\it value}\}}
command does {\em not} force a new line or paragraph.

You can also use the {\tt \\indentrel\{{\it value}\}} command.
Here, the {\it value} argument is a {\em relative} indentation
which can be positive or negative.
Otherwise, it behaves in the same way as the {\tt \\indent} command.
\beginImportant
\begin{paste}{HTXFormatPage4xPaste2}{HTXFormatPage4xPatch2}
\pastebutton{HTXFormatPage4xPaste2}{Interpret}
\newline
{\tt let us start a new line \\newline \\indent\{10\} here }\newline
{\tt \\newline \\indentrel\{-5\} there}\newline
{\tt \\newline \\indentrel\{-5\} back}
\end{paste}
\endImportant

The {\tt \\centerline\{{\it some text}\}} command will center its
argument between the current left and right margins. The argument of
the command should not be more than a paragraph of text and should not
contain any commands that change the left margin. The centered text
will start on a new line.
\beginImportant
\begin{paste}{HTXFormatPage4xPaste3}{HTXFormatPage4xPatch3}
\pastebutton{HTXFormatPage4xPaste3}{Interpret}
\newline
{\tt previous text. \\centerline\{This could}\newline
{\tt be some heading.\} Carry on}
\end{paste}
\endImportant

Placing text in vertically aligned columns is easily done with the
{\tt \\tab\{{\it value}\}} command. The {\tt \\tab} command has the
immediate effect of placing the next word {\it value} characters to
the right of the current left margin.
\beginImportant
\begin{paste}{HTXFormatPage4xPaste4}{HTXFormatPage4xPatch4}
\pastebutton{HTXFormatPage4xPaste4}{Interpret}
\newline
{\tt \\indent\{5\}\\newline}\newline
{\tt Team A \\tab\{17\}Score\\tab\{25\}Team B\\tab\{42\}Score\\newline}
\newline
{\tt 012345678901234567890123456789012345678901234567890\\newline}
\newline
{\tt Green-Red\\tab\{17\}4\\tab\{25\}Blue-Black\\tab\{42\}6\\newline}
\newline
{\tt \\indent\{0\}}
\end{paste}
\endImportant

If you wish to preserve the indentation of a piece of text
you can use the {\tt verbatim} group command. Simply place
a {\tt \\begin\{verbatim\}} and {\tt \\end\{verbatim\}} around
the text. Note that Hyperdoc commands will
not be interpreted within the {\tt verbatim} group.
\beginImportant
\begin{paste}{HTXFormatPage4xPaste5}{HTXFormatPage4xPatch5}
\pastebutton{HTXFormatPage4xPaste5}{Interpret}
\newline
{\tt \\begin\{verbatim\}}
\begin{verbatim}
This    spacing     will be      preserved
                    {\bf is}     preserved
\end{verbatim}
{\tt \\end\{verbatim\}}\newline
\end{paste}







\end{scroll}
\beginmenu
\menulink{Next -- Creating Lists and Tables}{HTXFormatPage5}
\endmenu

\end{page}

\end{chunk}
\subsection{HTXFormatPage4xPatch1 patch}
\label{HTXFormatPage4xPatch1}
\index{patch!HTXFormatPage4xPatch1!htxformatpage4.ht}
\index{htxformatpage4.ht!patch!HTXFormatPage4xPatch1}
\index{HTXFormatPage4xPatch1!htxformatpage4.ht!patch}
\begin{chunk}{htxformatpage4.ht}
\begin{patch}{HTXFormatPage4xPatch1}
\begin{paste}{HTXFormatPage4xPaste1A}{HTXFormatPage4xPatch1A}
\pastebutton{HTXFormatPage4xPaste1A}{Source}
\newline
let us start a new line \newline here
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage4xPatch1A patch}
\label{HTXFormatPage4xPatch1A}
\index{patch!HTXFormatPage4xPatch1A!htxformatpage4.ht}
\index{htxformatpage4.ht!patch!HTXFormatPage4xPatch1A}
\index{HTXFormatPage4xPatch1A!htxformatpage4.ht!patch}
\begin{chunk}{htxformatpage4.ht}
\begin{patch}{HTXFormatPage4xPatch1A}
\begin{paste}{HTXFormatPage4xPaste1B}{HTXFormatPage4xPatch1}
\pastebutton{HTXFormatPage4xPaste1B}{Interpret}
\newline
{\tt let us start a new line \\newline here }
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage4xPatch2 patch}
\label{HTXFormatPage4xPatch2}
\index{patch!HTXFormatPage4xPatch2!htxformatpage4.ht}
\index{htxformatpage4.ht!patch!HTXFormatPage4xPatch2}
\index{HTXFormatPage4xPatch2!htxformatpage4.ht!patch}
\begin{chunk}{htxformatpage4.ht}
\begin{patch}{HTXFormatPage4xPatch2}
\begin{paste}{HTXFormatPage4xPaste2A}{HTXFormatPage4xPatch2A}
\pastebutton{HTXFormatPage4xPaste2A}{Source}
\newline
let us start a new line\newline\indent{10} here
\newline\indentrel{-5} there
\newline\indentrel{-5} back
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage4xPatch2A patch}
\label{HTXFormatPage4xPatch2A}
\index{patch!HTXFormatPage4xPatch2A!htxformatpage4.ht}
\index{htxformatpage4.ht!patch!HTXFormatPage4xPatch2A}
\index{HTXFormatPage4xPatch2A!htxformatpage4.ht!patch}
\begin{chunk}{htxformatpage4.ht}
\begin{patch}{HTXFormatPage4xPatch2A}
\begin{paste}{HTXFormatPage4xPaste2B}{HTXFormatPage4xPatch2}
\pastebutton{HTXFormatPage4xPaste2B}{Interpret}
\newline
{\tt let us start a new line \\newline \\indent\{10\} here }\newline
{\tt \\newline \\indentrel\{-5\} there}\newline
{\tt \\newline \\indentrel\{-5\} back}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage4xPatch3 patch}
\label{HTXFormatPage4xPatch3}
\index{patch!HTXFormatPage4xPatch3!htxformatpage4.ht}
\index{htxformatpage4.ht!patch!HTXFormatPage4xPatch3}
\index{HTXFormatPage4xPatch3!htxformatpage4.ht!patch}
\begin{chunk}{htxformatpage4.ht}
\begin{patch}{HTXFormatPage4xPatch3}
\begin{paste}{HTXFormatPage4xPaste3A}{HTXFormatPage4xPatch3A}
\pastebutton{HTXFormatPage4xPaste3A}{Source}
\newline
previous text. \centerline{This could
be some heading.} Carry on
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage4xPatch3A patch}
\label{HTXFormatPage4xPatch3A}
\index{patch!HTXFormatPage4xPatch3A!htxformatpage4.ht}
\index{htxformatpage4.ht!patch!HTXFormatPage4xPatch3A}
\index{HTXFormatPage4xPatch3A!htxformatpage4.ht!patch}
\begin{chunk}{htxformatpage4.ht}
\begin{patch}{HTXFormatPage4xPatch3A}
\begin{paste}{HTXFormatPage4xPaste3B}{HTXFormatPage4xPatch3}
\pastebutton{HTXFormatPage4xPaste3B}{Interpret}
\newline
{\tt previous text. \\centerline\{This could}\newline
{\tt be some heading.\} Carry on}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage4xPatch4 patch}
\label{HTXFormatPage4xPatch4}
\index{patch!HTXFormatPage4xPatch4!htxformatpage4.ht}
\index{htxformatpage4.ht!patch!HTXFormatPage4xPatch4}
\index{HTXFormatPage4xPatch4!htxformatpage4.ht!patch}
\begin{chunk}{htxformatpage4.ht}
\begin{patch}{HTXFormatPage4xPatch4}
\begin{paste}{HTXFormatPage4xPaste4A}{HTXFormatPage4xPatch4A}
\pastebutton{HTXFormatPage4xPaste4A}{Source}
\newline
\indent{5}\newline
Team A \tab{17}Score\tab{25}Team B\tab{42}Score\newline
012345678901234567890123456789012345678901234567890\newline
Green-Red\tab{17}4\tab{25}Blue-Black\tab{42}6\newline
\indent{0}
\end{paste}
\end{patch}
\begin{patch}{HTXFormatPage4xPatch4A}
\begin{paste}{HTXFormatPage4xPaste4B}{HTXFormatPage4xPatch4}
\pastebutton{HTXFormatPage4xPaste4B}{Interpret}
\newline
{\tt \\indent\{5\}\\newline}\newline
{\tt Team A \\tab\{17\}Score\\tab\{25\}Team B\\tab\{42\}Score\\newline}
\newline
{\tt 012345678901234567890123456789012345678901234567890\\newline}
\newline
{\tt Green-Red\\tab\{17\}4\\tab\{25\}Blue-Black\\tab\{42\}6\\newline}
\newline
{\tt \\indent\{0\}}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage4xPatch5 patch}
\label{HTXFormatPage4xPatch5}
\index{patch!HTXFormatPage4xPatch5!htxformatpage4.ht}
\index{htxformatpage4.ht!patch!HTXFormatPage4xPatch5}
\index{HTXFormatPage4xPatch5!htxformatpage4.ht!patch}
\begin{chunk}{htxformatpage4.ht}
\begin{patch}{HTXFormatPage4xPatch5}
\begin{paste}{HTXFormatPage4xPaste5A}{HTXFormatPage4xPatch5A}
\pastebutton{HTXFormatPage4xPaste5A}{Source}
\begin{verbatim}
This    spacing     will be      preserved
                    {\bf is}     preserved
\end{verbatim}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage4xPatch5A patch}
\label{HTXFormatPage4xPatch5A}
\index{patch!HTXFormatPage4xPatch5A!htxformatpage4.ht}
\index{htxformatpage4.ht!patch!HTXFormatPage4xPatch5A}
\index{HTXFormatPage4xPatch5A!htxformatpage4.ht!patch}
\begin{chunk}{htxformatpage4.ht}
\begin{patch}{HTXFormatPage4xPatch5A}
\begin{paste}{HTXFormatPage4xPaste5B}{HTXFormatPage4xPatch5}
\pastebutton{HTXFormatPage4xPaste5B}{Interpret}
\newline
{\tt \\begin\{verbatim\}}
\begin{verbatim}
This    spacing     will be      preserved
                    {\bf is}     preserved
\end{verbatim}
{\tt \\end\{verbatim\}}\newline
\end{paste}
\end{patch}

\end{chunk}
\section{htxformatpage5.ht}
\pagetitle{HTXFormatPage5}{htxformatpage5.ht}{Creating Lists and Tables}
\pageto{notitle}{HTXFormatPage6}
\begin{chunk}{htxformatpage5.ht}
\begin{page}{HTXFormatPage5}{Creating Lists and Tables}
\centerline{\fbox{{\tt \thispage}}}\newline
\begin{scroll}

The {\tt \\begin\{items\} {\rm -}  \\end\{items\}} 
group command constructs itemized lists.
The {\tt \\item} command separates the items in the list.
The indentation rules for the list group are different from those
of a paragraph. The first line of an item will
normally extend further to the left than the rest of the lines.
Both commands accept {\em optional} arguments.
Optional arguments are enclosed in square brackets ({\tt \[ \]}) rather
than braces.

The indentation of subsequent lines in an item is determined by the
optional argument {\it some text} in the 
{\tt \\begin\{items\}\[{\it some text}\]} 
command. The optional argument is {\em not}
displayed. Its width is calculated and used to indent all subsequent
lines in the group except from the first line of each new item. This
indentation rule applies to all text {\em before} the first 
{\tt \\item} command as well.

The {\tt \\item\[{\it some text}\]} command specifies the start of a
new item.  The {\it some text} optional argument will be displayed in
{\em bold} font at the current left-page-margin. Then, the text
following the command will be displayed in normal fashion with the
above indentation rule.
\beginImportant
\begin{paste}{HTXFormatPage5xPaste1}{HTXFormatPage5xPatch1}
\pastebutton{HTXFormatPage5xPaste1}{Interpret}
\newline
{\tt \\indent\{5\}}\newline
{\tt \\begin\{items\}\[how wide am I\]}\newline
{\tt Here we carry on but a \\newline} \newline
{\tt new line will be indented } \newline
{\tt \\item\[how wide am I\] fits nicely. 
Here is a \\newline new line in an item.}\newline
{\tt \\item\[again\] to show another item}\newline
{\tt \\item\[\\\\tab\]\\tab\{0\} can be used \\tab\{15\} effectively}
\newline
{\tt \\end\{items\}}\newline
{\tt \\indent\{0\}}\newline
\end{paste}
\endImportant


Note that the {\tt \\begin\{items\}} command immediately sets the left-
page-margin to a new value. Subsequent 
{\tt \\tab} or {\tt \\centerline} commands
refer to this new margin.
Any explicit margin setting commands included
in the group {\em will} have the normal effect.
The {\tt \\par} command does not produce
the standard paragraph indentation within a list group --- it behaves
instead like {\tt \\newline}.


You can nest list groups like the following example suggests.
\beginImportant
\begin{paste}{HTXFormatPage5xPaste2}{HTXFormatPage5xPatch2}
\pastebutton{HTXFormatPage5xPaste2}{Interpret}
\newline
{\tt \\begin\{items\}\[quitealot\]}\newline
{\tt A nested list:}\newline
{\tt \\item\[The first\] item of an itemized list is on this line.}
\newline
{\tt \\item\[The second\] item of the list starts here.  
It contains another}\newline
{\tt list nested inside it.}\newline
{\tt \\begin\{items\}\[somuchmore\]}\newline
{\tt \\item \[First\]\\tab\{0\}This is the first item of an 
enumerated}\newline
{\tt list that is nested within the itemized list.}\newline
{\tt \\item \[Second\]\\tab\{0\}This is the second item of the 
inner list.}\newline
{\tt \\end\{items\}}\newline
{\tt This is the rest of the second item of the outer list.  It}\newline
{\tt is no more interesting than any other part of the item.}\newline
{\tt \\item\[The third\] item of the list.}\newline
{\tt \\end\{items\}}\newline
\end{paste}
\endImportant

Another facility for presenting lists is the {\tt \\table} command.
The correct syntax for it is : {\tt \\table\{\{{\it item a}\} 
\{{\it item b}\} {\it ..}\}}.
The items in the braces will be placed in as many aligned columns
as is possible for the current window dimensions or page width.
If one item is particularly long there will probably be only one column
in the table. Here is a table of color names.
\beginImportant
\begin{paste}{HTXFormatPage5xPaste3}{HTXFormatPage5xPatch3}
\pastebutton{HTXFormatPage5xPaste3}{Interpret}
\newline
{\tt
\\table\{
\{Dark Orchid\} \{Dark Salmon\} \{Dark Sea Green\} \{Dark Slate Blue\}
\{Dark Slate Gray\} \{Dark Turquoise\} \{Dark Violet\} \{Deep Pink\}
\{Deep Sky Blue\} \{Dodger Blue\} \{Floral White\} \{Forest Green\}
\{Ghost White\} \{Hot Pink\} \{Indian Red\} \{Lavender Blush\}
\}
}
\end{paste}
\endImportant




\end{scroll}
\beginmenu
\menulink{Next -- Boxes and Lines}{HTXFormatPage6}
\endmenu

\end{page}

\end{chunk}
\subsection{HTXFormatPage5xPatch1 patch}
\label{HTXFormatPage5xPatch1}
\index{patch!HTXFormatPage5xPatch1!htxformatpage5.ht}
\index{htxformatpage5.ht!patch!HTXFormatPage5xPatch1}
\index{HTXFormatPage5xPatch1!htxformatpage5.ht!patch}
\begin{chunk}{htxformatpage5.ht}
\begin{patch}{HTXFormatPage5xPatch1}
\begin{paste}{HTXFormatPage5xPaste1A}{HTXFormatPage5xPatch1A}
\pastebutton{HTXFormatPage5xPaste1A}{Source}
\newline
\indent{5}
\begin{items}[how wide am I]
Here we carry on but a \newline
new line will be indented
\item[how wide am I] fits nicely. Here is a \newline new line in an item.
\item[again] to show another item
\item[\\tab]\tab{0} can be used \tab{15} effectively
\end{items}
\indent{0}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage5xPatch1A patch}
\label{HTXFormatPage5xPatch1A}
\index{patch!HTXFormatPage5xPatch1A!htxformatpage5.ht}
\index{htxformatpage5.ht!patch!HTXFormatPage5xPatch1A}
\index{HTXFormatPage5xPatch1A!htxformatpage5.ht!patch}
\begin{chunk}{htxformatpage5.ht}
\begin{patch}{HTXFormatPage5xPatch1A}
\begin{paste}{HTXFormatPage5xPaste1B}{HTXFormatPage5xPatch1}
\pastebutton{HTXFormatPage5xPaste1B}{Interpret}
\newline
{\tt \\indent\{5\}}\newline
{\tt \\begin\{items\}\[how wide am I\]}\newline
{\tt Here we carry on but a \\newline} \newline
{\tt new line will be indented } \newline
{\tt \\item\[how wide am I\] fits nicely. 
Here is a \\newline new line in an item.}\newline
{\tt \\item\[again\] to show another item}\newline
{\tt \\item\[\\\\tab\]\\tab\{0\} can be used \\tab\{15\} effectively}
\newline
{\tt \\end\{items\}}\newline
{\tt \\indent\{0\}}\newline
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage5xPatch2 patch}
\label{HTXFormatPage5xPatch2}
\index{patch!HTXFormatPage5xPatch2!htxformatpage5.ht}
\index{htxformatpage5.ht!patch!HTXFormatPage5xPatch2}
\index{HTXFormatPage5xPatch2!htxformatpage5.ht!patch}
\begin{chunk}{htxformatpage5.ht}
\begin{patch}{HTXFormatPage5xPatch2}
\begin{paste}{HTXFormatPage5xPaste2A}{HTXFormatPage5xPatch2A}
\pastebutton{HTXFormatPage5xPaste2A}{Source}
\newline
\begin{items}[quitealot]
A nested list:
\item[The first] item of an itemized list is on this line.
\item[The second] item of the list starts here.  It contains another
list nested inside it.
\begin{items}[somuchmore]
\item [First]\tab{0}This is the first item of the
list that is nested within the itemized list.
\item [Second]\tab{0}This is the second item of the inner list.
\end{items}
This is the rest of the second item of the outer list.  It
is no more interesting than any other part of the item.
\item [The third] item of the list.
\end{items}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage5xPatch2A patch}
\label{HTXFormatPage5xPatch2A}
\index{patch!HTXFormatPage5xPatch2A!htxformatpage5.ht}
\index{htxformatpage5.ht!patch!HTXFormatPage5xPatch2A}
\index{HTXFormatPage5xPatch2A!htxformatpage5.ht!patch}
\begin{chunk}{htxformatpage5.ht}
\begin{patch}{HTXFormatPage5xPatch2A}
\begin{paste}{HTXFormatPage5xPaste2B}{HTXFormatPage5xPatch2}
\pastebutton{HTXFormatPage5xPaste2B}{Interpret}
\newline
{\tt \\begin\{items\}\[quitealot\]}\newline
{\tt A nested list:}\newline
{\tt \\item\[The first\] item of an itemized list is on this line.}
\newline
{\tt \\item\[The second\] item of the list starts here.  
It contains another}\newline
{\tt list nested inside it.}\newline
{\tt \\begin\{items\}\[somuchmore\]}\newline
{\tt \\item \[First\]\\tab\{0\}This is the first item of an 
enumerated}\newline
{\tt list that is nested within the itemized list.}\newline
{\tt \\item \[Second\]\\tab\{0\}This is the second item of 
the inner list.}\newline
{\tt \\end\{items\}}\newline
{\tt This is the rest of the second item of the outer list.  It}
\newline
{\tt is no more interesting than any other part of the item.}\newline
{\tt \\item\[The third\] item of the list.}\newline
{\tt \\end\{items\}}\newline
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage5xPatch3 patch}
\label{HTXFormatPage5xPatch3}
\index{patch!HTXFormatPage5xPatch3!htxformatpage5.ht}
\index{htxformatpage5.ht!patch!HTXFormatPage5xPatch3}
\index{HTXFormatPage5xPatch3!htxformatpage5.ht!patch}
\begin{chunk}{htxformatpage5.ht}
\begin{patch}{HTXFormatPage5xPatch3}
\begin{paste}{HTXFormatPage5xPaste3A}{HTXFormatPage5xPatch3A}
\pastebutton{HTXFormatPage5xPaste3A}{Source}
\newline
\table{
{Dark Orchid} {Dark Salmon} {Dark Sea Green} {Dark Slate Blue} 
{Dark Slate Gray}
{Dark Turquoise} {Dark Violet} {Deep Pink} {Deep Sky Blue} {Dodger Blue}
{Floral White} {Forest Green} {Ghost White} {Hot Pink} {Indian Red}
{Lavender Blush}
}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage5xPatch3A patch}
\label{HTXFormatPage5xPatch3A}
\index{patch!HTXFormatPage5xPatch3A!htxformatpage5.ht}
\index{htxformatpage5.ht!patch!HTXFormatPage5xPatch3A}
\index{HTXFormatPage5xPatch3A!htxformatpage5.ht!patch}
\begin{chunk}{htxformatpage5.ht}
\begin{patch}{HTXFormatPage5xPatch3A}
\begin{paste}{HTXFormatPage5xPaste3B}{HTXFormatPage5xPatch3}
\pastebutton{HTXFormatPage5xPaste3B}{Interpret}
\newline
{\tt
\\table\{
\{Dark Orchid\} \{Dark Salmon\} \{Dark Sea Green\} \{Dark Slate Blue\}
\{Dark Slate Gray\} \{Dark Turquoise\} \{Dark Violet\} \{Deep Pink\}
\{Deep Sky Blue\} \{Dodger Blue\} \{Floral White\} \{Forest Green\}
\{Ghost White\} \{Hot Pink\} \{Indian Red\} \{Lavender Blush\}
\}
}
\end{paste}
\end{patch}

\end{chunk}
\section{htxformatpage6}
\pagetitle{HTXFormatPage6}{htxformatpage6.ht}{Boxes and Lines}
\begin{chunk}{htxformatpage6.ht}
\begin{page}{HTXFormatPage6}{Boxes and Lines}
\centerline{\fbox{{\tt \thispage}}}\newline
\begin{scroll}

The {\tt \\fbox} command can be used to place a box around one or more
words. The argument of the {\tt \\fbox} command is the text that will be
placed in the box. This command should only be used for text that can fit
in one line.

\beginImportant
\begin{paste}{HTXFormatPage6xPaste1}{HTXFormatPage6xPatch1}
\pastebutton{HTXFormatPage6xPaste1}{Interpret}
\newline
{\tt \\fbox\{Boxed!\}}\newline
\end{paste}
\endImportant


Use the {\tt \\horizontalline} command to draw a horizontal line
across the window. This might be useful for added emphasis.

\beginImportant
\begin{paste}{HTXFormatPage6xPaste2}{HTXFormatPage6xPatch2}
\pastebutton{HTXFormatPage6xPaste2}{Interpret}
\newline
{\tt \\horizontalline}\newline
\end{paste}
\endImportant

\end{scroll}
\beginmenu
\menulink{Next -- Micro-Spacing}{HTXFormatPage7}
\endmenu

\end{page}

\end{chunk}
\subsection{HTXFormatPage6xPatch1 patch}
\label{HTXFormatPage6xPatch1}
\index{patch!HTXFormatPage6xPatch1!htxformatpage6.ht}
\index{htxformatpage6.ht!patch!HTXFormatPage6xPatch1}
\index{HTXFormatPage6xPatch1!htxformatpage6.ht!patch}
\begin{chunk}{htxformatpage6.ht}
\begin{patch}{HTXFormatPage6xPatch1}
\begin{paste}{HTXFormatPage6xPaste1A}{HTXFormatPage6xPatch1A}
\pastebutton{HTXFormatPage6xPaste1A}{Source}
\newline
\fbox{Boxed!}
\end{paste}
\end{patch}
\begin{patch}{HTXFormatPage6xPatch1A}
\begin{paste}{HTXFormatPage6xPaste1B}{HTXFormatPage6xPatch1}
\pastebutton{HTXFormatPage6xPaste1B}{Interpret}
\newline
{\tt \\fbox\{Boxed!\}}\newline
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage6xPatch2 patch}
\label{HTXFormatPage6xPatch2}
\index{patch!HTXFormatPage6xPatch2!htxformatpage6.ht}
\index{htxformatpage6.ht!patch!HTXFormatPage6xPatch2}
\index{HTXFormatPage6xPatch2!htxformatpage6.ht!patch}
\begin{chunk}{htxformatpage6.ht}
\begin{patch}{HTXFormatPage6xPatch2}
\begin{paste}{HTXFormatPage6xPaste2A}{HTXFormatPage6xPatch2A}
\pastebutton{HTXFormatPage6xPaste2A}{Source}
\newline
\horizontalline
\end{paste}
\end{patch}
\begin{patch}{HTXFormatPage6xPatch2A}
\begin{paste}{HTXFormatPage6xPaste2B}{HTXFormatPage6xPatch2}
\pastebutton{HTXFormatPage6xPaste2B}{Interpret}
\newline
{\tt \\horizontalline}\newline
\end{paste}
\end{patch}

\end{chunk}
\section{htxformatpage7}
\pagetitle{HTXFormatPage7}{htxformatpage7.ht}{Micro-Spacing}
\begin{chunk}{htxformatpage7.ht}
\begin{page}{HTXFormatPage7}{Micro-Spacing}
\centerline{\fbox{{\tt \thispage}}}\newline
\begin{scroll}

There are three commands that one can use to exercise finer control
over the appearance of text on a page: {\tt \\space}, {\tt \\hspace}
and {\tt \\vspace}.

The {\tt \\space\{{\it value}\}} command accepts an integer argument
and simply changes the position of the next character to the right or
to the left.  A negative argument will move the next character to the
left and a positive one to the right. The unit of movement is {\it the
width of a character}. In this way one can overstrike characters to
produce various effects.

\beginImportant
\begin{paste}{HTXFormatPage7xPaste1}{HTXFormatPage7xPatch1}
\pastebutton{HTXFormatPage7xPaste1}{Interpret}
\newline
{\tt 0\\space\{-1\}\\}\newline
{\tt underlined\\space\{-10\}__________}\newline
\end{paste}
\endImportant


The {\tt \\hspace\{{\it value}\}} command
is similar to the {\tt \\space\{{\it value}\}} command.
It also accepts an integer argument and
changes the position of the next character to the right or to the left.
A negative argument will move the next character to the left and a
positive one to the right. The unit of movement is {\it a pixel}.
The {\it value} argument specifies an offset from the default placement
of the character.

\beginImportant
\begin{paste}{HTXFormatPage7xPaste2}{HTXFormatPage7xPatch2}
\pastebutton{HTXFormatPage7xPaste2}{Interpret}
\newline
{\tt x\\hspace\{-4\}x\\hspace\{-3\}x\\hspace\{-2\}x\\hspace\{-1\}x\%}\newline
{\tt x\\hspace\{1\}x\\hspace\{2\}x\\hspace\{3\}x\\hspace\{4\}x}
\end{paste}
\endImportant

The {\tt \\vspace\{{\it value}\}} command is similar to the
{\tt \\hspace\{{\it value}\}} command but (as the name suggests)
works in the vertical direction. The unit of movement is {\it a
pixel}. The {\it value} argument specifies an offset from {\it
the next line}. A negative argument moves the next character up
and a positive down. This command can be used for subscripts and
superscripts. One drawback in the use of {\tt \\vspace} is that
it can only work with a particular font at a time. This is
because the inter-line spacing depends on the font being used
and the value of it is needed to get "back" on the line.
In general, the command {\tt \\vspace\{{\it - ils}\}} will
have a null effect when {\it ils} = ( font ascent + font descent + 5 ).
The example below assumes that {\it ils} = 25 e.g. the Rom14 font
on the RISC System/6000.

\beginImportant
\begin{paste}{HTXFormatPage7xPaste3}{HTXFormatPage7xPatch3}
\pastebutton{HTXFormatPage7xPaste3}{Interpret}
\newline
{\tt CO\\vspace\{-18\}2\\vspace\{-32\} + CaO ->}\newline
{\tt CaCO\\vspace\{-18\}3\\vspace\{-32\}\\newline}\newline
{\tt R\\space\{-1\}~\\vspace\{-18\}æv\\vspace\{-32\}}\newline
{\tt \\hspace\{4\}-\\hspace\{8\}---\\hspace\{-12\}}\newline
{\tt \\vspace\{-32\}1\\space\{-1\}\\vspace\{-7\}2}\newline
{\tt \\vspace\{-36\}\\hspace\{8\}g\\space\{-1\}~}\newline
{\tt \\vspace\{-18\}æv\\vspace\{-32\}\\hspace\{2\}R}\newline
{\tt \\space\{-1\}~ = T\\vspace\{-18\}æv\\vspace\{-32\}}\newline
{\tt \\vspace\{-25\}}
\end{paste}
\endImportant


\end{scroll}
\beginmenu
\menulink{Next -- Bitmaps and Images}{HTXFormatPage8}
\endmenu

\end{page}

\end{chunk}
\subsection{HTXFormatPage7xPatch1 patch}
\label{HTXFormatPage7xPatch1}
\index{patch!HTXFormatPage7xPatch1!htxformatpage7.ht}
\index{htxformatpage7.ht!patch!HTXFormatPage7xPatch1}
\index{HTXFormatPage7xPatch1!htxformatpage7.ht!patch}
\begin{chunk}{htxformatpage7.ht}
\begin{patch}{HTXFormatPage7xPatch1}
\begin{paste}{HTXFormatPage7xPaste1A}{HTXFormatPage7xPatch1A}
\pastebutton{HTXFormatPage7xPaste1A}{Source}
\newline
0\space{-1}\\
underlined\space{-10}__________
\end{paste}
\end{patch}
\begin{patch}{HTXFormatPage7xPatch1A}
\begin{paste}{HTXFormatPage7xPaste1B}{HTXFormatPage7xPatch1}
\pastebutton{HTXFormatPage7xPaste1B}{Interpret}
\newline
{\tt 0\\space\{-1\}\\}\newline
{\tt underlined\\space\{-10\}__________}\newline
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage7xPatch2 patch}
\label{HTXFormatPage7xPatch2}
\index{patch!HTXFormatPage7xPatch2!htxformatpage7.ht}
\index{htxformatpage7.ht!patch!HTXFormatPage7xPatch2}
\index{HTXFormatPage7xPatch2!htxformatpage7.ht!patch}
\begin{chunk}{htxformatpage7.ht}
\begin{patch}{HTXFormatPage7xPatch2}
\begin{paste}{HTXFormatPage7xPaste2A}{HTXFormatPage7xPatch2A}
\pastebutton{HTXFormatPage7xPaste2A}{Source}
\newline
x\hspace{-4}x\hspace{-3}x\hspace{-2}x\hspace{-1}x%
x\hspace{1}x\hspace{2}x\hspace{3}x\hspace{4}x
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage7xPatch2A patch}
\label{HTXFormatPage7xPatch2A}
\index{patch!HTXFormatPage7xPatch2A!htxformatpage7.ht}
\index{htxformatpage7.ht!patch!HTXFormatPage7xPatch2A}
\index{HTXFormatPage7xPatch2A!htxformatpage7.ht!patch}
\begin{chunk}{htxformatpage7.ht}
\begin{patch}{HTXFormatPage7xPatch2A}
\begin{paste}{HTXFormatPage7xPaste2B}{HTXFormatPage7xPatch2}
\pastebutton{HTXFormatPage7xPaste2B}{Interpret}
\newline
{\tt x\\hspace\{-4\}x\\hspace\{-3\}x\\hspace\{-2\}x\\hspace\{-1\}x\%}
\newline
{\tt x\\hspace\{1\}x\\hspace\{2\}x\\hspace\{3\}x\\hspace\{4\}x}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage7xPatch3 patch}
\label{HTXFormatPage7xPatch3}
\index{patch!HTXFormatPage7xPatch3!htxformatpage7.ht}
\index{htxformatpage7.ht!patch!HTXFormatPage7xPatch3}
\index{HTXFormatPage7xPatch3!htxformatpage7.ht!patch}
\begin{chunk}{htxformatpage7.ht}
\begin{patch}{HTXFormatPage7xPatch3}
\begin{paste}{HTXFormatPage7xPaste3A}{HTXFormatPage7xPatch3A}
\pastebutton{HTXFormatPage7xPaste3A}{Source}
\newline
CO\vspace{-18}2\vspace{-32} + CaO ->
CaCO\vspace{-18}3\vspace{-32}\newline
R\space{-1}~\vspace{-18}æv\vspace{-32}
\hspace{4}-\hspace{8}---\hspace{-12}
\vspace{-32}1\space{-1}\vspace{-7}2
\vspace{-36}\hspace{8}g\space{-1}~
\vspace{-18}æv\vspace{-32}\hspace{2}R
\space{-1}~ = T\vspace{-18}æv\vspace{-32}
\vspace{-25}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage7xPatch3A patch}
\label{HTXFormatPage7xPatch3A}
\index{patch!HTXFormatPage7xPatch3A!htxformatpage7.ht}
\index{htxformatpage7.ht!patch!HTXFormatPage7xPatch3A}
\index{HTXFormatPage7xPatch3A!htxformatpage7.ht!patch}
\begin{chunk}{htxformatpage7.ht}
\begin{patch}{HTXFormatPage7xPatch3A}
\begin{paste}{HTXFormatPage7xPaste3B}{HTXFormatPage7xPatch3}
\pastebutton{HTXFormatPage7xPaste3B}{Interpret}
\newline
{\tt CO\\vspace\{-18\}2\\vspace\{-32\} + CaO ->}\newline
{\tt CaCO\\vspace\{-18\}3\\vspace\{-32\}\\newline}\newline
{\tt R\\space\{-1\}~\\vspace\{-18\}æv\\vspace\{-32\}}\newline
{\tt \\hspace\{4\}-\\hspace\{8\}---\\hspace\{-12\}}\newline
{\tt \\vspace\{-32\}1\\space\{-1\}\\vspace\{-7\}2}\newline
{\tt \\vspace\{-36\}\\hspace\{8\}g\\space\{-1\}~}\newline
{\tt \\vspace\{-18\}æv\\vspace\{-32\}\\hspace\{2\}R}\newline
{\tt \\space\{-1\}~ = T\\vspace\{-18\}æv\\vspace\{-32\}}\newline
{\tt \\vspace\{-25\}}
\end{paste}
\end{patch}

\end{chunk}
\section{htxformatpage8}
\pagetitle{HTXFormatPage8}{htxformatpage8.ht}{Bitmaps and Images}
\begin{chunk}{htxformatpage8.ht}
\begin{page}{HTXFormatPage8}{Bitmaps and Images}
\centerline{\fbox{{\tt \thispage}}}\newline
\begin{scroll}

The commands {\tt \\inputbitmap\{{\it filename}\}}
and {\tt \\inputimage\{{\it filename}\}}
allow you to include an X11 bitmap or an
Axiom-generated viewport in a Hyperdoc
page.

In the case of the {\tt \\inputbitmap} command
the {\it filename} parameter must be the full pathname
of an X11 bitmap file.

\beginImportant
\begin{paste}{HTXFormatPage8xPaste1}{HTXFormatPage8xPatch1}
\pastebutton{HTXFormatPage8xPaste1}{Interpret}
\newline
{\tt \\inputbitmap\{\env{AXIOM}/doc/bitmaps/sup.bitmap\} }
\end{paste}
\endImportant

The {\it filename} parameter of the {\tt \\inputimage} command must be
the full pathname of a {\it compressed XPM image} file without the
name extensions.  Hyperdoc always adds ".xpm.Z" to whatever filename
you give and looks for the augmented filename.  Such files can be
generated by Axiom command \axiomOp{write} with the {\tt "image"} or
{\tt "pixmap"} options.

\beginImportant
\begin{paste}{HTXFormatPage8xPaste2}{HTXFormatPage8xPatch2}
\pastebutton{HTXFormatPage8xPaste2}{Interpret}
\newline
{\tt \\inputimage\{\env{AXIOM}/doc/viewports/ugProblemNumericPage30.view/image\}}
\end{paste}
\endImportant

Be careful not to break the pathname across lines.

The {\tt \\inputimage} command will automatically select
the {\it image.xpm} or the {\it image.bm} file for you
based on the capabilities of your X server. 

For your convenience, there are two macros defined
in \centerline{ {\bf util.ht}.}
The {\tt \\viewport} macro eliminates the need to specify
the {\tt .view/image} part and the
{\tt \\axiomViewport} macro automatically selects viewport
files in the system directories. The above {\tt \\inputimage}
could have been written
\beginImportant
{\tt \\viewport\{\env{AXIOM}/doc/viewports/ugProblemNumericPage30\}}
\endImportant
or
\beginImportant
{\tt \\axiomViewport\{ugProblemNumericPage30\}}
\endImportant



\end{scroll}
\beginmenu
\menulink{Back to Formatting menu}{HTXFormatTopPage}
\endmenu

\end{page}

\end{chunk}
\subsection{HTXFormatPage8xPatch1 patch}
\label{HTXFormatPage8xPatch1}
\index{patch!HTXFormatPage8xPatch1!htxformatpage8.ht}
\index{htxformatpage8.ht!patch!HTXFormatPage8xPatch1}
\index{HTXFormatPage8xPatch1!htxformatpage8.ht!patch}
\begin{chunk}{htxformatpage8.ht}
\begin{patch}{HTXFormatPage8xPatch1}
\begin{paste}{HTXFormatPage8xPaste1A}{HTXFormatPage8xPatch1A}
\pastebutton{HTXFormatPage8xPaste1A}{Source}
\newline
\inputbitmap{\env{AXIOM}/doc/bitmaps/sup.bitmap}
\end{paste}
\end{patch}
\begin{patch}{HTXFormatPage8xPatch1A}
\begin{paste}{HTXFormatPage8xPaste1B}{HTXFormatPage8xPatch1}
\pastebutton{HTXFormatPage8xPaste1B}{Interpret}
\newline
{\tt \\inputbitmap\{\env{AXIOM}/doc/bitmaps/sup.bitmap\} }
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXFormatPage8xPatch2 patch}
\label{HTXFormatPage8xPatch2}
\index{patch!HTXFormatPage8xPatch2!htxformatpage8.ht}
\index{htxformatpage8.ht!patch!HTXFormatPage8xPatch2}
\index{HTXFormatPage8xPatch2!htxformatpage8.ht!patch}
\begin{chunk}{htxformatpage8.ht}
\begin{patch}{HTXFormatPage8xPatch2}
\begin{paste}{HTXFormatPage8xPaste2A}{HTXFormatPage8xPatch2A}
\pastebutton{HTXFormatPage8xPaste2A}{Source}
\newline
\inputimage{\env{AXIOM}/doc/viewports/ugProblemNumericPage30.view/image}
\end{paste}
\end{patch}
\end{chunk}
\subsection{HTXFormatPage8xPatch2A patch}
\label{HTXFormatPage8xPatch2A}
\index{patch!HTXFormatPage8xPatch2A!htxformatpage8.ht}
\index{htxformatpage8.ht!patch!HTXFormatPage8xPatch2A}
\index{HTXFormatPage8xPatch2A!htxformatpage8.ht!patch}
\begin{chunk}{htxformatpage8.ht}
\begin{patch}{HTXFormatPage8xPatch2A}
\begin{paste}{HTXFormatPage8xPaste2B}{HTXFormatPage8xPatch2}
\pastebutton{HTXFormatPage8xPaste2B}{Interpret}
\newline
{\tt \\inputimage
\{\env{AXIOM}/doc/viewports/ugProblemNumericPage30.view/image\}}
\end{paste}
\end{patch}

\end{chunk}
\section{htxformattoppage.ht}
\pagetitle{HTXFormatTopPage}{htxformattoppage.ht}
{Formatting in Hyperdoc}
\pageto{notitle}{HTXFormatPage1}
\pageto{notitle}{HTXFormatPage2}
\pageto{notitle}{HTXFormatPage3}
\pageto{notitle}{HTXFormatPage4}
\pageto{notitle}{HTXFormatPage5}
\pageto{notitle}{HTXFormatPage6}
\pageto{notitle}{HTXFormatPage7}
\pageto{notitle}{HTXFormatPage8}
\begin{chunk}{htxformattoppage.ht}
\begin{page}{HTXFormatTopPage}{Formatting in Hyperdoc}
\centerline{\fbox{{\tt \thispage}}}\newline

Hyperdoc offers various facilities for formatting text and images.
You can learn about these facilities by clicking on the topics below.
\begin{scroll}
\beginmenu
\menudownlink{Special Characters}{HTXFormatPage1}
\menudownlink{Formatting without commands}{HTXFormatPage2}
\menudownlink{Using different fonts}{HTXFormatPage3}
\menudownlink{Indentation}{HTXFormatPage4}
\menudownlink{Creating Lists and Tables}{HTXFormatPage5}
\menudownlink{Boxes and Lines}{HTXFormatPage6}
\menudownlink{Micro-Spacing}{HTXFormatPage7}
\menudownlink{Bitmaps and Images}{HTXFormatPage8}
\endmenu
\end{scroll}
\end{page}


\end{chunk}
\section{htxintropage1.ht}
\pagetitle{HTXIntroPage1}{htxintropage1.ht}{What Hyperdoc does}
\pageto{notitle}{HTXIntroPage2}
\pageto{notitle}{ugHyperPage}
\begin{chunk}{htxintropage1.ht}
\begin{page}{HTXIntroPage1}{What Hyperdoc does}
\centerline{\fbox{{\tt \thispage}}}\newline
\beginscroll

Take a close look at the objects in the Hyperdoc window you are now
reading.  Most of them are text. Resize the window using the window
manager facilities. The text is reformatted to fit the window
border. This action is performed by Hyperdoc. At the simplest level,
it provides a method for {\em formatting} text in a window.  In fact,
it can place other things on the window as well, such as bitmaps or
color images. The {\em buttons} you see at either side at the top of
the window are bitmaps.

Move the cursor so that it rests on one of those buttons. You notice
that the cursor has changed appearance. This indicates that there is
an action associated with the button. This action will be performed
when you click the mouse button over the {\em active area}. If you are
familiar with Hyperdoc, you know that the active area can be words,
bitmaps, images or {\em input areas}. In fact, anything that can be
displayed in a Hyperdoc window can be an active area.

So, what can the action associated with an active area be? Hyperdoc
allows quite a bit of freedom in defining that action. We will have a
close look at this issue \downlink{later on}{HTXLinkTopPage}. For now,
recall the various actions that you have encountered so far ---
executing Axiom commands, popping up new windows, providing parameters
for other active areas, and replacing or changing the contents of the
window. The most common action is to bring up some Hyperdoc text in
the same or a different window.  This lets us create {\em links}
between pieces of text and images. A system with such capability is
usually called a {\em hypertext} system.  Hyperdoc is in fact much
more.

\endscroll
\beginmenu
\menulink{Next -- How Hyperdoc does it}{HTXIntroPage2}
\menuwindowlink{Review some features of Hyperdoc}{ugHyperPage}
\endmenu

\helppage{ugHyperPage}
\end{page}

\end{chunk}
\section{htxintropage2.ht}
\pagetitle{HTXIntroPage2}{htxintropage2.ht}{How Hyperdoc does it}
\pageto{notitle}{HTXIntroPage3}
\begin{chunk}{htxintropage2.ht}
\begin{page}{HTXIntroPage2}{How Hyperdoc does it}
{\centerline{\fbox{{\tt \thispage}}}\newline}
\beginscroll

Hyperdoc can read the {\em hypertext} information from standard text
files. This means that you can create or change this information with
any text editor. Once this information has been entered into the
files, a special program, called {\bf htadd}, scans these files and
produces a database (another file called {\bf ht.db}) of {\em objects}
encountered in the files. Hyperdoc consults this database when it
first starts and so knows where it might find the definitions of these
objects. You can maintain several such databases on different
directories. You indicate which database you want Hyperdoc to consult
by setting an {\em environment variable} called {\bf HTPATH}.

In general, hypertext must obviously use some kind of special (that is,
non-textual) marks for all the  extra functionality it provides. In
Hyperdoc, these marks are some special characters --- special
in the sense that they are not interpreted as ordinary displayable text.
These characters, however, are part of the standard ASCII set.
There is also a way to display these special characters as text .
The Hyperdoc special characters are :

\beginImportant
\noindent{\em Special Characters}: 
{\tt \table{{\$}{\\}{\{}{\}}{\[}{\]}{\%}{\#}}}
\endImportant

Hyperdoc uses the special characters to distinguish between
{\em text} and {\em commands} (by {\em text}, we mean here anything
displayable). The commands are instructions to
Hyperdoc to treat some text in a particular way. Some commands
define special Hyperdoc objects. The most important objects
are {\em pages}, {\em patches}, and {\em macros}.
A {\em page} is a description of the contents of a
Hyperdoc window. A {\em patch} is a portion of a page.
A {\em macro} is a user-defined new Hyperdoc command.
Some commands allow special text {\em formatting} and others
associate some text with an action.

In order to display anything at all in \HyperName, you must define a
{\em page}. The next section explains how to define a {\em page} and put
some simple text into it.
\endscroll
\beginmenu
\menudownlink{Next -- Define a simple text page}{HTXIntroPage3}
\endmenu

\end{page}


\end{chunk}
\section{htxintropage3.ht}
\pagetitle{HTXIntroPage3}{htxintropage3.ht}{A simple text page}
\pageto{notitle}{HTXLinkPage6}
\pageto{notitle}{HTXTryPage}
\pageto{notitle}{HTXFormatTopPage}
\begin{chunk}{htxintropage3.ht}
\begin{page}{HTXIntroPage3}{A simple text page}
{\centerline{\fbox{{\tt \thispage}}}\newline}
\begin{scroll}


A page is defined by a {\em group} command. Group commands are used to
delimit a group, that is, to declare where a group starts and where it
ends. The proper syntax for a page definition is as follows:
\beginImportant
{\tt \\begin\{page\}\{{\it name}\}\{{\it a title}\}}
\newline
.
\newline
.
\newline
.
\newline
{\tt \\end\{page\}}
\beginImportant

Note the use of the special characters {\tt \\}, {\tt \{} and {\tt
\}}.  The {\tt \\} (backslash) character introduces a command, in this
case, {\tt begin}.  The {\tt \{ \}} (braces) delimit the {\em
parameters} to the command.  The first parameter (the word {\tt page})
specifies this as a page definition command.

The second parameter can be any single unbroken word consisting of
alphanumeric characters only, and specifies the name of the page by
which it can be referred to by other commands. You should choose this
internal name with care so as to avoid potential conflict with page
names that are defined by the Axiom system. This caveat only applies
in the case where you have started Hyperdoc with the Axiom database
--- see \downlink{later on}{HTXLinkPage6}. It is suggested that the
page names you define start with the letters {\tt UX} (standing for
{\tt U}ser e{\tt X}tensions). You can have a look at the Axiom system
database file {\centerline{\bf \env{AXIOM}/doc/ht.db} }
which contains the names of all pages, macros and patches used by
Axiom.

The third parameter specifies a title for the page.
The title of a page is the area at the very top
of the window, between the buttons. Virtually anything
that can be put in the main page can also be put in the
title. As an example, {\em this} page's
declaration is like this:\newline
{\tt \\begin\{page\}\{\thispage\}\{A simple text page\}}

Everything you type between the {\tt \\begin\{page\}} command and the
next {\tt \\end\{page\}} command will become the body of the page. It
is an error to insert another {\tt \\begin\{page\}} between the two,
that is, this group command cannot be nested.

There is another useful group command that should be mentioned here
--- the {\em scroll} command. It controls the portion of the page that
will be scrollable. Hyperdoc will split a page in three sections:
a {\em header}, a {\em scroll region} and a {\em footer}. Hyperdoc
will always try to keep the header and footer regions visible on the
page; the header at the top and the footer at the bottom. The middle
scroll region will be truncated and a scroll bar will be automatically
provided if the window becomes too small for the whole contents of the
page. Only one scroll region can be defined in a page and the correct
syntax is as follows:
\beginImportant
{\tt \\begin\{scroll\}}
\newline
.
\newline
.
\newline
.
\newline
{\tt \\end\{scroll\}}
\beginImportant

This group should be placed inside the relevant page group. The text
between the {\tt \\begin\{page\}} and {\tt \\begin\{scroll\}} commands
defines the header region, the text inside the scroll group defines
the scroll region and the text between the {\tt \\end\{scroll\}} and
{\tt \\end\{page\}} commands defines the footer region. It is
important to keep the header and footer areas small.  Use them to
display information that might be needed at any time by the user.  If
you don't define a scroll region in your page, you may find that a
portion of the page is truncated.

You are now ready to experiment with a page of your own. If you just
want to display some text on a page, you don't need any other
Hyperdoc commands. Just make sure that the text you type for the
title, header, scroll and footer regions does not contain (for the
moment) any of the Hyperdoc special characters.

\end{scroll}
\beginmenu
\menuwindowlink{Try out what you learned}{HTXTryPage}
\menudownlink{Next -- Learn how to format text}{HTXFormatTopPage}
\endmenu
\end{page}


\end{chunk}
\section{htxintrotoppage.ht}
\pagetitle{HTXIntroTopPage}{htxintrotoppage.ht}{First Steps}
\pageto{notitle}{HTXIntroPage1}
\pageto{notitle}{HTXIntroPage2}
\pageto{notitle}{HTXIntroPage3}
\begin{chunk}{htxintrotoppage.ht}
\begin{page}{HTXIntroTopPage}{First Steps}
\centerline{\fbox{{\tt \thispage}}}\newline
\beginscroll

Hyperdoc is both a way of presenting information and
a customisable front-end. Axiom uses
it for its own purpose as a front-end and documentation system.
Hyperdoc has special facilities that allow it to interact
very closely with Axiom.  The \Browse{} facility, the Basic
Commands section and the ability to execute Axiom commands
by clicking on Hyperdoc text are witness to this.

These pages will show you the features of Hyperdoc that might
make it appropriate for your own use in, for example, providing
documentation for Axiom code that you write or some other purpose.

It is recommended that you get familiar with the {\em use} of
Hyperdoc before proceeding.

\endscroll
\beginmenu
\menudownlink{What Hyperdoc does}{HTXIntroPage1}
\menudownlink{How Hyperdoc does it}{HTXIntroPage2}
\menudownlink{Define a simple text page}{HTXIntroPage3}
\endmenu

\end{page}

\end{chunk}
\section{htxlinkpage1.ht}
\pagetitle{HTXLinkPage1}{htxlinkpage1.ht}{Linking to a named page}
\pageto{notitle}{HTXLinkTopPage}
\pageto{notitle}{TestHelpPage}
\pageto{notitle}{HTXLinkPage2}
\begin{chunk}{htxlinkpage1.ht}
\begin{page}{HTXLinkPage1}{Linking to a named page}
\centerline{\fbox{{\tt \thispage}}}\newline
\begin{scroll}

In Hyperdoc, hypertext links are specified by different flavors of the
{\tt \\link} command. These commands take two arguments. One argument
specifies the active area, that is, the {\it trigger} of the link. The
second argument specifies the {\it target} of the link, that is, a
page. The trigger can be quite arbitrary Hyperdoc text and can include
images or whole paragraphs. The trigger text will be formatted in the
normal fashion but its default font will be the font specified by the
ActiveFont resource.

The simplest kind of Hyperdoc link is a link to a named page.
Clicking on the trigger will cause the named page to appear in a
Hyperdoc window.
There are three flavors for such a link.
\begin{items}[123456]
\item\menuitemstyle{{\tt \\windowlink\{{\it trigger}\}
\{{\it page name}\}}}
\newline
This link command, when activated, will create a new 
window for the named page.
\newline
There will be no \centerline{\UpBitmap{}  or \ReturnBitmap{}}  
buttons on the new page.
The new page will have a \centerline{\ExitBitmap{}} button, however.
The original page containing the {\tt \\windowlink} 
command will be unaffected.
\item\menuitemstyle{{\tt \\downlink\{{\it trigger}\}\{{\it page name}\}} }
\newline This link command, when activated, will cause the
current page to be replaced by the target page
in the same Hyperdoc window.
A \centerline{\UpBitmap{}}  button will automatically be placed
on the new page allowing you to get back to the page
containing the {\tt \\downlink} command.
If the current page has a \centerline{\ReturnBitmap{}} button then
the target page will also carry it. The associated
target page of that button will be the same as it is
in the current page.
\item\menuitemstyle{{\tt \\memolink\{{\it trigger}\}\{{\it page name}\}}}
\newline This link command is similar to the {\tt \\downlink} command.
In addition, it will cause a \centerline{\ReturnBitmap{}}  
button to be included in
the target page and all pages {\tt \\downlink}ed from it. 
This button will act as a
direct link to the page containing the {\tt \\memolink} command allowing
a short-cut to be taken.
\end{items}

\beginImportant
\begin{paste}{HTXLinkPage1xPaste1}{HTXLinkPage1xPatch1}
\pastebutton{HTXLinkPage1xPaste1}{Interpret}
\newline
{\tt \\windowlink
\{windowlink to Actions menu\}\{HTXLinkTopPage\}\\newline}
\newline
{\tt \\downlink\{downlink to Actions menu\}\{HTXLinkTopPage\}\\newline}
\newline
{\tt \\memolink\{memolink to Actions menu\}\{HTXLinkTopPage\}}
\end{paste}
\endImportant


There is a fourth button that can appear at the top of the page
next to the \centerline{\ExitBitmap{}} button.
Its purpose is to provide access to a particular {\it help page}
associated with the current page.
That is the \centerline{\HelpBitmap{}} button. The command to use
is
\centerline{{\tt \\helppage\{{\it help page name}\}}}
The {\tt \\helppage} command {\it must } be placed
just before the {\tt \\end\{page\}} command.
For instance, to get a help button on this page
the following command is used.
\centerline{{\tt {\\helppage\{TestHelpPage\}}}}
Clicking on the help button at the top
will display the {\tt TestHelpPage} page in a new window.

\end{scroll}
\beginmenu
\menulink{Next -- Standard Pages}{HTXLinkPage2}
\endmenu

\helppage{TestHelpPage}
\end{page}

\end{chunk}
\subsection{HTXLinkPage1xPatch1 patch}
\label{HTXLinkPage1xPatch1}
\index{patch!HTXLinkPage1xPatch1!htxlinkpage1.ht}
\index{htxlinkpage1.ht!patch!HTXLinkPage1xPatch1}
\index{HTXLinkPage1xPatch1!htxlinkpage1.ht!patch}
\begin{chunk}{htxlinkpage1.ht}
\begin{patch}{HTXLinkPage1xPatch1}
\begin{paste}{HTXLinkPage1xPaste1A}{HTXLinkPage1xPatch1A}
\pastebutton{HTXLinkPage1xPaste1A}{Source}
\newline
\windowlink{windowlink to Actions
menu}{HTXLinkTopPage}\newline
\downlink{downlink to Actions menu}{HTXLinkTopPage}\newline
\memolink{memolink to Actions menu}{HTXLinkTopPage}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXLinkPage1xPatch1A patch}
\label{HTXLinkPage1xPatch1A}
\index{patch!HTXLinkPage1xPatch1A!htxlinkpage1.ht}
\index{htxlinkpage1.ht!patch!HTXLinkPage1xPatch1A}
\index{HTXLinkPage1xPatch1A!htxlinkpage1.ht!patch}
\begin{chunk}{htxlinkpage1.ht}
\begin{patch}{HTXLinkPage1xPatch1A}
\begin{paste}{HTXLinkPage1xPaste1B}{HTXLinkPage1xPatch1}
\pastebutton{HTXLinkPage1xPaste1B}{Interpret}
\newline
{\tt \\windowlink
\{windowlink to Actions menu\}\{HTXLinkTopPage\}\\newline}
\newline
{\tt \\downlink\{downlink to Actions menu\}\{HTXLinkTopPage\}\\newline}
\newline
{\tt \\memolink\{memolink to Actions menu\}\{HTXLinkTopPage\}}
\end{paste}
\end{patch}

\end{chunk}
\pagetitle{TestHelpPage}{htxlinkpage1.ht}{Test Help Page}
\begin{chunk}{htxlinkpage1.ht}
\begin{page}{TestHelpPage}{Test Help Page}
\begin{scroll}

\vspace{100}
\centerline{Is this any help?}
\end{scroll}
\end{page}

\end{chunk}
\section{htxlinkpage2.ht}
\pagetitle{HTXLinkPage2}{htxlinkpage2.ht}{Standard Pages}
\pageto{notitle}{HTXLinkPage6}
\pageto{notitle}{SpadNotConnectedPage}
\pageto{notitle}{UnknownPage}
\pageto{notitle}{ErrorPage}
\pageto{notitle}{ProtectedQuitPage}
\pageto{notitle}{HTXLinkPage3}
\begin{chunk}{htxlinkpage2.ht}
\begin{page}{HTXLinkPage2}{Standard Pages}
\centerline{\fbox{{\tt \thispage}}}\newline
\begin{scroll}

You have reached this page after performing
a series of mouse clicks on Hyperdoc
active areas. Each time, a {\tt \\link}
command was activated. Well, how does it all
start?
The answer is that Hyperdoc always puts up
a particular page called {\tt RootPage} when
it starts up. If this page is not found in the database,
Hyperdoc will immediately exit.
It is, of course, desirable that the {\tt RootPage}
contains links to other pages!
It is possible to override
Axiom's choice of {\tt RootPage} and provide your own
to Hyperdoc. This is done in the same way as
you would override any Axiom-defined page and is
discussed in \downlink{How to use your pages with Hyperdoc}{HTXLinkPage6}.



You may have noticed that Hyperdoc
uses some pages when certain events occur.
There is a page that is put up, for instance,
whenever Hyperdoc cannot connect to Axiom.
Another page is put up whenever there is a formatting
error and yet another when a request for an unknown page
is made. Finally, there is a page that prompts
for confirmation when you press the
exit button on the initial page.


These pages have standard names and must be provided
in the Hyperdoc page database.
They are already defined in the Axiom system
Hyperdoc page database so that you do not have to
define them yourself.

Here are the pages required by Hyperdoc. You can click on any of these
to see their contents. Click on their exit buttons when you are finished.

\beginImportant
\begin{paste}{HTXLinkPage2xPaste1}{HTXLinkPage2xPatch1}
\pastebutton{HTXLinkPage2xPaste1}{Interpret}
\newline
{\tt \\table\{}\newline
{\tt \{\\windowlink\{SpadNotConnectedPage\}\{SpadNotConnectedPage\}\}}
\newline
{\tt \{\\windowlink\{UnknownPage\}\{UnknownPage\}\}}\newline
{\tt \{\\windowlink\{ErrorPage\}\{ErrorPage\}\}}\newline
{\tt \{\\windowlink\{ProtectedQuitPage\}\{ProtectedQuitPage\}\}}\newline
{\tt \}}\newline
\end{paste}
\endImportant


In addition, Hyperdoc uses certain bitmaps for its buttons.
They are also provided in the Axiom system
bitmap directory and Hyperdoc knows where to find them.

The bitmap files required by Hyperdoc are the following.
\newline
\tab{7}{\it exit.bitmap}\tab{22} = \tab{25}{\ExitBitmap{}} \newline
\tab{7}{\it help2.bitmap}\tab{22} = \tab{25}{\HelpBitmap{}} \newline
\tab{7}{\it up3.bitmap}\tab{22} = \tab{25}{\UpBitmap{}}\newline
\tab{7}{\it return3.bitmap}\tab{22} = \tab{25}{\ReturnBitmap{}}\newline
\tab{7}{\it noop.bitmap}\tab{22} = \tab{25}{\NoopBitmap{}}

These files must exist in your current directory if
the {\tt AXIOM} environment variable is not set.
If it is, then Hyperdoc will assume that it points
to the Axiom system directory and will look for
these files in
{\bf \$AXIOM/doc/bitmaps}.

\end{scroll}
\beginmenu
\menulink{Next -- Active Axiom commands}{HTXLinkPage3}
\endmenu

\end{page}

\end{chunk}
\subsection{HTXLinkPage2xPatch1 patch}
\label{HTXLinkPage2xPatch1}
\index{patch!HTXLinkPage2xPatch1!htxlinkpage2.ht}
\index{htxlinkpage2.ht!patch!HTXLinkPage2xPatch1}
\index{HTXLinkPage2xPatch1!htxlinkpage2.ht!patch}
\begin{chunk}{htxlinkpage2.ht}
\begin{patch}{HTXLinkPage2xPatch1}
\begin{paste}{HTXLinkPage2xPaste1A}{HTXLinkPage2xPatch1A}
\pastebutton{HTXLinkPage2xPaste1A}{Source}
\newline
\table{
{\windowlink{SpadNotConnectedPage}{SpadNotConnectedPage}}
{\windowlink{UnknownPage}{UnknownPage}}
{\windowlink{ErrorPage}{ErrorPage}}
{\windowlink{ProtectedQuitPage}{ProtectedQuitPage}}
}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXLinkPage2xPatch1A patch}
\label{HTXLinkPage2xPatch1A}
\index{patch!HTXLinkPage2xPatch1A!htxlinkpage2.ht}
\index{htxlinkpage2.ht!patch!HTXLinkPage2xPatch1A}
\index{HTXLinkPage2xPatch1A!htxlinkpage2.ht!patch}
\begin{chunk}{htxlinkpage2.ht}
\begin{patch}{HTXLinkPage2xPatch1A}
\begin{paste}{HTXLinkPage2xPaste1B}{HTXLinkPage2xPatch1}
\pastebutton{HTXLinkPage2xPaste1B}{Interpret}
\newline
{\tt \\table\{}\newline
{\tt \{\\windowlink\{SpadNotConnectedPage\}\{SpadNotConnectedPage\}\}}
\newline
{\tt \{\\windowlink\{UnknownPage\}\{UnknownPage\}\}}\newline
{\tt \{\\windowlink\{ErrorPage\}\{ErrorPage\}\}}\newline
{\tt \{\\windowlink\{ProtectedQuitPage\}\{ProtectedQuitPage\}\}}\newline
{\tt \}}\newline
\end{paste}
\end{patch}

\end{chunk}
\section{htxlinkpage3.ht}
\pagetitle{HTXLinkPage3}{htxlinkpage3.ht}{Active Axiom commands}
\pageto{notitle}{HTXLinkPage4}
\begin{chunk}{htxlinkpage3.ht.ht}
\begin{page}{HTXLinkPage3}{Active Axiom commands}
\centerline{\fbox{{\tt \thispage}}}\newline
\begin{scroll}

This section explains how to include Axiom
commands in your page. The commands we will
introduce are actually {\it macros} that are defined
in
\centerline{{\bf \env{AXIOM}/doc/util.ht}}
This means that you can use them only if you include
this file in your Hyperdoc database.

The first command to learn is
\horizontalline
{\tt \\axiomcommand\{ {\it command }
{\tt \ \\free\{}{\it var1 var2 ...}
{\tt \}\ \\bound\{}{\it var}{\tt \}\ \}} }
\horizontalline


The {\tt \\free\{\}} and {\tt \\bound\{\}} directives are optional.
We will come to them in a minute. The {\it command} above is the
text of the Axiom command. Only single line commands are allowed
here.
This text will be displayed in the reserved AxiomFont logical
font.  The area of the text will be active and clicking on it
will attempt to send the command to Axiom for evaluation.
A new Axiom interpreter window (and Axiom frame)
will be created if this was the first Axiom command
activated in the current page. If not, the command will be sent
to the already opened Axiom interpreter window for the current page.
Note that it {\it is} necessary to escape special
Hyperdoc characters with the {\tt '\\'} backslash character.
The exceptions are the characters {\tt \[\]}; they do not
need to be escaped in this context.

\beginImportant
\begin{paste}{HTXLinkPage3xPaste1}{HTXLinkPage3xPatch1}
\pastebutton{HTXLinkPage3xPaste1}{Interpret}
\newline
{\tt \\axiomcommand\{ l:=brace[1,2,3] ; length:=\\\# l ; m:=[1,2]\}}
\end{paste}
\endImportant


The optional {\tt \\free\{\}} and {\tt \\bound\{\}} directives
provide dependency control. The reader of a Hyperdoc
page is not forced to click on the commands in the
order in which in they appear on the page.  If the
correct {\tt \\free\{\}} and {\tt \\bound\{\}}
specifications are made, clicking on a command
will result in execution of all those other
commands that should be executed before it.
This will {\it only} happen the first time the command is
clicked.

So, how are the dependencies specified?  The arguments of the {\tt
\\free\{\}} directive must be space-separated words (labels). The
argument of {\tt \\bound\{\}} must be a single (unique for the page)
label. Each label in the {\tt \\free\{\}} list must exist as an
argument to one (and only one) {\tt \\bound\{\}} directive somewhere
in the current page.  When the command is activated, Hyperdoc will
look in the {\tt \\free\{\}} list and check each label.  For each
label, it will find the command that specifies that label in its {\tt
\\bound\{\}} directive and execute it if it has not been already
executed.  The order of labels in the {\tt \\free\{\}} directive list
is respected. Hyperdoc will follow all dependency links recursively.

Here is  an example.
Clicking on the third command will automatically
execute all of them in the correct sequence.
Note that in this case the order of labels in the last
line is immaterial since {\tt v2} explicitly depends on {\tt v1}.

\beginImportant
\begin{paste}{HTXLinkPage3xPaste2}{HTXLinkPage3xPatch2}
\pastebutton{HTXLinkPage3xPaste2}{Interpret}
\newline
{\tt \\axiomcommand\{a:=1;d:=4 \\bound\{v1\}\}}\newline
{\tt \\newline}\newline
{\tt \\axiomcommand\{b:=a+3 \\free\{v1\} \\bound\{v2\}\}}\newline
{\tt \\newline}\newline
{\tt \\axiomcommand\{c:=b+d \\free\{v1 v2\} \\bound\{v3\}\}}\newline
\end{paste}
\endImportant

The second command deals with multi-line Axiom
code. This is the command to use for execution of
an Axiom {\it pile}. It is a {\it group}
command. The proper syntax for it is as follows:
\horizontalline
{\tt \\begin\{spadsrc\}
\ [\\free\{{\it var1 var2} ...\}\ \\bound\{{\it var}\}]}
\newline
.
\newline
.
\newline
{\tt \\end\{spadsrc\}}
\horizontalline

Again, the {\tt \\free} and {\tt \\bound} directives are
optional. If they are specified (in exactly the same way
as {\tt \\axiomcommand}), they must be enclosed in
square brackets {\tt []}.
The lines between the {\tt \\begin} and {\tt \\end}
contain the Axiom statements. Indentation
will be respected. Hyperdoc will
actually save this part in a temporary file
and instruct Axiom to read the file
with the {\tt )read} system command.

Here is an example. The execution of the following
fragment is dependent on the {\tt v3} label.
Make sure that previous commands are active (and
hence the label {\tt v3} is "visible") before
trying to execute it. If the label {\tt v3}
is not seen in the page, Hyperdoc will
print an error message on standard output
and ignore the dependency.


\beginImportant
\begin{paste}{HTXLinkPage3xPaste3}{HTXLinkPage3xPatch3}
\pastebutton{HTXLinkPage3xPaste3}{Interpret}
\newline
{\tt \\begin\{spadsrc\}\ [\\free\{v3\}\ \\bound\{v4\}]}\newline
{\tt f\ x\ ==}\newline
{\tt \ \ \ x+c}\newline
{\tt f\ 3}\newline
{\tt \\end\{spadsrc\}}
\end{paste}
\endImportant

There is, in fact, more that one can do
with Axiom commands. In pages elsewhere
in the system, Axiom commands appear next
to button like this \ \MenuDotBitmap{}.
Clicking on this button, one can see the output
for that command. The output has been
pre-computed and is also stored in
Hyperdoc files. This is done using
{\it patch} and {\it paste}.
It is the same mechanism that
is used to alternatively display
Hyperdoc source and interpreted
result in this and other pages.
It is explained \downlink{later on}{HTXAdvPage5}.


\end{scroll}
\beginmenu
\menulink{Next -- Linking to Lisp}{HTXLinkPage4}
\endmenu

\end{page}

\end{chunk}
\subsection{HTXLinkPage3xPatch1 patch}
\label{HTXLinkPage3xPatch1}
\index{patch!HTXLinkPage3xPatch1!htxlinkpage3.ht}
\index{htxlinkpage3.ht!patch!HTXLinkPage3xPatch1}
\index{HTXLinkPage3xPatch1!htxlinkpage3.ht!patch}
\begin{chunk}{htxlinkpage3.ht}
\begin{patch}{HTXLinkPage3xPatch1}
\begin{paste}{HTXLinkPage3xPaste1A}{HTXLinkPage3xPatch1A}
\pastebutton{HTXLinkPage3xPaste1A}{Source}
\newline
\axiomcommand{ l:=brace[1,2,3] ; length:=\# l ; m:=[1,2]}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXLinkPage3xPatch1A patch}
\label{HTXLinkPage3xPatch1A}
\index{patch!HTXLinkPage3xPatch1A!htxlinkpage3.ht}
\index{htxlinkpage3.ht!patch!HTXLinkPage3xPatch1A}
\index{HTXLinkPage3xPatch1A!htxlinkpage3.ht!patch}
\begin{chunk}{htxlinkpage3.ht}
\begin{patch}{HTXLinkPage3xPatch1A}
\begin{paste}{HTXLinkPage3xPaste1B}{HTXLinkPage3xPatch1}
\pastebutton{HTXLinkPage3xPaste1B}{Interpret}
\newline
{\tt \\axiomcommand\{ l:=brace[1,2,3] ; length:=\\\# l ; m:=[1,2]\}}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXLinkPage3xPatch2 patch}
\label{HTXLinkPage3xPatch2}
\index{patch!HTXLinkPage3xPatch2!htxlinkpage3.ht}
\index{htxlinkpage3.ht!patch!HTXLinkPage3xPatch2}
\index{HTXLinkPage3xPatch2!htxlinkpage3.ht!patch}
\begin{chunk}{htxlinkpage3.ht}
\begin{patch}{HTXLinkPage3xPatch2}
\begin{paste}{HTXLinkPage3xPaste2A}{HTXLinkPage3xPatch2A}
\pastebutton{HTXLinkPage3xPaste2A}{Source}
\newline
\axiomcommand{a:=1;d:=4 \bound{v1}}
\newline
\axiomcommand{b:=a+3 \free{v1} \bound{v2}}
\newline
\axiomcommand{c:=b+d \free{v1 v2} \bound{v3}}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXLinkPage3xPatch2A patch}
\label{HTXLinkPage3xPatch2A}
\index{patch!HTXLinkPage3xPatch2A!htxlinkpage3.ht}
\index{htxlinkpage3.ht!patch!HTXLinkPage3xPatch2A}
\index{HTXLinkPage3xPatch2A!htxlinkpage3.ht!patch}
\begin{chunk}{htxlinkpage3.ht}
\begin{patch}{HTXLinkPage3xPatch2A}
\begin{paste}{HTXLinkPage3xPaste2B}{HTXLinkPage3xPatch2}
\pastebutton{HTXLinkPage3xPaste2B}{Interpret}
\newline
{\tt \\axiomcommand\{a:=1;d:=4 \\bound\{v1\}\}}\newline
{\tt \\newline}\newline
{\tt \\axiomcommand\{b:=a+3 \\free\{v1\} \\bound\{v2\}\}}\newline
{\tt \\newline}\newline
{\tt \\axiomcommand\{c:=b+d \\free\{v1 v2\} \\bound\{v3\}\}}\newline
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXLinkPage3xPatch3 patch}
\label{HTXLinkPage3xPatch3}
\index{patch!HTXLinkPage3xPatch3!htxlinkpage3.ht}
\index{htxlinkpage3.ht!patch!HTXLinkPage3xPatch3}
\index{HTXLinkPage3xPatch3!htxlinkpage3.ht!patch}
\begin{chunk}{htxlinkpage3.ht}
\begin{patch}{HTXLinkPage3xPatch3}
\begin{paste}{HTXLinkPage3xPaste3A}{HTXLinkPage3xPatch3A}
\pastebutton{HTXLinkPage3xPaste3A}{Source}
\newline
\begin{spadsrc} [\free{v3} \bound{v4}]
f x ==
   x+c
f 3
\end{spadsrc}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXLinkPage3xPatch3A patch}
\label{HTXLinkPage3xPatch3A}
\index{patch!HTXLinkPage3xPatch3A!htxlinkpage3.ht}
\index{htxlinkpage3.ht!patch!HTXLinkPage3xPatch3A}
\index{HTXLinkPage3xPatch3A!htxlinkpage3.ht!patch}
\begin{chunk}{htxlinkpage3.ht}
\begin{patch}{HTXLinkPage3xPatch3A}
\begin{paste}{HTXLinkPage3xPaste3B}{HTXLinkPage3xPatch3}
\pastebutton{HTXLinkPage3xPaste3B}{Interpret}
\newline
{\tt \\begin\{spadsrc\}\ [\\free\{v3\}\ \\bound\{v4\}]}\newline
{\tt f\ x\ ==}\newline
{\tt \ \ \ x+c}\newline
{\tt f\ 3}\newline
{\tt \\end\{spadsrc\}}
\end{paste}
\end{patch}

\end{chunk}
\section{htxlinkpage4.ht}
\pagetitle{HTXLinkPage4}{htxlinkpage4.ht}{Linking to Lisp}
\pageto{notitle}{HTXLinkPage5}
\begin{chunk}{htxlinkpage4.ht}
\begin{page}{HTXLinkPage4}{Linking to Lisp}
\centerline{\fbox{{\tt \thispage}}}\newline
\begin{scroll}

Another feature of the Axiom\hspace{2}--Hyperdoc
link is the ability to execute {\it Lisp}
code at a click of a button.
There are two things one can do.

The first is to cause the evaluation
of a {\it Lisp} form and ignore (as far as Hyperdoc
is concerned) its value. The evaluation of the function
might have an effect however on your Axiom session.

The command for this is
\horizontalline
\centerline{ {\tt \\lispcommand\{{\it text}\}\{{\it Lisp form}\}}}
\horizontalline

Here is an example. We will first define a {\it Lisp} function
and then execute it.  Notice that the Hyperdoc
special characters must be escaped (this is on top
of {\it Lisp} escaping conventions).


\beginImportant
\begin{paste}{HTXLinkPage4xPaste1}{HTXLinkPage4xPatch1}
\pastebutton{HTXLinkPage4xPaste1}{Interpret}
\newline
{\tt \\lispcommand\{Definition\}\{(defun HTXTESTFUNCTION ()}\newline
{\tt  (print "Hello from HyperDoc \\\\\\\\ \\\% \\\{ \\\}"))\}} \newline
{\tt \\newline}\newline
{\tt \\lispcommand\{Execution\}\{(HTXTESTFUNCTION)\}} \newline
\end{paste}
\endImportant

Your command will be executed as soon as
Axiom completes any computation it might be
carrying out.


%\axiomcommand{)lisp (defun f () (pprint "hello"))}
%\lispcommand{f}{(|f|)}


The second thing you can do is quite powerful. It allows you
to delegate to a {\it Lisp} function
the {\it dynamic} creation of a page. This is used
in \Browse{} to present
the Axiom Library in a hypertext form.

The command to use is a lot like the {\tt link} commands
you encountered \downlink{earlier}{HTXLinkPage1} and comes in three 
flavors.
\centerline{{\tt \\lispwindowlink\{{\it trigger}\}\{{\it Lisp form}\}}}
\centerline{{\tt \\lispdownlink\{{\it trigger}\}\{{\it Lisp form}\}}}
\centerline{{\tt \\lispmemolink\{{\it trigger}\}\{{\it Lisp form}\}}}

The difference between the three versions is the same as before.
When such a link is activated, Hyperdoc issues the
{\it Lisp form} to Axiom and waits for a full
page definition. An important point to note is that
Hyperdoc does {\it not} use
the value of the {\it Lisp form} but, instead, it
depends on its {\it side-effects}.
What {\it must} happen during evaluation
of the form is enough evaluations of a special {\it Lisp}
function called {\bf issueHT} to define a page.
The argument of {\bf issueHT} is a string
containing Hyperdoc text. Perhaps an example will clarify
matters.

First we will define a {\it Lisp} function that accepts
a string argument and calls {\bf issueHT} a few times.
The strings that are passed to {\bf issueHT} construct
a Hyperdoc page that would just contain our
original argument centered roughly on the page.
Then we write the {\tt \\lisplink} with a call to
the function. Finally, we execute a {\it Lisp}
command that just pretty--prints the function's definition.



\beginImportant
\begin{paste}{HTXLinkPage4xPaste2}{HTXLinkPage4xPatch2}
\pastebutton{HTXLinkPage4xPaste2}{Interpret}
\newline
{\tt \\lispcommand\{Definition\}\{(defun HTXTESTPAGE (x) (|issueHT|}\newline
{\tt  "\\\\\\\\begin\\\{page\\\}\\\{LispTestPage\\\}\\\{Lisp Test Page\\\}}\newline
{\tt  \\\\\\\\vspace\\\{150\\\} \\\\\\\\centerline\\\{") (|issueHT| x) 
(|issueHT|}\newline
{\tt  "\\\} \\\\\\\\end\\\{page\\\}" ) ) \}}\newline
{\tt \\newline}\newline
{\tt \\lispwindowlink\{Link to it\}\{(HTXTESTPAGE "Hi there")\}}\newline
{\tt \\newline}\newline
{\tt \\lispcommand\{Show Lisp definition\}
\{(pprint (symbol-function 'HTXTESTPAGE))\}}\newline
\end{paste}
\endImportant

The {\tt '\\\{'} and {\tt '\\\}'} is required to escape
Hyperdoc's special characters {\tt '\{'} and {\tt  '\}'}.
The {\tt '\\\\\\\\'} has the following rationale.
We need to send to Hyperdoc (from {\it Lisp}) the sequence
{\tt \\begin}. But {\tt '\\'} is a special {\it Lisp}
character. Therefore the {\it Lisp} string must be
{\tt '\\\\begin'}. But to specify this
in Hyperdoc we need to escape the two {\tt '\\'}.
Therefore, we write {\tt '\\\\\\\\begin'}.


The definition of {\tt HTXTESTPAGE} would have been written in {\it Lisp}
as follows.
\begin{verbatim}
(defun HTXTESTPAGE (X)
   (|issueHT|
      "\\begin{page}{LispTestPage}{Lisp Test Page} 
\\vspace{200} \\centerline{")
   (|issueHT| X)
   (|issueHT| "} \\end{page}"))
\end{verbatim}



You should not execute {\tt HTXTESTPAGE} in the
{\it Lisp} environment manually. It is meant to
be executed {\it only} in response to a
Hyperdoc request.

Can you pop-up a named page from {\it Lisp} regardless of
user action? Yes --- use {\it Lisp} function {\bf linkToHTPage}
with the page name as a string argument. Click on the
{\tt \\axiomcommand} below. Then, in your Axiom
session, you can repeat it if you like.

\beginImportant
\begin{paste}{HTXLinkPage4xPaste3}{HTXLinkPage4xPatch3}
\pastebutton{HTXLinkPage4xPaste3}{Interpret}
\newline
{\tt \\axiomcommand\{)lisp (|linkToHTPage| "RootPage")\}}
\end{paste}
\endImportant

You can also pop-up a {\it dynamic} page regardless of user action.
To do this, make sure you evaluate the {\it Lisp form}
{\bf (|startHTPage| 50)} before using {\bf issueHT}.
The example below requires the {\tt HTXTESTPAGE} function
to be defined in {\it Lisp} so you should make sure
you have executed the command above that defines it.

\beginImportant
\begin{paste}{HTXLinkPage4xPaste4}{HTXLinkPage4xPatch4}
\pastebutton{HTXLinkPage4xPaste4}{Interpret}
\newline
{\tt \\axiomcommand\{
)lisp (progn (|startHTPage| 50)(HTXTESTPAGE "Immediately"))\}}
\end{paste}
\endImportant

Now, the most important use of this facility
so far has been in the \Browse{} and Basic Commands components of
Hyperdoc. Instead of giving you details of the various
\Browse{} {\it Lisp} functions, a few macros are defined in
\centerline{{\bf \$AXIOM/doc/util.ht}}

The most important defined macros are
\beginImportant
\table{
{ {\tt \\axiomType\{{\it constructor}\}} }
{ {\tt \\axiomOp\{{\it operation}\}} }
{ {\tt \\axiomOpFrom\{{\it operation }\}\{{\it constructor}\}}}
}
\endImportant

Here are some examples of their use.
\beginImportant
\begin{paste}{HTXLinkPage4xPaste5}{HTXLinkPage4xPatch5}
\pastebutton{HTXLinkPage4xPaste5}{Interpret}
\newline
{\tt \\axiomType\{Expression Integer\}}\newline
{\tt \newline}\newline
{\tt \\axiomType\{Expression\}}\newline
{\tt \newline}\newline
{\tt \\axiomType\{EXPR\}}\newline
{\tt \newline}\newline
{\tt \\axiomOp\{reduce\}}\newline
{\tt \newline}\newline
{\tt \\axiomOp\{as*\}}\newline
{\tt \newline}\newline
{\tt \\axiomOpFrom\{reduce\}\{Expression\}}\newline
\end{paste}
\endImportant

The macro {\tt \\axiomType} brings up the \Browse{}
constructor page for the constructor specified.
You can specify a full name, or an abbreviation
or just the top level name.
The macro {\tt \\axiomOp} brings up a list of operations
matching the argument.
The macro {\tt \\axiomOpFrom} shows documentation
about the specified operation whose origin is
constructor. No wildcard in the operation name
or type abbreviation is
allowed here.  You should also specify just the top level type.

\end{scroll}
\beginmenu
\menulink{Next -- Linking to Unix}{HTXLinkPage5}
\endmenu

\end{page}

\end{chunk}
\pagetitle{HTXLinkPage4xPatch1}{htxlinkpage4.ht}{HTXLinkPage4xPatch1 patch}
\begin{chunk}{htxlinkpage4.ht}
\begin{patch}{HTXLinkPage4xPatch1}
\begin{paste}{HTXLinkPage4xPaste1A}{HTXLinkPage4xPatch1A}
\pastebutton{HTXLinkPage4xPaste1A}{Source}
\newline
\lispcommand{Definition}{(defun HTXTESTFUNCTION ()
(print "Hello from HyperDoc \\\\ \% \{ \}"))}
\newline
\lispcommand{Execution}{(HTXTESTFUNCTION)}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXLinkPage4xPatch1A patch}
\label{HTXLinkPage4xPatch1A}
\index{patch!HTXLinkPage4xPatch1A!htxlinkpage4.ht}
\index{htxlinkpage4.ht!patch!HTXLinkPage4xPatch1A}
\index{HTXLinkPage4xPatch1A!htxlinkpage4.ht!patch}
\begin{chunk}{htxlinkpage4.ht}
\begin{patch}{HTXLinkPage4xPatch1A}
\begin{paste}{HTXLinkPage4xPaste1B}{HTXLinkPage4xPatch1}
\pastebutton{HTXLinkPage4xPaste1B}{Interpret}
\newline
{\tt \\lispcommand\{Definition\}\{
(defun HTXTESTFUNCTION ()
 (print "Hello from HyperDoc \\\\\\\\ \\\% \\\{ \\\}"))\}} \newline
{\tt \\newline}\newline
{\tt \\lispcommand\{Execution\}\{(HTXTESTFUNCTION)\}} \newline
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXLinkPage4xPatch2 patch}
\label{HTXLinkPage4xPatch2}
\pageto{Definition}{LispFunctions}
\index{patch!HTXLinkPage4xPatch2!htxlinkpage4.ht}
\index{htxlinkpage4.ht!patch!HTXLinkPage4xPatch2}
\index{HTXLinkPage4xPatch2!htxlinkpage4.ht!patch}
\begin{chunk}{htxlinkpage4.ht}
\begin{patch}{HTXLinkPage4xPatch2}
\begin{paste}{HTXLinkPage4xPaste2A}{HTXLinkPage4xPatch2A}
\pastebutton{HTXLinkPage4xPaste2A}{Source}
\newline
\lispcommand{Definition}{(defun HTXTESTPAGE (x) (|issueHT|
"\\\\begin\{page\}\{LispTestPage\}\{Lisp Test Page\}
\\\\vspace\{150\} \\\\centerline\{") (|issueHT| x) (|issueHT|
"\} \\\\end\{page\}" ) ) }
\newline
\lispwindowlink{Link to it}{(HTXTESTPAGE "Hi there")}
\newline
\lispcommand{Show Lisp definition}{(pprint (symbol-function 'HTXTESTPAGE))}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXLinkPage4xPatch2A patch}
\label{HTXLinkPage4xPatch2A}
\index{patch!HTXLinkPage4xPatch2A!htxlinkpage4.ht}
\index{htxlinkpage4.ht!patch!HTXLinkPage4xPatch2A}
\index{HTXLinkPage4xPatch2A!htxlinkpage4.ht!patch}
\begin{chunk}{htxlinkpage4.ht}
\begin{patch}{HTXLinkPage4xPatch2A}
\begin{paste}{HTXLinkPage4xPaste2B}{HTXLinkPage4xPatch2}
\pastebutton{HTXLinkPage4xPaste2B}{Interpret}
\newline
{\tt \\lispcommand\{Definition\}\{(defun HTXTESTPAGE (x) 
(|issueHT|}\newline
{\tt  "\\\\\\\\begin\\\{page\\\}\\\{LispTestPage\\\}
\\\{Lisp Test Page\\\}}\newline
{\tt  \\\\\\\\vspace\\\{150\\\} \\\\\\\\centerline\\\{") 
(|issueHT| x) (|issueHT|}\newline
{\tt  "\\\} \\\\\\\\end\\\{page\\\}" ) ) \}}\newline
{\tt \\newline}\newline
{\tt \\lispwindowlink\{Link to it\}\{(HTXTESTPAGE "Hi there")\}}
\newline
{\tt \\newline}\newline
{\tt \\lispcommand\{Show Lisp definition\}
\{(pprint (symbol-function 'HTXTESTPAGE))\}}\newline
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXLinkPage4xPatch3 patch}
\label{HTXLinkPage4xPatch3}
\index{patch!HTXLinkPage4xPatch3!htxlinkpage4.ht}
\index{htxlinkpage4.ht!patch!HTXLinkPage4xPatch3}
\index{HTXLinkPage4xPatch3!htxlinkpage4.ht!patch}
\begin{chunk}{htxlinkpage4.ht}
\begin{patch}{HTXLinkPage4xPatch3}
\begin{paste}{HTXLinkPage4xPaste3A}{HTXLinkPage4xPatch3A}
\pastebutton{HTXLinkPage4xPaste3A}{Source}
\newline
\axiomcommand{)lisp (|linkToHTPage| "RootPage")}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXLinkPage4xPatch3A patch}
\label{HTXLinkPage4xPatch3A}
\index{patch!HTXLinkPage4xPatch3A!htxlinkpage4.ht}
\index{htxlinkpage4.ht!patch!HTXLinkPage4xPatch3A}
\index{HTXLinkPage4xPatch3A!htxlinkpage4.ht!patch}
\begin{chunk}{htxlinkpage4.ht}
\begin{patch}{HTXLinkPage4xPatch3A}
\begin{paste}{HTXLinkPage4xPaste3B}{HTXLinkPage4xPatch3}
\pastebutton{HTXLinkPage4xPaste3B}{Interpret}
\newline
{\tt \\axiomcommand\{)lisp (|linkToHTPage| "RootPage")\}}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXLinkPage4xPatch4 patch}
\label{HTXLinkPage4xPatch4}
\index{patch!HTXLinkPage4xPatch4!htxlinkpage4.ht}
\index{htxlinkpage4.ht!patch!HTXLinkPage4xPatch4}
\index{HTXLinkPage4xPatch4!htxlinkpage4.ht!patch}
\begin{chunk}{htxlinkpage4.ht}
\begin{patch}{HTXLinkPage4xPatch4}
\begin{paste}{HTXLinkPage4xPaste4A}{HTXLinkPage4xPatch4A}
\pastebutton{HTXLinkPage4xPaste4A}{Source}
\newline
\axiomcommand{)lisp (progn (|startHTPage| 50)(HTXTESTPAGE "Immediately"))}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXLinkPage4xPatch4A patch}
\label{HTXLinkPage4xPatch4A}
\index{patch!HTXLinkPage4xPatch4A!htxlinkpage4.ht}
\index{htxlinkpage4.ht!patch!HTXLinkPage4xPatch4A}
\index{HTXLinkPage4xPatch4A!htxlinkpage4.ht!patch}
\begin{chunk}{htxlinkpage4.ht}
\begin{patch}{HTXLinkPage4xPatch4A}
\begin{paste}{HTXLinkPage4xPaste4B}{HTXLinkPage4xPatch4}
\pastebutton{HTXLinkPage4xPaste4B}{Interpret}
\newline
{\tt \\axiomcommand\{
)lisp (progn (|startHTPage| 50)(HTXTESTPAGE "Immediately"))\}}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXLinkPage4xPatch5 patch}
\label{HTXLinkPage4xPatch5}
\index{patch!HTXLinkPage4xPatch5!htxlinkpage4.ht}
\index{htxlinkpage4.ht!patch!HTXLinkPage4xPatch5}
\index{HTXLinkPage4xPatch5!htxlinkpage4.ht!patch}
\begin{chunk}{htxlinkpage4.ht}
\begin{patch}{HTXLinkPage4xPatch5}
\begin{paste}{HTXLinkPage4xPaste5A}{HTXLinkPage4xPatch5A}
\pastebutton{HTXLinkPage4xPaste5A}{Source}
\newline
\axiomType{Expression Integer}
\newline
\axiomType{Expression}
\newline
\axiomType{EXPR}
\newline
\axiomOp{reduce}
\newline
\axiomOp{as*}
\newline
\axiomOpFrom{reduce}{Expression}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXLinkPage4xPatch5A patch}
\label{HTXLinkPage4xPatch5A}
\index{patch!HTXLinkPage4xPatch5A!htxlinkpage4.ht}
\index{htxlinkpage4.ht!patch!HTXLinkPage4xPatch5A}
\index{HTXLinkPage4xPatch5A!htxlinkpage4.ht!patch}
\begin{chunk}{htxlinkpage4.ht}
\begin{patch}{HTXLinkPage4xPatch5A}
\begin{paste}{HTXLinkPage4xPaste5B}{HTXLinkPage4xPatch5}
\pastebutton{HTXLinkPage4xPaste5B}{Interpret}
\newline
{\tt \\axiomType\{Expression Integer\}}\newline
{\tt \newline}\newline
{\tt \\axiomType\{Expression\}}\newline
{\tt \newline}\newline
{\tt \\axiomType\{EXPR\}}\newline
{\tt \newline}\newline
{\tt \\axiomOp\{reduce\}}\newline
{\tt \newline}\newline
{\tt \\axiomOp\{as*\}}\newline
{\tt \newline}\newline
{\tt \\axiomOpFrom\{reduce\}\{Expression\}}\newline
\end{paste}
\end{patch}

\end{chunk}
\section{htxlinkpage5.ht}
\pagetitle{HTXLinkPage5}{htxlinkpage5.ht}{Linking to Unix}
\begin{chunk}{htxlinkpage5.ht}
\begin{page}{HTXLinkPage5}{Linking to Unix}
\centerline{\fbox{{\tt \thispage}}}\newline
\begin{scroll}

Let us conclude the tour of Hyperdoc
actions that can be triggered with a click of a button
with two more facilities. These are
\beginImportant
\table{
{ {\tt \\unixcommand\{{\it trigger text}\}\{{\it unix command}\}}}
{ {\tt \\unixlink\{{\it trigger text}\}\{{\it unix command}\}}}
}
\endImportant


The first one, {\tt \\unixcommand}, is very much like
{\tt \\axiomcommand} and {\tt \\lispcommand}.
The trigger text becomes an active area. Clicking on it
will force Hyperdoc to pass the second argument
to the system as a shell command to be executed.
The shell used is {\bf /bin/sh}.
Hyperdoc ignores the output of the command.


\beginImportant
\begin{paste}{HTXLinkPage5xPaste1}{HTXLinkPage5xPatch1}
\pastebutton{HTXLinkPage5xPaste1}{Interpret}
\newline
{\tt \\unixcommand\{List \\\$HOME directory\}\{ls \\\$HOME\}}\newline
\end{paste}
\endImportant

The {\tt \\unixlink} command delegates to a another
program the creation of a dynamic page. When the trigger
text is activated, Hyperdoc will invoke the command
specified in the second argument. It will then start reading
the {\it standard output} of the command until
a complete page has been received. It is important that
a single page and nothing more is written by the command.
This command is essentially a {\tt \\downlink}, i.e.
the new page replaces the current page in the window.
There aren't any other flavours of {\tt \\unixlink}.
A trivial example is to use {\bf cat} on a Hyperdoc
file known to contain just one page.

\beginImportant
\begin{paste}{HTXLinkPage5xPaste2}{HTXLinkPage5xPatch2}
\pastebutton{HTXLinkPage5xPaste2}{Interpret}
\newline
{\tt \\unixlink\{Some file\}} \newline
{\tt \{cat\\ \\env\{AXIOM\}/doc/HTXplay.ht\}}
\end{paste}
\endImportant


Two things to notice in the second argument of
{\tt \\unixlink}: You must use a {\it hard space}
{\tt '\\\ '} to preserve the spacing in the command.
Also, the {\tt \\env} command allows you to use
an environment variable in Hyperdoc text.

With a little ingenuity (and maybe some shell and {\bf awk} scripts !)
, one can use these
facilities to create, say, a point-and-click
directory viewer which allows you to edit
a file by clicking on its name.

\end{scroll}
\beginmenu
\menulink{Next -- How to use your pages with Hyperdoc}{HTXLinkPage6}
\endmenu

\end{page}

\end{chunk}
\subsection{HTXLinkPage5xPatch1 patch}
\label{HTXLinkPage5xPatch1}
\index{patch!HTXLinkPage5xPatch1!htxlinkpage5.ht}
\index{htxlinkpage5.ht!patch!HTXLinkPage5xPatch1}
\index{HTXLinkPage5xPatch1!htxlinkpage5.ht!patch}
\begin{chunk}{htxlinkpage5.ht}
\begin{patch}{HTXLinkPage5xPatch1}
\begin{paste}{HTXLinkPage5xPaste1A}{HTXLinkPage5xPatch1A}
\pastebutton{HTXLinkPage5xPaste1A}{Source}
\newline
\unixcommand{List \$HOME directory}{ls \$HOME}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXLinkPage5xPatch1A patch}
\label{HTXLinkPage5xPatch1A}
\index{patch!HTXLinkPage5xPatch1A!htxlinkpage5.ht}
\index{htxlinkpage5.ht!patch!HTXLinkPage5xPatch1A}
\index{HTXLinkPage5xPatch1A!htxlinkpage5.ht!patch}
\begin{chunk}{htxlinkpage5.ht}
\begin{patch}{HTXLinkPage5xPatch1A}
\begin{paste}{HTXLinkPage5xPaste1B}{HTXLinkPage5xPatch1}
\pastebutton{HTXLinkPage5xPaste1B}{Interpret}
\newline
{\tt \\unixcommand\{List \\\$HOME directory\}\{ls \\\$HOME\}}\newline
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXLinkPage5xPatch2 patch}
\label{HTXLinkPage5xPatch2}
\index{patch!HTXLinkPage5xPatch2!htxlinkpage5.ht}
\index{htxlinkpage5.ht!patch!HTXLinkPage5xPatch2}
\index{HTXLinkPage5xPatch2!htxlinkpage5.ht!patch}
\begin{chunk}{htxlinkpage5.ht}
\begin{patch}{HTXLinkPage5xPatch2}
\begin{paste}{HTXLinkPage5xPaste2A}{HTXLinkPage5xPatch2A}
\pastebutton{HTXLinkPage5xPaste2A}{Source}
\newline
\unixlink{Some file}
{cat\ \env{AXIOM}/doc/HTXplay.ht}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXLinkPage5xPatch2A patch}
\label{HTXLinkPage5xPatch2A}
\index{patch!HTXLinkPage5xPatch2A!htxlinkpage5.ht}
\index{htxlinkpage5.ht!patch!HTXLinkPage5xPatch2A}
\index{HTXLinkPage5xPatch2A!htxlinkpage5.ht!patch}
\begin{chunk}{htxlinkpage5.ht}
\begin{patch}{HTXLinkPage5xPatch2A}
\begin{paste}{HTXLinkPage5xPaste2B}{HTXLinkPage5xPatch2}
\pastebutton{HTXLinkPage5xPaste2B}{Interpret}
\newline
{\tt \\unixlink\{Some file\}} \newline
{\tt \{cat\\ \\env\{AXIOM\}/doc/HTXplay.ht\}}
\end{paste}
\end{patch}

\end{chunk}
\section{htxlinkpage6.ht}
\pagetitle{HTXLinkPage6}{htxlinkpage6.ht}
{How to use your pages with Hyperdoc}
\begin{chunk}{htxlinkpage6.ht}
\begin{page}{HTXLinkPage6}{How to use your pages with Hyperdoc}
\centerline{\fbox{{\tt \thispage}}}\newline
\begin{scroll}

Let us say that you have written a few Hyperdoc
pages and you would like to incorporate them in the system.
Here is what you should do.

Put all your files in some directory and make sure that
they all have the {\bf .ht} extension.

You will need a way of "hooking" into a system--defined
Hyperdoc page. The proper way to do this is to use
the {\tt \\localinfo} macro. The Axiom system
Hyperdoc page database includes, as it should,
a {\tt RootPage}. This is the page that first comes up
when you start Hyperdoc. This page contains
a line like this.
\beginImportant
\newline
{\tt \\localinfo}
\endImportant

This macro is defined in
\centerline{ {\bf \env{AXIOM}/doc/util.ht}}
to be (see \downlink{Macros}{HTXAdvPage3} to learn how to define macros):
\beginImportant
\newline
{\tt \\newcommand\{\\localinfo\}\{\}}
\endImportant
which is an empty definition (the second argument of {\tt \\newcommand}).
The idea then is that you {\it override} this definition of the macro
with your own.
To do that, include a definition like the following in one (possibly the
one that contains your top--level page) of your files. You can
put this definition in its own file if you like.
\beginImportant
\newline
{\tt \\newcommand\{\\localinfo\}
\{\\menuwindowlink\{{\it active text}\}} \newline
{\tt \{{\it page name}\} \\tab\{16\}{\it short description}\}}
\endImportant

If you have a look at the initial Hyperdoc page, you will probably be
able to decipher what this does. The macro {\tt \\menuwindowlink} is
defined (again in {\bf util.ht}) and is responsible for putting the
little square to the left of the active area.  Specify a word or two
for {\it active text}. That will become the trigger of the {\tt
\\link}. Specify the page name of your top--level page in {\it page
name}. Finally, you can give a comment about the topic under {\it
short description}. That will appear to the right of the {\it active
text}.

The next thing you need to do is to create a {\it local database}
for your files. You will use the {\bf \env{AXIOM}/bin/htadd} program.
This program will create an {\bf ht.db} file that summarises your
definitions and acts as an index. Let us present an example
of its use. Suppose you have two files {\bf user1.ht} and {\bf user2.ht}
in directory {\bf /u/sugar/Hyperdoc}. You should create the {\bf ht.db}
in that same directory. To create the {\bf ht.db} file you issue to
the unix shell:
\beginImportant
\newline
{\tt htadd -f /u/sugar/Hyperdoc 
/u/sugar/Hyperdoc/user1.ht /u/sugar/Hyperdoc/user2.ht}
\centerline{or ,if you are already in /u/sugar/Hyperdoc}
{\tt htadd -l ./user1.ht ./user2.ht}
\endImportant


The options and conventions for {\bf htadd} will be explained below.
To start Hyperdoc with your own pages, you now need to tell
it where to search for {\bf ht.db} files and Hyperdoc {\bf .ht}
files. To do this, define the shell environment variable
{\bf HTPATH}. The value should be a colon {\tt ':'} separated
list of directory full pathnames.
The order of the directories is respected with earlier entries overriding
later ones. Since we want all the Axiom pages but need to override the
{\tt \\localinfo} macro, we should use the value
\centerline{{\bf /u/sugar/Hyperdoc:\env{AXIOM}/doc}}
The way that you define environment variables depends on the shell
you are using. In the {\bf /bin/csh}, it would be
\newline
{\bf setenv HTPATH /u/sugar/Hyperdoc:\env{AXIOM}{}/doc{}/hypertex{}/pages}



\beginImportant
\begin{paste}{HTXLinkPage6xPaste1}{HTXLinkPage6xPatch1}
\pastebutton{HTXLinkPage6xPaste1}{Options for {\bf htadd}}
\newline
\end{paste}
\endImportant


\beginImportant
\begin{paste}{HTXLinkPage6xPaste2}{HTXLinkPage6xPatch2}
\pastebutton{HTXLinkPage6xPaste2}{Where does Hyperdoc look for files}
\newline
\end{paste}
\endImportant



\end{scroll}
\beginmenu
\menulink{Back to Actions menu}{HTXLinkTopPage}
\endmenu

\end{page}

\end{chunk}
\subsection{HTXLinkPage6xPatch1 patch}
\label{HTXLinkPage6xPatch1}
\index{patch!HTXLinkPage6xPatch1!htxlinkpage6.ht}
\index{htxlinkpage6.ht!patch!HTXLinkPage6xPatch1}
\index{HTXLinkPage6xPatch1!htxlinkpage6.ht!patch}
\begin{chunk}{htxlinkpage6.ht}
\begin{patch}{HTXLinkPage6xPatch1}
\begin{paste}{HTXLinkPage6xPaste1A}{HTXLinkPage6xPatch1A}
\pastebutton{HTXLinkPage6xPaste1A}{Hide}
\newline
Name:

{\tt htadd - create or modify a Hyperdoc database}
\vspace{}
\newline
Syntax:

{\tt htadd [ -l | -s | -f\ }{\it path}{\tt ] 
[ -d | -n ]\ }{\it filename ...}
\vspace{}
\newline
Options:\indentrel{4}\newline
{\tt -l}\tab{8}\indentrel{8}
build {\bf ht.db} database in current working directory.
This is the default behaviour if no {\tt -l}, {\tt -s} or {\tt -f}
is specified.

\indentrel{-8}\newline
{\tt -s}\tab{8}\indentrel{8}
build {\bf ht.db} database in {\it system} directory. The
system directory is built as follows. If the {\tt AXIOM}
variable is defined, the {\bf \$AXIOM/doc} directory
is used. If {\tt AXIOM} is not defined, the
{\bf /usr/local/axiom/doc} directory is used.


\indentrel{-8}\newline
{\tt -f\ }{\it path}\newline\tab{8}\indentrel{8}
build {\bf ht.db} database in specified {\it path}.

\indentrel{-8}\newline
{\tt -d}\tab{8}\indentrel{8}
delete the entries in the specified files from {\bf ht.db}.

\indentrel{-8}\newline
{\tt -n}\tab{8}\indentrel{8}
delete {\bf ht.db} and create a new one using only the files
specified.

If none of {\tt -n} and {\tt -d} is specified, the {\bf ht.db}
is updated with the entries in the file specified.


\indentrel{-8}
\indentrel{-4}
\vspace{}\newline
Filename interpretation :
\indentrel{12}\newline
A full pathname (i.e. anything that has a {\tt '/'} in it)
will be taken do be a completely specified file.
Otherwise, the following interpretation will occur:
If the {\tt HTPATH} variable is defined, the directories
specified in it will be tried in order. If {\tt HTPATH}
is not defined, then, if {\tt AXIOM} is defined, the
{\bf \$AXIOM/doc} will be tried, else
the file will be deemed missing and {\bf htadd} will fail.
\indentrel{-12}
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXLinkPage6xPatch1A patch}
\label{HTXLinkPage6xPatch1A}
\index{patch!HTXLinkPage6xPatch1A!htxlinkpage6.ht}
\index{htxlinkpage6.ht!patch!HTXLinkPage6xPatch1A}
\index{HTXLinkPage6xPatch1A!htxlinkpage6.ht!patch}
\begin{chunk}{htxlinkpage6.ht}
\begin{patch}{HTXLinkPage6xPatch1A}
\begin{paste}{HTXLinkPage6xPaste1B}{HTXLinkPage6xPatch1}
\pastebutton{HTXLinkPage6xPaste1B}{Options for {\bf htadd}}
\newline
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXLinkPage6xPatch2 patch}
\label{HTXLinkPage6xPatch2}
\index{patch!HTXLinkPage6xPatch2!htxlinkpage6.ht}
\index{htxlinkpage6.ht!patch!HTXLinkPage6xPatch2}
\index{HTXLinkPage6xPatch2!htxlinkpage6.ht!patch}
\begin{chunk}{htxlinkpage6.ht}
\begin{patch}{HTXLinkPage6xPatch2}
\begin{paste}{HTXLinkPage6xPaste2A}{HTXLinkPage6xPatch2A}
\pastebutton{HTXLinkPage6xPaste2A}{Hide}
\indentrel{12}\newline

The Hyperdoc program is \centerline{{\bf \env{AXIOM}/lib/hypertex}} If
{\tt AXIOM} is defined and {\tt HTPATH} is not (this is the case when
Axiom starts Hyperdoc) Hyperdoc will look in 
\centerline{{\bf \env{AXIOM}/doc}} 
for the {\bf ht.db} file and all
Hyperdoc pages.  If {\tt HTPATH} is defined, it is assumed that it
alone points to the directories to be searched (the above default will
NOT be searched unless explicitly specified in {\tt HTPATH}).  For
each directory in {\tt HTPATH}, the {\bf ht.db} file, if there, will
be read.  Each file listed in {\bf ht.db} will then be searched for in
the complete sequence of directories in {\tt HTPATH}. Note that the
{\bf ht.db} does not keep full pathnames of files.  If a {\it page},
{\it macro} or {\it patch} (specified in some {\bf ht.db}) happens to
be (in a file) in more than one of the directories specified in 
{\tt HTPATH}, Hyperdoc will print a warning and explain which version in
which file is ignored. Generally, earlier directories in {\tt HTPATH}
are preferred over later ones.

\indentrel{-12}\newline
\end{paste}
\end{patch}

\end{chunk}
\subsection{HTXLinkPage6xPatch2A patch}
\label{HTXLinkPage6xPatch2A}
\index{patch!HTXLinkPage6xPatch2A!htxlinkpage6.ht}
\index{htxlinkpage6.ht!patch!HTXLinkPage6xPatch2A}
\index{HTXLinkPage6xPatch2A!htxlinkpage6.ht!patch}
\begin{chunk}{htxlinkpage6.ht}
\begin{patch}{HTXLinkPage6xPatch2A}
\begin{paste}{HTXLinkPage6xPaste2B}{HTXLinkPage6xPatch2}
\pastebutton{HTXLinkPage6xPaste2B}{Where does Hyperdoc look for files}}
\newline
\end{paste}
\end{patch}

\end{chunk}
\section{htxlinktoppage.ht}
\pagetitle{HTXLinkTopPage}{htxlinktoppage.ht}{Actions in Hyperdoc}
\pageto{notitle}{HTXLinkPage1}
\pageto{notitle}{HTXLinkPage2}
\pageto{notitle}{HTXLinkPage3}
\pageto{notitle}{HTXLinkPage4}
\pageto{notitle}{HTXLinkPage5}
\pageto{notitle}{HTXLinkPage6}
\begin{chunk}{htxlinktoppage.ht}
\begin{page}{HTXLinkTopPage}{Actions in Hyperdoc}
\centerline{\fbox{{\tt \thispage}}}\newline
Hyperdoc offers various types of hypertext links.
You can learn about these facilities by clicking on the topics below.
\begin{scroll}
\beginmenu
\menudownlink{Linking to a named page}{HTXLinkPage1}
\menudownlink{Standard pages}{HTXLinkPage2}
\menudownlink{Active Axiom commands}{HTXLinkPage3}
\menudownlink{Linking to Lisp}{HTXLinkPage4}
\menudownlink{Linking to Unix}{HTXLinkPage5}
\menudownlink{How to use your pages with Hyperdoc}{HTXLinkPage6}
\endmenu
\end{scroll}
\end{page}

\end{chunk}
\section{htxtoppage.ht}
\pagetitle{HTXTopPage}{htxtoppage.ht}{Extending Hyperdoc}
\pagepic{ps/v71htxtoppage.eps}{htxtoppage}{0.50}
\pagefrom{Reference}{TopReferencePage}
\pageto{Introduction}{HTXIntroTopPage}
\pageto{Formatting}{HTXFormatTopPage}
\pageto{Actions}{HTXLinkTopPage}
\pageto{Advanced features}{HTXAdvTopPage}
\pageto{Try it!}{HTXTryPage}
\begin{chunk}{htxtoppage.ht}
\begin{page}{HTXTopPage}{Extending Hyperdoc}
\centerline{\fbox{{\tt \thispage}}}\newline
This is a guide to extending Hyperdoc. You can learn
how to write your own Hyperdoc pages and link them to the
Hyperdoc page database that Axiom uses.
\begin{scroll}
\beginmenu
\menumemolink{Introduction}{HTXIntroTopPage} 
\tab{20} An easy start.
\menumemolink{Formatting}{HTXFormatTopPage} 
\tab{20} Learn how to format text.
\menumemolink{Actions}{HTXLinkTopPage} 
\tab{20} Learn how to define actions.
\menumemolink{Advanced features}{HTXAdvTopPage} 
\tab{20} More effects.
\menuwindowlink{Try it!}{HTXTryPage} 
\tab{20} Try out what you learn.
\endmenu
\end{scroll}
\end{page}

\end{chunk}
\section{htxtrypage.ht}
\pagetitle{HTXTryPage}{htxtrypage.ht}{Try out Hyperdoc}
\begin{chunk}{htxtrypage.ht}
\begin{page}{HTXTryPage}{Try out Hyperdoc}
\centerline{\fbox{{\tt \thispage}}}\newline

This page allows you to quickly experiment with Hyperdoc.
It is a good idea to keep it handy as you learn about various commands.

\beginscroll

We are going to use here the Hyperdoc facilities that allow
us to communicate with external programs and files. For more
information see \downlink{later on}{HTXLinkPage5}.
\beginmenu
\item\menuitemstyle{
In order to use the buttons at the bottom of this page, you must
first specify a name for the file you are going to use to hold
Hyperdoc commands. Edit the input area below to change the
name of the file.}
\item\menuitemstyle{
If the file you specified does not yet exist, click on the
{\bf Initialize} button below. This action will fill the file
with the minimum of Hyperdoc commands necessary to define a page.}
\item\menuitemstyle{
If you want to edit the file, just click on the {\bf Edit} button.
This action will pop up a window, and invoke the {\it vi}
editor on the file. Alternatively, use an editor of your choice.}
\item\menuitemstyle{
Once you have finished making the changes to the file, update it and
click on the {\bf Link} button. Hyperdoc will then read
the file, interpret it as a new page, and display the page on
this window. If you change the file and want to display it again,
just get back to this page and click on {\bf Link} again. }
\endmenu
\endscroll
\beginmenu
{\it Filename: }{\inputstring{filename}{40}{\env{HOME}/HTXplay.ht}}
\menuunixcommand{Initialize}
{cp\space{1}\env{AXIOM}/doc/HTXplay.ht 
\stringvalue{filename}} \tab{20} Get a fresh copy from the system.
\menuunixcommand{Edit}{xterm -T "\stringvalue{filename}" -e vi 
\stringvalue{filename}} \tab{20} Edit the file.
\menuunixwindow{Link}{cat \space{1}\stringvalue{filename}} 
\tab{20} Link to the page defined in the file.
\endmenu
{\it Important : The file must contain
one and only one page definition and must not contain any 
macro or patch definitions.}
\end{page}

\end{chunk}
\chapter{NAG Library Routines}
\section{nagaux.ht}
\pagetitle{manpageXXonline}{nagaux.ht}{NAG On-line Documentation}
\begin{chunk}{nagaux.ht}
\begin{page}{manpageXXonline}{NAG On-line Documentation}
\beginscroll
\begin{verbatim}



     DOC INTRO(3NAG)   Foundation Library (12/10/92)   DOC INTRO(3NAG)



                    Introduction to NAG On-Line Documentation


          The on-line documentation for the NAG Foundation Library has been
          generated automatically from the same base material used to
          create the printed Reference Manual. To make the documentation
          readable on the widest range of machines, only the basic set of
          ascii characters has been used.

          Certain mathematical symbols have been constructed using plain
          ascii characters:

          integral signs                /
                                        |

                                        /

          summation signs               --
                                        >
                                        --

          square root signs                ----
                                          /
                                        \/


          Large brackets are constructed using vertical stacks of the
          equivalent ascii character:

                              (  )  [  ]  {  }  |
                              (  )  [  ]  {  }  |
                              (  )  [  ]  {  }  |


          Fractions are represented as:

                                       a
                                      ---
                                      x+1


          Greek letters are represented by their names enclosed in round
          brackets:

                  (alpha)  (beta)  (gamma) .....

                  (Alpha)  (Beta)  (Gamma) .....


          Some characters are accented using:

                  ^     ~     
                  X     X     X

          Other mathematical symbols are represented as follows:

                 *           times

                 <=>         left-right arrow

                 <-          left arrow

                 ~           similar to

                 ~=          similar or equal to

                 ==          equivalent to

                 >=          greater than or equal to

                 <=          less than or equal to

                 >>          much greater than

                 <<          much less than

                 >~          greater than or similar to

                 /=          not equal to

                 dd          partial derivative

                 +-          plus or minus

                 (nabla)     Nabla

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXsummary}{nagaux.ht}{NAG Documentation: summary}
\begin{chunk}{nagaux.ht}
\begin{page}{manpageXXsummary}{NAG Documentation: summary}
\beginscroll
\begin{verbatim}



     SUMMARY(3NAG)     Foundation Library (12/10/92)     SUMMARY(3NAG)



          Introduction                                     List of Routines
          List of Routines

          The NAG Foundation Library contains three categories of routines
          which can be called by users. They are listed separately in the
          three sections below.

          Fully Documented Routines
                254 routines, for each of which an individual routine
                document is provided. These are regarded as the primary
                contents of the Foundation Library.

          Fundamental Support Routines
                83 comparatively simple routines which are documented in
                compact form in the relevant Chapter Introductions (F06,
                X01, X02).

          Routines from the NAG Fortran Library
                An additional 167 routines from the NAG Fortran Library,
                which are used as auxiliaries in the Foundation Library.
                They are not documented in this publication, but can be
                called if you are already familiar with their use in the
                Fortran Library. Only their names are given here.


          Note: all the routines in the above categories have names ending
          in 'F'. Occasionally this publication may refer to routines whose
          names end in some other letter (e.g. 'Z', 'Y', 'X'). These are
          auxiliary routines whose names may be passed as parameters to a
          Foundation Library routine; you only need to know their names,
          not how to call them directly.

          Fully Documented Routines

          The Foundation Library contains 254 user-callable routines, for
          each of which an individual routine document is provided, in the
          following chapters:

          C02 -- Zeros of Polynomials

          C02AFF  All zeros of complex polynomial, modified Laguerre method

          C02AGF  All zeros of real polynomial, modified Laguerre method

          C05 -- Roots of One or More Transcendental Equations

          C05ADF  Zero of continuous function in given interval, Bus and
                  Dekker algorithm

          C05NBF  Solution of system of nonlinear equations using function
                  values only

          C05PBF  Solution of system of nonlinear equations using 1st
                  derivatives

          C05ZAF  Check user's routine for calculating 1st derivatives

          C06 -- Summation of Series

          C06EAF  Single 1-D real discrete Fourier transform, no extra
                  workspace

          C06EBF  Single 1-D Hermitian discrete Fourier transform, no extra
                  workspace

          C06ECF  Single 1-D complex discrete Fourier transform, no extra
                  workspace

          C06EKF  Circular convolution or correlation of two real vectors,
                  no extra workspace

          C06FPF  Multiple 1-D real discrete Fourier transforms

          C06FQF  Multiple 1-D Hermitian discrete Fourier transforms

          C06FRF  Multiple 1-D complex discrete Fourier transforms

          C06FUF  2-D complex discrete Fourier transform

          C06GBF  Complex conjugate of Hermitian sequence

          C06GCF  Complex conjugate of complex sequence

          C06GQF  Complex conjugate of multiple Hermitian sequences

          C06GSF  Convert Hermitian sequences to general complex sequences

          D01 -- Quadrature

          D01AJF  1-D quadrature, adaptive, finite interval, strategy due
                  to Piessens and de Doncker, allowing for badly-behaved
                  integrands

          D01AKF  1-D quadrature, adaptive, finite interval, method
                  suitable for oscillating functions

          D01ALF  1-D quadrature, adaptive, finite interval, allowing for
                  singularities at user-specified break-points

          D01AMF  1-D quadrature, adaptive, infinite or semi-infinite
                  interval

          D01ANF  1-D quadrature, adaptive, finite interval, weight
                  function cos((omega)x) or sin((omega)x)

          D01APF  1-D quadrature, adaptive, finite interval, weight
                  function with end-point singularities of algebraico-
                  logarithmic type

          D01AQF  1-D quadrature, adaptive, finite interval, weight
                  function 1/(x-c), Cauchy principal value (Hilbert
                  transform)

          D01ASF  1-D quadrature, adaptive, semi-infinite interval, weight
                  function cos((omega)x) or sin((omega)x)

          D01BBF  Weights and abscissae for Gaussian quadrature rules

          D01FCF  Multi-dimensional adaptive quadrature over hyper-
                  rectangle

          D01GAF  1-D quadrature, integration of function defined by data
                  values, Gill-Miller method

          D01GBF  Multi-dimensional quadrature over hyper-rectangle, Monte
                  Carlo method

          D02 -- Ordinary Differential Equations

          D02BBF  ODEs, IVP, Runge-Kutta-Merson method, over a range,
                  intermediate output

          D02BHF  ODEs, IVP, Runge-Kutta-Merson method, until function of
                  solution is zero

          D02CJF  ODEs, IVP, Adams method, until function of solution is
                  zero, intermediate output

          D02EJF  ODEs, stiff IVP, BDF method, until function of solution
                  is zero, intermediate output

          D02GAF  ODEs, boundary value problem, finite difference technique
                  with deferred correction, simple nonlinear problem

          D02GBF  ODEs, boundary value problem, finite difference technique
                  with deferred correction, general linear problem

          D02KEF  2nd order Sturm-Liouville problem, regular/singular
                  system, finite/infinite range, eigenvalue and
                  eigenfunction, user-specified break-points

          D02RAF  ODEs, general nonlinear boundary value problem, finite
                  difference technique with deferred correction,
                  continuation facility

          D03 -- Partial Differential Equations

          D03EDF  Elliptic PDE, solution of finite difference equations by
                  a multigrid technique

          D03EEF  Discretize a 2nd order elliptic PDE on a rectangle

          D03FAF  Elliptic PDE, Helmholtz equation, 3-D Cartesian co-
                  ordinates

          E01 -- Interpolation

          E01BAF  Interpolating functions, cubic spline interpolant, one
                  variable

          E01BEF  Interpolating functions, monotonicity-preserving,
                  piecewise cubic Hermite, one variable

          E01BFF  Interpolated values, interpolant computed by E01BEF,
                  function only, one variable

          E01BGF  Interpolated values, interpolant computed by E01BEF,
                  function and 1st derivative, one variable

          E01BHF  Interpolated values, interpolant computed by E01BEF,
                  definite integral, one variable

          E01DAF  Interpolating functions, fitting bicubic spline, data on
                  rectangular grid

          E01SAF  Interpolating functions, method of Renka and Cline, two
                  variables

          E01SBF  Interpolated values, evaluate interpolant computed by
                  E01SAF, two variables

          E01SEF  Interpolating functions, modified Shepard's method, two
                  variables

          E01SFF  Interpolated values, evaluate interpolant computed by
                  E01SEF, two variables

          E02 -- Curve and Surface Fitting

          E02ADF  Least-squares curve fit, by polynomials, arbitrary data
                  points

          E02AEF  Evaluation of fitted polynomial in one variable from
                  Chebyshev series form (simplified parameter list)

          E02AGF  Least-squares polynomial fit, values and derivatives may
                  be constrained, arbitrary data points,

          E02AHF  Derivative of fitted polynomial in Chebyshev series form

          E02AJF  Integral of fitted polynomial in Chebyshev series form

          E02AKF  Evaluation of fitted polynomial in one variable, from
                  Chebyshev series form

          E02BAF  Least-squares curve cubic spline fit (including
                  interpolation)

          E02BBF  Evaluation of fitted cubic spline, function only

          E02BCF  Evaluation of fitted cubic spline, function and
                  derivatives

          E02BDF  Evaluation of fitted cubic spline, definite integral

          E02BEF  Least-squares cubic spline curve fit, automatic knot
                  placement

          E02DAF  Least-squares surface fit, bicubic splines

          E02DCF  Least-squares surface fit by bicubic splines with
                  automatic knot placement, data on rectangular grid

          E02DDF  Least-squares surface fit by bicubic splines with
                  automatic knot placement, scattered data

          E02DEF  Evaluation of a fitted bicubic spline at a vector of
                  points

          E02DFF  Evaluation of a fitted bicubic spline at a mesh of points

          E02GAF  L -approximation by general linear function
                   1

          E02ZAF  Sort 2-D data into panels for fitting bicubic splines

          E04 -- Minimizing or Maximizing a Function

          E04DGF  Unconstrained minimum, pre-conditioned conjugate gradient
                  algorithm, function of several variables using 1st
                  derivatives

          E04DJF  Read optional parameter values for E04DGF from external
                  file

          E04DKF  Supply optional parameter values to E04DGF

          E04FDF  Unconstrained minimum of a sum of squares, combined
                  Gauss-Newton and modified Newton algorithm using function
                  values only

          E04GCF  Unconstrained minimum of a sum of squares, combined
                  Gauss-Newton and quasi-Newton algorithm, using 1st
                  derivatives

          E04JAF  Minimum, function of several variables, quasi-Newton
                  algorithm, simple bounds, using function values only

          E04MBF  Linear programming problem

          E04NAF  Quadratic programming problem

          E04UCF  Minimum, function of several variables, sequential QP
                  method, nonlinear constraints, using function values and
                  optionally 1st derivatives

          E04UDF  Read optional parameter values for E04UCF from external
                  file

          E04UEF  Supply optional parameter values to E04UCF

          E04YCF  Covariance matrix for nonlinear least-squares problem

          F01 -- Matrix Factorizations

          F01BRF  LU factorization of real sparse matrix

          F01BSF  LU factorization of real sparse matrix with known
                  sparsity pattern

                    T
          F01MAF  LL  factorization of real sparse symmetric positive-
                  definite matrix

                     T
          F01MCF  LDL  factorization of real symmetric positive-definite
                  variable-bandwidth matrix

          F01QCF  QR factorization of real m by n matrix (m>=n)

                                                                      T
          F01QDF  Operations with orthogonal matrices, compute QB or Q B
                  after factorization by F01QCF

          F01QEF  Operations with orthogonal matrices, form columns of Q
                  after factorization by F01QCF

          F01RCF  QR factorization of complex m by n matrix (m>=n)

                                                                   H
          F01RDF  Operations with unitary matrices, compute QB or Q B after
                  factorization by F01RCF

          F01REF  Operations with unitary matrices, form columns of Q after
                  factorization by F01RCF

          F02 -- Eigenvalues and Eigenvectors

          F02AAF  All eigenvalues of real symmetric matrix

          F02ABF  All eigenvalues and eigenvectors of real symmetric matrix

          F02ADF  All eigenvalues of generalized real symmetric-definite
                  eigenproblem

          F02AEF  All eigenvalues and eigenvectors of generalized real
                  symmetric-definite eigenproblem

          F02AFF  All eigenvalues of real matrix

          F02AGF  All eigenvalues and eigenvectors of real matrix

          F02AJF  All eigenvalues of complex matrix

          F02AKF  All eigenvalues and eigenvectors of complex matrix

          F02AWF  All eigenvalues of complex Hermitian matrix

          F02AXF  All eigenvalues and eigenvectors of complex Hermitian
                  matrix

          F02BBF  Selected eigenvalues and eigenvectors of real symmetric
                  matrix

          F02BJF  All eigenvalues and optionally eigenvectors of
                  generalized eigenproblem by QZ algorithm, real matrices

          F02FJF  Selected eigenvalues and eigenvectors of sparse symmetric
                  eigenproblem

          F02WEF  SVD of real matrix

          F02XEF  SVD of complex matrix

          F04 -- Simultaneous Linear Equations

          F04ADF  Approximate solution of complex simultaneous linear
                  equations with multiple right-hand sides

          F04ARF  Approximate solution of real simultaneous linear
                  equations, one right-hand side

          F04ASF  Accurate solution of real symmetric positive-definite
                  simultaneous linear equations, one right-hand side

          F04ATF  Accurate solution of real simultaneous linear equations,
                  one right-hand side

          F04AXF  Approximate solution of real sparse simultaneous linear
                  equations (coefficient matrix already factorized by
                  F01BRF or F01BSF)

          F04FAF  Approximate solution of real symmetric positive-definite
                  tridiagonal simultaneous linear equations, one right-hand
                  side

          F04JGF  Least-squares (if rank = n) or minimal least-squares (if
                  rank <n) solution of m real equations in n unknowns, rank
                  <=n, m>=n

          F04MAF  Real sparse symmetric positive-definite simultaneous
                  linear equations (coefficient matrix already factorized)

          F04MBF  Real sparse symmetric simultaneous linear equations

          F04MCF  Approximate solution of real symmetric positive-definite
                  variable-bandwidth simultaneous linear equations
                  (coefficient matrix already factorized)

          F04QAF  Sparse linear least-squares problem, m real equations in
                  n unknowns

          F07 -- Linear Equations (LAPACK)

          F07ADF  (DGETRF) LU factorization of real m by n matrix

          F07AEF  (DGETRS) Solution of real system of linear equations,
                  multiple right-hand sides, matrix already factorized by
                  F07ADF

          F07FDF  (DPOTRF) Cholesky factorization of real symmetric
                  positive-definite matrix

          F07FEF  (DPOTRS) Solution of real symmetric positive-definite
                  system of linear equations, multiple right-hand sides,
                  matrix already factorized by F07FDF

          G01 -- Simple Calculations on Statistical Data

          G01AAF  Mean, variance, skewness, kurtosis etc, one variable,
                  from raw data

          G01ADF  Mean, variance, skewness, kurtosis etc, one variable,
                  from frequency table

          G01AEF  Frequency table from raw data


          G01AFF  Two-way contingency table analysis, with (chi) /Fisher's
                  exact test

          G01ALF  Computes a five-point summary (median, hinges and
                  extremes)

          G01ARF  Constructs a stem and leaf plot

          G01EAF  Computes probabilities for the standard Normal
                  distribution

          G01EBF  Computes probabilities for Student's t-distribution

                                                  2
          G01ECF  Computes probabilities for (chi)  distribution

          G01EDF  Computes probabilities for F-distribution

          G01EEF  Computes upper and lower tail probabilities and
                  probability density function for the beta distribution

          G01EFF  Computes probabilities for the gamma distribution

          G01FAF  Computes deviates for the standard Normal distribution

          G01FBF  Computes deviates for Student's t-distribution

                                                 2
          G01FCF  Computes deviates for the (chi)  distribution

          G01FDF  Computes deviates for the F-distribution

          G01FEF  Computes deviates for the beta distribution

          G01FFF  Computes deviates for the gamma distribution

          G01HAF  Computes probabilities for the bivariate Normal
                  distribution

          G02 -- Correlation and Regression Analysis

          G02BNF  Kendall/Spearman non-parametric rank correlation
                  coefficients, no missing values, overwriting input data

          G02BQF  Kendall/Spearman non-parametric rank correlation
                  coefficients, no missing values, preserving input data

          G02BXF  Computes (optionally weighted) correlation and covariance
                  matrices

          G02CAF  Simple linear regression with constant term, no missing
                  values

          G02DAF  Fits a general (multiple) linear regression model

          G02DGF  Fits a general linear regression model for new dependent
                  variable

          G02DNF  Computes estimable function of a general linear
                  regression model and its standard error

          G02FAF  Calculates standardized residuals and influence
                  statistics

          G02GBF  Fits a generalized linear model with binomial errors

          G02GCF  Fits a generalized linear model with Poisson errors

          G03 -- Multivariate Methods

          G03AAF  Performs principal component analysis

          G03ADF  Performs canonical correlation analysis

          G03BAF  Computes orthogonal rotations for loading matrix,
                  generalized orthomax criterion

          G05 -- Random Number Generators

          G05CAF  Pseudo-random double precision numbers, uniform
                  distribution over (0,1)

          G05CBF  Initialise random number generating routines to give
                  repeatable sequence

          G05CCF  Initialise random number generating routines to give non-
                  repeatable sequence

          G05CFF  Save state of random number generating routines

          G05CGF  Restore state of random number generating routines

          G05DDF  Pseudo-random double precision numbers, Normal
                  distribution

          G05DFF  Pseudo-random double precision numbers, Cauchy
                  distribution

          G05DPF  Pseudo-random double precision numbers, Weibull
                  distribution

          G05DYF  Pseudo-random integer from uniform distribution

          G05DZF  Pseudo-random logical (boolean) value

          G05EAF  Set up reference vector for multivariate Normal
                  distribution

          G05ECF  Set up reference vector for generating pseudo-random
                  integers, Poisson distribution

          G05EDF  Set up reference vector for generating pseudo-random
                  integers, binomial distribution

          G05EHF  Pseudo-random permutation of an integer vector

          G05EJF  Pseudo-random sample from an integer vector

          G05EXF  Set up reference vector from supplied cumulative
                  distribution function or probability distribution
                  function

          G05EYF  Pseudo-random integer from reference vector

          G05EZF  Pseudo-random multivariate Normal vector from reference
                  vector

          G05FAF  Generates a vector of pseudo-random numbers from a
                  uniform distribution

          G05FBF  Generates a vector of pseudo-random numbers from a
                  (negative) exponential distribution

          G05FDF  Generates a vector of pseudo-random numbers from a Normal
                  distribution

          G05FEF  Generates a vector of pseudo-random numbers from a beta
                  distribution

          G05FFF  Generates a vector of pseudo-random numbers from a gamma
                  distribution

          G05HDF  Generates a realisation of a multivariate time series
                  from a VARMA model

          G08 -- Nonparameteric Statistics

          G08AAF  Sign test on two paired samples

          G08ACF  Median test on two samples of unequal size

          G08AEF  Friedman two-way analysis of variance on k matched
                  samples

          G08AFF  Kruskal-Wallis one-way analysis of variance on k samples
                  of unequal size

          G08AGF  Performs the Wilcoxon one sample (matched pairs) signed
                  rank test

          G08AHF  Performs the Mann-Whitney U test on two independent
                  samples

          G08AJF  Computes the exact probabilities for the Mann-Whitney U
                  statistic, no ties in pooled sample

          G08AKF  Computes the exact probabilities for the Mann-Whitney U
                  statistic, ties in pooled sample

                                    2
          G08CGF  Performs the (chi)  goodness of fit test, for standard
                  continuous distributions

          G13 -- Time Series Analysis

          G13AAF  Univariate time series, seasonal and non-seasonal
                  differencing

          G13ABF  Univariate time series, sample autocorrelation function

          G13ACF  Univariate time series, partial autocorrelations from
                  autocorrelations

          G13ADF  Univariate time series, preliminary estimation, seasonal
                  ARIMA model

          G13AFF  Univariate time series, estimation, seasonal ARIMA model

          G13AGF  Univariate time series, update state set for forecasting

          G13AHF  Univariate time series, forecasting from state set

          G13AJF  Univariate time series, state set and forecasts, from
                  fully specified seasonal ARIMA model

          G13ASF  Univariate time series, diagnostic checking of residuals,
                  following G13AFF

          G13BAF  Multivariate time series, filtering (pre-whitening) by an
                  ARIMA model

          G13BCF  Multivariate time series, cross correlations

          G13BDF  Multivariate time series, preliminary estimation of
                  transfer function model

          G13BEF  Multivariate time series, estimation of multi-input model

          G13BJF  Multivariate time series, state set and forecasts from
                  fully specified multi-input model

          G13CBF  Univariate time series, smoothed sample spectrum using
                  spectral smoothing by the trapezium frequency (Daniell)
                  window

          G13CDF  Multivariate time series, smoothed sample cross spectrum
                  using spectral smoothing by the trapezium frequency
                  (Daniell) window

          M01 -- Sorting

          M01CAF  Sort a vector, double precision numbers

          M01DAF  Rank a vector, double precision numbers

          M01DEF  Rank rows of a matrix, double precision numbers

          M01DJF  Rank columns of a matrix, double precision numbers

          M01EAF  Rearrange a vector according to given ranks, double
                  precision numbers

          M01ZAF  Invert a permutation

          S -- Approximations of Special Functions

                                        z
          S01EAF  Complex exponential, e

          S13AAF  Exponential integral E (x)
                                        1

          S13ACF  Cosine integral Ci(x)

          S13ADF  Sine integral Si(x)

          S14AAF  Gamma function

          S14ABF  Log Gamma function

          S14BAF  Incomplete gamma functions P(a,x) and Q(a,x)

          S15ADF  Complement of error function erfc x

          S15AEF  Error function erf x

          S17ACF  Bessel function Y (x)
                                   0

          S17ADF  Bessel function Y (x)
                                   1

          S17AEF  Bessel function J (x)
                                   0

          S17AFF  Bessel function J (x)
                                   1

          S17AGF  Airy function Ai(x)

          S17AHF  Airy function Bi(x)

          S17AJF  Airy function Ai'(x)

          S17AKF  Airy function Bi'(x)

          S17DCF  Bessel functions Y      (z), real a>=0, complex z,
                                    (nu)+a
                  (nu)=0,1,2,...

          S17DEF  Bessel functions J      (z), real a>=0, complex z,
                                    (nu)+a
                  (nu)=0,1,2,...

          S17DGF  Airy functions Ai(z) and Ai'(z), complex z

          S17DHF  Airy functions Bi(z) and Bi'(z), complex z

                                    (j)
          S17DLF  Hankel functions H      (z), j=1,2, real a>=0, complex z,
                                    (nu)+a
                  (nu)=0,1,2,...

          S18ACF  Modified Bessel function K (x)
                                            0

          S18ADF  Modified Bessel function K (x)
                                            1

          S18AEF  Modified Bessel function I (x)
                                            0

          S18AFF  Modified Bessel function I (x)
                                            1

          S18DCF  Modified Bessel functions K      (z), real a>=0, complex
                                             (nu)+a
                  z, (nu)=0,1,2,...

          S18DEF  Modified Bessel functions I      (z), real a>=0, complex
                                             (nu)+a
                  z, (nu)=0,1,2,...

          S19AAF  Kelvin function ber x

          S19ABF  Kelvin function bei x

          S19ACF  Kelvin function ker x

          S19ADF  Kelvin function kei x

          S20ACF  Fresnel integral S(x)

          S20ADF  Fresnel integral C(x)

          S21BAF  Degenerate symmetrised elliptic integral of 1st kind
                  R (x,y)
                   C

          S21BBF  Symmetrised elliptic integral of 1st kind R (x,y,z)
                                                             F

          S21BCF  Symmetrised elliptic integral of 2nd kind R (x,y,z)
                                                             D

          S21BDF  Symmetrised elliptic integral of 3rd kind R (x,y,z,r)
                                                             J

          X04 -- Input/Output Utilities

          X04AAF  Return or set unit number for error messages

          X04ABF  Return or set unit number for advisory messages

          X04CAF  Print a real general matrix

          X04DAF  Print a complex general matrix

          X05 -- Date and Time Utilities

          X05AAF  Return date and time as an array of integers

          X05ABF  Convert array of integers representing date and time to
                  character string

          X05ACF  Compare two character strings representing date and time

          X05BAF  Return the CPU time



          Fundamental Support Routines

          The following fundamental support routines are provided and are
          documented in compact form in the relevant chapter introductory
          material:

          F06 -- Linear Algebra Support Routines

          F06AAF  (DROTG) Generate real plane rotation

          F06EAF  (DDOT) Dot product of two real vectors

          F06ECF  (DAXPY) Add scalar times real vector to real vector

          F06EDF  (DSCAL) Multiply real vector by scalar

          F06EFF  (DCOPY) Copy real vector

          F06EGF  (DSWAP) Swap two real vectors

          F06EJF  (DNRM2) Compute Euclidean norm of real vector

          F06EKF  (DASUM) Sum the absolute values of real vector elements

          F06EPF  (DROT) Apply real plane rotation

          F06GAF  (ZDOTU) Dot product of two complex vectors, unconjugated

          F06GBF  (ZDOTC) Dot product of two complex vectors, conjugated

          F06GCF  (ZAXPY) Add scalar times complex vector to complex vector

          F06GDF  (ZSCAL) Multiply complex vector by complex scalar

          F06GFF  (ZCOPY) Copy complex vector

          F06GGF  (ZSWAP) Swap two complex vectors

          F06JDF  (ZDSCAL) Multiply complex vector by real scalar

          F06JJF  (DZNRM2) Compute Euclidean norm of complex vector

          F06JKF  (DZASUM) Sum the absolute values of complex vector
                  elements

          F06JLF  (IDAMAX) Index, real vector element with largest absolute
                  value

          F06JMF  (IZAMAX) Index, complex vector element with largest
                  absolute value

          F06PAF  (DGEMV) Matrix-vector product, real rectangular matrix

          F06PBF  (DGBMV) Matrix-vector product, real rectangular band
                  matrix

          F06PCF  (DSYMV) Matrix-vector product, real symmetric matrix

          F06PDF  (DSBMV) Matrix-vector product, real symmetric band matrix

          F06PEF  (DSPMV) Matrix-vector product, real symmetric packed
                  matrix

          F06PFF  (DTRMV) Matrix-vector product, real triangular matrix

          F06PGF  (DTBMV) Matrix-vector product, real triangular band
                  matrix

          F06PHF  (DTPMV) Matrix-vector product, real triangular packed
                  matrix

          F06PJF  (DTRSV) System of equations, real triangular matrix

          F06PKF  (DTBSV) System of equations, real triangular band matrix

          F06PLF  (DTPSV) System of equations, real triangular packed
                  matrix

          F06PMF  (DGER) Rank-1 update, real rectangular matrix

          F06PPF  (DSYR) Rank-1 update, real symmetric matrix

          F06PQF  (DSPR) Rank-1 update, real symmetric packed matrix

          F06PRF  (DSYR2) Rank-2 update, real symmetric matrix

          F06PSF  (DSPR2) Rank-2 update, real symmetric packed matrix

          F06SAF  (ZGEMV) Matrix-vector product, complex rectangular matrix

          F06SBF  (ZGBMV) Matrix-vector product, complex rectangular band
                  matrix

          F06SCF  (ZHEMV) Matrix-vector product, complex Hermitian matrix

          F06SDF  (ZHBMV) Matrix-vector product, complex Hermitian band
                  matrix

          F06SEF  (ZHPMV) Matrix-vector product, complex Hermitian packed
                  matrix

          F06SFF  (ZTRMV) Matrix-vector product, complex triangular matrix

          F06SGF  (ZTBMV) Matrix-vector product, complex triangular band
                  matrix

          F06SHF  (ZTPMV) Matrix-vector product, complex triangular packed
                  matrix

          F06SJF  (ZTRSV) System of equations, complex triangular matrix

          F06SKF  (ZTBSV) System of equations, complex triangular band
                  matrix

          F06SLF  (ZTPSV) System of equations, complex triangular packed
                  matrix

          F06SMF  (ZGERU) Rank-1 update, complex rectangular matrix,
                  unconjugated vector

          F06SNF  (ZGERC) Rank-1 update, complex rectangular matrix,
                  conjugated vector

          F06SPF  (ZHER) Rank-1 update, complex Hermitian matrix

          F06SQF  (ZHPR) Rank-1 update, complex Hermitian packed matrix

          F06SRF  (ZHER2) Rank-2 update, complex Hermitian matrix

          F06SSF  (ZHPR2) Rank-2 update, complex Hermitian packed matrix

          F06YAF  (DGEMM) Matrix-matrix product, two real rectangular
                  matrices

          F06YCF  (DSYMM) Matrix-matrix product, one real symmetric matrix,
                  one real rectangular matrix

          F06YFF  (DTRMM) Matrix-matrix product, one real triangular
                  matrix, one real rectangular matrix

          F06YJF  (DTRSM) Solves a system of equations with multiple right-
                  hand sides, real triangular coefficient matrix

          F06YPF  (DSYRK) Rank-k update of a real symmetric matrix

          F06YRF  (DSYR2K) Rank-2k update of a real symmetric matrix

          F06ZAF  (ZGEMM) Matrix-matrix product, two complex rectangular
                  matrices

          F06ZCF  (ZHEMM) Matrix-matrix product, one complex Hermitian
                  matrix, one complex rectangular matrix

          F06ZFF  (ZTRMM) Matrix-matrix product, one complex triangular
                  matrix, one complex rectangular matrix

          F06ZJF  (ZTRSM) Solves system of equations with multiple right-
                  hand sides, complex triangular coefficient matrix

          F06ZPF  (ZHERK) Rank-k update of a complex Hermitian matrix

          F06ZRF  (ZHER2K) Rank-2k update of a complex Hermitian matrix

          F06ZTF  (ZSYMM) Matrix-matrix product, one complex symmetric
                  matrix, one complex rectangular matrix

          F06ZUF  (ZSYRK) Rank-k update of a complex symmetric matrix

          F06ZWF  (ZSYR2K) Rank-2k update of a complex symmetric matrix

          X01 -- Mathematical Constants

          X01AAF  (pi)

          X01ABF  Euler's constant, (gamma)

          X02 -- Machine Constants

          X02AHF  Largest permissible argument for SIN and COS

          X02AJF  Machine precision

          X02AKF  Smallest positive model number

          X02ALF  Largest positive model number

          X02AMF  Safe range of floating-point arithmetic

          X02ANF  Safe range of complex floating-point arithmetic

          X02BBF  Largest representable integer

          X02BEF  Maximum number of decimal digits that can be represented

          X02BHF  Parameter of floating-point arithmetic model, b

          X02BJF  Parameter of floating-point arithmetic model, p

          X02BKF  Parameter of floating-point arithmetic model, e
                                                                 min

          X02BLF  Parameter of floating-point arithmetic model, e
                                                                 max

          X02DJF  Parameter of floating-point arithmetic model, ROUNDS



          Routines from the NAG Fortran Library

          A number of routines from the NAG Fortran Library are used in the
          Foundation Library as auxiliaries and are not documented here:

          A00AAF

          A02AAF  A02ABF  A02ACF

          C02AJF

          C05AZF  C05NCF  C05PCF

          C06FAF  C06FBF  C06FCF  C06FFF  C06FJF  C06FKF

          C06HAF  C06HBF  C06HCF  C06HDF

          D02CBF  D02CHF  D02NMF  D02NSF  D02NVF  D02PAF

          D02XAF  D02XKF  D02YAF  D02ZAF

          E02AFF

          E04GBF  E04GEF  E04YAF

          F01ADF  F01AEF  F01AFF  F01AGF  F01AHF  F01AJF

          F01AKF  F01AMF  F01APF  F01ATF  F01AUF  F01AVF

          F01AWF  F01AXF  F01BCF  F01BTF  F01CRF  F01LBF

          F01LZF  F01QAF  F01QFF  F01QGF  F01QJF  F01QKF

          F01RFF  F01RGF  F01RJF  F01RKF

          F02AMF  F02ANF  F02APF  F02AQF  F02AVF  F02AYF

          F02BEF  F02SWF  F02SXF  F02SYF  F02SZF  F02UWF

          F02UXF  F02UYF  F02WDF  F02WUF  F02XUF

          F03AAF  F03ABF  F03AEF  F03AFF

          F04AAF  F04AEF  F04AFF  F04AGF  F04AHF  F04AJF

          F04AMF  F04ANF  F04AYF  F04LDF  F04YAF  F04YCF

          F06BAF  F06BCF  F06BLF  F06BMF  F06BNF  F06CAF

          F06CCF  F06CLF  F06DBF  F06DFF  F06FBF  F06FCF

          F06FDF  F06FGF  F06FJF  F06FLF  F06FPF  F06FQF

          F06FRF  F06FSF  F06HBF  F06HGF  F06HQF  F06HRF

          F06KFF  F06KJF  F06KLF  F06QFF  F06QHF  F06QKF

          F06QRF  F06QSF  F06QTF  F06QVF  F06QWF  F06QXF

          F06RAF  F06RJF  F06TFF  F06THF  F06TTF  F06TXF

          F06VJF  F06VKF  F06VXF

          F07AGF  F07AHF  F07AJF  F07FGF  F07FHF  F07FJF

          F07TJF

          G01CEF

          G02BAF  G02BUF  G02BWF  G02DDF

          G13AEF

          M01CBF  M01CCF  M01DBF  M01DCF  M01DFF  M01ZBF

          P01ABF  P01ACF

          S01BAF  S07AAF  S15ABF

          X03AAF

          X04BAF  X04BBF  X04CBF  X04DBF

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXintro}{nagaux.ht}{NAG Documentation: introduction}
\begin{chunk}{nagaux.ht}
\begin{page}{manpageXXintro}{NAG Documentation: introduction}
\beginscroll
\begin{verbatim}



     INTRO(3NAG)       Foundation Library (12/10/92)       INTRO(3NAG)



          Introduction                               Essential Introduction
          Essential Introduction to the NAG Foundation Library

          This document is essential reading for any prospective user of
          the Library.

          This document appears in both the Handbook and the Reference
          Manual for the NAG Foundation Library, but with a different
          Section 3 to describe the different forms of routine
          documentation in the two publications.

          1. The Library and its Documentation

          1.1. Structure of the Library

          1.2. Structure of the Documentation

          1.3. On-line Documentation

          1.4. Implementations of the Library

          1.5. Library Identification

          1.6. Fortran Language Standards

          2. Using the Library

          2.1. General Advice

          2.2. Programming Advice

          2.3. Error handling and the Parameter IFAIL

          2.4. Input/output in the Library

          2.5. Auxiliary Routines

          3. Using the Reference Manual

          3.1. General Guidance

          3.2. Structure of Routine Documents

          3.3. Specifications of Parameters

          3.3.1. Classification of Parameters

          3.3.2. Constraints and Suggested Values

          3.3.3. Array Parameters

          3.4. Implementation-dependent Information

          3.5. Example Programs and Results

          3.6. Summary for New Users

          4. Relationship between the Foundation Library 
             and other NAG Libraries

          4.1. NAG Fortran Library

          4.2. NAG Workstation Library

          4.3. NAG C Library

          5. Contact between Users and NAG

          6. General Information about NAG

          7. References



          1. The Library and its Documentation

          1.1. Structure of the Library

          The NAG Foundation Library is a comprehensive collection of
          Fortran 77 routines for the solution of numerical and statistical
          problems. The word 'routine' is used to denote 'subroutine' or '
          function'.

          The Library is divided into chapters, each devoted to a branch of
          numerical analysis or statistics. Each chapter has a three-
          character name and a title, e.g.

               D01 -- Quadrature

          Exceptionally one chapter (S) has a one-character name. (The
          chapters and their names are based on the ACM modified SHARE
          classification index [1].)

          All documented routines in the Library have six-character names,
          beginning with the characters of the chapter name, e.g.

               D01AJF

          Note that the second and third characters are digits, not
          letters; e.g. 0 is the digit zero, not the letter O. The last
          letter of each routine name is always 'F'.

          1.2. Structure of the Documentation

          There are two types of manual for the NAG Foundation Library: a
          Handbook and a Reference Manual.

          The Handbook has the same chapter structure as the Library: each
          chapter of routines in the Library has a corresponding chapter
          (of the same name) in the Handbook. The chapters occur in
          alphanumeric order. General introductory documents and indexes
          are placed at the beginning of the Handbook.

          Each chapter in the Handbook contains a Chapter Introduction,
          followed by concise summaries of the functionality and parameter
          specifications of each routine in the chapter. Exceptionally, in
          some chapters (F06, X01, X02) which contain simple support
          routines, there are no concise summaries: all the routines are
          described together in the Chapter Introduction.

          The Reference Manual provides complete reference documentation
          for the NAG Foundation Library. In the Reference Manual, each
          chapter consists of the following documents:

               Chapter Introduction, e.g. Introduction -- D01;

               Chapter Contents, e.g. Contents -- D01;

               routine documents, one for each documented routine in the
               chapter.

          A routine document has the same name as the routine which it
          describes. Within each chapter, routine documents occur in
          alphanumeric order. As in the Handbook, chapters F06, X01 and X02
          do not contain separate documentation for individual routines.

          The general introductory documents, indexes and chapter
          introductions are the same in the Reference Manual as in the
          Handbook. The only exception is that the Essential Introduction
          contains a different Section 3 in the two publications, to
          describe the different forms of routine documentation.

          1.3. On-line Documentation

          Extensive on-line documentation is included as an integral part
          of the Foundation Library product. This consists of a number of
          components:

               -- general introductory material, including the Essential
               Introduction

               -- a summary list of all documented routines

               -- a KWIC Index

               -- Chapter Introductions

               -- routine documents

               -- example programs, data and results.

          The material has been derived in a number of forms to cater for
          different user requirements, e.g. UNIX man pages, plain text,
          RICH TEXT format etc, and the appropriate version is included on
          the distribution media. For each implementation of the Foundation
          Library the specific documentation (Installers' Note, Users' Note
          etc) gives details of what is provided.

          1.4. Implementations of the Library

          The NAG Foundation Library is available on many different
          computer systems. For each distinct system, an implementation of
          the Library is prepared by NAG, e.g. the IBM RISC System/6000
          implementation. The implementation is distributed as a tested
          compiled library.

          An implementation is usually specific to a range of machines; it
          may also be specific to a particular operating system or
          compilation system.

          Essentially the same facilities are provided in all
          implementations of the Library, but, because of differences in
          arithmetic behaviour and in the compilation system, routines
          cannot be expected to give identical results on different
          systems, especially for sensitive numerical problems.

          The documentation supports all implementations of the Library,
          with the help of a few simple conventions, and a small amount of
          implementation-dependent information, which is published in a
          separate Users' Note for each implementation (see Section 3.4).

          1.5. Library Identification

          You must know which implementation of the Library you are using
          or intend to use. To find out which implementation of the Library
          is available on your machine, you can run a program which calls
          the NAG Foundation Library routine A00AAF. This routine has no
          parameters; it simply outputs text to the advisory message unit
          (see Section 2.4). An example of the output is:


          *** Start of NAG Foundation Library implementation details ***
          Implementation title: IBM RISC System/6000
          Precision: FORTRAN double precision
          Product Code: FFIB601D
          Release: 1
          *** End of NAG Foundation Library implementation details ***

          (The product code can be ignored, except possibly when
          communicating with NAG; see Section 4.)

          1.6. Fortran Language Standards

          All routines in the Library conform to ANSI Standard Fortran 90
          [8].

          Most of the routines in the Library were originally written to
          conform to the earlier Fortran 66 [6] and Fortran 77 [7]
          standards, and their calling sequences contain some parameters
          which are not strictly necessary in Fortran 90.

          2. Using the Library

          2.1. General Advice

          A NAG Foundation Library routine cannot be guaranteed to return
          meaningful results, irrespective of the data supplied to it. Care
          and thought must be exercised in:

          (a) formulating the problem;

          (b) programming the use of library routines;

          (c) assessing the significance of the results.

          2.2. Programming Advice

          The NAG Foundation Library and its documentation are designed on
          the assumption that users know how to write a calling program in
          Fortran.

          When programming a call to a routine, read the routine document
          carefully, especially the description of the Parameters. This
          states clearly which parameters must have values assigned to them
          on entry to the routine, and which return useful values on exit.
          See Section 3.3 for further guidance.

          If a call to a Library routine results in an unexpected error
          message from the system (or possibly from within the Library),
          check the following:


              Has the NAG routine been called with the correct number of
              parameters?

              Do the parameters all have the correct type?

              Have all array parameters been dimensioned correctly?

          Remember that all floating-point parameters must be declared to
          be double precision, either with an explicit DOUBLE PRECISION
          declaration (or COMPLEX(KIND(1.0D0)) if they are complex), or by
          using a suitable IMPLICIT statement.

          Avoid the use of NAG-type names for your own program units or
          COMMON blocks: in general, do not use names which contain a
          three-character NAG chapter name embedded in them; they may clash
          with the names of an auxiliary routine or COMMON block used by
          the NAG Library.

          2.3. Error handling and the Parameter IFAIL

          NAG Foundation Library routines may detect various kinds of
          error, failure or warning conditions. Such conditions are handled
          in a systematic way by the Library. They fall roughly into three
          classes:

          (i)   an invalid value of a parameter on entry to a routine;

          (ii)  a numerical failure during computation (e.g. approximate
                singularity of a matrix, failure of an iteration to
                converge);

          (iii) a warning that although the computation has been completed,
                the results cannot be guaranteed to be completely reliable.

          All three classes are handled in the same way by the Library, and
          are all referred to here simply as 'errors'.

          The error-handling mechanism uses the parameter IFAIL, which is
          the last parameter in the calling sequence of most NAG Foundation
          Library routines. IFAIL serves two purposes:

          (i)   it allows users to specify what action a Library routine
                should take if it detects an error;

          (ii)  it reports the outcome of a call to a Library routine,
                either success (IFAIL = 0) or failure (IFAIL /= 0, with
                different values indicating different reasons for the
                failure, as explained in Section 6 of the routine document)
                .

          For the first purpose IFAIL must be assigned a value before
          calling the routine; since IFAIL is reset by the routine, it must
          be passed as a variable, not as an integer constant. Allowed
          values on entry are:

              IFAIL=0: an error message is output, and execution is
              terminated ('hard failure');

              IFAIL=+1: execution continues without any error message;

              IFAIL=-1: an error message is output, and execution
              continues.

          The settings IFAIL =+-1 are referred to as 'soft failure'.
          The safest choice is to set IFAIL to 0, but this is not always
          convenient: some routines return useful results even though a
          failure (in some cases merely a warning) is indicated. However,
          if IFAIL is set to +- 1 on entry, it is essential for the program
          to test its value on exit from the routine, and to take
          appropriate action.

          The specification of IFAIL in Section 5 of a routine document
          suggests a suitable setting of IFAIL for that routine.

          2.4. Input/output in the Library

          Most NAG Foundation Library routines perform no output to an
          external file, except possibly to output an error message. All
          error messages are written to a logical error message unit. This
          unit number (which is set by default to 6 in most
          implementations) can be changed by calling the Library routine
          X04AAF.

          Some NAG Foundation Library routines may optionally output their
          final results, or intermediate results to monitor the course of
          computation. All output other than error messages is written to a
          logical advisory message unit. This unit number (which is also
          set by default to 6 in most implementations) can be changed by
          calling the Library routine X04ABF. Although it is logically
          distinct from the error message unit, in practice the two unit
          numbers may be the same.

          All output from the Library is formatted.

          The only Library routines which perform input from an external
          file are a few 'option-setting' routines in Chapter E04: the unit
          number is a parameter to the routine, and all input is formatted.

          You must ensure that the relevant Fortran unit numbers are
          associated with the desired external files, either by an OPEN
          statement in your calling program, or by operating system
          commands.

          2.5. Auxiliary Routines

          In addition to those Library routines which are documented and
          are intended to be called by users, the Library also contains
          many auxiliary routines.

          In general, you need not be concerned with them at all, although
          you may be made aware of their existence if, for example, you
          examine a memory map of an executable program which calls NAG
          routines. The only exception is that when calling some NAG
          Foundation Library routines, you may be required or allowed to
          supply the name of an auxiliary routine from the Library as an
          external procedure parameter. The routine documents give the
          necessary details. In such cases, you only need to supply the
          name of the routine; you never need to know details of its
          parameter-list.

          NAG auxiliary routines have names which are similar to the name
          of the documented routine(s) to which they are related, but with
          last letter 'Z', 'Y', and so on, e.g. D01AJZ is an auxiliary
          routine called by D01AJF.

          3. Using the Reference Manual

          3.1. General Guidance

          The Reference Manual is designed to serve the following
          functions:

              -- to give background information about different areas of
              numerical and statistical computation;

              -- to advise on the choice of the most suitable NAG
              Foundation Library routine or routines to solve a particular
              problem;

              -- to give all the information needed to call a NAG
              Foundation Library routine correctly from a Fortran program,
              and to assess the results.

          At the beginning of the Manual are some general introductory
          documents. The following may help you to find the chapter, and
          possibly the routine, which you need to solve your problem:

              Contents     -- a list of routines in the Library, by
              Summary      chapter;

              KWIC Index   -- a keyword index to chapters and routines.

          Having found a likely chapter or routine, you should read the
          corresponding Chapter Introduction, which gives background
          information about that area of numerical computation, and
          recommendations on the choice of a routine, including indexes,
          tables or decision trees.

          When you have chosen a routine, you must consult the routine
          document. Each routine document is essentially self-contained (it
          may contain references to related documents). It includes a
          description of the method, detailed specifications of each
          parameter, explanations of each error exit, and remarks on
          accuracy.

          Example programs which illustrate the use of each routine are
          distributed with the Library in machine-readable form.

          3.2. Structure of Routine Documents

          All routine documents have the same structure, consisting of nine
          numbered sections:

               1.  Purpose

               2.  Specification

               3.  Description

               4.  References

               5.  Parameters (see Section 3.3 below)

               6.  Error Indicators

               7.  Accuracy

               8.  Further Comments

               9.  Example (see Section 3.5 below)

          In a few documents, Section 5 also includes a description of
          printed output which may optionally be produced by the routine.

          3.3. Specifications of Parameters

          Section 5 of each routine document contains the specification of
          the parameters, in the order of their appearance in the parameter
          list.

          3.3.1.  Classification of Parameters

          Parameters are classified as follows:

          Input : you must assign values to these parameters on or before
          entry to the routine, and these values are unchanged on exit from
          the routine.

          Output : you need not assign values to these parameters on or
          before entry to the routine; the routine may assign values to
          them.

          Input/Output : you must assign values to these parameters on or
          before entry to the routine, and the routine may then change
          these values.

          Workspace: array parameters which are used as workspace by the
          routine. You must supply arrays of the correct type and
          dimension, but you need not be concerned with their contents.

          External Procedure: a subroutine or function which must be
          supplied (e.g. to evaluate an integrand or to print intermediate
          output). Usually it must be supplied as part of your calling
          program, in which case its specification includes full details of
          its parameter-list and specifications of its parameters (all
          enclosed in a box). Its parameters are classified in the same way
          as those of the Library routine, but because you must write the
          procedure rather than call it, the significance of the
          classification is different:

              Input : values may be supplied on entry, which your procedure
              must not change.

              Output : you may or must assign values to these parameters
              before exit from your procedure.

              Input/Output : values may be supplied on entry, and you may
              or must assign values to them before exit from your
              procedure.

          Occasionally, as mentioned in Section 2.5, the procedure can be
          supplied from the NAG Library, and then you only need to know its
          name.

          User Workspace: array parameters which are passed by the Library
          routine to an external procedure parameter. They are not used by
          the routine, but you may use them to pass information between
          your calling program and the external procedure.

          3.3.2.  Constraints and Suggested Values

          The word 'Constraint:' or 'Constraints:' in the specification of
          an Input parameter introduces a statement of the range of valid
          values for that parameter, e.g.

              Constraint: N > 0.

          If the routine is called with an invalid value for the parameter
          (e.g. N = 0), the routine will usually take an error exit,
          returning a non-zero value of IFAIL (see Section 2.3).

          In newer documents constraints on parameters of type CHARACTER
          only list uppercase alphabetic characters, e.g.

              Constraint: STRING = 'A' or 'B'.

          In practice all routines with CHARACTER parameters will permit
          the use of lower case characters.

          The phrase 'Suggested Value:' introduces a suggestion for a
          reasonable initial setting for an Input parameter (e.g. accuracy
          or maximum number of iterations) in case you are unsure what
          value to use; you should be prepared to use a different setting
          if the suggested value turns out to be unsuitable for your
          problem.

          3.3.3.  Array Parameters

          Most array parameters have dimensions which depend on the size of
          the problem. In Fortran terminology they have 'adjustable
          dimensions': the dimensions occurring in their declarations are
          integer variables which are also parameters of the Library
          routine.

          For example, a Library routine might have the specification:


               SUBROUTINE <name> (M, N, A, B, LDB)
               INTEGER       M, N, A(N), B(LDB,N), LDB

          For a one-dimensional array parameter, such as A in this example,
          the specification would begin:

           3:  A(N) -- DOUBLE PRECISION array                         Input

          You must ensure that the dimension of the array, as declared in
          your calling (sub)program, is at least as large as the value you
          supply for N. It may be larger; but the routine uses only the
          first N elements.

          For a two-dimensional array parameter, such as B in the example,
          the specification might be:

           4:  B(LDB,N) -- DOUBLE PRECISION array              Input/Output
               On entry: the m by n matrix B.

          and the parameter LDB might be described as follows:

           5:  LDB -- INTEGER                                         Input
               On entry: the first dimension of the array B as declared in
               the (sub)program from which <name> is called. Constraint:
               LDB >= M.

          You must supply the first dimension of the array B, as declared
          in your calling (sub)program, through the parameter LDB, even
          though the number of rows actually used by the routine is
          determined by the parameter M. You must ensure that the first
          dimension of the array is at least as large as the value you
          supply for M. The extra parameter LDB is needed because Fortran
          does not allow information about the dimensions of array
          parameters to be passed automatically to a routine.

          You must also ensure that the second dimension of the array, as
          declared in your calling (sub)program, is at least as large as
          the value you supply for N. It may be larger, but the routine
          only uses the first N columns.

          A program to call the hypothetical routine used as an example in
          this section might include the statements:


               INTEGER AA(100), BB(100,50)
               LDB = 100
               .
               .
               .
               M = 80
               N = 20
               CALL <name>(M,N,AA,BB,LDB)

          Fortran requires that the dimensions which occur in array
          declarations, must be greater than zero. Many NAG routines are
          designed so that they can be called with a parameter like N in
          the above example set to 0 (in which case they would usually exit
          immediately without doing anything). If so, the declarations in
          the Library routine would use the 'assumed size' array dimension,
          and would be given as:


               INTEGER        M, N, A(*), B(LDB,*), LDB

          However, the original declaration of an array in your calling
          program must always have constant dimensions, greater than or
          equal to 1.

          Consult an expert or a textbook on Fortran, if you have
          difficulty in calling NAG routines with array parameters.

          3.4. Implementation-dependent Information

          In order to support all implementations of the Foundation
          Library, the Manual has adopted a convention of using bold
          italics to distinguish terms which have different interpretations
          in different implementations.

          For example, machine precision denotes the relative precision to
          which double precision floating-point numbers are stored in the
          computer, e.g. in an implementation with approximately 16 decimal
          digits of precision, machine precision has a value of
                          - 16
          approximately 10    .

          The precise value of machine precision is given by the function
          X02AJF. Other functions in Chapter X02 return the values of other
          implementation-dependent constants, such as the overflow
          threshold, or the largest representable integer. Refer to the X02

          Chapter Introduction for more details.

          For each implementation of the Library, a separate Users' Note is
          provided. This is a short document, revised at each Mark. At most
          installations it is available in machine-readable form. It gives
          any necessary additional information which applies specifically
          to that implementation, in particular:

              -- the interpretation of bold italicised terms;

              -- the values returned by X02 routines;

              -- the default unit numbers for output (see Section 2.4).

          3.5. Example Programs and Results

          The last section of each routine document describes an example
          problem which can be solved by simple use of the routine. The
          example programs themselves, together with data and results, are
          not printed in the routine document, but are distributed in
          machine-readable form with the Library. The programs are designed
          so that they can fairly easily be modified, and so serve as the
          basis for a simple program to solve a user's own problem.

          The results distributed with each implementation were obtained
          using that implementation of the Library; they may not be
          identical to the results obtained with other implementations.

          3.6. Summary for New Users

          If you are unfamiliar with the NAG Foundation Library and are
          thinking of using a routine from it, please follow these
          instructions:

          (a) read the whole of the Essential Introduction;

          (b) consult the Contents Summary or KWIC Index to choose an
              appropriate chapter or routine;

          (c) read the relevant Chapter Introduction;

          (d) choose a routine, and read the routine document. If the
              routine does not after all meet your needs, return to steps
              (b) or (c);

          (e) read the Users' Note for your implementation;

          (f) consult local documentation, which should be provided by your
              local support staff, about access to the NAG Library on your
              computing system.

          You should now be in a position to include a call to the routine
          in a program, and to attempt to run it. You may of course need to
          refer back to the relevant documentation in the case of
          difficulties, for advice on assessment of results, and so on.

          As you become familiar with the Library, some of steps (a) to (f)
          can be omitted, but it is always essential to:

              -- be familiar with the Chapter Introduction;

              -- read the routine document;

              -- be aware of the Users' Note for your implementation.

          4. Relationship between the Foundation Library 
             and other NAG Libraries

          4.1. NAG Fortran Library

          The Foundation Library is a strict subset of the full NAG Fortran
          Library (Mark 15 or later). Routines in both libraries have
          identical source code (apart from any modifications necessary for
          implementation on a specific system) and hence can be called in
          exactly the same way, though you should consult the relevant
          implementation-specific documentation for details such as values
          of machine constants.

          By its very nature, the Foundation Library cannot contain the
          same extensive range of routines as the full Fortran Library. If
          your application requires a routine which is not in the
          Foundation Library, then please consult NAG for information on
          relevant material available in the Fortran Library.

          Some routines which occur as user-callable routines in the full
          Fortran Library are included as auxiliary routines in the
          Foundation Library but they are not documented in this
          publication and direct calls to them should only be made if you
          are already familiar with their use in the Fortran Library. A
          list of all such auxiliary routines is given at the end of the
          Foundation Library Contents Summary.

          Whereas the full Fortran Library may be provided in either a
          single precision or a double precision version, the Foundation
          Library is always provided in double precision.

          4.2. NAG Workstation Library

          The Foundation Library is a successor product to an earlier,
          smaller subset of the full NAG Fortran Library which was called
          the NAG Workstation Library. The Foundation Library has greater
          functionality than the Workstation Library but is not strictly
          upwards compatible, i.e., a number of routines in the earlier
          product have been replaced by new material to reflect recent
          algorithmic developments.
          If you have used the Workstation Library and wish to convert your
          programs to call routines from the Foundation Library, please
          consult the document 'Converting from the Workstation Library' in
          this Manual.

          4.3. NAG C Library

          NAG has also developed a library of numerical and statistical
          software for use by C programmers. This now contains over 200
          user-callable functions and provides similar (but not identical)
          coverage to that of the Foundation Library. Please contact NAG
          for further details if you have a requirement for similar quality
          library code in C.

          5. Contact between Users and NAG

          If you are using the NAG Foundation Library in a multi-user
          environment and require further advice please consult your local
          support staff who will be receiving regular information from NAG.
          This covers such matters as:

               -- obtaining a copy of the Users' Note for your
               implementation;

               -- obtaining information about local access to the Library;

               -- seeking advice about using the Library;

               -- reporting suspected errors in routines or documents;

               -- making suggestions for new routines or features;

               -- purchasing NAG documentation.

          If you are unable to make contact with a local source of support
          or are in a single-user environment then please contact NAG
          directly at any one of the addresses given at the beginning of
          this publication.

          6. General Information about NAG

          NAG produces and distributes numerical, symbolic, statistical and
          graphical software for the solution of problems in a wide range
          of applications in such areas as science, engineering, financial
          analysis and research.

          For users who write programs and build packages NAG produces sub-
          program libraries in a range of computer languages (Ada, C,
          Fortran, Pascal, Turbo Pascal). NAG also provides a number of
          Fortran programming support products in the NAGWare range --
          Fortran 77 programming tools, Fortran 90 compilers for a number
          of machine platforms (including PC-DOS) and VecPar 77 for
          restructuring and tuning programs for execution on vector or
          parallel computers.

          For users who do not wish to program in the traditional sense but
          want the same reliability and qualities offered by our libraries,
          NAG provides several powerful mathematical and statistical
          packages for interactive use. A major addition to this range of
          packages is Axiom -- the powerful symbolic solver which includes
          a Hypertext system and graphical capabilities.

          For further details of any of these products, please contact NAG
          at one of the addresses given at the beginning of this
          publication.

          References [2], [3], [4], and [5] discuss various aspects of the
          design and development of the NAG Library, and NAG's technical
          policies and organisation.

          7. References

          [1]   (1960--1976) Collected Algorithms from ACM Index by subject
                to algorithms.

          [2]   Ford B (1982) Transportable Numerical Software. Lecture
                Notes in Computer Science. 142 128--140.

          [3]   Ford B, Bentley J, Du Croz J J and Hague S J (1979) The NAG
                Library 'machine'. Software Practice and Experience. 9(1)
                65--72.

          [4]   Ford B and Pool J C T (1984) The Evolving NAG Library
                Service. Sources and Development of Mathematical Software.
                (ed W Cowell) Prentice-Hall. 375--397.

          [5]   Hague S J, Nugent S M and Ford B (1982) Computer-based
                Documentation for the NAG Library. Lecture Notes in Computer
                Science. 142 91--127.

          [6]   (1966) USA Standard Fortran. Publication X3.9. American
                National Standards Institute.

          [7]   (1978) American National Standard Fortran. Publication X3.9.
                American National Standards Institute.

          [8]   (1991) American National Standard Programming Language
                Fortran 90. Publication X3.198.
                American National Standards Institute.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXkwic}{nagaux.ht}{NAG Documentation: keyword in context}
\begin{chunk}{nagaux.ht}
\begin{page}{manpageXXkwic}{NAG Documentation: keyword in context}
\beginscroll
\begin{verbatim}



     KWIC(3NAG)        Foundation Library (12/10/92)        KWIC(3NAG)



          Introduction                                  Keywords in Context
          Keywords in Context

          Pre-computed weights and                                 D01BBF
          abscissae
          for Gaussian quadrature rules, restricted choice of ...

          Sum the                                                  F06EKF
          absolute
          values of real vector elements (DASUM)

          Sum the                                                  F06JKF
          absolute
          values of complex vector elements (DZASUM)

          Index, real vector element with largest                  F06JLF
          absolute
          value (IDAMAX)

          Index, complex vector element with largest               F06JMF
          absolute
          value (IZAMAX)

          ODEs, IVP,                                               D02CJF
          Adams
          method, until function of solution is zero, ...

          1-D quadrature,                                          D01AJF
          adaptive
          , finite interval, strategy due to Piessens and de ...

          1-D quadrature,                                          D01AKF
          adaptive
          , finite interval, method suitable for oscillating ...

          1-D quadrature,                                          D01ALF
          adaptive
          , finite interval, allowing for singularities at ...

          1-D quadrature,                                          D01AMF
          adaptive
          , infinite or semi-infinite interval

          1-D quadrature,                                          D01ANF
          adaptive
          , finite interval, weight function cos((omega)x) ...

          1-D quadrature,                                          D01APF
          adaptive
          , finite interval, weight function with end-point ...

          1-D quadrature,                                          D01AQF
          adaptive
          , finite interval, weight function 1/(x-c), ...

          1-D quadrature,                                          D01ASF
          adaptive
          , semi-infinite interval, weight function cos((omega)x)

          Multi-dimensional                                        D01FCF
          adaptive
          quadrature over hyper-rectangle

          Add                                                      F06ECF
          scalar times real vector to real vector (DAXPY)

          Add                                                      F06GCF
          scalar times complex vector to complex vector (ZAXPY)

          Return or set unit number for                            X04ABF
          advisory
          messages

          Airy                                                     S17AGF
          function Ai(x)

          Airy                                                     S17AHF
          function Bi(x)

          Airy                                                     S17AJF
          function Ai'(x)

          Airy                                                     S17AKF
          function Bi'(x)

          Airy                                                     S17DGF
          functions Ai(z) and Ai('z), complex z

          Airy                                                     S17DHF
          functions Bi(z) and Bi'(z), complex z

          Airy function                                            S17AGF
          Ai(x)

          Airy function                                            S17AJF
          Ai'(x)

          Airy functions                                           S17DGF
          Ai(z)
          and Ai'(z), complex z

          Airy functions Ai(z) and                                 S17DGF
          Ai'(z)
          , complex z
          algebraico-logarithmic
          type

          Two-way contingency table                                G01AFF
          analysis
                      2
          , with (chi) /Fisher's exact test

          Performs principal component                             G03AAF
          analysis

          Performs canonical correlation                           G03ADF
          analysis

          Friedman two-way                                         G08AEF
          analysis
          of variance on k matched samples

          Kruskal-Wallis one-way                                   G08AFF
          analysis
          of variance on k samples of unequal size

          L -                                                      E02GAF
           1
          approximation
          by general linear function

          Approximation                                            E02

          Approximation                                            S
          of special functions

          ARIMA
          model

          Univariate time series, estimation, seasonal             G13AFF
          ARIMA
          model

          ARIMA
          model

          ARIMA
          model

          Safe range of floating-point                             X02AMF
          arithmetic

          Safe range of complex floating-point                     X02ANF
          arithmetic

          Parameter of floating-point                              X02BHF
          arithmetic
          model, b

          Parameter of floating-point                              X02BJF
          arithmetic
          model, p

          Parameter of floating-point                              X02BKF
          arithmetic
          model, e
                  min

          Parameter of floating-point                              X02BLF
          arithmetic
          model, e
                  max

          Parameter of floating-point                              X02DJF
          arithmetic
          model, ROUNDS

          Univariate time series, sample                           G13ABF
          autocorrelation
          function

          Univariate time series, partial                          G13ACF
          autocorrelations
          from autocorrelations

          Univariate time series, partial autocorrelations from    G13ACF
          autocorrelations

          Least-squares cubic spline curve fit,                    E02BEF
          automatic
          knot placement

          Least-squares surface fit by bicubic splines with        E02DCF
          automatic
          knot placement, data on rectangular grid

          Least-squares surface fit by bicubic splines with        E02DDF
          automatic
          knot placement, scattered data

          B-splines                                                E02

          Matrix-vector product, real rectangular                  F06PBF
          band
          matrix (DGBMV)

          Matrix-vector product, real symmetric                    F06PDF
          band
          matrix (DSBMV)

          Matrix-vector product, real triangular                   F06PGF
          band
          matrix (DTBMV)

          System of equations, real triangular                     F06PKF
          band
          matrix (DTBSV)

          Matrix-vector product, complex rectangular               F06SBF
          band
          matrix (ZGBMV)

          Matrix-vector product, complex Hermitian                 F06SDF
          band
          matrix (ZHBMV)

          Matrix-vector product, complex triangular                F06SGF
          band
          matrix (ZTBMV)

          System of equations, complex triangular                  F06SKF
          band
          matrix (ZTBSV)

          bandwidth
          matrix

          Solution of real symmetric positive-definite variable-   F04MCF
          bandwidth
          simultaneous linear equations (coefficient matrix ...

          Basic                                                    F06
          Linear Algebra Subprograms

          ODEs, stiff IVP,                                         D02EJF
          BDF
          method, until function of solution is zero,
          intermediate ...

          Kelvin function                                          S19ABF
          bei
          x

          Kelvin function                                          S19AAF
          ber
          x

          Bessel                                                   S17ACF
          function Y (x)
                    0

          Bessel                                                   S17ADF
          function Y (x)
                    1

          Bessel                                                   S17AEF
          function J (x)
                    0

          Bessel                                                   S17AFF
          function J (x)
                    1

          Bessel                                                   S17DCF
          functions Y      (z), complex z, real (nu)>=0, ...
                     (nu)+n

          Bessel                                                   S17DEF
          functions J      (z), complex z, real (nu)>=0, ...
                     (nu)+n

          Modified                                                 S18ACF
          Bessel
          function K (x)
                    0

          Modified                                                 S18ADF
          Bessel
          function K (x)
                    1

          Modified                                                 S18AEF
          Bessel
          function I (x)
                    0

          Modified                                                 S18AFF
          Bessel
          function I (x)
                    1

          Modified                                                 S18DCF
          Bessel
          functions K      (z), complex z, real (nu)>=0, ...
                     (nu)+n

          Modified                                                 S18DEF
          Bessel
          functions I      (z), complex z, real (nu)>=0, ...
                     (nu)+n

          beta
          distribution

          Computes deviates for the                                G01FEF
          beta
          distribution

          Generates a vector of pseudo-random numbers from a       G05FEF
          beta
          distribution

          Interpolating functions, fitting                         E01DAF
          bicubic
          spline, data on rectangular grid

          Least-squares surface fit,                               E02DAF
          bicubic
          splines

          Least-squares surface fit by                             E02DCF
          bicubic
          splines with automatic knot placement, data on ...

          Least-squares surface fit by                             E02DDF
          bicubic
          splines with automatic knot placement, scattered data

          Evaluation of a fitted                                   E02DEF
          bicubic
          spline at a vector of points

          Evaluation of a fitted                                   E02DFF
          bicubic
          spline at a mesh of points

          Sort 2-D data into panels for fitting                    E02ZAF
          bicubic
          splines

          Fits a generalized linear model with                     G02GBF
          binomial
          errors

          binomial
          distribution

          Computes probability for the                             G01HAF
          bivariate
          Normal distribution

          Airy function                                            S17AHF
          Bi(x)

          Airy function                                            S17AKF
          Bi'(x)

          Airy functions                                           S17DHF
          Bi(z)
          and Bi'(z), complex z

          Airy functions Bi(z) and                                 S17DHF
          Bi'(z)
          , complex z

          BLAS                                                     F06

          Pseudo-random logical                                    G05DZF
          (boolean)
          value

          ODEs,                                                    D02GAF
          boundary
          value problem, finite difference technique with ...

          ODEs,                                                    D02GBF
          boundary
          value problem, finite difference technique with ...

          ODEs, general nonlinear                                  D02RAF
          boundary
          value problem, finite difference technique with ...

          bounds
          , using function values only

          break-points

          break-points

          Zero of continuous function in given interval,           C05ADF
          Bus
          and Dekker algorithm

          Performs                                                 G03ADF
          canonical
          correlation analysis

          Carlo
          method

          Elliptic PDE, Helmholtz equation, 3-D                    D03FAF
          Cartesian
          co-ordinates

          Cauchy
          principal value (Hilbert transform)

          Pseudo-random real numbers,                              G05DFF

          Cauchy
          distribution

          character
          string

          Compare two                                              X05ACF
          character
          strings representing date and time

          Evaluation of fitted polynomial in one variable from     E02AEF
          Chebyshev
          series form (simplified parameter list)

          Derivative of fitted polynomial in                       E02AHF
          Chebyshev
          series form

          Integral of fitted polynomial in                         E02AJF
          Chebyshev
          series form

          Evaluation of fitted polynomial in one variable, from    E02AKF
          Chebyshev
          series form

          Check                                                    C05ZAF
          user's routine for calculating 1st derivatives

          Univariate time series, diagnostic                       G13ASF
          checking
          of residuals, following G13AFF

          Cholesky                                                 F07FDF
          factorization of real symmetric positive-definite ...

          Circular                                                 C06EKF
          convolution or correlation of two real vectors, no ...

          Cosine integral                                          S13ACF
          Ci(x)

          Interpolating functions, method of Renka and             E01SAF
          Cline
          , two variables

          Elliptic PDE, Helmholtz equation, 3-D Cartesian          D03FAF
          co-ordinates

          coefficient
          matrix already factorized by F01MCF)

          coefficient
          matrix (DTRSM)

          coefficient
          matrix (ZTRSM)

          Kendall/Spearman non-parametric rank correlation         G02BNF
          coefficients
          , no missing values, overwriting input data

          Kendall/Spearman non-parametric rank correlation         G02BQF
          coefficients
          , no missing values, preserving input data

          Operations with orthogonal matrices, form                F01QEF
          columns
          of Q after factorization by F01QCF

          Operations with unitary matrices, form                   F01REF
          columns
          of Q after factorization by F01RCF

          Rank                                                     M01DJF
          columns
          of a matrix, real numbers

          Compare                                                  X05ACF
          two character strings representing date and time

          Complement                                               S15ADF
          of error function erfcx

          Unconstrained minimum, pre-                              E04DGF
          conditioned
          conjugate gradient algorithm, function of several ...

          Complex                                                  C06GBF
          conjugate
          of Hermitian sequence

          Complex                                                  C06GCF
          conjugate
          of complex sequence

          Complex                                                  C06GQF
          conjugate
          of multiple Hermitian sequences

          Unconstrained minimum, pre-conditioned                   E04DGF
          conjugate
          gradient algorithm, function of several variables ...

          Dot product of two complex vectors,                      F06GBF
          conjugated
          (ZDOTC)

          Rank-1 update, complex rectangular matrix,               F06SNF
          conjugated
          vector (ZGERC)

          Mathematical                                             X01
          Constants

          Machine                                                  X02
          Constants

          constrained
          , arbitrary data points

          constraints
          , using function values and optionally 1st ...

          Two-way                                                  G01AFF
          contingency
                                    2
          table analysis, with (chi) /Fisher's ...

          continuation
          facility

          Zero of                                                  C05ADF
          continuous
          function in given interval, Bus and Dekker algorithm

                   2
          continuous
          distributions

          Convert                                                  C06GSF
          Hermitian sequences to general complex sequences

          Convert                                                  X05ABF
          array of integers representing date and time to ...

          Circular                                                 C06EKF
          convolution
          or correlation of two real vectors, no extra ...

          Copy                                                     F06EFF
          real vector (DCOPY)

          Copy                                                     F06GFF
          complex vector (ZCOPY)

          correction
          , simple nonlinear problem

          correction
          , general linear problem

          correction
          , continuation facility

          Circular convolution or                                  C06EKF
          correlation
          of two real vectors, no extra workspace

          Kendall/Spearman non-parametric rank                     G02BNF
          correlation
          coefficients, no missing values, overwriting ...

          Kendall/Spearman non-parametric rank                     G02BQF
          correlation
          coefficients, no missing values, preserving input ...

          Computes (optionally weighted)                           G02BXF
          correlation
          and covariance matrices

          Performs canonical                                       G03ADF
          correlation
          analysis

          Multivariate time series, cross-                         G13BCF
          correlations

          cos
          ((omega)x) or sin((omega)x)

          cos
          ((omega)x) or sin((omega)x)

          Cosine                                                   S13ACF
          integral Ci(x)

          Covariance                                               E04YCF
          matrix for nonlinear least-squares problem

          Computes (optionally weighted) correlation and           G02BXF
          covariance
          matrices

          Return the                                               X05BAF
          CPU
          time

          Multivariate time series,                                G13BCF
          cross-correlations

          Multivariate time series, smoothed sample                G13CDF
          cross
          spectrum using spectral smoothing by the trapezium ...

          Interpolating functions,                                 E01BAF
          cubic
          spline interpolant, one variable

          cubic
          Hermite, one variable

          Least-squares curve                                      E02BAF
          cubic
          spline fit (including interpolation)

          Evaluation of fitted                                     E02BBF
          cubic
          spline, function only

          Evaluation of fitted                                     E02BCF
          cubic
          spline, function and derivatives

          Evaluation of fitted                                     E02BDF
          cubic
          spline, definite integral

          Least-squares                                            E02BEF
          cubic
          spline curve fit, automatic knot placement

          Set up reference vector from supplied                    G05EXF
          cumulative
          distribution function or probability distribution ...

          Least-squares                                            E02ADF
          curve
          fit, by polynomials, arbitrary data points

          Least-squares                                            E02BAF
          curve
          cubic spline fit (including interpolation)

          Least-squares cubic spline                               E02BEF
          curve
          fit, automatic knot placement

          Fresnel integral                                         S20ADF
          C(x)

          Daniell)
          window

          Daniell)
          window

          Return                                                   X05AAF
          date
          and time as an array of integers

          Convert array of integers representing                   X05ABF
          date
          and time to character string

          Compare two character strings representing               X05ACF
          date
          and time

          deferred
          correction, simple nonlinear problem

          deferred
          correction, general linear problem

          deferred
          correction, continuation facility

          Interpolated values, interpolant computed by E01BEF,     E01BHF
          definite
          integral, one variable

          Evaluation of fitted cubic spline,                       E02BDF
          definite
          integral

          definite
          matrix

             T
          LDL  factorization of real symmetric positive-           F01MCF
          definite
          variable-bandwidth matrix

          definite

          definite

          Solution of real symmetric positive-                     F04ASF
          definite
          simultaneous linear equations, one right-hand side ...

          Solution of real symmetric positive-                     F04FAF
          definite
          tridiagonal simultaneous linear equations, one ...

          Real sparse symmetric positive-                          F04MAF
          definite
          simultaneous linear equations (coefficient matrix ...

          Solution of real symmetric positive-                     F04MCF
          definite
          variable-bandwidth simultaneous linear equations ...

          Cholesky factorization of real symmetric positive-       F07FDF
          definite
          matrix (DPOTRF)

          Solution of real symmetric positive-                     F07FEF
          definite
          system of linear equations, multiple right-hand ...

          Degenerate                                               S21BAF
          symmetrised elliptic integral of 1st kind R  ...
                                                     C

          Dekker
          algorithm

          Computes upper and lower tail and probability            G01EEF
          density
          function probabilities for the beta distribution

          Solution of system of nonlinear equations using 1st      C05PBF
          derivatives

          Check user's routine for calculating 1st                 C05ZAF
          derivatives

          derivative
          , one variable

          Least-squares polynomial fit, values and                 E02AGF
          derivatives
          may be constrained, arbitrary data points

          Derivative                                               E02AHF
          of fitted polynomial in Chebyshev series form

          Evaluation of fitted cubic spline, function and          E02BCF
          derivatives

          derivatives

          derivatives

          derivatives

          Computes                                                 G01FAF
          deviates
          for the standard Normal distribution

          Computes                                                 G01FBF
          deviates
          for Student's t-distribution

          Computes                                                 G01FCF
          deviates
                       2
          for the (chi)  distribution

          Computes                                                 G01FDF
          deviates
          for the F-distribution

          Computes                                                 G01FEF
          deviates
          for the beta distribution

          Computes                                                 G01FFF
          deviates
          for the gamma distribution

          Univariate time series,                                  G13ASF
          diagnostic
          checking of residuals, following G13AFF

          ODEs, boundary value problem, finite                     D02GAF
          difference
          technique with deferred correction, simple ...

          ODEs, boundary value problem, finite                     D02GBF
          difference
          technique with deferred correction, general linear ...

          difference
          technique with deferred correction, continuation ...

          Elliptic PDE, solution of finite                         D03EDF
          difference
          equations by a multigrid technique

          Univariate time series, seasonal and non-seasonal        G13AAF
          differencing

          Single 1-D real                                          C06EAF
          discrete
          Fourier transform, no extra workspace

          Single 1-D Hermitian                                     C06EBF
          discrete
          Fourier transform, no extra workspace

          Single 1-D complex                                       C06ECF
          discrete
          Fourier transform, no extra workspace

          Multiple 1-D real                                        C06FPF
          discrete
          Fourier transforms

          Multiple 1-D Hermitian                                   C06FQF
          discrete
          Fourier transforms

          Multiple 1-D complex                                     C06FRF
          discrete
          Fourier transforms

          2-D complex                                              C06FUF
          discrete
          Fourier transform

          Discretize                                               D03EEF
          a 2nd order elliptic PDE on a rectangle

          Computes probabilities for the standard Normal           G01EAF
          distribution

          Computes probabilities for Student's t-                  G01EBF
          distribution

                                          2
          Computes probabilities for (chi)                         G01ECF
          distribution

          Computes probabilities for F-                            G01EDF
          distribution

          distribution

          Computes probabilities for the gamma                     G01EFF
          distribution

          Computes deviates for the standard Normal                G01FAF
          distribution

          Computes deviates for Student's t-                       G01FBF
          distribution

                                         2
          Computes deviates for the (chi)                          G01FCF
          distribution

          Computes deviates for the F-                             G01FDF
          distribution

          Computes deviates for the beta                           G01FEF
          distribution

          Computes deviates for the gamma                          G01FFF
          distribution

          Computes probability for the bivariate Normal            G01HAF
          distribution

          Pseudo-random real numbers, uniform                      G05CAF
          distribution
          over (0,1)

          Pseudo-random real numbers, Normal                       G05DDF
          distribution

          Pseudo-random real numbers, Cauchy                       G05DFF
          distribution

          Pseudo-random real numbers, Weibull                      G05DPF
          distribution

          Pseudo-random integer from uniform                       G05DYF
          distribution

          Set up reference vector for multivariate Normal          G05EAF
          distribution

          distribution

          distribution

          Set up reference vector from supplied cumulative         G05EXF
          distribution
          function or probability distribution function

          distribution
          function

          Generates a vector of random numbers from a uniform      G05FAF
          distribution

          distribution

          Generates a vector of random numbers from a Normal       G05FDF
          distribution

          distribution

          distribution

               2
          (chi)  goodness of fit test, for standard continuous     G08CGF
          distributions

          Inverse                                                  G01F
          distributions

          Doncker
          , allowing for badly-behaved integrands

          Dot                                                      F06EAF
          product of two real vectors (DDOT)

          Dot                                                      F06GAF
          product of two complex vectors, unconjugated (ZDOTU)

          Dot                                                      F06GBF
          product of two complex vectors, conjugated (ZDOTC)

          eigenfunction
          , user-specified break-points

          All eigenvalues of generalized real                      F02ADF
          eigenproblem
          of the form Ax=(lambda)Bx where A and B are ...

          All eigenvalues and eigenvectors of generalized real     F02AEF
          eigenproblem
          of the form Ax=(lambda)Bx where A and B are ...

          eigenproblem
          by QZ algorithm, real matrices

          eigenproblem

          eigenvalue
          and eigenfunction, user-specified break-points

          All                                                      F02AAF
          eigenvalues
          of real symmetric matrix

          All                                                      F02ABF
          eigenvalues
          and eigenvectors of real symmetric matrix

          All                                                      F02ADF
          eigenvalues
          of generalized real eigenproblem of the form
          Ax=(lambda)Bx

          All                                                      F02AEF
          eigenvalues
          and eigenvectors of generalized real ...

          All                                                      F02AFF
          eigenvalues
          of real matrix

          All                                                      F02AGF
          eigenvalues
          and eigenvectors of real matrix

          All                                                      F02AJF
          eigenvalues
          of complex matrix

          All                                                      F02AKF
          eigenvalues
          and eigenvectors of complex matrix

          All                                                      F02AWF
          eigenvalues
          of complex Hermitian matrix

          All                                                      F02AXF
          eigenvalues
          and eigenvectors of complex Hermitian matrix

          Selected                                                 F02BBF
          eigenvalues
          and eigenvectors of real symmetric matrix

          All                                                      F02BJF
          eigenvalues
          and optionally eigenvectors of generalized ...

          Selected                                                 F02FJF
          eigenvalues
          and eigenvectors of sparse symmetric eigenproblem

          All eigenvalues and                                      F02ABF
          eigenvectors
          of real symmetric matrix

          All eigenvalues and                                      F02AEF
          eigenvectors
          of generalized real eigenproblem of the form ...

          All eigenvalues and                                      F02AGF
          eigenvectors
          of real matrix

          All eigenvalues and                                      F02AKF
          eigenvectors
          of complex matrix

          All eigenvalues and                                      F02AXF
          eigenvectors
          of complex Hermitian matrix

          Selected eigenvalues and                                 F02BBF
          eigenvectors
          of real symmetric matrix

          All eigenvalues and optionally                           F02BJF
          eigenvectors
          of generalized eigenproblem by QZ algorithm, ...

          Selected eigenvalues and                                 F02FJF
          eigenvectors
          of sparse symmetric eigenproblem

          Elliptic                                                 D03EDF
          PDE, solution of finite difference equations by a ...

          Discretize a 2nd order                                   D03EEF
          elliptic
          PDE on a rectangle

          Elliptic                                                 D03FAF
          PDE, Helmholtz equation, 3-D Cartesian co-ordinates

          Degenerate symmetrised                                   S21BAF
          elliptic
          integral of 1st kind R (x,y)
                                C

          Symmetrised                                              S21BBF
          elliptic
          integral of 1st kind R (x,y,z)
                                F

          Symmetrised                                              S21BCF
          elliptic
          integral of 2nd kind R (x,y,z)
                                D

          Symmetrised                                              S21BDF
          elliptic
          integral of 3rd kind R (x,y,z,r)
                                J

          end-point
          singularities of algebraico-logarithmic type

          error

          Fits a generalized linear model with binomial            G02GBF
          errors

          Fits a generalized linear model with Poisson             G02GCF
          errors

          Complement of                                            S15ADF
          error
          function erfc x

          Error                                                    S15AEF
          function erf x

          Return or set unit number for                            X04AAF
          error
          messages

          Computes                                                 G02DNF
          estimable
          function of a general linear regression model and ...

          Univariate time series, preliminary                      G13ADF
          estimation
          , seasonal ARIMA model

          Univariate time series,                                  G13AFF
          estimation
          , seasonal ARIMA model

          Multivariate time series, preliminary                    G13BDF
          estimation
          of transfer function model

          Multivariate time series,                                G13BEF
          estimation
          of multi-input model

          Compute                                                  F06EJF
          Euclidean
          norm of real vector (DNRM2)

          Compute                                                  F06JJF
          Euclidean
          norm of complex vector (DZNRM2)

          Evaluation                                               E02AEF
          of fitted polynomial in one variable from ...

          Evaluation                                               E02AKF
          of fitted polynomial in one variable, from ...

          Evaluation                                               E02BBF
          of fitted cubic spline, function only

          Evaluation                                               E02BCF
          of fitted cubic spline, function and derivatives

          Evaluation                                               E02BDF
          of fitted cubic spline, definite integral

          Evaluation                                               E02DEF
          of a fitted bicubic spline at a vector of points

          Evaluation                                               E02DFF
          of a fitted bicubic spline at a mesh of points

                                        2
          exact
          test

          Computes the                                             G08AJF
          exact
          probabilities for the Mann-Whitney U statistic, no ...

          Computes the                                             G08AKF
          exact
          probabilities for the Mann-Whitney U statistic, ties ..

          exponential
          distribution

          Complex                                                  S01EAF
          exponential
             z
          , e

          Exponential                                              S13AAF
          integral E (x)
                    1

          Computes a five-point summary (median, hinges and        G01ALF
          extremes)

          Computes probabilities for                               G01EDF
          F
          -distribution

          Computes deviates for the                                G01FDF
          F
          -distribution

          LU                                                       F01BRF
          factorization
          of real sparse matrix

          LU                                                       F01BSF
          factorization
          of real sparse matrix with known sparsity pattern

            T
          LL                                                       F01MAF
          factorization
          of real sparse symmetric positive-definite matrix

             T
          LDL                                                      F01MCF
          factorization
          of real symmetric positive-definite ...

          QR                                                       F01QCF
          factorization
          of real m by n matrix (m>=n)

                                       T
          factorization
          by F01QCF

          factorization
          by F01QCF

          QR                                                       F01RCF
          factorization
          of complex m by n matrix (m>=n)

                                               H
          factorization
          by F01RCF

          factorization
          by F01RCF

          LU                                                       F07ADF
          factorization
          of real m by n matrix (DGETRF)

          Cholesky                                                 F07FDF
          factorization
          of real symmetric positive-definite matrix ...

          Multivariate time series,                                G13BAF
          filtering
          (pre-whitening) by an ARIMA model

          1-D quadrature, adaptive,                                D01AJF
          finite
          interval, strategy due to Piessens and de Doncker, ...

          1-D quadrature, adaptive,                                D01AKF
          finite
          interval, method suitable for oscillating functions

          1-D quadrature, adaptive,                                D01ALF
          finite
          interval, allowing for singularities at user-specified

          1-D quadrature, adaptive,                                D01ANF
          finite
          interval, weight function cos((omega)x) or sin...

          1-D quadrature, adaptive,                                D01APF
          finite
          interval, weight function with end-point ...

          1-D quadrature, adaptive,                                D01AQF
          finite
          interval, weight function 1/(x-c), Cauchy ...

          ODEs, boundary value problem,                            D02GAF
          finite
          difference technique with deferred correction, simple .

          ODEs, boundary value problem,                            D02GBF
          finite
          difference technique with deferred correction, general

          finite/infinite
          range, eigenvalue and eigenfunction, ...

          ODEs, general nonlinear boundary value problem,          D02RAF
          finite
          difference technique with deferred correction, ...

          Elliptic PDE, solution of                                D03EDF
          finite
          difference equations by a multigrid technique

                                                    2
          Fisher's
          exact test

          Interpolating functions,                                 E01DAF
          fitting
          bicubic spline, data on rectangular grid

          Least-squares curve                                      E02ADF
          fit
          , by polynomials, arbitrary data points

          Evaluation of                                            E02AEF
          fitted
          polynomial in one variable from Chebyshev series form .

          Least-squares polynomial                                 E02AGF
          fit
          , values and derivatives may be constrained, arbitrary

          Derivative of                                            E02AHF
          fitted
          polynomial in Chebyshev series form

          Integral of                                              E02AJF
          fitted
          polynomial in Chebyshev series form

          Evaluation of                                            E02AKF
          fitted
          polynomial in one variable, from Chebyshev series form

          Least-squares curve cubic spline                         E02BAF
          fit
          (including interpolation)

          Evaluation of                                            E02BBF
          fitted
          cubic spline, function only

          Evaluation of                                            E02BCF
          fitted
          cubic spline, function and derivatives

          Evaluation of                                            E02BDF
          fitted
          cubic spline, definite integral

          Least-squares cubic spline curve                         E02BEF
          fit
          , automatic knot placement

          Least-squares surface                                    E02DAF
          fit
          , bicubic splines

          Least-squares surface                                    E02DCF
          fit
          by bicubic splines with automatic knot placement, data
          on ...

          Least-squares surface                                    E02DDF
          fit
          by bicubic splines with automatic knot placement, ...

          Evaluation of a                                          E02DEF
          fitted
          bicubic spline at a vector of points

          Evaluation of a                                          E02DFF
          fitted
          bicubic spline at a mesh of points

          Sort 2-D data into panels for                            E02ZAF
          fitting
          bicubic splines

          Fits                                                     G02DAF
          a general (multiple) linear regression model

          Fits                                                     G02DGF
          a general linear regression model for new dependent ...

          Fits                                                     G02GBF
          a generalized linear model with binomial errors

          Fits                                                     G02GCF
          a generalized linear model with Poisson errors

                            2
          Performs the (chi)  goodness of                          G08CGF
          fit
          test, for standard continuous distributions

          Goodness of                                              G08
          fit
          tests

          Computes a                                               G01ALF
          five-point
          summary (median, hinges and extremes)

          Safe range of                                            X02AMF
          floating-point
          arithmetic

          Safe range of complex                                    X02ANF
          floating-point
          arithmetic

          Parameter of                                             X02BHF
          floating-point
          arithmetic model, b

          Parameter of                                             X02BJF
          floating-point
          arithmetic model, p

          Parameter of                                             X02BKF
          floating-point
          arithmetic model, e
                             min

          Parameter of                                             X02BLF
          floating-point
          arithmetic model, e
                             max

          Parameter of                                             X02DJF
          floating-point
          arithmetic model, ROUNDS

          Univariate time series, update state set for             G13AGF
          forecasting

          Univariate time series,                                  G13AHF
          forecasting
          from state set

          Univariate time series, state set and                    G13AJF
          forecasts
          , from fully specified seasonal ARIMA model

          Multivariate time series, state set and                  G13BJF
          forecasts
          from fully specified multi-input model

          Single 1-D real discrete                                 C06EAF
          Fourier
          transform, no extra workspace

          Single 1-D Hermitian discrete                            C06EBF
          Fourier
          transform, no extra workspace

          Single 1-D complex discrete                              C06ECF
          Fourier
          transform, no extra workspace

          Multiple 1-D real discrete                               C06FPF
          Fourier
          transforms

          Multiple 1-D Hermitian discrete                          C06FQF
          Fourier
          transforms

          Multiple 1-D complex discrete                            C06FRF
          Fourier
          transforms

          2-D complex discrete                                     C06FUF
          Fourier
          transform

          frequency
          table

          Frequency                                                G01AEF
          table from raw data

          frequency
          (Daniell) window

          frequency
          (Daniell) window

          Fresnel                                                  S20ACF
          integral S(x)

          Fresnel                                                  S20ADF
          integral C(x)

          Friedman                                                 G08AEF
          two-way analysis of variance on k matched samples

          Computes probabilities for the                           G01EFF
          gamma
          distribution

          Computes deviates for the                                G01FFF
          gamma
          distribution

          Generates a vector of pseudo-random numbers from a       G05FFF
          gamma
          distribution

          Gamma                                                    S14AAF
          function

          Log                                                      S14ABF
          Gamma
          function

          Incomplete                                               S14BAF
          gamma
          functions P(a,x) and Q(a,x)

          Unconstrained minimum of a sum of squares, combined      E04FDF
          Gauss-Newton
          and modified Newton algorithm using function ...

          Unconstrained minimum of a sum of squares, combined      E04GCF
          Gauss-Newton
          and quasi-Newton algorithm, using 1st derivatives

          Pre-computed weights and abscissae for                   D01BBF
          Gaussian
          quadrature rules, restricted choice of rule

          All eigenvalues of                                       F02ADF
          generalized
          real eigenproblem of the form Ax=(lambda)Bx where ...

          All eigenvalues and eigenvectors of                      F02AEF
          generalized
          real eigenproblem of the form Ax=(lambda)Bx where ...

          All eigenvalues and optionally eigenvectors of           F02BJF
          generalized
          eigenproblem by QZ algorithm, real matrices

          Fits a                                                   G02GBF
          generalized
          linear model with binomial errors

          Fits a                                                   G02GCF
          generalized
          linear model with Poisson errors

          Computes orthogonal rotations for loading matrix,        G03BAF
          generalized
          orthomax criterion

          Generate                                                 F06AAF
          real plane rotation (DROTG)

          Initialise random number                                 G05CBF
          generating
          routines to give repeatable sequence

          Initialise random number                                 G05CCF
          generating
          routines to give non-repeatable sequence

          Save state of random number                              G05CFF
          generating
          routines

          Restore state of random number                           G05CGF
          generating
          routines

          Set up reference vector for                              G05ECF
          generating
          pseudo-random integers, Poisson distribution

          Set up reference vector for                              G05EDF
          generating
          pseudo-random integers, binomial distribution

          Generates                                                G05FAF
          a vector of random numbers from a uniform ...

          Generates                                                G05FBF
          a vector of random numbers from an (negative) ...

          Generates                                                G05FDF
          a vector of random numbers from a Normal distribution

          Generates                                                G05FEF
          a vector of pseudo-random numbers from a beta ...

          Generates                                                G05FFF
          a vector of pseudo-random numbers from a gamma ...

          Generates                                                G05HDF
          a realisation of a multivariate time series from a ...

          Gill-Miller
          method

                            2
          Performs the (chi)                                       G08CGF
          goodness
          of fit test, for standard continuous distributions

          Goodness                                                 G08
          of fit tests

          Unconstrained minimum, pre-conditioned conjugate         E04DGF
          gradient
          algorithm, function of several variables using 1st ...

          Hankel                                                   S17DLF
                     (j)
          functions H      (z), j=1,2, ...
                     (nu)+n

          Elliptic PDE,                                            D03FAF
          Helmholtz
          equation, 3-D Cartesian co-ordinates

          Hermite
          , one variable

          Single 1-D                                               C06EBF
          Hermitian
          discrete Fourier transform, no extra workspace

          Multiple 1-D                                             C06FQF
          Hermitian
          discrete Fourier transforms

          Complex conjugate of                                     C06GBF
          Hermitian
          sequence

          Complex conjugate of multiple                            C06GQF
          Hermitian
          sequences

          Convert                                                  C06GSF
          Hermitian
          sequences to general complex sequences

          All eigenvalues of complex                               F02AWF
          Hermitian
          matrix

          All eigenvalues and eigenvectors of complex              F02AXF
          Hermitian
          matrix

          Matrix-vector product, complex                           F06SCF
          Hermitian
          matrix (ZHEMV)

          Matrix-vector product, complex                           F06SDF
          Hermitian
          band matrix (ZHBMV)

          Matrix-vector product, complex                           F06SEF
          Hermitian
          packed matrix (ZHPMV)

          Rank-1 update, complex                                   F06SPF
          Hermitian
          matrix (ZHER)

          Rank-1 update, complex                                   F06SQF
          Hermitian
          packed matrix (ZHPR)

          Rank-2 update, complex                                   F06SRF
          Hermitian
          matrix (ZHER2)

          Rank-2 update, complex                                   F06SSF
          Hermitian
          packed matrix (ZHPR2)

          Matrix-matrix product, one complex                       F06ZCF
          Hermitian
          matrix, one complex rectangular matrix (ZHEMM)

          Rank-k update of a complex                               F06ZPF
          Hermitian
          matrix (ZHERK)

          Rank-2k update of a complex                              F06ZRF
          Hermitian
          matrix (ZHER2K)

          Hilbert
          transform)

          Computes a five-point summary (median,                   G01ALF
          hinges
          and extremes)

          Multi-dimensional adaptive quadrature over               D01FCF
          hyper-rectangle

          Multi-dimensional quadrature over                        D01GBF
          hyper-rectangle
          , Monte Carlo method

          Incomplete                                               S14BAF
          gamma functions P(a,x) and Q(a,x)

          Index                                                    F06JLF
          , real vector element with largest absolute value
          (IDAMAX)

          Index                                                    F06JMF
          , complex vector element with largest absolute value ..

          1-D quadrature, adaptive,                                D01AMF
          infinite
          or semi-infinite interval

          1-D quadrature, adaptive, infinite or semi-              D01AMF
          infinite
          interval

          1-D quadrature, adaptive, semi-                          D01ASF
          infinite
          interval, weight function cos((omega)x) or ...

          infinite
          range, eigenvalue and eigenfunction, user-specified ...

          Calculates standardized residuals and                    G02FAF
          influence
          statistics

          Initialise                                               G05CBF
          random number generating routines to give ...

          Initialise                                               G05CCF
          random number generating routines to give ...

          input
          data

          input
          data

          Multivariate time series, estimation of multi-           G13BEF
          input
          model

          input
          model

          Input/output                                             X04
          utilities

          Pseudo-random                                            G05DYF
          integer
          from uniform distribution

          Set up reference vector for generating pseudo-random     G05ECF
          integers
          , Poisson distribution

          Set up reference vector for generating pseudo-random     G05EDF
          integers
          , binomial distribution

          Pseudo-random permutation of an                          G05EHF
          integer
          vector

          Pseudo-random sample from an                             G05EJF
          integer
          vector

          Pseudo-random                                            G05EYF
          integer
          from reference vector

          Largest representable                                    X02BBF
          integer

          Return date and time as an array of                      X05AAF
          integers

          Convert array of                                         X05ABF
          integers
          representing date and time to character string

          integral
          , one variable

          Integral                                                 E02AJF
          of fitted polynomial in Chebyshev series form

          Evaluation of fitted cubic spline, definite              E02BDF
          integral

          Exponential                                              S13AAF
          integral
          E (x)
           1

          Cosine                                                   S13ACF
          integral
          Ci(x)

          Sine                                                     S13ADF
          integral
          Si(x)

          Fresnel                                                  S20ACF
          integral
          S(x)

          Fresnel                                                  S20ADF
          integral
          C(x)

          Degenerate symmetrised elliptic                          S21BAF
          integral
          of 1st kind R (x,y)
                       C

          Symmetrised elliptic                                     S21BBF
          integral
          of 1st kind R (x,y,z)
                       F

          Symmetrised elliptic                                     S21BCF
          integral
          of 2nd kind R (x,y,z)
                       D

          Symmetrised elliptic                                     S21BDF
          integral
          of 3rd kind R (x,y,z,r)
                       J

          1-D quadrature,                                          D01GAF
          integration
          of function defined by data values, Gill-Miller ...

          Numerical                                                D01
          integration

          Interpolating                                            E01BAF
          functions, cubic spline interpolant, one variable

          Interpolating functions, cubic spline                    E01BAF
          interpolant
          , one variable

          Interpolating                                            E01BEF
          functions, monotonicity-preserving, piecewise ...

          Interpolated                                             E01BFF
          values, interpolant computed by E01BEF, function ...

          Interpolated values,                                     E01BFF
          interpolant
          computed by E01BEF, function only, one variable

          Interpolated                                             E01BGF
          values, interpolant computed by E01BEF, function ...

          Interpolated values,                                     E01BGF
          interpolant
          computed by E01BEF, function and 1st derivative, ...

          Interpolated                                             E01BHF
          values, interpolant computed by E01BEF, definite ...

          Interpolated values,                                     E01BHF
          interpolant
          computed by E01BEF, definite integral, one variable

          Interpolating                                            E01DAF
          functions, fitting bicubic spline, data on ...

          Interpolating                                            E01SAF
          functions, method of Renka and Cline, two ...

          Interpolating                                            E01SEF
          functions, modified Shepard's method, two ...

          Least-squares curve cubic spline fit (including          E02BAF
          interpolation)

          Inverse                                                  G01F
          distributions

          Invert                                                   M01ZAF
          a permutation

          iterative
          refinement

          iterative
          refinement

          ODEs,                                                    D02BBF
          IVP
          , Runge-Kutta-Merson method, over a range, intermediate

          ODEs,                                                    D02BHF
          IVP
          , Runge-Kutta-Merson method, until function of solution
          is ...

          ODEs,                                                    D02CJF
          IVP
          , Adams method, until function of solution is zero, ...

          ODEs, stiff                                              D02EJF
          IVP
          , BDF method, until function of solution is zero, ...

          Kelvin function                                          S19ADF
          kei
          x

          Kelvin                                                   S19AAF
          function ber x

          Kelvin                                                   S19ABF
          function bei x

          Kelvin                                                   S19ACF
          function ker x

          Kelvin                                                   S19ADF
          function kei x

          Kendall/Spearman                                         G02BNF
          non-parametric rank correlation ...

          Kendall/Spearman                                         G02BQF
          non-parametric rank correlation ...

          Kelvin function                                          S19ACF
          ker
          x

          Least-squares cubic spline curve fit, automatic          E02BEF
          knot
          placement

          knot
          placement, data on rectangular grid

          knot
          placement, scattered data

          Kruskal-Wallis                                           G08AFF
          one-way analysis of variance on k samples of ...

          Mean, variance, skewness,                                G01AAF
          kurtosis
          etc, one variable, from raw data

          Mean, variance, skewness,                                G01ADF
          kurtosis
          etc, one variable, from frequency table

          All zeros of complex polynomial, modified                C02AFF
          Laguerre
          method

          All zeros of real polynomial, modified                   C02AGF
          Laguerre
          method

          Index, real vector element with                          F06JLF
          largest
          absolute value (IDAMAX)

          Index, complex vector element with                       F06JMF
          largest
          absolute value (IZAMAX)

          Largest                                                  X02ALF
          positive model number

          Largest                                                  X02BBF
          representable integer

          LDL                                                      F01MCF
          T
            factorization of real symmetric positive-definite ...

          Constructs a stem and                                    G01ARF
          leaf
          plot

          Least-squares                                            E02ADF
          curve fit, by polynomials, arbitrary data points

          Least-squares                                            E02AGF
          polynomial fit, values and derivatives may be ...

          Least-squares                                            E02BAF
          curve cubic spline fit (including interpolation)

          Least-squares                                            E02BEF
          cubic spline curve fit, automatic knot placement

          Least-squares                                            E02DAF
          surface fit, bicubic splines

          Least-squares                                            E02DCF
          surface fit by bicubic splines with automatic ...

          Least-squares                                            E02DDF
          surface fit by bicubic splines with automatic ...

          Covariance matrix for nonlinear                          E04YCF
          least-squares
          problem

          Least-squares                                            F04JGF
          (if rank=n) or minimal least-squares (if ...

          Least-squares (if rank=n) or minimal                     F04JGF
          least-squares
          (if rank<n) solution of m real equations ...

          Sparse linear                                            F04QAF
          least-squares
          problem, m real equations in n unknowns

          linear
          problem

          L -approximation by general                              E02GAF
           1
          linear
          function

          Linear                                                   E04MBF
          programming problem

          Solution of complex simultaneous                         F04ADF
          linear
          equations with multiple right-hand sides

          Solution of real simultaneous                            F04ARF
          linear
          equations, one right-hand side

          linear
          equations, one right-hand side using iterative ...

          Solution of real simultaneous                            F04ATF
          linear
          equations, one right-hand side using iterative ...

          Solution of real sparse simultaneous                     F04AXF
          linear
          equations (coefficient matrix already factorized)

          linear
          equations, one right-hand side

          Real sparse symmetric positive-definite simultaneous     F04MAF
          linear
          equations (coefficient matrix already factorized by ...

          Real sparse symmetric simultaneous                       F04MBF
          linear
          equations

          linear
          equations (coefficient matrix already factorized by ...

          Sparse                                                   F04QAF
          linear
          least-squares problem, m real equations in n ...

          Solution of real system of                               F07AEF
          linear
          equations, multiple right-hand sides, matrix already ..

          linear
          equations, multiple right-hand sides, matrix already ..

          Simple                                                   G02CAF
          linear
          regression with constant term, no missing values

          Fits a general (multiple)                                G02DAF
          linear
          regression model

          Fits a general                                           G02DGF
          linear
          regression model for new dependent variable

          Computes estimable function of a general                 G02DNF
          linear
          regression model and its standard error

          Fits a generalized                                       G02GBF
          linear
          model with binomial errors

          Fits a generalized                                       G02GCF
          linear
          model with Poisson errors

          Basic                                                    F06
          Linear
          Algebra Subprograms

          2nd order Sturm-                                         D02KEF
          Liouville
          problem, regular/singular system, finite/infinite ...

          Computes orthogonal rotations for                        G03BAF
          loading
          matrix, generalized orthomax criterion

          Location                                                 G08
          tests

          Log                                                      S14ABF
          Gamma function

          algebraico-
          logarithmic
          type

          Computes upper and                                       G01EEF
          lower
          tail and probability density function probabilities for

          LU                                                       F01BRF
          factorization of real sparse matrix

          LU                                                       F01BSF
          factorization of real sparse matrix with known sparsity

          LU                                                       F07ADF
          factorization of real m by n matrix (DGETRF)

          Machine                                                  X02AJF
          precision

          Machine                                                  X02
          Constants

          Performs the                                             G08AHF
          Mann-Whitney
          U test on two independent samples

          Computes the exact probabilities for the                 G08AJF
          Mann-Whitney
          U statistic, no ties in pooled sample

          Computes the exact probabilities for the                 G08AKF
          Mann-Whitney
          U statistic, ties in pooled sample

          Friedman two-way analysis of variance on k               G08AEF
          matched
          samples

          Performs the Wilcoxon one-sample (                       G08AGF
          matched
          pairs) signed rank test

          Mathematical                                             X01
          Constants

          Maximization                                             E04

          Maximum                                                  X02BEF
          number of decimal digits that can be represented

          Mean                                                     G01AAF
          , variance, skewness, kurtosis etc, one variable, from

          Mean                                                     G01ADF
          , variance, skewness, kurtosis etc, one variable, from

          Computes a five-point summary (                          G01ALF
          median
          , hinges and extremes)

          Median                                                   G08ACF
          test on two samples of unequal size

          ODEs, IVP, Runge-Kutta-                                  D02BBF
          Merson
          method, over a range, intermediate output

          ODEs, IVP, Runge-Kutta-                                  D02BHF
          Merson
          method, until function of solution is zero (simple ...

          Evaluation of a fitted bicubic spline at a               E02DFF
          mesh
          of points

          Miller
          method

          Least-squares (if rank=n) or                             F04JGF
          minimal
          least-squares (if rank<n) solution of m real ...

          Minimization                                             E04

          Unconstrained                                            E04DGF
          minimum
          , pre-conditioned conjugate gradient algorithm, ...

          Unconstrained                                            E04FDF
          minimum
          of a sum of squares, combined Gauss-Newton and ...

          Unconstrained                                            E04GCF
          minimum
          of a sum of squares, combined Gauss-Newton and ...

          Minimum                                                  E04JAF
          , function of several variables, quasi-Newton ...

          Minimum                                                  E04UCF
          , function of several variables, sequential QP method,

          missing
          values, overwriting input data

          missing
          values, preserving input data

          Simple linear regression with constant term, no          G02CAF
          missing
          values

          Fits a general (multiple) linear regression              G02DAF
          model

          Fits a general linear regression                         G02DGF
          model
          for new dependent variable

          model
          and its standard error

          Fits a generalized linear                                G02GBF
          model
          with binomial errors

          Fits a generalized linear                                G02GCF
          model
          with Poisson errors

          model

          model

          Univariate time series, estimation, seasonal ARIMA       G13AFF
          model

          model

          model

          model

          Multivariate time series, estimation of multi-input      G13BEF
          model

          model

          Smallest positive                                        X02AKF
          model
          number

          Largest positive                                         X02ALF
          model
          number

          Parameter of floating-point arithmetic                   X02BHF
          model
          , b

          Parameter of floating-point arithmetic                   X02BJF
          model
          , p

          Parameter of floating-point arithmetic                   X02BKF
          model
          , e
             min

          Parameter of floating-point arithmetic                   X02BLF
          model
          , e
             max

          Parameter of floating-point arithmetic                   X02DJF
          model
          , ROUNDS

          All zeros of complex polynomial,                         C02AFF
          modified
          Laguerre method

          All zeros of real polynomial,                            C02AGF
          modified
          Laguerre method

          Interpolating functions,                                 E01SEF
          modified
          Shepard's method, two variables

          modified
          Newton algorithm using function values only ...

          Modified                                                 S18ACF
          Bessel function K (x)
                           0

          Modified                                                 S18ADF
          Bessel function K (x)
                           1

          Modified                                                 S18AEF
          Bessel function I (x)
                           0

          Modified                                                 S18AFF
          Bessel function I (x)
                           1

          Modified                                                 S18DCF
          Bessel functions K      (z), real ...
                            (nu)+n

          Modified                                                 S18DEF
          Bessel functions I      (z), real ...
                            (nu)+n

          Interpolating functions,                                 E01BEF
          monotonicity-preserving
          , piecewise cubic Hermite, one variable

          Multi-dimensional quadrature over hyper-rectangle,       D01GBF
          Monte
          Carlo method

          Multi-dimensional                                        D01FCF
          adaptive quadrature over hyper-rectangle

          Multi-dimensional                                        D01GBF
          quadrature over hyper-rectangle, Monte ...

          Multivariate time series, estimation of                  G13BEF
          multi-input
          model

          multi-input
          model

          multigrid
          technique

          Multiple                                                 C06FPF
          1-D real discrete Fourier transforms

          Multiple                                                 C06FQF
          1-D Hermitian discrete Fourier transforms

          Multiple                                                 C06FRF
          1-D complex discrete Fourier transforms

          Complex conjugate of                                     C06GQF
          multiple
          Hermitian sequences

          multiple
          right-hand sides

          Solves a system of equations with                        F06YJF
          multiple
          right-hand sides, real triangular coefficient matrix ..

          Solves system of equations with                          F06ZJF
          multiple
          right-hand sides, complex triangular coefficient ...

          Solution of real system of linear equations,             F07AEF
          multiple
          right-hand sides, matrix already factorized by ...

          multiple
          right-hand sides, matrix already factorized by ...
          Fits a general (                                         G02DAF
          multiple)
          linear regression model

          Multiply                                                 F06EDF
          real vector by scalar (DSCAL)

          Multiply                                                 F06GDF
          complex vector by complex scalar (ZSCAL)

          Multiply                                                 F06JDF
          complex vector by real scalar (ZDSCAL)

          Set up reference vector for                              G05EAF
          multivariate
          Normal distribution

          Pseudo-random                                            G05EZF
          multivariate
          Normal vector from reference vector

          Generates a realisation of a                             G05HDF
          multivariate
          time series from a VARMA model

          Multivariate                                             G13BAF
          time series, filtering (pre-whitening) by an ...

          Multivariate                                             G13BCF
          time series, cross-correlations

          Multivariate                                             G13BDF
          time series, preliminary estimation of transfer ...

          Multivariate                                             G13BEF
          time series, estimation of multi-input model

          Multivariate                                             G13BJF
          time series, state set and forecasts from fully ...

          Multivariate                                             G13CDF
          time series, smoothed sample cross spectrum ...

          Generates a vector of random numbers from an (           G05FBF
          negative)
          exponential distribution

          Newton
          and modified Newton algorithm using function values ...

          Newton
          algorithm using function values only
          Newton
          and quasi-Newton algorithm, using 1st derivatives

          Newton
          algorithm, using 1st derivatives

          Minimum, function of several variables, quasi-           E04JAF
          Newton
          algorithm, simple bounds, using function values only

          Kendall/Spearman                                         G02BNF
          non-parametric
          rank correlation coefficients, no missing ...

          Kendall/Spearman                                         G02BQF
          non-parametric
          rank correlation coefficients, no missing ...

          Initialise random number generating routines to give     G05CCF
          non-repeatable
          sequence

          Univariate time series, seasonal and                     G13AAF
          non-seasonal
          differencing

          Non-parametric                                           G08
          tests

          Solution of system of                                    C05NBF
          nonlinear
          equations using function values only

          Solution of system of                                    C05PBF
          nonlinear
          equations using 1st derivatives

          nonlinear
          problem

          ODEs, general                                            D02RAF
          nonlinear
          boundary value problem, finite difference technique ...

          nonlinear
          constraints, using function values and optionally ...

          Covariance matrix for                                    E04YCF
          nonlinear
          least-squares problem

          Nonlinear                                                E04
          optimization

          Nonlinear                                                E04
          regression

          Compute Euclidean                                        F06EJF
          norm
          of real vector (DNRM2)

          Compute Euclidean                                        F06JJF
          norm
          of complex vector (DZNRM2)

          Computes probabilities for the standard                  G01EAF
          Normal
          distribution

          Computes deviates for the standard                       G01FAF
          Normal
          distribution

          Computes probability for the bivariate                   G01HAF
          Normal
          distribution

          Pseudo-random real numbers,                              G05DDF
          Normal
          distribution

          Set up reference vector for multivariate                 G05EAF
          Normal
          distribution

          Pseudo-random multivariate                               G05EZF
          Normal
          vector from reference vector

          Generates a vector of random numbers from a              G05FDF
          Normal
          distribution

          Numerical                                                D01
          integration

          ODEs                                                     D02BBF
          , IVP, Runge-Kutta-Merson method, over a range, ...

          ODEs                                                     D02BHF
          , IVP, Runge-Kutta-Merson method, until function of ...

          ODEs                                                     D02CJF
          , IVP, Adams method, until function of solution is
          zero, ...

          ODEs                                                     D02EJF
          , stiff IVP, BDF method, until function of solution is

          ODEs                                                     D02GAF
          , boundary value problem, finite difference technique .

          ODEs                                                     D02GBF
          , boundary value problem, finite difference technique .

          ODEs                                                     D02RAF
          , general nonlinear boundary value problem, finite ...

          Kruskal-Wallis                                           G08AFF
          one-way
          analysis of variance on k samples of unequal size

          Performs the Wilcoxon                                    G08AGF
          one-sample
          (matched pairs) signed rank test

          Operations                                               F01QDF
                                                   H
          with orthogonal matrices, compute QB or Q B ...

          Operations                                               F01QEF
          with orthogonal matrices, form columns of Q ...

          Operations                                               F01RDF
                                                H
          with unitary matrices, compute QB or Q B ...

          Operations                                               F01REF
          with unitary matrices, form columns of Q after ...

          Nonlinear                                                E04
          optimization

          Operations with                                          F01QDF
          orthogonal
                                   T
          matrices, compute QB or Q B after ...

          Operations with                                          F01QEF
          orthogonal
          matrices, form columns of Q after factorization ...

          Computes                                                 G03BAF
          orthogonal
          rotations for loading matrix, generalized orthomax ...

          orthomax
          criterion

          oscillating
          functions

          Incomplete gamma functions                               S14BAF
          P(a,x)
          and Q(a,x)

          Matrix-vector product, real symmetric                    F06PEF
          packed
          matrix (DSPMV)

          Matrix-vector product, real triangular                   F06PHF
          packed
          matrix (DTPMV)

          System of equations, real triangular                     F06PLF
          packed
          matrix (DTPSV)

          Rank-1 update, real symmetric                            F06PQF
          packed
          matrix (DSPR)

          Rank-2 update, real symmetric                            F06PSF
          packed
          matrix (DSPR2)

          Matrix-vector product, complex Hermitian                 F06SEF
          packed
          matrix (ZHPMV)

          Matrix-vector product, complex triangular                F06SHF
          packed
          matrix (ZTPMV)

          System of equations, complex triangular                  F06SLF
          packed
          matrix (ZTPSV)

          Rank-1 update, complex Hermitian                         F06SQF
          packed
          matrix (ZHPR)

          Rank-2 update, complex Hermitian                         F06SSF
          packed
          matrix (ZHPR2)

          Sign test on two                                         G08AAF
          paired
          samples

          Performs the Wilcoxon one-sample (matched                G08AGF
          pairs)
          signed rank test

          Kendall/Spearman non-                                    G02BNF
          parametric
          rank correlation coefficients, no missing values, ...

          Kendall/Spearman non-                                    G02BQF
          parametric
          rank correlation coefficients, no missing values, ...

          Non-                                                     G08
          parametric
          tests

          Univariate time series,                                  G13ACF
          partial
          autocorrelations from autocorrelations

          Elliptic                                                 D03EDF
          PDE
          , solution of finite difference equations by a
          multigrid ...

          Discretize a 2nd order elliptic                          D03EEF
          PDE
          on a rectangle

          Elliptic                                                 D03FAF
          PDE
          , Helmholtz equation, 3-D Cartesian co-ordinates

          Pseudo-random                                            G05EHF
          permutation
          of an integer vector

          Invert a                                                 M01ZAF
          permutation

          Interpolating functions, monotonicity-preserving,        E01BEF
          piecewise
          cubic Hermite, one variable

          Piessens
          and de Doncker, allowing for badly-behaved integrands

          Generate real                                            F06AAF
          plane
          rotation (DROTG)
          Apply real                                               F06EPF
          plane
          rotation (DROT)

          Constructs a stem and leaf                               G01ARF
          plot

          Fits a generalized linear model with                     G02GCF
          Poisson
          errors

          Poisson
          distribution

          All zeros of complex                                     C02AFF
          polynomial
          , modified Laguerre method

          All zeros of real                                        C02AGF
          polynomial
          , modified Laguerre method

          Least-squares curve fit, by                              E02ADF
          polynomials
          , arbitrary data points

          Evaluation of fitted                                     E02AEF
          polynomial
          in one variable from Chebyshev series form ...

          Least-squares                                            E02AGF
          polynomial
          fit, values and derivatives may be constrained, ...

          Derivative of fitted                                     E02AHF
          polynomial
          in Chebyshev series form

          Integral of fitted                                       E02AJF
          polynomial
          in Chebyshev series form

          Evaluation of fitted                                     E02AKF
          polynomial
          in one variable, from Chebyshev series form

          pooled
          sample

          pooled
          sample

          Pre-computed                                             D01BBF
          weights and abscissae for Gaussian quadrature ...

          Unconstrained minimum,                                   E04DGF
          pre-conditioned
          conjugate gradient algorithm, function of ...

          Multivariate time series, filtering (                    G13BAF
          pre-whitening)
          by an ARIMA model

          Machine                                                  X02AJF
          precision

          Univariate time series,                                  G13ADF
          preliminary
          estimation, seasonal ARIMA model

          Multivariate time series,                                G13BDF
          preliminary
          estimation of transfer function model

          principal
          value (Hilbert transform)

          Performs                                                 G03AAF
          principal
          component analysis

          Print                                                    X04CAF
          a real general matrix

          Print                                                    X04DAF
          a complex general matrix

          Computes                                                 G01EAF
          probabilities
          for the standard Normal distribution

          Computes                                                 G01EBF
          probabilities
          for Student's t-distribution

          Computes                                                 G01ECF
          probabilities
                   2
          for (chi)  distribution

          Computes                                                 G01EDF
          probabilities
          for F-distribution

          Computes upper and lower tail and                        G01EEF
          probability
          density function probabilities for the beta ...

          probabilities
          for the beta distribution

          Computes                                                 G01EFF
          probabilities
          for the gamma distribution

          Computes                                                 G01HAF
          probability
          for the bivariate Normal distribution

          probability
          distribution function

          Computes the exact                                       G08AJF
          probabilities
          for the Mann-Whitney U statistic, no ties in ...

          Computes the exact                                       G08AKF
          probabilities
          for the Mann-Whitney U statistic, ties in ...

          Dot                                                      F06EAF
          product
          of two real vectors (DDOT)

          Dot                                                      F06GAF
          product
          of two complex vectors, unconjugated (ZDOTU)

          Dot                                                      F06GBF
          product
          of two complex vectors, conjugated (ZDOTC)

          Matrix-vector                                            F06PAF
          product
          , real rectangular matrix (DGEMV)

          Matrix-vector                                            F06PBF
          product
          , real rectangular band matrix (DGBMV)

          Matrix-vector                                            F06PCF
          product
          , real symmetric matrix (DSYMV)

          Matrix-vector                                            F06PDF
          product
          , real symmetric band matrix (DSBMV)

          Matrix-vector                                            F06PEF
          product
          , real symmetric packed matrix (DSPMV)

          Matrix-vector                                            F06PFF
          product
          , real triangular matrix (DTRMV)

          Matrix-vector                                            F06PGF
          product
          , real triangular band matrix (DTBMV)

          Matrix-vector                                            F06PHF
          product
          , real triangular packed matrix (DTPMV)

          Matrix-vector                                            F06SAF
          product
          , complex rectangular matrix (ZGEMV)

          Matrix-vector                                            F06SBF
          product
          , complex rectangular band matrix (ZGBMV)

          Matrix-vector                                            F06SCF
          product
          , complex Hermitian matrix (ZHEMV)

          Matrix-vector                                            F06SDF
          product
          , complex Hermitian band matrix (ZHBMV)

          Matrix-vector                                            F06SEF
          product
          , complex Hermitian packed matrix (ZHPMV)

          Matrix-vector                                            F06SFF
          product
          , complex triangular matrix (ZTRMV)

          Matrix-vector                                            F06SGF
          product
          , complex triangular band matrix (ZTBMV)

          Matrix-vector                                            F06SHF
          product
          , complex triangular packed matrix (ZTPMV)

          Matrix-matrix                                            F06YAF
          product
          , two real rectangular matrices (DGEMM)

          Matrix-matrix                                            F06YCF
          product
          , one real symmetric matrix, one real rectangular ...

          Matrix-matrix                                            F06YFF
          product
          , one real triangular matrix, one real rectangular ...

          Matrix-matrix                                            F06ZAF
          product
          , two complex rectangular matrices (ZGEMM)

          Matrix-matrix                                            F06ZCF
          product
          , one complex Hermitian matrix, one complex ...

          Matrix-matrix                                            F06ZFF
          product
          , one complex triangular matrix, one complex ...

          Matrix-matrix                                            F06ZTF
          product
          , one complex symmetric matrix, one complex ...

          Linear                                                   E04MBF
          programming
          problem

          Pseudo-random                                            G05CAF
          real numbers, uniform distribution over (0,1)

          Pseudo-random                                            G05DDF
          real numbers, Normal distribution

          Pseudo-random                                            G05DFF
          real numbers, Cauchy distribution

          Pseudo-random                                            G05DPF
          real numbers, Weibull distribution

          Pseudo-random                                            G05DYF
          integer from uniform distribution

          Pseudo-random                                            G05DZF
          logical (boolean) value

          Set up reference vector for generating                   G05ECF
          pseudo-random
          integers, Poisson distribution

          Set up reference vector for generating                   G05EDF
          pseudo-random
          integers, binomial distribution

          Pseudo-random                                            G05EHF
          permutation of an integer vector

          Pseudo-random                                            G05EJF
          sample from an integer vector

          Pseudo-random                                            G05EYF
          integer from reference vector

          Pseudo-random                                            G05EZF
          multivariate Normal vector from reference vector

          Generates a vector of                                    G05FEF
          pseudo-random
          numbers from a beta distribution

          Generates a vector of                                    G05FFF
          pseudo-random
          numbers from a gamma distribution

          Incomplete gamma functions P(a,x) and                    S14BAF
          Q(a,x)

          QP                                                       E04NAF
          problem

          Minimum, function of several variables, sequential       E04UCF
          QP
          method, nonlinear constraints, using function values
          and ...

          QR                                                       F01QCF
          factorization of real m by n matrix (m<=n)

          QR                                                       F01RCF
          factorization of complex m by n matrix (m<=n)

          1-D                                                      D01AJF
          quadrature
          , adaptive, finite interval, strategy due to ...

          1-D                                                      D01AKF
          quadrature
          , adaptive, finite interval, method suitable for ...

          1-D                                                      D01ALF
          quadrature
          , adaptive, finite interval, allowing for ...
          1-D                                                      D01AMF
          quadrature
          , adaptive, infinite or semi-infinite interval

          1-D                                                      D01ANF
          quadrature
          , adaptive, finite interval, weight function
          cos((omega)x) ...

          1-D                                                      D01APF
          quadrature
          , adaptive, finite interval, weight function with ...

          1-D                                                      D01AQF
          quadrature
          , adaptive, finite interval, weight function ...

          1-D                                                      D01ASF
          quadrature
          , adaptive, semi-infinite interval, weight function ...

          Pre-computed weights and abscissae for Gaussian          D01BBF
          quadrature
          rules, restricted choice of rule

          Multi-dimensional adaptive                               D01FCF
          quadrature
          over hyper-rectangle

          1-D                                                      D01GAF
          quadrature
          , integration of function defined by data values, ...

          Multi-dimensional                                        D01GBF
          quadrature
          over hyper-rectangle, Monte Carlo method

          quasi-Newton
          algorithm, using 1st derivatives

          Minimum, function of several variables,                  E04JAF
          quasi-Newton
          algorithm, simple bounds, using function values ...

          QZ
          algorithm, real matrices

          Pseudo-                                                  G05CAF
          random
          real numbers, uniform distribution over (0,1)

          Initialise                                               G05CBF
          random
          number generating routines to give repeatable sequence

          Initialise                                               G05CCF
          random
          number generating routines to give non-repeatable ...

          Save state of                                            G05CFF
          random
          number generating routines

          Restore state of                                         G05CGF
          random
          number generating routines

          Pseudo-                                                  G05DDF
          random
          real numbers, Normal distribution

          Pseudo-                                                  G05DFF
          random
          real numbers, Cauchy distribution

          Pseudo-                                                  G05DPF
          random
          real numbers, Weibull distribution

          Pseudo-                                                  G05DYF
          random
          integer from uniform distribution

          Pseudo-                                                  G05DZF
          random
          logical (boolean) value

          Set up reference vector for generating pseudo-           G05ECF
          random
          integers, Poisson distribution

          Set up reference vector for generating pseudo-           G05EDF
          random
          integers, binomial distribution

          Pseudo-                                                  G05EHF
          random
          permutation of an integer vector

          Pseudo-                                                  G05EJF
          random
          sample from an integer vector

          Pseudo-                                                  G05EYF
          random
          integer from reference vector

          Pseudo-                                                  G05EZF
          random
          multivariate Normal vector from reference vector

          Generates a vector of                                    G05FAF
          random
          numbers from a uniform distribution

          Generates a vector of                                    G05FBF
          random
          numbers from an (negative) exponential distribution

          Generates a vector of                                    G05FDF
          random
          numbers from a Normal distribution

          Generates a vector of pseudo-                            G05FEF
          random
          numbers from a beta distribution

          Generates a vector of pseudo-                            G05FFF
          random
          numbers from a gamma distribution

          ODEs, IVP, Runge-Kutta-Merson method, over a             D02BBF
          range
          , intermediate output

          range
          , eigenvalue and eigenfunction, user-specified ...

          Safe                                                     X02AMF
          range
          of floating-point arithmetic

          Safe                                                     X02ANF
          range
          of complex floating-point arithmetic

          Least-squares (if                                        F04JGF
          rank=n)
          or minimal least-squares (if rank<n) ...

          rank
          <n) solution of m real equations in n unknowns, ...

          rank
          <=n,m>=n

          Rank-1                                                   F06PMF
          update, real rectangular matrix (DGER)

          Rank-1                                                   F06PPF
          update, real symmetric matrix (DSYR)

          Rank-1                                                   F06PQF
          update, real symmetric packed matrix (DSPR)

          Rank-2                                                   F06PRF
          update, real symmetric matrix (DSYR2)

          Rank-2                                                   F06PSF
          update, real symmetric packed matrix (DSPR2)

          Rank-1                                                   F06SMF
          update, complex rectangular matrix, unconjugated ...

          Rank-1                                                   F06SNF
          update, complex rectangular matrix, conjugated vector .

          Rank-1                                                   F06SPF
          update, complex Hermitian matrix (ZHER)

          Rank-1                                                   F06SQF
          update, complex Hermitian packed matrix (ZHPR)

          Rank-2                                                   F06SRF
          update, complex Hermitian matrix (ZHER2)

          Rank-2                                                   F06SSF
          update, complex Hermitian packed matrix (ZHPR2)

          Rank-k                                                   F06YPF
          update of a real symmetric matrix (DSYRK)

          Rank-2k                                                  F06YRF
          update of a real symmetric matrix (DSYR2K)

          Rank-k                                                   F06ZPF
          update of a complex Hermitian matrix (ZHERK)

          Rank-2k                                                  F06ZRF
          update of a complex Hermitian matrix (ZHER2K)

          Rank-k                                                   F06ZUF
          update of a complex symmetric matrix (ZSYRK)

          Rank-2k                                                  F06ZWF
          update of a complex symmetric matrix (ZHER2K)

          Kendall/Spearman non-parametric                          G02BNF
          rank
          correlation coefficients, no missing values,
          overwriting ...

          Kendall/Spearman non-parametric                          G02BQF
          rank
          correlation coefficients, no missing values, preserving

          rank
          test

          Rank                                                     M01DAF
          a vector, real numbers

          Rank                                                     M01DEF
          rows of a matrix, real numbers

          Rank                                                     M01DJF
          columns of a matrix, real numbers

          Rearrange a vector according to given                    M01EAF
          ranks
          , real numbers

          Generates a                                              G05HDF
          realisation
          of a multivariate time series from a VARMA model

          Rearrange                                                M01EAF
          a vector according to given ranks, real numbers

          Multi-dimensional adaptive quadrature over hyper-        D01FCF
          rectangle

          Multi-dimensional quadrature over hyper-                 D01GBF
          rectangle
          , Monte Carlo method

          Discretize a 2nd order elliptic PDE on a                 D03EEF
          rectangle

          rectangular
          grid

          rectangular
          grid

          Matrix-vector product, real                              F06PAF
          rectangular
          matrix (DGEMV)

          Matrix-vector product, real                              F06PBF
          rectangular
          band matrix (DGBMV)

          Rank-1 update, real                                      F06PMF
          rectangular
          matrix (DGER)

          Matrix-vector product, complex                           F06SAF
          rectangular
          matrix (ZGEMV)

          Matrix-vector product, complex                           F06SBF
          rectangular
          band matrix (ZGBMV)

          Rank-1 update, complex                                   F06SMF
          rectangular
          matrix, unconjugated vector (ZGERU)

          Rank-1 update, complex                                   F06SNF
          rectangular
          matrix, conjugated vector (ZGERC)

          Matrix-matrix product, two real                          F06YAF
          rectangular
          matrices (DGEMM)

          rectangular
          matrix (DSYMM)

          rectangular
          matrix (DTRMM)

          Matrix-matrix product, two complex                       F06ZAF
          rectangular
          matrices (ZGEMM)

          rectangular
          matrix (ZHEMM)

          rectangular
          matrix (ZTRMM)

          rectangular
          matrix (ZSYMM)

          Set up                                                   G05EAF
          reference
          vector for multivariate Normal distribution

          Set up                                                   G05ECF
          reference
          vector for generating pseudo-random integers, ...

          Set up                                                   G05EDF
          reference
          vector for generating pseudo-random integers, ...

          Set up                                                   G05EXF
          reference
          vector from supplied cumulative distribution ...

          Pseudo-random integer from                               G05EYF
          reference
          vector

          Pseudo-random multivariate Normal vector from            G05EZF
          reference
          vector

          refinement

          refinement

          Simple linear                                            G02CAF
          regression
          with constant term, no missing values

          Fits a general (multiple) linear                         G02DAF
          regression
          model

          Fits a general linear                                    G02DGF
          regression
          model for new dependent variable

          Computes estimable function of a general linear          G02DNF
          regression
          model and its standard error

          Nonlinear                                                E04
          regression

          2nd order Sturm-Liouville problem,                       D02KEF
          regular/singular
          system, finite/infinite range, eigenvalue ...

          Interpolating functions, method of                       E01SAF
          Renka
          and Cline, two variables

          Calculates standardized                                  G02FAF
          residuals
          and influence statistics
          Univariate time series, diagnostic checking of           G13ASF
          residuals
          , following G13AFF

          right-hand
          sides

          Solution of real simultaneous linear equations, one      F04ARF
          right-hand
          side

          right-hand
          side using iterative refinement

          Solution of real simultaneous linear equations, one      F04ATF
          right-hand
          side using iterative refinement

          right-hand
          side

          Solves a system of equations with multiple               F06YJF
          right-hand
          sides, real triangular coefficient matrix (DTRSM)

          Solves system of equations with multiple                 F06ZJF
          right-hand
          sides, complex triangular coefficient matrix (ZTRSM)

          Solution of real system of linear equations, multiple    F07AEF
          right-hand
          sides, matrix already factorized by F07ADF (DGETRS)

          right-hand
          sides, matrix already factorized by F07FDF (DPOTRS)

          Generate real plane                                      F06AAF
          rotation
          (DROTG)

          Apply real plane                                         F06EPF
          rotation
          (DROT)

          Computes orthogonal                                      G03BAF
          rotations
          for loading matrix, generalized orthomax criterion

          rules
          , restricted choice of rule

          rule
          ODEs, IVP,                                               D02BBF
          Runge-Kutta-Merson
          method, over a range, intermediate output

          ODEs, IVP,                                               D02BHF
          Runge-Kutta-Merson
          method, until function of solution is zero ...

          Safe                                                     X02AMF
          range of floating-point arithmetic

          Safe                                                     X02ANF
          range of complex floating-point arithmetic

          Pseudo-random                                            G05EJF
          sample
          from an integer vector

          Sign test on two paired                                  G08AAF
          samples

          Median test on two                                       G08ACF
          samples
          of unequal size

          Friedman two-way analysis of variance on k matched       G08AEF
          samples

          Kruskal-Wallis one-way analysis of variance on k         G08AFF
          samples
          of unequal size

          Performs the Wilcoxon one-                               G08AGF
          sample
          (matched pairs) signed rank test

          Performs the Mann-Whitney U test on two independent      G08AHF
          samples

          sample

          sample

          Univariate time series,                                  G13ABF
          sample
          autocorrelation function

          Univariate time series, smoothed                         G13CBF
          sample
          spectrum using spectral smoothing by the trapezium ...

          Multivariate time series, smoothed                       G13CDF
          sample
          cross spectrum using spectral smoothing by the ...

          Add                                                      F06ECF
          scalar
          times real vector to real vector (DAXPY)

          Multiply real vector by                                  F06EDF
          scalar
          (DSCAL)

          Add                                                      F06GCF
          scalar
          times complex vector to complex vector (ZAXPY)

          Multiply complex vector by complex                       F06GDF
          scalar
          (ZSCAL)

          Multiply complex vector by real                          F06JDF
          scalar
          (ZDSCAL)

          scattered
          data

          Univariate time series,                                  G13AAF
          seasonal
          and non-seasonal differencing

          Univariate time series, seasonal and non-                G13AAF
          seasonal
          differencing

          Univariate time series, preliminary estimation,          G13ADF
          seasonal
          ARIMA model

          Univariate time series, estimation,                      G13AFF
          seasonal
          ARIMA model

          seasonal
          ARIMA model

          1-D quadrature, adaptive, infinite or                    D01AMF
          semi-infinite
          interval

          1-D quadrature, adaptive,                                D01ASF
          semi-infinite
          interval, weight function cos((omega)x) ...
          Complex conjugate of Hermitian                           C06GBF
          sequence

          Complex conjugate of complex                             C06GCF
          sequence

          Complex conjugate of multiple Hermitian                  C06GQF
          sequences

          Convert Hermitian                                        C06GSF
          sequences
          to general complex sequences

          Convert Hermitian sequences to general complex           C06GSF
          sequences

          sequence

          sequence

          Minimum, function of several variables,                  E04UCF
          sequential
          QP method, nonlinear constraints, using function ...

          Interpolating functions, modified                        E01SEF
          Shepard's
          method, two variables

          Sign                                                     G08AAF
          test on two paired samples

          Performs the Wilcoxon one-sample (matched pairs)         G08AGF
          signed
          rank test

          Solution of complex                                      F04ADF
          simultaneous
          linear equations with multiple right-hand sides

          Solution of real                                         F04ARF
          simultaneous
          linear equations, one right-hand side

          Solution of real symmetric positive-definite             F04ASF
          simultaneous
          linear equations, one right-hand side using ...

          Solution of real                                         F04ATF
          simultaneous
          linear equations, one right-hand side using ...

          Solution of real sparse                                  F04AXF
          simultaneous
          linear equations (coefficient matrix already ...

          simultaneous
          linear equations, one right-hand side

          Real sparse symmetric positive-definite                  F04MAF
          simultaneous
          linear equations (coefficient matrix already ...

          Real sparse symmetric                                    F04MBF
          simultaneous
          linear equations

          simultaneous
          linear equations (coefficient matrix already ...

          sin
          ((omega)x)

          sin
          ((omega)x)

          Sine                                                     S13ADF
          integral Si(x)

          2nd order Sturm-Liouville problem, regular/              D02KEF
          singular
          system, finite/infinite range, eigenvalue and ...

          singularities
          at user-specified break-points

          singularities
          of algebraico-logarithmic type

          Mean, variance,                                          G01AAF
          skewness
          , kurtosis etc, one variable, from raw data

          Mean, variance,                                          G01ADF
          skewness
          , kurtosis etc, one variable, from frequency table

          Smallest                                                 X02AKF
          positive model number

          Univariate time series,                                  G13CBF
          smoothed
          sample spectrum using spectral smoothing by the ...

          smoothing
          by the trapezium frequency (Daniell) window

          Multivariate time series,                                G13CDF
          smoothed
          sample cross spectrum using spectral smoothing by ...

          smoothing
          by the trapezium frequency (Daniell) window

          Sort                                                     E02ZAF
          2-D data into panels for fitting bicubic splines

          Sort                                                     M01CAF
          a vector, real numbers

          LU factorization of real                                 F01BRF
          sparse
          matrix

          LU factorization of real                                 F01BSF
          sparse
          matrix with known sparsity pattern

          LU factorization of real sparse matrix with known        F01BSF
          sparsity
          pattern

            T
          LL  factorization of real                                F01MAF
          sparse
          symmetric positive-definite matrix

          Selected eigenvalues and eigenvectors of                 F02FJF
          sparse
          symmetric eigenproblem

          Solution of real                                         F04AXF
          sparse
          simultaneous linear equations (coefficient matrix ...

          Real                                                     F04MAF
          sparse
          symmetric positive-definite simultaneous linear ...

          Real                                                     F04MBF
          sparse
          symmetric simultaneous linear equations

          Sparse                                                   F04QAF
          linear least-squares problem, m real equations in ...

          Kendall/                                                 G02BNF
          Spearman
          non-parametric rank correlation coefficients, no ...

          Kendall/                                                 G02BQF
          Spearman
          non-parametric rank correlation coefficients, no ...

          Approximation of                                         S
          special
          functions

          Univariate time series, smoothed sample                  G13CBF
          spectrum
          using spectral smoothing by the trapezium frequency ...

          spectral
          smoothing by the trapezium frequency (Daniell) window

          Multivariate time series, smoothed sample cross          G13CDF
          spectrum
          using spectral smoothing by the trapezium frequency ...

          spectral
          smoothing by the trapezium frequency (Daniell) window

          Interpolating functions, cubic                           E01BAF
          spline
          interpolant, one variable

          Interpolating functions, fitting bicubic                 E01DAF
          spline
          , data on rectangular grid

          Least-squares curve cubic                                E02BAF
          spline
          fit (including interpolation)

          Evaluation of fitted cubic                               E02BBF
          spline
          , function only

          Evaluation of fitted cubic                               E02BCF
          spline
          , function and derivatives

          Evaluation of fitted cubic                               E02BDF
          spline
          , definite integral

          Least-squares cubic                                      E02BEF
          spline
          curve fit, automatic knot placement
          Least-squares surface fit, bicubic                       E02DAF
          splines

          Least-squares surface fit by bicubic                     E02DCF
          splines
          with automatic knot placement, data on rectangular grid

          Least-squares surface fit by bicubic                     E02DDF
          splines
          with automatic knot placement, scattered data

          Evaluation of a fitted bicubic                           E02DEF
          spline
          at a vector of points

          Evaluation of a fitted bicubic                           E02DFF
          spline
          at a mesh of points

          Sort 2-D data into panels for fitting bicubic            E02ZAF
          splines

          B-                                                       E02
          splines

          Least-                                                   E02ADF
          squares
          curve fit, by polynomials, arbitrary data points

          Least-                                                   E02AGF
          squares
          polynomial fit, values and derivatives may be ...

          Least-                                                   E02BAF
          squares
          curve cubic spline fit (including interpolation)

          Least-                                                   E02BEF
          squares
          cubic spline curve fit, automatic knot placement

          Least-                                                   E02DAF
          squares
          surface fit, bicubic splines

          Least-                                                   E02DCF
          squares
          surface fit by bicubic splines with automatic knot ...

          Least-                                                   E02DDF
          squares
          surface fit by bicubic splines with automatic knot ...
          Unconstrained minimum of a sum of                        E04FDF
          squares
          , combined Gauss-Newton and modified Newton algorithm .

          Unconstrained minimum of a sum of                        E04GCF
          squares
          , combined Gauss-Newton and quasi-Newton algorithm, ...

          Covariance matrix for nonlinear least-                   E04YCF
          squares
          problem

          Least-                                                   F04JGF
          squares
          (if rank=n) or minimal least-squares (if ...

          Least-squares (if rank=n) or minimal least-              F04JGF
          squares
          (if rank<n) solution of m real equations in n ...

          Sparse linear least-                                     F04QAF
          squares
          problem, m real equations in n unknowns

          Computes probabilities for the                           G01EAF
          standard
          Normal distribution

          Computes deviates for the                                G01FAF
          standard
          Normal distribution

          standard
          error

                            2
          Performs the (chi)  goodness of fit test, for            G08CGF
          standard
          continuous distributions

          Calculates                                               G02FAF
          standardized
          residuals and influence statistics

          Calculates standardized residuals and influence          G02FAF
          statistics

          statistic
          , no ties in pooled sample

          statistic
          , ties in pooled sample
          Constructs a                                             G01ARF
          stem
          and leaf plot

          ODEs,                                                    D02EJF
          stiff
          IVP, BDF method, until function of solution is zero, ..

          Computes probabilities for                               G01EBF
          Student's
          t-distribution

          Computes deviates for                                    G01FBF
          Student's
          t-distribution

          2nd order                                                D02KEF
          Sturm-Liouville
          problem, regular/singular system, ...

          Basic Linear Algebra                                     F06
          Subprograms

          Unconstrained minimum of a                               E04FDF
          sum
          of squares, combined Gauss-Newton and modified Newton .

          Unconstrained minimum of a                               E04GCF
          sum
          of squares, combined Gauss-Newton and quasi-Newton ...

          Sum                                                      F06EKF
          the absolute values of real vector elements (DASUM)

          Sum                                                      F06JKF
          the absolute values of complex vector elements (DZASUM)

          Computes a five-point                                    G01ALF
          summary
          (median, hinges and extremes)

          Least-squares                                            E02DAF
          surface
          fit, bicubic splines

          Least-squares                                            E02DCF
          surface
          fit by bicubic splines with automatic knot placement, .

          Least-squares                                            E02DDF
          surface
          fit by bicubic splines with automatic knot placement, .
          SVD                                                      F02WEF
          of real matrix

          SVD                                                      F02XEF
          of complex matrix

          Swap                                                     F06EGF
          two real vectors (DSWAP)

          Swap                                                     F06GGF
          two complex vectors (ZSWAP)

          Fresnel integral                                         S20ACF
          S(x)

            T
          LL  factorization of real sparse                         F01MAF
          symmetric
          positive-definite matrix

             T
          LDL  factorization of real                               F01MCF
          symmetric
          positive-definite variable-bandwidth matrix

          All eigenvalues of real                                  F02AAF
          symmetric
          matrix

          All eigenvalues and eigenvectors of real                 F02ABF
          symmetric
          matrix

          symmetric
          and B is positive-definite

          symmetric
          and B is positive-definite

          Selected eigenvalues and eigenvectors of real            F02BBF
          symmetric
          matrix

          Selected eigenvalues and eigenvectors of sparse          F02FJF
          symmetric
          eigenproblem

          Solution of real                                         F04ASF
          symmetric
          positive-definite simultaneous linear equations, ...

          Solution of real                                         F04FAF
          symmetric
          positive-definite tridiagonal simultaneous linear ...

          Real sparse                                              F04MAF
          symmetric
          positive-definite simultaneous linear equations ...

          Real sparse                                              F04MBF
          symmetric
          simultaneous linear equations

          Solution of real                                         F04MCF
          symmetric
          positive-definite variable-bandwidth simultaneous ...

          Matrix-vector product, real                              F06PCF
          symmetric
          matrix (DSYMV)

          Matrix-vector product, real                              F06PDF
          symmetric
          band matrix (DSBMV)

          Matrix-vector product, real                              F06PEF
          symmetric
          packed matrix (DSPMV)

          Rank-1 update, real                                      F06PPF
          symmetric
          matrix (DSYR)

          Rank-1 update, real                                      F06PQF
          symmetric
          packed matrix (DSPR)

          Rank-2 update, real                                      F06PRF
          symmetric
          matrix (DSYR2)

          Rank-2 update, real                                      F06PSF
          symmetric
          packed matrix (DSPR2)

          Matrix-matrix product, one real                          F06YCF
          symmetric
          matrix, one real rectangular matrix (DSYMM)

          Rank-k update of a real                                  F06YPF
          symmetric
          matrix (DSYRK)

          Rank-2k update of a real                                 F06YRF
          symmetric
          matrix (DSYR2K)

          Matrix-matrix product, one complex                       F06ZTF
          symmetric
          matrix, one complex rectangular matrix (ZSYMM)

          Rank-k update of a complex                               F06ZUF
          symmetric
          matrix (ZSYRK)

          Rank-2k update of a complex                              F06ZWF
          symmetric
          matrix (ZHER2K)

          Cholesky factorization of real                           F07FDF
          symmetric
          positive-definite matrix (DPOTRF)

          Solution of real                                         F07FEF
          symmetric
          positive-definite system of linear equations, ...

          Degenerate                                               S21BAF
          symmetrised
          elliptic integral of 1st kind R (x,y)
                                         C

          Symmetrised                                              S21BBF
          elliptic integral of 1st kind R (x,y,z)
                                         F

          Symmetrised                                              S21BCF
          elliptic integral of 2nd kind R (x,y,z)
                                         D

          Symmetrised                                              S21BDF
          elliptic integral of 3rd kind R (x,y,z,r)
                                         J

          Solution of                                              C05NBF
          system
          of nonlinear equations using function values only

          Solution of                                              C05PBF
          system
          of nonlinear equations using 1st derivatives

          2nd order Sturm-Liouville problem, regular/singular      D02KEF
          system
          , finite/infinite range, eigenvalue and eigenfunction,

          System                                                   F06PJF
          of equations, real triangular matrix (DTRSV)

          System                                                   F06PKF
          of equations, real triangular band matrix (DTBSV)

          System                                                   F06PLF
          of equations, real triangular packed matrix (DTPSV)

          System                                                   F06SJF
          of equations, complex triangular matrix (ZTRSV)

          System                                                   F06SKF
          of equations, complex triangular band matrix (ZTBSV)

          System                                                   F06SLF
          of equations, complex triangular packed matrix (ZTPSV)

          Solves a                                                 F06YJF
          system
          of equations with multiple right-hand sides, real ...

          Solves                                                   F06ZJF
          system
          of equations with multiple right-hand sides, complex ..

          Solution of real                                         F07AEF
          system
          of linear equations, multiple right-hand sides, matrix

          Solution of real symmetric positive-definite             F07FEF
          system
          of linear equations, multiple right-hand sides, matrix

          Computes probabilities for Student's                     G01EBF
          t-distribution

          Computes deviates for Student's                          G01FBF
          t-distribution

          table

          Frequency                                                G01AEF
          table
          from raw data

          Two-way contingency                                      G01AFF
          table
                              2
          analysis, with (chi) /Fisher's exact test

          Computes upper and lower                                 G01EEF
          tail
          and probability density function probabilities for the

                                        2
          test

          Sign                                                     G08AAF
          test
          on two paired samples

          Median                                                   G08ACF
          test
          on two samples of unequal size

          test

          Performs the Mann-Whitney U                              G08AHF
          test
          on two independent samples

                            2
          Performs the (chi)  goodness of fit                      G08CGF
          test
          , for standard continuous distributions

          Goodness of fit                                          G08
          tests

          Location                                                 G08
          tests

          Non-parametric                                           G08
          tests

          ties
          in pooled sample

          ties
          in pooled sample

          Generates a realisation of a multivariate                G05HDF
          time
          series from a VARMA model

          Univariate                                               G13AAF
          time
          series, seasonal and non-seasonal differencing

          Univariate                                               G13ABF
          time
          series, sample autocorrelation function

          Univariate                                               G13ACF
          time
          series, partial autocorrelations from autocorrelations

          Univariate                                               G13ADF
          time
          series, preliminary estimation, seasonal ARIMA model

          Univariate                                               G13AFF
          time
          series, estimation, seasonal ARIMA model

          Univariate                                               G13AGF
          time
          series, update state set for forecasting

          Univariate                                               G13AHF
          time
          series, forecasting from state set

          Univariate                                               G13AJF
          time
          series, state set and forecasts, from fully specified .

          Univariate                                               G13ASF
          time
          series, diagnostic checking of residuals, following
          G13AFF

          Multivariate                                             G13BAF
          time
          series, filtering (pre-whitening) by an ARIMA model

          Multivariate                                             G13BCF
          time
          series, cross-correlations

          Multivariate                                             G13BDF
          time
          series, preliminary estimation of transfer function
          model

          Multivariate                                             G13BEF
          time
          series, estimation of multi-input model

          Multivariate                                             G13BJF
          time
          series, state set and forecasts from fully specified ..

          Univariate                                               G13CBF
          time
          series, smoothed sample spectrum using spectral ...

          Multivariate                                             G13CDF
          time
          series, smoothed sample cross spectrum using spectral .

          Return date and                                          X05AAF
          time
          as an array of integers

          Convert array of integers representing date and          X05ABF
          time
          to character string

          Compare two character strings representing date and      X05ACF
          time

          Return the CPU                                           X05BAF
          time

          Multivariate time series, preliminary estimation of      G13BDF
          transfer
          function model

          Single 1-D real discrete Fourier                         C06EAF
          transform
          , no extra workspace

          Single 1-D Hermitian discrete Fourier                    C06EBF
          transform
          , no extra workspace

          Single 1-D complex discrete Fourier                      C06ECF
          transform
          , no extra workspace

          Multiple 1-D real discrete Fourier                       C06FPF
          transforms

          Multiple 1-D Hermitian discrete Fourier                  C06FQF
          transforms

          Multiple 1-D complex discrete Fourier                    C06FRF
          transforms

          2-D complex discrete Fourier                             C06FUF
          transform

          transform)

          trapezium
          frequency (Daniell) window
          trapezium
          frequency (Daniell) window

          Matrix-vector product, real                              F06PFF
          triangular
          matrix (DTRMV)

          Matrix-vector product, real                              F06PGF
          triangular
          band matrix (DTBMV)

          Matrix-vector product, real                              F06PHF
          triangular
          packed matrix (DTPMV)

          System of equations, real                                F06PJF
          triangular
          matrix (DTRSV)

          System of equations, real                                F06PKF
          triangular
          band matrix (DTBSV)

          System of equations, real                                F06PLF
          triangular
          packed matrix (DTPSV)

          Matrix-vector product, complex                           F06SFF
          triangular
          matrix (ZTRMV)

          Matrix-vector product, complex                           F06SGF
          triangular
          band matrix (ZTBMV)

          Matrix-vector product, complex                           F06SHF
          triangular
          packed matrix (ZTPMV)

          System of equations, complex                             F06SJF
          triangular
          matrix (ZTRSV)

          System of equations, complex                             F06SKF
          triangular
          band matrix (ZTBSV)

          System of equations, complex                             F06SLF
          triangular
          packed matrix (ZTPSV)

          Matrix-matrix product, one real                          F06YFF
          triangular
          matrix, one real rectangular matrix (DTRMM)

          triangular
          coefficient matrix (DTRSM)

          Matrix-matrix product, one complex                       F06ZFF
          triangular
          matrix, one complex rectangular matrix (ZTRMM)

          triangular
          coefficient matrix (ZTRSM)

          Solution of real symmetric positive-definite             F04FAF
          tridiagonal
          simultaneous linear equations, one right-hand side

          Two-way                                                  G01AFF
                                                2
          contingency table analysis, with (chi)  ...

          Sign test on                                             G08AAF
          two
          paired samples

          Median test on                                           G08ACF
          two
          samples of unequal size

          Friedman                                                 G08AEF
          two-way
          analysis of variance on k matched samples

          Performs the Mann-Whitney U test on                      G08AHF
          two
          independent samples

          Compare                                                  X05ACF
          two
          character strings representing date and time

          Dot product of two complex vectors,                      F06GAF
          unconjugated
          (ZDOTU)

          Rank-1 update, complex rectangular matrix,               F06SMF
          unconjugated
          vector (ZGERU)

          Unconstrained                                            E04DGF
          minimum, pre-conditioned conjugate gradient ...

          Unconstrained                                            E04FDF
          minimum of a sum of squares, combined ...

          Unconstrained                                            E04GCF
          minimum of a sum of squares, combined ...

          Switch for taking precautions to avoid                   X02DAF
          underflow

          Pseudo-random real numbers,                              G05CAF
          uniform
          distribution over (0,1)

          Pseudo-random integer from                               G05DYF
          uniform
          distribution

          Generates a vector of random numbers from a              G05FAF
          uniform
          distribution

          Operations with                                          F01RDF
          unitary
                                   H
          matrices, compute QB or Q B after ...

          Operations with                                          F01REF
          unitary
          matrices, form columns of Q after factorization by ...

          Univariate                                               G13AAF
          time series, seasonal and non-seasonal differencing

          Univariate                                               G13ABF
          time series, sample autocorrelation function

          Univariate                                               G13ACF
          time series, partial autocorrelations from ...

          Univariate                                               G13ADF
          time series, preliminary estimation, seasonal ...

          Univariate                                               G13AFF
          time series, estimation, seasonal ARIMA model

          Univariate                                               G13AGF
          time series, update state set for forecasting

          Univariate                                               G13AHF
          time series, forecasting from state set

          Univariate                                               G13AJF
          time series, state set and forecasts, from fully ...

          Univariate                                               G13ASF
          time series, diagnostic checking of residuals, ...

          Univariate                                               G13CBF
          time series, smoothed sample spectrum using ...

          Rank-1                                                   F06PMF
          update
          , real rectangular matrix (DGER)

          Rank-1                                                   F06PPF
          update
          , real symmetric matrix (DSYR)

          Rank-1                                                   F06PQF
          update
          , real symmetric packed matrix (DSPR)

          Rank-2                                                   F06PRF
          update
          , real symmetric matrix (DSYR2)

          Rank-2                                                   F06PSF
          update
          , real symmetric packed matrix (DSPR2)

          Rank-1                                                   F06SMF
          update
          , complex rectangular matrix, unconjugated vector
          (ZGERU)

          Rank-1                                                   F06SNF
          update
          , complex rectangular matrix, conjugated vector (ZGERC)

          Rank-1                                                   F06SPF
          update
          , complex Hermitian matrix (ZHER)

          Rank-1                                                   F06SQF
          update
          , complex Hermitian packed matrix (ZHPR)

          Rank-2                                                   F06SRF
          update
          , complex Hermitian matrix (ZHER2)

          Rank-2                                                   F06SSF
          update
          , complex Hermitian packed matrix (ZHPR2)
          Rank-k                                                   F06YPF
          update
          of a real symmetric matrix (DSYRK)

          Rank-2k                                                  F06YRF
          update
          of a real symmetric matrix (DSYR2K)

          Rank-k                                                   F06ZPF
          update
          of a complex Hermitian matrix (ZHERK)

          Rank-2k                                                  F06ZRF
          update
          of a complex Hermitian matrix (ZHER2K)

          Rank-k                                                   F06ZUF
          update
          of a complex symmetric matrix (ZSYRK)

          Rank-2k                                                  F06ZWF
          update
          of a complex symmetric matrix (ZHER2K)

          Univariate time series,                                  G13AGF
          update
          state set for forecasting

          Computes                                                 G01EEF
          upper
          and lower tail and probability density function ...

          Input/output                                             X04
          utilities

          Mean,                                                    G01AAF
          variance
          , skewness, kurtosis etc, one variable, from raw data

          Mean,                                                    G01ADF
          variance
          , skewness, kurtosis etc, one variable, from ...

          Friedman two-way analysis of                             G08AEF
          variance
          on k matched samples

          Kruskal-Wallis one-way analysis of                       G08AFF
          variance
          on k samples of unequal size

          VARMA
          model

          Circular convolution or correlation of two real          C06EKF
          vectors
          , no extra workspace

          Evaluation of a fitted bicubic spline at a               E02DEF
          vector
          of points

          Dot product of two real                                  F06EAF
          vectors
          (DDOT)

          Add scalar times real                                    F06ECF
          vector
          to real vector (DAXPY)

          Add scalar times real vector to real                     F06ECF
          vector
          (DAXPY)

          Multiply real                                            F06EDF
          vector
          by scalar (DSCAL)

          Copy real                                                F06EFF
          vector
          (DCOPY)

          Swap two real                                            F06EGF
          vectors
          (DSWAP)

          Compute Euclidean norm of real                           F06EJF
          vector
          (DNRM2)

          Sum the absolute values of real                          F06EKF
          vector
          elements (DASUM)

          Dot product of two complex                               F06GAF
          vectors
          , unconjugated (ZDOTU)

          Dot product of two complex                               F06GBF
          vectors
          , conjugated (ZDOTC)

          Add scalar times complex                                 F06GCF
          vector
          to complex vector (ZAXPY)

          Add scalar times complex vector to complex               F06GCF
          vector
          (ZAXPY)

          Multiply complex                                         F06GDF
          vector
          by complex scalar (ZSCAL)

          Copy complex                                             F06GFF
          vector
          (ZCOPY)

          Swap two complex                                         F06GGF
          vectors
          (ZSWAP)

          Multiply complex                                         F06JDF
          vector
          by real scalar (ZDSCAL)

          Compute Euclidean norm of complex                        F06JJF
          vector
          (DZNRM2)

          Sum the absolute values of complex                       F06JKF
          vector
          elements (DZASUM)

          Index, real                                              F06JLF
          vector
          element with largest absolute value (IDAMAX)

          Index, complex                                           F06JMF
          vector
          element with largest absolute value (IZAMAX)

          Matrix-                                                  F06PAF
          vector
          product, real rectangular matrix (DGEMV)

          Matrix-                                                  F06PBF
          vector
          product, real rectangular band matrix (DGBMV)

          Matrix-                                                  F06PCF
          vector
          product, real symmetric matrix (DSYMV)

          Matrix-                                                  F06PDF
          vector
          product, real symmetric band matrix (DSBMV)

          Matrix-                                                  F06PEF
          vector
          product, real symmetric packed matrix (DSPMV)

          Matrix-                                                  F06PFF
          vector
          product, real triangular matrix (DTRMV)

          Matrix-                                                  F06PGF
          vector
          product, real triangular band matrix (DTBMV)

          Matrix-                                                  F06PHF
          vector
          product, real triangular packed matrix (DTPMV)

          Matrix-                                                  F06SAF
          vector
          product, complex rectangular matrix (ZGEMV)

          Matrix-                                                  F06SBF
          vector
          product, complex rectangular band matrix (ZGBMV)

          Matrix-                                                  F06SCF
          vector
          product, complex Hermitian matrix (ZHEMV)

          Matrix-                                                  F06SDF
          vector
          product, complex Hermitian band matrix (ZHBMV)

          Matrix-                                                  F06SEF
          vector
          product, complex Hermitian packed matrix (ZHPMV)

          Matrix-                                                  F06SFF
          vector
          product, complex triangular matrix (ZTRMV)

          Matrix-                                                  F06SGF
          vector
          product, complex triangular band matrix (ZTBMV)

          Matrix-                                                  F06SHF
          vector
          product, complex triangular packed matrix (ZTPMV)

          vector
          (ZGERU)
          Rank-1 update, complex rectangular matrix, conjugated    F06SNF
          vector
          (ZGERC)

          Set up reference                                         G05EAF
          vector
          for multivariate Normal distribution

          Set up reference                                         G05ECF
          vector
          for generating pseudo-random integers, Poisson ...

          Set up reference                                         G05EDF
          vector
          for generating pseudo-random integers, binomial ...

          Pseudo-random permutation of an integer                  G05EHF
          vector

          Pseudo-random sample from an integer                     G05EJF
          vector

          Set up reference                                         G05EXF
          vector
          from supplied cumulative distribution function or ...

          Pseudo-random integer from reference                     G05EYF
          vector

          Pseudo-random multivariate Normal                        G05EZF
          vector
          from reference vector

          vector

          Generates a                                              G05FAF
          vector
          of random numbers from a uniform distribution

          Generates a                                              G05FBF
          vector
          of random numbers from an (negative) exponential ...

          Generates a                                              G05FDF
          vector
          of random numbers from a Normal distribution

          Generates a                                              G05FEF
          vector
          of pseudo-random numbers from a beta distribution

          Generates a                                              G05FFF
          vector
          of pseudo-random numbers from a gamma distribution

          Sort a                                                   M01CAF
          vector
          , real numbers

          Rank a                                                   M01DAF
          vector
          , real numbers

          Rearrange a                                              M01EAF
          vector
          according to given ranks, real numbers

          Kruskal-                                                 G08AFF
          Wallis
          one-way analysis of variance on k samples of unequal ..

          Pseudo-random real numbers,                              G05DPF
          Weibull
          distribution

          1-D quadrature, adaptive, finite interval,               D01ANF
          weight
          function cos((omega)x) or sin((omega)x)

          1-D quadrature, adaptive, finite interval,               D01APF
          weight
          function with end-point singularities of ...

          1-D quadrature, adaptive, finite interval,               D01AQF
          weight
          function 1/(x-c), Cauchy principal value ...

          1-D quadrature, adaptive, semi-infinite interval,        D01ASF
          weight
          function cos((omega)x) or sin((omega)x)

          Pre-computed                                             D01BBF
          weights
          and abscissae for Gaussian quadrature rules, ...

          Computes (optionally                                     G02BXF
          weighted)
          correlation and covariance matrices

          Multivariate time series, filtering (pre-                G13BAF
          whitening)
          by an ARIMA model

          Performs the Mann-                                       G08AHF
          Whitney
          U test on two independent samples

          Computes the exact probabilities for the Mann-           G08AJF
          Whitney
          U statistic, no ties in pooled sample

          Computes the exact probabilities for the Mann-           G08AKF
          Whitney
          U statistic, ties in pooled sample

          Performs the                                             G08AGF
          Wilcoxon
          one-sample (matched pairs) signed rank test

          window

          window

          Two-way contingency table analysis, with                 G01AFF
               2
          (chi)
          /Fisher's exact test

          Computes probabilities for                               G01ECF
               2
          (chi)
          distribution

          Computes deviates for the                                G01FCF
               2
          (chi)
          distribution

          Performs the                                             G08CGF
               2
          (chi)
          goodness of fit test, for standard continuous ...

          All                                                      C02AFF
          zeros
          of complex polynomial, modified Laguerre method

          All                                                      C02AGF
          zeros
          of real polynomial, modified Laguerre method

          Zero                                                     C05ADF
          of continuous function in given interval, Bus and
          Dekker ...

          zero
          (simple driver)

          zero
          , intermediate output (simple driver)

          zero
          , intermediate output (simple driver)

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXconvert}{nagaux.ht}{NAG Documentation: conversion}
\begin{chunk}{nagaux.ht}
\begin{page}{manpageXXconvert}{NAG Documentation: conversion}
\beginscroll
\begin{verbatim}



     CONVERSION(3NAG)  Foundation Library (12/10/92)  CONVERSION(3NAG)



          Introduction              Converting from the Workstation Library
          Converting from the Workstation Library

          The NAG Foundation Library is a successor product to an earlier,
          smaller subset of the full NAG Fortran Library which was called
          the NAG Workstation Library. The Foundation Library has been
          designed to be upwards compatible, in terms of functionality,
          with the Workstation Library. However some routines that were
          present in the Workstation Library have been replaced by more up-
          to-date routines from the NAG Fortran Library, which provide
          improved algorithms or software design.

          The list below gives the names of those routines which were
          available in the Workstation Library, but are not included in the
          Foundation Library. For each such routine, it also gives the name
          of the routine in the Foundation Library which best covers the
          same functionality.

              Workstation    Foundation
              Library        Library

              C02AEF         C02AGF

              D02CBF         D02CJF

              D02CHF         D02CJF

              D02EBF         D02EJF

              D02EHF         D02EJF

              D02HAF         D02GAF

              D02HBF         D02RAF

              D02SAF         D02RAF

              E02DBF         E02DEF

              E04VDF         E04UCF

              E04ZCF         E04UCF (see Note 1)

              F01BTF         F07ADF

              F01BXF         F07FDF

              F02WAF         F02WEF

              F04AYF         F07AEF

              F04AZF         F07FEF

              F04YAF         G02DAF

              G01ABF         G02BXF (with M = 2)

              G01BAF         G01EBF

              G01BBF         G01EDF

              G01BCF         G01ECF

              G01BDF         G01EEF

              G01CAF         G01FBF

              G01CBF         G01FDF

              G01CCF         G01FCF

              G01CDF         G01FEF

              G01CEF         G01FAF

              G02BAF         G02BXF

              G02BGF         G02BXF

              G02CEF         G02DAF (see Note 2)

              G02CGF         G02DAF

              G02CJF         G02DAF

              G05DBF         G05FBF

              G05DCF         G05CAF (see Note 3)

              G05DEF         G05FFF

              G05DHF         G05FFF (see Note 4)

              G05EGF         G05HDF

              G05EWF         G05HDF

              G08ABF         G08AGF

              G08ADF         G08AHF

              M01AKF         M01DAF

              M01APF         M01CAF

              S15ABF         G01EAF

              S15ACF         G01EAF

              X02AAF         X02AJF

              X02ACF         X02ALF

          Notes:

          1.    E04ZCF checks user-supplied routines for evaluating the
                first derivatives of the objective function and constraint
                functions supplied to E04VDF. This functionality is now
                provided by E04UCF, using the optional parameters Verify
                Objective Gradients and Verify Constraint Gradients.

          2.    G02CEF selects variables to be included in a linear
                regression performed by G02CGF. This functionality is now
                provided by the parameter ISX of G02DAF.

          3.    A call to G05DCF can be replaced by a simple transformation
                of the result of a call to G05CAF. The statement
                     X = G05DCF(A,B)
                can be replaced by the statements

                     X = G05CAF(X)
                     X = A + B*LOG(X/(1.0D0-X))

                                                            2
          4.    G05DHF generates random numbers from a (chi)  distribution
                with N degrees of freedom. This can be achieved by calling
                G05FFF with the values DBLE(N)/2.0D0 and 2.0D0 for the
                parameters A and B respectively.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\section{nagc.ht}
\pagetitle{manpageXXc02}{nagc.ht}{ Zeros of Polynomials}
\begin{chunk}{nagc.ht}
\begin{page}{manpageXXc02}{NAG Documentation: c02}
\beginscroll
\begin{verbatim}



     C02(3NAG)         Foundation Library (12/10/92)         C02(3NAG)



          C02 -- Zeros of Polynomials                   Introduction -- C02
                                    Chapter C02
                               Zeros of Polynomials

          1. Scope of the Chapter

          This chapter is concerned with computing the zeros of a
          polynomial with real or complex coefficients.

          2. Background to the Problems

          Let f(z) be a polynomial of degree n with complex coefficients
          a :
           i

                            n    n-1    n-2
                   f(z)==a z +a z   +a z   +...+a   z+a ,  a /=0.
                          0    1      2          n-1   n    0

          A complex number z  is called a zero of f(z) (or equivalently a
                            1
          root of the equation f(z)=0), if:

                                      f(z )=0.
                                         1

          If z  is a zero, then f(z) can be divided by a factor (z-z ):
              1                                                     1

                                f(z)=(z-z )f (z)                        (1)
                                         1  1

          where f (z) is a polynomial of degree n-1. By the Fundamental
                 1
          Theorem of Algebra, a polynomial f(z) always has a zero, and so
          the process of dividing out factors (z-z ) can be continued until
                                                  i
          we have a complete factorization of f(z)

                           f(z)==a (z-z )(z-z )...(z-z ).
                                  0    1     2        n

          Here the complex numbers z ,z ,...,z  are the zeros of f(z); they
                                    1  2      n
          may not all be distinct, so it is sometimes more convenient to
          write:

                                   m       m          m
                                    1       2          k
                     f(z)==a (z-z )  (z-z )  ...(z-z )  ,  k<=n,
                            0    1       2          k

          with distinct zeros z ,z ,...,z  and multiplicities m >=1. If
                               1  2      k                     i
          m =1, z  is called a single zero, if m >1, z  is called a
           i     i                              i     i
          multiple or repeated zero; a multiple zero is also a zero of the
          derivative of f(z).

          If the coefficients of f(z) are all real, then the zeros of f(z)
          are either real or else occur as pairs of conjugate complex
          numbers x+iy and x-iy. A pair of complex conjugate zeros are the
                                                 2
          zeros of a quadratic factor of f(z), (z +rz+s), with real
          coefficients r and s.

          Mathematicians are accustomed to thinking of polynomials as
          pleasantly simple functions to work with. However the problem of
          numerically computing the zeros of an arbitrary polynomial is far
          from simple. A great variety of algorithms have been proposed, of
          which a number have been widely used in practice; for a fairly
          comprehensive survey, see Householder [1]. All general algorithms
          are iterative. Most converge to one zero at a time; the
          corresponding factor can then be divided out as in equation (1)
          above - this process is called deflation or, loosely, dividing
          out the zero - and the algorithm can be applied again to the
          polynomial f (z). A pair of complex conjugate zeros can be
                      1
          divided out together - this corresponds to dividing f(z) by a
          quadratic factor.

          Whatever the theoretical basis of the algorithm, a number of
          practical problems arise: for a thorough discussion of some of
          them see Peters and Wilkinson [2] and Wilkinson [3]. The most
          elementary point is that, even if z  is mathematically an exact
                                             1
          zero of f(z), because of the fundamental limitations of computer
          arithmetic the computed value of f(z ) will not necessarily be
                                              1
          exactly 0.0. In practice there is usually a small region of
          values of z about the exact zero at which the computed value of
          f(z) becomes swamped by rounding errors. Moreover in many
          algorithms this inaccuracy in the computed value of f(z) results
          in a similar inaccuracy in the computed step from one iterate to
          the next. This limits the precision with which any zero can be
          computed. Deflation is another potential cause of trouble, since,
          in the notation of equation (1), the computed coefficients of
          f (z) will not be completely accurate, especially if z  is not an
           1                                                    1
          exact zero of f(z); so the zeros of the computed f (z) will
                                                            1
          deviate from the zeros of f(z).

          A zero is called ill-conditioned if it is sensitive to small
          changes in the coefficients of the polynomial. An ill-conditioned
          zero is likewise sensitive to the computational inaccuracies just
          mentioned. Conversely a zero is called well-conditioned if it is
          comparatively insensitive to such perturbations. Roughly speaking
          a zero which is well separated from other zeros is well-
          conditioned, while zeros which are close together are ill-
          conditioned, but in talking about 'closeness' the decisive factor
          is not the absolute distance between neighbouring zeros but their
          ratio: if the ratio is close to 1 the zeros are ill-conditioned.
          In particular, multiple zeros are ill-conditioned. A multiple
          zero is usually split into a cluster of zeros by perturbations in
          the polynomial or computational inaccuracies.

          2.1. References

          [1]   Householder A S (1970) The Numerical Treatment of a Single
                Nonlinear Equation. McGraw-Hill.

          [2]   Peters G and Wilkinson J H (1971) Practical Problems Arising
                in the Solution of Polynomial Equations. J. Inst. Maths
                Applics. 8 16--35.

          [3]   Wilkinson J H (1963) Rounding Errors in Algebraic Processes,
                Chapter 2. HMSO.

          3. Recommendations on Choice and Use of Routines

          3.1. Discussion

          Two routines are available: C02AFF for polynomials with complex
          coefficients and C02AGF for polynomials with real coefficients.

          C02AFF and C02AGF both use a variant of Laguerre's Method due to
          BT Smith to calculate each zero until the degree of the deflated
          polynomial is less than 3, whereupon the remaining zeros are
          obtained using the 'standard' closed formulae for a quadratic or
          linear equation.

          The accuracy of the roots will depend on how ill-conditioned they
          are. Peters and Wilkinson [2] describe techniques for estimating
          the errors in the zeros after they have been computed.

          3.2. Index

           Zeros of a complex polynomial                             C02AFF
           Zeros of a real polynomial                                C02AGF


          C02 -- Zeros of Polynomials                       Contents -- C02
          Chapter C02

          Zeros of Polynomials

          C02AFF  All zeros of complex polynomial, modified Laguerre method

          C02AGF  All zeros of real polynomial, modified Laguerre method

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXc02aff}{nagc.ht}{ Roots of a complex polynomial equation}
\begin{chunk}{nagc.ht}
\begin{page}{manpageXXc02aff}{NAG Documentation: c02aff}
\beginscroll
\begin{verbatim}



     C02AFF(3NAG)      Foundation Library (12/10/92)      C02AFF(3NAG)



          C02 -- Zeros of Polynomials                                C02AFF
                  C02AFF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          C02AFF finds all the roots of a complex polynomial equation,
          using a variant of Laguerre's Method.

          2. Specification

                 SUBROUTINE C02AFF (A, N, SCALE, Z, W, IFAIL)
                 INTEGER          N, IFAIL
                 DOUBLE PRECISION A(2,N+1), Z(2,N), W(4*(N+1))
                 LOGICAL          SCALE

          3. Description

          The routine attempts to find all the roots of the nth degree
          complex polynomial equation

                               n    n-1    n-2
                       P(z)=a z +a z   +a z   +...+a   z+a =0.
                             0    1      2          n-1   n

          The roots are located using a modified form of Laguerre's Method,
          originally proposed by Smith [2].

          The method of Laguerre [3] can be described by the iterative
          scheme

                                             -n*P(z )
                                                   k
                          L(z )=z   -z = ----------------,
                             k   k+1  k             
                                         P'(z )+-  /H(z )
                                             k   \/    k

                                           2
          where H(z )=(n-1)*[(n-1)*(P'(z )) -n*P(z )P''(z )], and z  is
                   k                    k         k      k         0
          specified.

          The sign in the denominator is chosen so that the modulus of the
          Laguerre step at z , viz. |L(z )|, is as small as possible. The
                            k           k
          method can be shown to be cubically convergent for isolated roots
          (real or complex) and linearly convergent for multiple roots.
          The routine generates a sequence of iterates z , z , z ,..., such
                                                        1   2   3
          that |P(z   )|<|P(z )| and ensures that z   +L(z   ) 'roughly'
                   k+1       k                     k+1    k+1
          lies inside a circular region of radius |F| about z  known to
                                                             k
          contain a zero of P(z); that is, |L(z   )|<=|F|, where F denotes
                                               k+1
          the Fejer bound (see Marden [1]) at the point z . Following Smith
                                                         k
          [2], F is taken to be min(B,1.445*n*R), where B is an upper bound
          for the magnitude of the smallest zero given by

                                                         1/n
                      B=1.0001*min(\/n*L(z ),|r |,|a /a |   ),
                                          k    1    n  0

          r  is the zero X of smaller magnitude of the quadratic equation
           1

                                           2
                    2(P''(z )/(2*n*(n-1)))X +2(P'(z )/n)X+P(z )=0
                           k                       k         k

          and the Cauchy lower bound R for the smallest zero is computed
          (using Newton's Method) as the positive root of the polynomial
          equation

                         n      n-1      n-2
                    |a |z +|a |z   +|a |z   +...+|a   |z-|a |=0.
                      0      1        2            n-1     n

          Starting from the origin, successive iterates are generated
          according to the rule z   =z +L(z ) for k = 1,2,3,... and L(z )
                                 k+1  k    k                           k
          is 'adjusted' so that |P(z   )|<|P(z )| and |L(z   )|<=|F|. The
                                    k+1       k           k+1
          iterative procedure terminates if P(z   ) is smaller in absolute
                                               k+1
          value than the bound on the rounding error in P(z   ) and the
                                                           k+1
          current iterate z =z    is taken to be a zero of P(z). The
                           p  k+1
                              ~
          deflated polynomial P(z)=P(z)/(z-z ) of degree n-1 is then
                                            p
          formed, and the above procedure is repeated on the deflated
          polynomial until n<3, whereupon the remaining roots are obtained
          via the 'standard' closed formulae for a linear (n = 1) or
          quadratic (n = 2) equation.

          To obtain the roots of a quadratic polynomial, C02AHF(*) can be
          used.

          4. References

          [1]   Marden M (1966) Geometry of Polynomials. Mathematical
                Surveys. 3 Am. Math. Soc., Providence, RI.

          [2]   Smith B T (1967) ZERPOL: A Zero Finding Algorithm for
                Polynomials Using Laguerre's Method. Technical Report.
                Department of Computer Science, University of Toronto,
                Canada.

          [3]   Wilkinson J H (1965) The Algebraic Eigenvalue Problem.
                Clarendon Press.

          5. Parameters

           1:  A(2,N+1) -- DOUBLE PRECISION array                     Input
               On entry: if A is declared with bounds (2,0:N), then A(1,i)
               and A(2,i) must contain the real and imaginary parts of a
                                                                        i
                                          n-i
               (i.e., the coefficient of z   ), for i=0,1,...,n.
               Constraint: A(1,0) /= 0.0 or A(2,0) /= 0.0.

           2:  N -- INTEGER                                           Input
               On entry: the degree of the polynomial, n. Constraint: N >=
               1.

           3:  SCALE -- LOGICAL                                       Input
               On entry: indicates whether or not the polynomial is to be
               scaled. See Section 8 for advice on when it may be
               preferable to set SCALE = .FALSE. and for a description of
               the scaling strategy. Suggested value: SCALE = .TRUE..

           4:  Z(2,N) -- DOUBLE PRECISION array                      Output
               On exit: the real and imaginary parts of the roots are
               stored in Z(1,i) and Z(2,i) respectively, for i=1,2,...,n.

           5:  W(4*(N+1)) -- DOUBLE PRECISION array               Workspace

           6:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry A(1,0) = 0.0 and A(2,0) = 0.0,

               or       N < 1.

          IFAIL= 2
               The iterative procedure has failed to converge. This error
               is very unlikely to occur. If it does, please contact NAG
               immediately, as some basic assumption for the arithmetic has
               been violated. See also Section 8.

          IFAIL= 3
               Either overflow or underflow prevents the evaluation of P(z)
               near some of its zeros. This error is very unlikely to
               occur. If it does, please contact NAG immediately. See also
               Section 8.

          7. Accuracy

          All roots are evaluated as accurately as possible, but because of
          the inherent nature of the problem complete accuracy cannot be
          guaranteed.

          8. Further Comments

          If SCALE = .TRUE., then a scaling factor for the coefficients is
          chosen as a power of the base B of the machine so that the
                                                                EMAX-P
          largest coefficient in magnitude approaches THRESH = B      .
          Users should note that no scaling is performed if the largest
          coefficient in magnitude exceeds THRESH, even if SCALE = .TRUE..
          (For definition of B, EMAX and P see the Chapter Introduction
          X02.)

          However, with SCALE = .TRUE., overflow may be encountered when
          the input coefficients a ,a ,a ,...,a  vary widely in magnitude,
                                  0  1  2      n
                                                    (4*P)
          particularly on those machines for which B      overflows. In
          such cases, SCALE should be set to .FALSE. and the coefficients
          scaled so that the largest coefficient in magnitude does not
                  (EMAX-2*P)
          exceed B          .

          Even so, the scaling strategy used in C02AFF is sometimes
          insufficient to avoid overflow and/or underflow conditions. In
          such cases, the user is recommended to scale the independent
          variable (z) so that the disparity between the largest and
          smallest coefficient in magnitude is reduced. That is, use the
          routine to locate the zeros of the polynomial d*P(cz) for some
          suitable values of c and d. For example, if the original
                               -100   100 20                   -10
          polynomial was P(z)=2    i+2   z  , then choosing c=2    and
             100                                                     20
          d=2   , for instance, would yield the scaled polynomial i+z  ,
          which is well-behaved relative to overflow and underflow and has
                           10
          zeros which are 2   times those of P(z).

          If the routine fails with IFAIL = 2 or 3, then the real and
          imaginary parts of any roots obtained before the failure occurred
          are stored in Z in the reverse order in which they were found.
          Let n  denote the number of roots found before the failure
               R
          occurred. Then Z(1,n) and Z(2,n) contain the real and imaginary
          parts of the 1st root found, Z(1,n-1) and Z(2,n-1) contain the
          real and imaginary parts of the 2nd root found, ..., Z(1,n ) and
                                                                    R
          Z(2,n ) contain the real and imaginary parts of the n th root
               R                                               R
          found. After the failure has occurred, the remaining 2*(n-n )
                                                                     R
          elements of Z contain a large negative number (equal to
                         

          -1/(X02AMF().\/2)).

          9. Example

                                                 5    4    3    2
          To find the roots of the polynomial a z +a z +a z +a z +a z+a =0,
                                               0    1    2    3    4   5
          where a =(5.0+6.0i), a =(30.0+20.0i), a =-(0.2+6.0i),
                 0              1                2
          a =(50.0+100000.0i), a =-(2.0-40.0i) and a =(10.0+1.0i).
           3                    4                   5

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXc02agf}{nagc.ht}{ Roots of a real polynomial equation}
\begin{chunk}{nagc.ht}
\begin{page}{manpageXXc02agf}{NAG Documentation: c02agf}
\beginscroll
\begin{verbatim}



     C02AGF(3NAG)      Foundation Library (12/10/92)      C02AGF(3NAG)



          C02 -- Zeros of Polynomials                                C02AGF
                  C02AGF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          C02AGF finds all the roots of a real polynomial equation, using a
          variant of Laguerre's Method.

          2. Specification

                 SUBROUTINE C02AGF (A, N, SCALE, Z, W, IFAIL)
                 INTEGER          N, IFAIL
                 DOUBLE PRECISION A(N+1), Z(2,N), W(2*(N+1))
                 LOGICAL          SCALE

          3. Description

          The routine attempts to find all the roots of the nth degree real
          polynomial equation

                               n    n-1    n-2
                       P(z)=a z +a z   +a z   +...+a   z+a =0.
                             0    1      2          n-1   n

          The roots are located using a modified form of Laguerre's Method,
          originally proposed by Smith [2].

          The method of Laguerre [3] can be described by the iterative
          scheme

                                             -n*P(z )
                                                   k
                          L(z )=z   -z = ----------------,
                             k   k+1  k             
                                         P'(z )+-  /H(z )
                                             k   \/    k

                                           2
          where H(z )=(n-1)*[(n-1)*(P'(z )) -n*P(z )P''(z )], and z  is
                   k                    k         k      k         0
          specified.

          The sign in the denominator is chosen so that the modulus of the
          Laguerre step at z , viz. |L(z )|, is as small as possible. The
                            k           k
          method can be shown to be cubically convergent for isolated roots
          (real or complex) and linearly convergent for multiple roots.
          The routine generates a sequence of iterates z , z , z ,..., such
                                                        1   2   3
          that |P(z +1)|<|P(z )| and ensures that z   +L(z   ) 'roughly'
                   k         k                     k+1    k+1
          lies inside a circular region of radius |F| about z  known to
                                                             k
          contain a zero of P(z); that is, |L(z   )|<=|F|, where F denotes
                                               k+1
          the Fejer bound (see Marden [1]) at the point z . Following Smith
                                                         k
          [2], F is taken to be min(B,1.445*n*R), where B is an upper bound
          for the magnitude of the smallest zero given by

                                                         1/n
                      B=1.0001*min(\/n*L(z ),|r |,|a /a |   ),
                                          k    1    n  0

          r  is the zero X of smaller magnitude of the quadratic equation
           1

                                           2
                    2(P''(z )/(2*n*(n-1)))X +2(P'(z )/n)X+P(z )=0
                           k                       k         k

          and the Cauchy lower bound R for the smallest zero is computed
          (using Newton's Method) as the positive root of the polynomial
          equation

                         n      n-1      n-2
                    |a |z +|a |z   +|a |z   +...+|a   |z-|a |=0.
                      0      1        2            n-1     n

          Starting from the origin, successive iterates are generated
          according to the rule z   =z +L(z ) for k=1,2,3,... and L(z ) is
                                 k+1  k    k                         k
                                 k+1       k           k+1
          iterative procedure terminates if P(z   ) is smaller in absolute
                                               k+1
          value than the bound on the rounding error in P(z   ) and the
                                                           k+1
          current iterate z =z    is taken to be a zero of P(z) (as is its
                           p  k-1
                    

          conjugate z  if z  is complex). The deflated polynomial
                     p     p
          ~
          P(z)=P(z)/(z-z ) of degree n-1 if z  is real
                        p                    p
           ~                   
          (P(z)=P(z)/((z-z )(z-z )) of degree n-2 if z  is complex) is then
                          p     p                     p
          formed, and the above procedure is repeated on the deflated
          polynomial until n<3, whereupon the remaining roots are obtained
          via the 'standard' closed formulae for a linear (n = 1) or
          quadratic (n = 2) equation.

          To obtain the roots of a quadratic polynomial, C02AJF(*) can be
          used.

          4. References

          [1]   Marden M (1966) Geometry of Polynomials. Mathematical
                Surveys. 3 Am. Math. Soc., Providence, RI.

          [2]   Smith B T (1967) ZERPOL: A Zero Finding Algorithm for
                Polynomials Using Laguerre's Method. Technical Report.
                Department of Computer Science, University of Toronto,
                Canada.

          [3]   Wilkinson J H (1965) The Algebraic Eigenvalue Problem.
                Clarendon Press.

          5. Parameters

           1:  A(N+1) -- DOUBLE PRECISION array                       Input
               On entry: if A is declared with bounds (0:N), then A(i)
                                                          n-i
               must contain a  (i.e., the coefficient of z   ), for
                             i
               i=0,1,...,n. Constraint: A(0) /= 0.0.

           2:  N -- INTEGER                                           Input
               On entry: the degree of the polynomial, n. Constraint: N >=
               1.

           3:  SCALE -- LOGICAL                                       Input
               On entry: indicates whether or not the polynomial is to be
               scaled. See Section 8 for advice on when it may be
               preferable to set SCALE = .FALSE. and for a description of
               the scaling strategy. Suggested value: SCALE = .TRUE..

           4:  Z(2,N) -- DOUBLE PRECISION array                      Output
               On exit: the real and imaginary parts of the roots are
               stored in Z(1,i) and Z(2,i) respectively, for i=1,2,...,n.
               Complex conjugate pairs of roots are stored in consecutive
               pairs of elements of Z; that is, Z(1,i+1) = Z(1,i) and
               Z(2,i+1)=-Z(2,i).

           5:  W(2*(N+1)) -- DOUBLE PRECISION array               Workspace

           6:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.
               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry A(0) = 0.0,

               or       N < 1.

          IFAIL= 2
               The iterative procedure has failed to converge. This error
               is very unlikely to occur. If it does, please contact NAG
               immediately, as some basic assumption for the arithmetic has
               been violated. See also Section 8.

          IFAIL= 3
               Either overflow or underflow prevents the evaluation of P(z)
               near some of its zeros. This error is very unlikely to
               occur. If it does, please contact NAG immediately. See also
               Section 8.

          7. Accuracy

          All roots are evaluated as accurately as possible, but because of
          the inherent nature of the problem complete accuracy cannot be
          guaranteed.

          8. Further Comments

          If SCALE = .TRUE., then a scaling factor for the coefficients is
          chosen as a power of the base B of the machine so that the
                                                                EMAX-P
          largest coefficient in magnitude approaches THRESH = B      .
          Users should note that no scaling is performed if the largest
          coefficient in magnitude exceeds THRESH, even if SCALE = .TRUE..
          (For definition of B, EMAX and P see the Chapter Introduction
          X02.)

          However, with SCALE = .TRUE., overflow may be encountered when
          the input coefficients a ,a ,a ,...,a  vary widely in magnitude,
                                  0  1  2      n
                                                    (4*P)
          particularly on those machines for which B      overflows. In
          such cases, SCALE should be set to .FALSE. and the coefficients
          scaled so that the largest coefficient in magnitude does not
                  (EMAX-2*P)
          exceed B          .

          Even so, the scaling strategy used in C02AGF is sometimes
          insufficient to avoid overflow and/or underflow conditions. In
          such cases, the user is recommended to scale the independent
          variable (z) so that the disparity between the largest and
          smallest coefficient in magnitude is reduced. That is, use the
          routine to locate the zeros of the polynomial d*P(cz) for some
          suitable values of c and d. For example, if the original
                               -100  100 20                   -10
          polynomial was P(z)=2    +2   z  , then choosing c=2    and
             100                                                     20
          d=2   , for instance, would yield the scaled polynomial 1+z  ,
          which is well-behaved relative to overflow and underflow and has
                           10
          zeros which are 2   times those of P(z).

          If the routine fails with IFAIL = 2 or 3, then the real and
          imaginary parts of any roots obtained before the failure occurred
          are stored in Z in the reverse order in which they were found.
          Let n  denote the number of roots found before the failure
               R
          occurred. Then Z(1,n) and Z(2,n) contain the real and imaginary
          parts of the 1st root found, Z(1,n-1) and Z(2,n-1) contain the
          real and imaginary parts of the 2nd root found, ..., Z(1,n ) and
                                                                    R
          Z(2,n ) contain the real and imaginary parts of the n th root
               R                                               R
          found. After the failure has occurred, the remaining 2*(n-n )
                                                                     R
          elements of Z contain a large negative number (equal to
                         

          -1/(X02AMF().\/2)).

          9. Example

          To find the roots of the 5th degree polynomial
           5   4   3   2
          z +2z +3z +4z +5z+6=0.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXc05}{nagc.ht}
{ Roots of One or More Transcendental Equations}
\begin{chunk}{nagc.ht}
\begin{page}{manpageXXc05}{NAG Documentation: c05}
\beginscroll
\begin{verbatim}



     C05(3NAG)         Foundation Library (12/10/92)         C05(3NAG)



          C05 -- Roots of One or More Transcendental Equations
                                                         Introduction -- C05
                                    Chapter C05
                   Roots of One or More Transcendental Equations

          1. Scope of the Chapter

          This chapter is concerned with the calculation of real zeros of
          continuous real functions of one or more variables. (Complex
          equations must be expressed in terms of the equivalent larger
          system of real equations.)

          2. Background to the Problems

          The chapter divides naturally into two parts.

          2.1. A Single Equation

          The first deals with the real zeros of a real function of a
          single variable f(x).

          At present, there is only one routine with a simple calling
          sequence. This routine assumes that the user can determine an
          initial interval [a,b] within which the desired zero lies, that
          is f(a)*f(b)<0, and outside which all other zeros lie. The
          routine then systematically subdivides the interval to produce a
          final interval containing the zero. This final interval has a
          length bounded by the user's specified error requirements; the
          end of the interval where the function has smallest magnitude is
          returned as the zero. This routine is guaranteed to converge to a
          simple zero of the function. (Here we define a simple zero as a
          zero corresponding to a sign-change of the function.) The
          algorithm used is due to Bus and Dekker.

          2.2. Systems of Equations

          The routines in the second part of this chapter are designed to
          solve a set of nonlinear equations in n unknowns


                                                           T
                   f (x)=0,  i=1,2,...,n,  x=(x ,x ,...,x )             (1)
                    i                          1  2      n

          where T stands for transpose.

          It is assumed that the functions are continuous and
          differentiable so that the matrix of first partial derivatives of
          the functions, the Jacobian matrix J  (x)=ddf /ddx  evaluated at
                                              ij       i    j
          the point x, exists, though it may not be possible to calculate
          it directly.

          The functions f  must be independent, otherwise there will be an
                         i
          infinity of solutions and the methods will fail. However, even
          when the functions are independent the solutions may not be
          unique. Since the methods are iterative, an initial guess at the
          solution has to be supplied, and the solution located will
          usually be the one closest to this initial guess.

          2.3. References

          [1]   Gill P E and Murray W (1976) Algorithms for the Solution of
                the Nonlinear Least-squares Problem. NAC 71 National
                Physical Laboratory.

          [2]   More J J, Garbow B S and Hillstrom K E (1974) User Guide for
                Minpack-1. ANL-80-74 Argonne National Laboratory.

          [3]   Ortega J M and Rheinboldt W C (1970) Iterative Solution of
                Nonlinear Equations in Several Variables. Academic Press.

          [4]   Rabinowitz P (1970) Numerical Methods for Nonlinear
                Algebraic Equations. Gordon and Breach.

          3. Recommendations on Choice and Use of Routines

          3.1. Zeros of Functions of One Variable

          There is only one routine (C05ADF) for solving a single nonlinear
          equation. This routine is designed for solving problems where the
          function f(x) whose zero is to be calculated, can be coded as a
          user-supplied routine.

          C05ADF may only be used when the user can supply an interval
          [a,b] containing the zero, that is f(a)*f(b)<0.

          3.2. Solution of Sets of Nonlinear Equations

          The solution of a set of nonlinear equations

                        f (x ,x ,...,x )=0,  i=1,2,...,n                (2)
                         i  1  2      n

          can be regarded as a special case of the problem of finding a
          minimum of a sum of squares

                           m
                           /                    2
                     s(x)= |  [f (x ,x ,...,x )]   (m>=n).              (3)
                           /    i  1  2      n
                           i=1

          So the routines in Chapter E04 of the Library are relevant as
          well as the special nonlinear equations routines.

          There are two routines (C05NBF and C05PBF) for solving a set of
          nonlinear equations. These routines require the f  (and possibly
                                                           i
          their derivatives) to be calculated in user-supplied routines.
          These should be set up carefully so the Library routines can work
          as efficiently as possible.

          The main decision which has to be made by the user is whether to
                                  ddf
                                     i
          supply the derivatives  ----. It is advisable to do so if
                                  ddx
                                     j
          possible, since the results obtained by algorithms which use
          derivatives are generally more reliable than those obtained by
          algorithms which do not use derivatives.

          C05PBF requires the user to provide the derivatives, whilst
          C05NBF does not. C05NBF and C05PBF are easy-to-use routines. A
          routine, C05ZAF, is provided for use in conjunction with C05PBF
          to check the user-provided derivatives for consistency with the
          functions themselves. The user is strongly advised to make use of
          this routine whenever C05PBF is used.

          Firstly, the calculation of the functions and their derivatives
          should be ordered so that cancellation errors are avoided. This
          is particularly important in a routine that uses these quantities
          to build up estimates of higher derivatives.

          Secondly, scaling of the variables has a considerable effect on
          the efficiency of a routine. The problem should be designed so
          that the elements of x are of similar magnitude. The same comment
          applies to the functions, all the f  should be of comparable
                                             i
          size.

          The accuracy is usually determined by the accuracy parameters of
          the routines, but the following points may be useful:

          (i)   Greater accuracy in the solution may be requested by
                choosing smaller input values for the accuracy parameters.
                However, if unreasonable accuracy is demanded, rounding
                errors may become important and cause a failure.

          (ii)  Some idea of the accuracies of the x  may be obtained by
                                                    i
                monitoring the progress of the routine to see how many
                figures remain unchanged during the last few iterations.

          (iii) An approximation to the error in the solution x, given by e
                where e is the solution to the set of linear equations

                J(x)e=-f(x)

                                                  T
                where f(x)=(f (x),f (x),...,f (x))  (see Chapter F04).
                             1     2         n

          (iv)  If the functions f (x) are changed by small amounts
                                  i
                (epsilon) , for i=1,2,...,n, then the corresponding change
                         i
                in the solution x is given approximately by (sigma), where
                (sigma) is the solution of the set of linear equations

                J(x)(sigma)=-(epsilon), (see Chapter F04).

                Thus one can estimate the sensitivity of x to any
                uncertainties in the specification of f (x), for
                                                       i
                i=1,2,...,n.

          3.3. Index

          Zeros of functions of one variable:
               Bus and Dekker algorithm                              C05ADF
          Zeros of functions of several variables:
               easy-to-use                                           C05NBF
               easy-to-use, derivatives required                     C05PBF
          Checking Routine:
               Checks user-supplied Jacobian                         C05ZAF


          C05 -- Roots of One or More Transcendental Equations
                                                             Contents -- C05
          Chapter C05

          Roots of One or More Transcendental Equations

          C05ADF  Zero of continuous function in given interval, Bus and
                  Dekker algorithm

          C05NBF  Solution of system of nonlinear equations using function
                  values only

          C05PBF  Solution of system of nonlinear equations using 1st
                  derivatives

          C05ZAF  Check user's routine for calculating 1st derivatives

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXc05adf}{nagc.ht}
{ Zero of a continuous function in a given interval}
\begin{chunk}{nagc.ht}
\begin{page}{manpageXXc05adf}{NAG Documentation: c05adf}
\beginscroll
\begin{verbatim}



     C05ADF(3NAG)      Foundation Library (12/10/92)      C05ADF(3NAG)



          C05 -- Roots of One or More Transcendental Equations       C05ADF
                  C05ADF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          C05ADF locates a zero of a continuous function in a given
          interval by a combination of the methods of linear interpolation,
          extrapolation and bisection.

          2. Specification

                 SUBROUTINE C05ADF (A, B, EPS, ETA, F, X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION A, B, EPS, ETA, F, X
                 EXTERNAL         F

          3. Description

          The routine attempts to obtain an approximation to a simple zero
          of the function f(x) given an initial interval [a,b] such that
          f(a)*f(b)<=0. The zero is found by calls to C05AZF(*) whose
          specification should be consulted for details of the method used.

          The approximation x to the zero (alpha) is determined so that one
          or both of the following criteria are satisfied:

               (i) |x-(alpha)|<EPS,

               (ii) |f(x)|<ETA.

          4. References

          None.

          5. Parameters

           1:  A -- DOUBLE PRECISION                                  Input
               On entry: the lower bound of the interval, a.

           2:  B -- DOUBLE PRECISION                                  Input
               On entry: the upper bound of the interval, b. Constraint: B
               /= A.

           3:  EPS -- DOUBLE PRECISION                                Input
               On entry: the absolute tolerance to which the zero is
               required (see Section 3). Constraint: EPS > 0.0.

           4:  ETA -- DOUBLE PRECISION                                Input
               On entry: a value such that if |f(x)|<ETA, x is accepted as
               the zero. ETA may be specified as 0.0 (see Section 7).

           5:  F -- DOUBLE PRECISION FUNCTION, supplied by the user.
                                                    External Procedure
               F must evaluate the function f whose zero is to be
               determined.

               Its specification is:

                      DOUBLE PRECISION FUNCTION F (XX)
                      DOUBLE PRECISION XX

                1:  XX -- DOUBLE PRECISION                            Input
                    On entry: the point at which the function must be
                    evaluated.
               F must be declared as EXTERNAL in the (sub)program from
               which C05ADF is called. Parameters denoted as Input
               must not be changed by this procedure.

           6:  X -- DOUBLE PRECISION                                 Output
               On exit: the approximation to the zero.

           7:  IFAIL -- INTEGER                                Input/Output
               Before entry, IFAIL must be assigned a value. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               Unless the routine detects an error (see Section 6), IFAIL
               contains 0 on exit.

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               On entry EPS <= 0.0,

               or       A = B,

               or       F(A)*F(B)>0.0.

          IFAIL= 2
               Too much accuracy has been requested in the computation,
               that is, EPS is too small for the computer being used. The
               final value of X is an accurate approximation to the zero.

          IFAIL= 3
               A change in sign of f(x) has been determined as occurring
               near the point defined by the final value of X. However,
               there is some evidence that this sign-change corresponds to
               a pole of f(x).

          IFAIL= 4
               Indicates that a serious error has occurred in C05AZF(*).
               Check all routine calls. Seek expert help.

          7. Accuracy

          This depends on the value of EPS and ETA. If full machine
          accuracy is required, they may be set very small, resulting in an
          error exit with IFAIL = 2, although this may involve more
          iterations than a lesser accuracy. The user is recommended to set
          ETA = 0.0 and to use EPS to control the accuracy, unless he has
          considerable knowledge of the size of f(x) for values of x near
          the zero.

          8. Further Comments

          The time taken by the routine depends primarily on the time spent
          evaluating F (see Section 5).

          If it is important to determine an interval of length less than
          EPS containing the zero, or if the function F is expensive to
          evaluate and the number of calls to F is to be restricted, then
          use of C05AZF(*) is recommended. Use of C05AZF(*) is also
          recommended when the structure of the problem to be solved does
          not permit a simple function F to be written: the reverse
          communication facilities of C05AZF(*) are more flexible than the
          direct communication of F required by C05ADF.

          9. Example

                                                            -x
          The example program below calculates the zero of e  -x within the
          interval [0,1] to approximately 5 decimal places.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXc05nbf}{nagc.ht}
{ Solution of a system of nonlinear equations}
\begin{chunk}{nagc.ht}
\begin{page}{manpageXXc05nbf}{NAG Documentation: c05nbf}
\beginscroll
\begin{verbatim}



     C05NBF(3NAG)      Foundation Library (12/10/92)      C05NBF(3NAG)



          C05 -- Roots of One or More Transcendental Equations       C05NBF
                  C05NBF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          C05NBF is an easy-to-use routine to find a solution of a system
          of nonlinear equations by a modification of the Powell hybrid
          method.

          2. Specification

                 SUBROUTINE C05NBF (FCN, N, X, FVEC, XTOL, WA, LWA, IFAIL)
                 INTEGER          N, LWA, IFAIL
                 DOUBLE PRECISION X(N), FVEC(N), XTOL, WA(LWA)
                 EXTERNAL         FCN

          3. Description

          The system of equations is defined as:

                        f (x ,x ,...,x )=0, for i=1,2,...,n.
                         i  1  2      n

          C05NBF is based upon the MINPACK routine HYBRD1 (More et al [1]).
          It chooses the correction at each step as a convex combination of
          the Newton and scaled gradient directions. Under reasonable
          conditions this guarantees global convergence for starting points
          far from the solution and a fast rate of convergence. The
          Jacobian is updated by the rank-1 method of Broyden. At the
          starting point the Jacobian is approximated by forward
          differences, but these are not used again until the rank-1 method
          fails to produce satisfactory progress. For more details see
          Powell [2].

          4. References

          [1]   More J J, Garbow B S and Hillstrom K E User Guide for
                MINPACK-1. Technical Report ANL-80-74. Argonne National
                Laboratory.

          [2]   Powell M J D (1970) A Hybrid Method for Nonlinear Algebraic
                Equations. Numerical Methods for Nonlinear Algebraic
                Equations. (ed P Rabinowitz) Gordon and Breach.

          5. Parameters

           1:  FCN -- SUBROUTINE, supplied by the user.
                                                    External Procedure
               FCN must return the values of the functions f  at a point x.
                                                            i

               Its specification is:

                      SUBROUTINE FCN (N, X, FVEC, IFLAG)
                      INTEGER          N, IFLAG
                      DOUBLE PRECISION X(N), FVEC(N)

                1:  N -- INTEGER                                      Input
                    On entry: the number of equations, n.

                2:  X(N) -- DOUBLE PRECISION array                    Input
                    On entry: the components of the point x at which the
                    functions must be evaluated.

                3:  FVEC(N) -- DOUBLE PRECISION array                Output
                    On exit: the function values f (x) (unless IFLAG is
                                                  i
                    set to a negative value by FCN).

                4:  IFLAG -- INTEGER                           Input/Output
                    On entry: IFLAG > 0. On exit: in general, IFLAG should
                    not be reset by FCN. If, however, the user wishes to
                    terminate execution (perhaps because some illegal point
                    X has been reached), then IFLAG should be set to a
                    negative integer. This value will be returned through
                    IFAIL.
               FCN must be declared as EXTERNAL in the (sub)program
               from which C05NBF is called. Parameters denoted as
               Input must not be changed by this procedure.

           2:  N -- INTEGER                                           Input
               On entry: the number of equations, n. Constraint: N > 0.

           3:  X(N) -- DOUBLE PRECISION array                  Input/Output
               On entry: an initial guess at the solution vector. On
               exit: the final estimate of the solution vector.

           4:  FVEC(N) -- DOUBLE PRECISION array                     Output
               On exit: the function values at the final point, X.

           5:  XTOL -- DOUBLE PRECISION                               Input
               On entry: the accuracy in X to which the solution is
               required. Suggested value: the square root of the machine
               precision. Constraint: XTOL >= 0.0.

           6:  WA(LWA) -- DOUBLE PRECISION array                  Workspace

           7:  LWA -- INTEGER                                         Input
               On entry: the dimension of the array WA. Constraint:
               LWA>=N*(3*N+13)/2.

           8:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL< 0
               The user has set IFLAG negative in FCN. The value of IFAIL
               will be the same as the user's setting of IFLAG.

          IFAIL= 1
               On entry N <= 0,

               or       XTOL < 0.0,

               or       LWA<N*(3*N+13)/2.

          IFAIL= 2
               There have been at least 200*(N+1) evaluations of FCN.
               Consider restarting the calculation from the final point
               held in X.

          IFAIL= 3
               No further improvement in the approximate solution X is
               possible; XTOL is too small.

          IFAIL= 4
               The iteration is not making good progress. This failure exit
               may indicate that the system does not have a zero, or that
               the solution is very close to the origin (see Section 7).
               Otherwise, rerunning C05NBF from a different starting point
               may avoid the region of difficulty.

          7. Accuracy

             ^
          If x is the true solution, C05NBF tries to ensure that

                                   ^             ^
                              ||x-x||<=XTOL*||x||.

                                                     -k
          If this condition is satisfied with XTOL=10  , then the larger
          components of x have k significant decimal digits. There is a
          danger that the smaller components of x may have large relative
          errors, but the fast rate of convergence of C05NBF usually avoids
          this possibility.

          If XTOL is less than machine precision, and the above test is
          satisfied with the machine precision in place of XTOL, then the
          routine exits with IFAIL = 3.

          Note: this convergence test is based purely on relative error,
          and may not indicate convergence if the solution is very close to
          the origin.

          The test assumes that the functions are reasonably well behaved.
          If this condition is not satisfied, then C05NBF may incorrectly
          indicate convergence. The validity of the answer can be checked,
          for example, by rerunning C05NBF with a tighter tolerance.

          8. Further Comments

          The time required by C05NBF to solve a given problem depends on n
          , the behaviour of the functions, the accuracy requested and the
          starting point. The number of arithmetic operations executed by
                                                            2
          C05NBF to process each call of FCN is about 11.5*n . Unless FCN
          can be evaluated quickly, the timing of C05NBF will be strongly
          influenced by the time spent in FCN.

          Ideally the problem should be scaled so that at the solution the
          function values are of comparable magnitude.

          9. Example

          To determine the values x ,..., x  which satisfy the tridiagonal
                                   1       9
          equations:

                                  (3-2x )x -2x =-1
                                       1  1   2

                       -x -1+(3-2x )x -2x   =-1,  i=2,3,...,8
                         i        i  i   i+1

                                  -x +(3-2x )x =-1.
                                    8      9  9

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXc05pbf}{nagc.ht}
{ Solution of a system of nonlinear equations}
\begin{chunk}{nagc.ht}
\begin{page}{manpageXXc05pbf}{NAG Documentation: c05pbf}
\beginscroll
\begin{verbatim}



     C05PBF(3NAG)      Foundation Library (12/10/92)      C05PBF(3NAG)



          C05 -- Roots of One or More Transcendental Equations       C05PBF
                  C05PBF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          C05PBF is an easy-to-use routine to find a solution of a system
          of nonlinear equations by a modification of the Powell hybrid
          method. The user must provide the Jacobian.

          2. Specification

                 SUBROUTINE C05PBF (FCN, N, X, FVEC, FJAC, LDFJAC, XTOL,
                1                   WA, LWA, IFAIL)
                 INTEGER          N, LDFJAC, LWA, IFAIL
                 DOUBLE PRECISION X(N), FVEC(N), FJAC(LDFJAC,N), XTOL, WA
                1                 (LWA)
                 EXTERNAL         FCN

          3. Description

          The system of equations is defined as:

                          f (x ,x ,...,x )=0, i=1,2,...,n.
                           i  1  2      n

          C05PBF is based upon the MINPACK routine HYBRJ1 (More et al [1]).
          It chooses the correction at each step as a convex combination of
          the Newton and scaled gradient directions. Under reasonable
          conditions this guarantees global convergence for starting points
          far from the solution and a fast rate of convergence. The
          Jacobian is updated by the rank-1 method of Broyden. At the
          starting point the Jacobian is calculated, but it is not
          recalculated until the rank-1 method fails to produce
          satisfactory progress. For more details see Powell [2].

          4. References

          [1]   More J J, Garbow B S and Hillstrom K E User Guide for
                MINPACK-1. Technical Report ANL-80-74. Argonne National
                Laboratory.

          [2]   Powell M J D (1970) A Hybrid Method for Nonlinear Algebraic
                Equations. Numerical Methods for Nonlinear Algebraic
                Equations. (ed P Rabinowitz) Gordon and Breach.

          5. Parameters

           1:  FCN -- SUBROUTINE, supplied by the user.
                                                    External Procedure
               Depending upon the value of IFLAG, FCN must either return
               the values of the functions f  at a point x or return the
                                            i
               Jacobian at x.

               Its specification is:

                      SUBROUTINE FCN (N, X, FVEC, FJAC, LDFJAC, IFLAG)
                      INTEGER          N, LDFJAC, IFLAG
                      DOUBLE PRECISION X(N), FVEC(N), FJAC(LDFJAC,N)

                1:  N -- INTEGER                                      Input
                    On entry: the number of equations, n.

                2:  X(N) -- DOUBLE PRECISION array                    Input
                    On entry: the components of the point x at which the
                    functions or the Jacobian must be evaluated.

                3:  FVEC(N) -- DOUBLE PRECISION array                Output
                    On exit: if IFLAG = 1 on entry, FVEC must contain the
                    function values f (x) (unless IFLAG is set to a
                                     i
                    negative value by FCN). If IFLAG = 2 on entry, FVEC
                    must not be changed.

                4:  FJAC(LDFJAC,N) -- DOUBLE PRECISION array         Output
                    On exit: if IFLAG = 2 on entry, FJAC(i,j) must contain
                                  ddf
                                     i
                    the value of  ---- at the point x, for i,j=1,2,...,n
                                  ddx
                                     j
                    (unless IFLAG is set to a negative value by FCN).

                    If IFLAG = 1 on entry, FJAC must not be changed.

                5:  LDFJAC -- INTEGER                                 Input
                    On entry: the first dimension of FJAC.

                6:  IFLAG -- INTEGER                           Input/Output
                    On entry: IFLAG = 1 or 2:
                         if IFLAG = 1, FVEC is to be updated;

                         if IFLAG = 2, FJAC is to be updated.
                    On exit: in general, IFLAG should not be reset by FCN.
                    If, however, the user wishes to terminate execution
                    (perhaps because some illegal point x has been reached)
                    then IFLAG should be set to a negative integer. This
                    value will be returned through IFAIL.
               FCN must be declared as EXTERNAL in the (sub)program
               from which C05PBF is called. Parameters denoted as
               Input must not be changed by this procedure.

           2:  N -- INTEGER                                           Input
               On entry: the number of equations, n. Constraint: N > 0.

           3:  X(N) -- DOUBLE PRECISION array                  Input/Output
               On entry: an initial guess at the solution vector. On
               exit: the final estimate of the solution vector.

           4:  FVEC(N) -- DOUBLE PRECISION array                     Output
               On exit: the function values at the final point, X.

           5:  FJAC(LDFJAC,N) -- DOUBLE PRECISION array              Output
               On exit: the orthogonal matrix Q produced by the QR
               factorization of the final approximate Jacobian.

           6:  LDFJAC -- INTEGER                                      Input
               On entry:
               the first dimension of the array FJAC as declared in the
               (sub)program from which C05PBF is called.
               Constraint: LDFJAC >= N.

           7:  XTOL -- DOUBLE PRECISION                               Input
               On entry: the accuracy in X to which the solution is
               required. Suggested value: the square root of the machine
               precision. Constraint: XTOL >= 0.0.

           8:  WA(LWA) -- DOUBLE PRECISION array                  Workspace

           9:  LWA -- INTEGER                                         Input
               On entry: the dimension of the array WA. Constraint:
               LWA>=N*(N+13)/2.

          10:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL< 0
               A negative value of IFAIL indicates an exit from C05PBF
               because the user has set IFLAG negative in FCN. The value of
               IFAIL will be the same as the user's setting of IFLAG.

          IFAIL= 1
               On entry N <= 0,

               or       LDFJAC < N,

               or       XTOL < 0.0,

               or       LWA<N*(N+13)/2.

          IFAIL= 2
               There have been 100*(N+1) evaluations of the functions.
               Consider restarting the calculation from the final point
               held in X.

          IFAIL= 3
               No further improvement in the approximate solution X is
               possible; XTOL is too small.

          IFAIL= 4
               The iteration is not making good progress. This failure exit
               may indicate that the system does not have a zero or that
               the solution is very close to the origin (see Section 7).
               Otherwise, rerunning C05PBF from a different starting point
               may avoid the region of difficulty.

          7. Accuracy

             ^
          If x is the true solution, C05PBF tries to ensure that

                                  ^              ^
                             ||x-x|| <=XTOL*||x|| .
                                    2            2

                                                     -k
          If this condition is satisfied with XTOL=10  , then the larger
          components of x have k significant decimal digits. There is a
          danger that the smaller components of x may have large relative
          errors, but the fast rate of convergence of C05PBF usually avoids
          the possibility.

          If XTOL is less than machine precision and the above test is
          satisfied with the machine precision in place of XTOL, then the
          routine exits with IFAIL = 3.

          Note: this convergence test is based purely on relative error,
          and may not indicate convergence if the solution is very close to
          the origin.

          The test assumes that the functions and Jacobian are coded
          consistently and that the functions are reasonably well behaved.
          If these conditions are not satisfied then C05PBF may incorrectly
          indicate convergence. The coding of the Jacobian can be checked
          using C05ZAF. If the Jacobian is coded correctly, then the
          validity of the answer can be checked by rerunning C05PBF with a
          tighter tolerance.

          8. Further Comments

          The time required by C05PBF to solve a given problem depends on n
          , the behaviour of the functions, the accuracy requested and the
          starting point. The number of arithmetic operations executed by
                                2
          C05PBF is about 11.5*n  to process each evaluation of the
                                   3
          functions and about 1.3*n  to process each evaluation of the
          Jacobian. Unless FCN can be evaluated quickly, the timing of
          C05PBF will be strongly influenced by the time spent in FCN.

          Ideally the problem should be scaled so that, at the solution,
          the function values are of comparable magnitude.

          9. Example

          To determine the values x ,..., x  which satisfy the tridiagonal
                                   1       9
          equations:

                                  (3-2x )x -2x =-1
                                       1  1   2

                        -x   +(3-2x )x -2x   =-1,  i=2,3,...,8.
                          i-1      i  i   i+1

                                  -x +(3-2x )x =-1.
                                    8      9  9

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXc05zaf}{nagc.ht}
{ Checks the gradients of a set of non-linear functions}
\begin{chunk}{nagc.ht}
\begin{page}{manpageXXc05zaf}{NAG Documentation: c05zaf}
\beginscroll
\begin{verbatim}



     C05ZAF(3NAG)      Foundation Library (12/10/92)      C05ZAF(3NAG)



          C05 -- Roots of One or More Transcendental Equations       C05ZAF
                  C05ZAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          C05ZAF checks the user-provided gradients of a set of non-linear
          functions in several variables, for consistency with the
          functions themselves. The routine must be called twice.

          2. Specification

                 SUBROUTINE C05ZAF (M, N, X, FVEC, FJAC, LDFJAC, XP, FVECP,
                1                   MODE, ERR)
                 INTEGER          M, N, LDFJAC, MODE
                 DOUBLE PRECISION X(N), FVEC(M), FJAC(LDFJAC,N), XP(N),
                1                 FVECP(M), ERR(M)

          3. Description

          C05ZAF is based upon the MINPACK routine CHKDER (More et al [1]).
          It checks the ith gradient for consistency with the ith function
          by computing a forward-difference approximation along a suitably
          chosen direction and comparing this approximation with the user-
          supplied gradient along the same direction. The principal
          characteristic of C05ZAF is its invariance under changes in scale
          of the variables or functions.

          4. References

          [1]   More J J, Garbow B S and Hillstrom K E User Guide for
                MINPACK-1. Technical Report ANL-80-74. Argonne National
                Laboratory.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: the number of functions.

           2:  N -- INTEGER                                           Input
               On entry: the number of variables. For use with C05PBF and
               C05PCF(*), M = N.

           3:  X(N) -- DOUBLE PRECISION array                         Input
               On entry: the components of a point x, at which the
               consistency check is to be made. (See Section 8.)

           4:  FVEC(M) -- DOUBLE PRECISION array                      Input
               On entry: when MODE = 2, FVEC must contain the functions
               evaluated at x.

           5:  FJAC(LDFJAC,N) -- DOUBLE PRECISION array               Input
               On entry: when MODE = 2, FJAC must contain the user-
               supplied gradients. (The ith row of FJAC must contain the
               gradient of the ith function evaluated at the point x.)

           6:  LDFJAC -- INTEGER                                      Input
               On entry:
               the first dimension of the array FJAC as declared in the
               (sub)program from which C05ZAF is called.
               Constraint: LDFJAC >= M.

           7:  XP(N) -- DOUBLE PRECISION array                       Output
               On exit: when MODE = 1, XP is set to a neighbouring point
               to X.

           8:  FVECP(M) -- DOUBLE PRECISION array                     Input
               On entry: when MODE = 2, FVECP must contain the functions
               evaluated at XP.

           9:  MODE -- INTEGER                                        Input
               On entry: the value 1 on the first call and the value 2 on
               the second call of C05ZAF.

          10:  ERR(M) -- DOUBLE PRECISION array                      Output
               On exit: when MODE = 2, ERR contains measures of
               correctness of the respective gradients. If there is no loss
               of significance (see Section 8), then if ERR(i) is 1.0 the i
               th user-supplied gradient is correct, whilst if ERR(i) is 0.
               0 the ith gradient is incorrect. For values of ERR(i)
               between 0.0 and 1.0 the categorisation is less certain. In
               general, a value of ERR(i)>0.5 indicates that the ith
               gradient is probably correct.

          6. Error Indicators and Warnings

          None.

          7. Accuracy

          See below.

          8. Further Comments

          The time required by C05ZAF increases with M and N.

          C05ZAF does not perform reliably if cancellation or rounding
          errors cause a severe loss of significance in the evaluation of a
          function. Therefore, none of the components of x should be
          unusually small (in particular, zero) or any other value which
          may cause loss of significance. The relative differences between
          corresponding elements of FVECP and FVEC should be at least two
          orders of magnitude greater than the machine precision.

          9. Example

          This example checks the Jacobian matrix for a problem with 15
          functions of 3 variables. The results indicate that the first 7
          gradients are probably incorrect (this is caused by a deliberate
          error in the code to calculate the Jacobian).

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXc06}{nagc.ht}
{ Discrete Fourier transform of real or complex data values}
\begin{chunk}{nagc.ht}
\begin{page}{manpageXXc06}{NAG Documentation: c06}
\beginscroll
\begin{verbatim}



     C06(3NAG)         Foundation Library (12/10/92)         C06(3NAG)



          C06 -- Summation of Series                    Introduction -- C06
                                    Chapter C06
                                Summation of Series

          1. Scope of the Chapter

          This chapter is concerned with calculating the discrete Fourier
          transform of a sequence of real or complex data values, and
          applying it to calculate convolutions and correlations.

          2. Background to the Problems

          2.1. Discrete Fourier Transforms

          2.1.1.  Complex transforms

          Most of the routines in this chapter calculate the finite
          discrete Fourier transform  (DFT) of a sequence of n complex
          numbers z , for j=0,1,...,n-1. The transform is defined by:
                   j

                                  n-1
                          ^    1  --      (   2(pi)jk)
                          z = --- >  z exp(-i -------)                  (1)
                           k      --  j   (      n   )
                              \/n j=0

          for k=0,1,...,n-1. Note that equation (1) makes sense for all
                                             ^
          integral k and with this extension z  is periodic with period n,
                                              k
               ^  ^                        ^   ^
          i.e. z =z    , and in particular z  =z   .
                k  k+-n                     -k  n-k

                                    ^                                 ^
          If we write z =x +iy  and z =a +ib , then the definition of z
                       j  j   j      k  k   k                          k
          may be written in terms of sines and cosines as:

                            n-1
                         1  -- (     ( 2(pi)jk)      ( 2(pi)jk))
                    a = --- >  (x cos( -------)+y sin( -------))
                     k      -- ( j   (    n   )  j   (    n   ))
                        \/n j=0

                            n-1
                         1  -- (     ( 2(pi)jk)      ( 2(pi)jk))
                    b = --- >  (y cos( -------)-x sin( -------)).
                     k      -- ( j   (    n   )  j   (    n   ))
                        \/n j=0

          The original data values z  may conversely be recovered from the
                                    j
                    ^
          transform z  by an  inverse discrete Fourier transform:
                     k


                                  n-1
                               1  -- ^    (   2(pi)jk)
                          z = --- >  z exp(+i -------)                  (2)
                           j      --  k   (      n   )
                              \/n k=0

          for j=0,1,...,n-1. If we take the complex conjugate of (2), we
                                                               

                                                               ^
          find that the sequence z  is the DFT of the sequence z . Hence
                                  j                             k
                                          ^
          the inverse DFT of the sequence z  may be obtained by: taking the
                                           k
                                    ^
          complex conjugates of the z ; performing a DFT; and taking the
                                     k
          complex conjugates of the result.

          Notes: definitions of the discrete Fourier transform vary.
          Sometimes (2) is used as the definition of the DFT, and (1) as
                                                                      

          the definition of the inverse. Also the scale-factor of 1/\/n may
          be omitted in the definition of the DFT, and replaced by 1/n in
          the definition of the inverse.

          2.1.2. Real transforms

          If the original sequence is purely real valued, i.e. z =x , then
                                                                j  j

                                        n-1
                         ^           1  --      (   2(pi)jk)
                         z =a +ib = --- >  x exp(-i -------)
                          k  k   k      --  j   (      n   )
                                    \/n j=0

              ^                                ^
          and z    is the complex conjugate of z . Thus the DFT of a real
               n-k                              k
          sequence is a particular type of complex sequence, called a
          Hermitian sequence, or  half-complex or  conjugate symmetric with
          the properties:
                         a   =a  b   =-b  b =0 and, if n is even, b   =0.
                          n-k  k  n-k   k  0                       n/2

          Thus a Hermitian sequence of n complex data values can be
          represented by only n, rather than 2n, independent real values.
          This can obviously lead to economies in storage, the following
          scheme being used in this chapter: the real parts a  for
                                                             k
          0<=k<=n/2 are stored in normal order in the first n/2+1 locations
          of an array X of length n; the corresponding non-zero imaginary
          parts are stored in reverse order in the remaining locations of
          X. In other words, if X is declared with bounds (0:n-1) in the
                                                               ^
          user's (sub)program, the real and imaginary parts of z  are
                                                                k
          stored as follows:

                         if n=2s    if n=2s-1

              X(0)       a          a
                          0          0

              X(1)       a          a
                          1          1

              X(2)       a          a
                          2          2

              .          .          .

              .          .          .

              .          .          .

              X(s-1)     a          a
                          s-1        s-1

              X(s)       a          b
                          s          s-1

              X(s+1)     b          b
                          s-1        s-2

              .          .          .

              .          .          .

              .          .          .

              X(n-2)     b          b
                          2          2

              X(n-1)     b          b
                          1          1


                         (     n/2-1                                      )
                       1 (     --   (     ( 2(pi)jk)      ( 2(pi)jk))     )
          Hence   x = ---(a +2 >    (a cos( -------)-b sin( -------))+a   )
                   j     ( 0   --   ( k   (    n   )  k   (    n   ))  n/2)
                      \/n(     k=0                                        )

          where a    = 0 if n is odd.
                 n/2

          2.1.3.  Fourier integral transforms

          The usual application of the discrete Fourier transform is that
          of obtaining an approximation of the  Fourier integral transform


                                +infty
                                /
                          F(s)= |     f(t)exp(-i2(pi)st)dt
                                /
                                -infty

          when f(t) is negligible outside some region (0,c). Dividing the
          region into n equal intervals we have

                                    n-1
                                  c --
                           F(s)~= - >  f exp(-i2(pi)sjc/n)
                                  n --  j
                                    j=0

          and so

                                   n-1
                                 c --
                            F ~= - >  f exp(-i2(pi)jk/n)
                             k   n --  j
                                   j=0

          for k=0,1,...,n-1, where f =f(jc/n) and F =F(k/c).
                                    j              k

          Hence the discrete Fourier transform gives an approximation to
          the Fourier integral transform in the region s=0 to s=n/c.

          If the function f(t) is defined over some more general interval
          (a,b), then the integral transform can still be approximated by
          the discrete transform provided a shift is applied to move the
          point a to the origin.

          2.1.4.  Convolutions and correlations

          One of the most important applications of the discrete Fourier
          transform is to the computation of the discrete convolution or
          correlation of two vectors x and y defined (as in Brigham [1])
          by:

                                n-1
                                --
               convolution: z = >  x y
                             k  --  j k-j
                                j=0

                                n-1
                                -- 
               correlation: w = >  x y
                             k  --  j k+j
                                j=0

          (Here x and y are assumed to be periodic with period n.)

          Under certain circumstances (see Brigham [1]) these can be used
          as approximations to the convolution or correlation integrals
          defined by:

                                    +infty
                                    /
                              z(s)= |     x(t)y(s-t)dt
                                    /
                                    -infty

          and

                          +infty
                          /     
                    w(s)= |     x(t)y(s+t)dt,   -infty<s<+infty.
                          /
                          -infty

          For more general advice on the use of Fourier transforms, see
          Hamming [2]; more detailed information on the fast Fourier
          transform algorithm can be found in Van Loan [3] and Brigham [1].

          2.2. References

          [1]   Brigham E O (1973) The Fast Fourier Transform. Prentice-
                Hall.

          [2]   Hamming R W (1962) Numerical Methods for Scientists and
                Engineers. McGraw-Hill.

          [3]   Van Loan C (1992) Computational Frameworks for the Fast
                Fourier Transform. SIAM Philadelphia.

          3. Recommendations on Choice and Use of Routines

          3.1. One-dimensional Fourier Transforms

          The choice of routine is determined first of all by whether the
          data values constitute a real, Hermitian or general complex
          sequence. It is wasteful of time and storage to use an
          inappropriate routine.

          Two groups, each of three routines, are provided

                                   Group 1      Group 2

              Real sequences       C06EAF       C06FPF

              Hermitian sequences  C06EBF       C06FQF

              General complex      C06ECF       C06FRF
              sequences

          Group 1 routines each compute a single transform of length n,
          without requiring any extra working storage. The Group 1 routines
          impose some restrictions on the value of n, namely that no prime
          factor of n may exceed 19 and the total number of prime factors
          (including repetitions) may not exceed 20 (though the latter
                                                     6
          restriction only becomes relevant when n>10 ).

          Group 2 routines are designed to perform several transforms in a
          single call, all with the same value of n. They do however
          require more working storage. Even on scalar processors, they may
          be somewhat faster than repeated calls to Group 1 routines
          because of reduced overheads and because they pre-compute and
          store the required values of trigonometric functions. Group 2
          routines impose no practical restrictions on the value of n;
          however the fast Fourier transform algorithm ceases to be 'fast'
          if applied to values of n which cannot be expressed as a product
          of small prime factors. All the above routines are particularly
          efficient if the only prime factors of n are 2, 3 or 5.

          If extensive use is to be made of these routines, users who are
          concerned about efficiency are advised to conduct their own
          timing tests.

          To compute inverse discrete Fourier transforms the above routines
          should be used in conjunction with the utility routines C06GBF,
          C06GCF and C06GQF which form the complex conjugate of a Hermitian
          or general sequence of complex data values.

          3.2. Multi-dimensional Fourier Transforms

          C06FUF computes a 2-dimensional discrete Fourier transform of a
          2-dimensional sequence of complex data values. This is defined by

                         n -1 n -1
                          1    2          (   2(pi)j k )   (   2(pi)j k )
          ^         1    --   --          (         1 1)   (         2 2)
          z    = ------- >    >   z    exp(-i ---------)exp(-i ---------).
                         --   --          (      n     )   (      n     )
           k k     /n n  j =0 j =0 j j    (       1    )   (       2    )
            1 2  \/  1 2  1    2    1 2

          3.3. Convolution and Correlation

          C06EKF computes either the discrete convolution or the discrete
          correlation of two real vectors.

          3.4. Index

          Complex conjugate,
               complex sequence                                      C06GCF
               Hermitian sequence                                    C06GBF
               multiple Hermitian sequences                          C06GQF
          Complex sequence from Hermitian sequences                  C06GSF
          Convolution or Correlation
               real vectors                                          C06EKF
          Discrete Fourier Transform
               two-dimensional
                    complex sequence                                 C06FUF
               one-dimensional, multiple transforms
                    complex sequence                                 C06FRF
                    Hermitian sequence                               C06FQF
                    real sequence                                    C06FPF
               one-dimensional, single transforms
                    complex sequence                                 C06ECF
                    Hermitian sequence                               C06EBF
                    real sequence                                    C06EAF



          C06 -- Summation of Series                        Contents -- C06
          Chapter C06

          Summation of Series

          C06EAF  Single 1-D real discrete Fourier transform, no extra
                  workspace

          C06EBF  Single 1-D Hermitian discrete Fourier transform, no extra
                  workspace

          C06ECF  Single 1-D complex discrete Fourier transform, no extra
                  workspace

          C06EKF  Circular convolution or correlation of two real vectors,
                  no extra workspace

          C06FPF  Multiple 1-D real discrete Fourier transforms

          C06FQF  Multiple 1-D Hermitian discrete Fourier transforms

          C06FRF  Multiple 1-D complex discrete Fourier transforms

          C06FUF  2-D complex discrete Fourier transform

          C06GBF  Complex conjugate of Hermitian sequence

          C06GCF  Complex conjugate of complex sequence

          C06GQF  Complex conjugate of multiple Hermitian sequences

          C06GSF  Convert Hermitian sequences to general complex sequences

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXc06eaf}{nagc.ht}
{ Discrete Fourier transform of n real data values}
\begin{chunk}{nagc.ht}
\begin{page}{manpageXXc06eaf}{NAG Documentation: c06eaf}
\beginscroll
\begin{verbatim}



     C06EAF(3NAG)      Foundation Library (12/10/92)      C06EAF(3NAG)



          C06 -- Summation of Series                                 C06EAF
                  C06EAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          C06EAF calculates the discrete Fourier transform of a sequence of
          n real data values. (No extra workspace required.)

          2. Specification

                 SUBROUTINE C06EAF (X, N, IFAIL)
                 INTEGER          N, IFAIL
                 DOUBLE PRECISION X(N)

          3. Description

          Given a sequence of n real data values x , for j=0,1,...,n-1,
                                                  j
          this routine calculates their discrete Fourier transform defined
          by:

                            n-1
                    ^    1  --       (   2(pi)jk)
                    z = --- >  x *exp(-i -------), k=0,1,...,n-1.
                     k      --  j    (      n   )
                        \/n j=0

                                      1
          (Note the scale factor of  --- in this definition.) The
                                       

                                     \/n
                             ^
          transformed values z  are complex, but they form a Hermitian
                              k
                          ^                                ^
          sequence (i.e., z    is the complex conjugate of z ), so they are
                           n-k                              k
          completely determined by n real numbers (see also the Chapter
          Introduction).

          To compute the inverse discrete Fourier transform defined by:

                                   n-1
                           ^    1  --       (   2(pi)jk)
                           w = --- >  x *exp(+i -------),
                            k      --  j    (      n   )
                               \/n j=0

          this routine should be followed by a call of C06GBF to form the
                                    ^
          complex conjugates of the z .
                                     k

          The routine uses the fast Fourier transform (FFT) algorithm
          (Brigham [1]). There are some restrictions on the value of n (see
          Section 5).

          4. References

          [1]   Brigham E O (1973) The Fast Fourier Transform. Prentice-
                Hall.

          5. Parameters

           1:  X(N) -- DOUBLE PRECISION array                  Input/Output
               On entry: if X is declared with bounds (0:N-1) in the (sub)
               program from which C06EAF is called, then X(j) must contain
               x , for j=0,1,...,n-1. On exit: the discrete Fourier
                j
               transform stored in Hermitian form. If the components of the
                         ^
               transform z  are written as a +ib , and if X is declared
                          k                 k   k
               with bounds (0:N-1) in the (sub)program from which C06EAF is
               called, then for 0<=k<=n/2, a  is contained in X(k), and for
                                            k
               1<=k<=(n-1)/2, b  is contained in X(n-k). (See also Section
                               k
               2.1.2 of the Chapter Introduction, and the Example Program.)

           2:  N -- INTEGER                                           Input
               On entry: the number of data values, n. The largest prime
               factor of N must not exceed 19, and the total number of
               prime factors of N, counting repetitions, must not exceed
               20. Constraint: N > 1.

           3:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               At least one of the prime factors of N is greater than 19.

          IFAIL= 2
               N has more than 20 prime factors.

          IFAIL= 3
               N <= 1.

          7. Accuracy

          Some indication of accuracy can be obtained by performing a
          subsequent inverse transform and comparing the results with the
          original sequence (in exact arithmetic they would be identical).

          8. Further Comments

          The time taken by the routine is approximately proportional to
          n*logn, but also depends on the factorization of n. The routine
          is somewhat faster than average if the only prime factors of n
          are 2, 3 or 5; and fastest of all if n is a power of 2.

          On the other hand, the routine is particularly slow if n has
          several unpaired prime factors, i.e., if the 'square-free' part
          of n has several factors. For such values of n, routine C06FAF(*)
          (which requires an additional n elements of workspace) is
          considerably faster.

          9. Example

          This program reads in a sequence of real data values, and prints
          their discrete Fourier transform (as computed by C06EAF), after
          expanding it from Hermitian form into a full complex sequence.

          It then performs an inverse transform using C06GBF and C06EBF,
          and prints the sequence so obtained alongside the original data
          values.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXc06ebf}{nagc.ht}
{ Discrete Fourier transform of a Hermitian sequence}
\begin{chunk}{nagc.ht}
\begin{page}{manpageXXc06ebf}{NAG Documentation: c06ebf}
\beginscroll
\begin{verbatim}



     C06EBF(3NAG)      Foundation Library (12/10/92)      C06EBF(3NAG)



          C06 -- Summation of Series                                 C06EBF
                  C06EBF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          C06EBF calculates the discrete Fourier transform of a Hermitian
          sequence of n complex data values. (No extra workspace required.)

          2. Specification

                 SUBROUTINE C06EBF (X, N, IFAIL)
                 INTEGER          N, IFAIL
                 DOUBLE PRECISION X(N)

          3. Description

          Given a Hermitian sequence of n complex data values z  (i.e., a
                                                               j
          sequence such that z  is real and z    is the complex conjugate
                              0              n-j
          of z , for j=1,2,...,n-1) this routine calculates their discrete
              j
          Fourier transform defined by:

                            n-1
                    ^    1  --       (   2(pi)jk)
                    x = --- >  z *exp(-i -------), k=0,1,...,n-1.
                     k      --  j    (      n   )
                        \/n j=0

                                      1
          (Note the scale factor of  --- in this definition.) The
                                       

                                     \/n
                             ^
          transformed values x  are purely real (see also the the Chapter
                              k
          Introduction).

          To compute the inverse discrete Fourier transform defined by:

                                   n-1
                           ^    1  --       (   2(pi)jk)
                           y = --- >  z *exp(+i -------),
                            k      --  j    (      n   )
                               \/n j=0

          this routine should be preceded by a call of C06GBF to form the
          complex conjugates of the z .
                                     j

          The routine uses the fast Fourier transform (FFT) algorithm
          (Brigham [1]). There are some restrictions on the value of n (see
          Section 5).

          4. References

          [1]   Brigham E O (1973) The Fast Fourier Transform. Prentice-
                Hall.

          5. Parameters

           1:  X(N) -- DOUBLE PRECISION array                  Input/Output
               On entry: the sequence to be transformed stored in
               Hermitian form. If the data values z  are written as x +iy ,
                                                   j                 j   j
               and if X is declared with bounds (0:N-1) in the subroutine
               from which C06EBF is called, then for 0<=j<=n/2, x  is
                                                                 j
               contained in X(j), and for 1<=j<=(n-1)/2, y  is contained in
                                                          j
               X(n-j). (See also Section 2.1.2 of the Chapter Introduction
               and the Example Program.) On exit: the components of the
                                          ^
               discrete Fourier transform x . If X is declared with bounds
                                           k
               (0:N-1) in the (sub)program from which C06EBF is called,
                    ^
               then x  is stored in X(k), for k=0,1,...,n-1.
                     k

           2:  N -- INTEGER                                           Input
               On entry: the number of data values, n. The largest prime
               factor of N must not exceed 19, and the total number of
               prime factors of N, counting repetitions, must not exceed
               20. Constraint: N > 1.

           3:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               At least one of the prime factors of N is greater than 19.

          IFAIL= 2
               N has more than 20 prime factors.

          IFAIL= 3
               N <= 1.

          7. Accuracy

          Some indication of accuracy can be obtained by performing a
          subsequent inverse transform and comparing the results with the
          original sequence (in exact arithmetic they would be identical).

          8. Further Comments

          The time taken by the routine is approximately proportional to
          n*logn, but also depends on the factorization of n. The routine
          is somewhat faster than average if the only prime factors of n
          are 2, 3 or 5; and fastest of all if n is a power of 2.

          On the other hand, the routine is particularly slow if n has
          several unpaired prime factors, i.e., if the 'square-free' part
          of n has several factors. For such values of n, routine C06FBF(*)
          (which requires an additional n elements of workspace) is
          considerably faster.

          9. Example

          This program reads in a sequence of real data values which is
          assumed to be a Hermitian sequence of complex data values stored
          in Hermitian form. The input sequence is expanded into a full
          complex sequence and printed alongside the original sequence. The
          discrete Fourier transform (as computed by C06EBF) is printed
          out.

          The program then performs an inverse transform using C06EAF and
          C06GBF, and prints the sequence so obtained alongside the
          original data values.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXc06ecf}{nagc.ht}
{ Discrete Fourier transform of n complex data values}
\begin{chunk}{nagc.ht}
\begin{page}{manpageXXc06ecf}{NAG Documentation: c06ecf}
\beginscroll
\begin{verbatim}



     C06ECF(3NAG)      Foundation Library (12/10/92)      C06ECF(3NAG)



          C06 -- Summation of Series                                 C06ECF
                  C06ECF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          C06ECF calculates the discrete Fourier transform of a sequence of
          n complex data values. (No extra workspace required.)

          2. Specification

                 SUBROUTINE C06ECF (X, Y, N, IFAIL)
                 INTEGER          N, IFAIL
                 DOUBLE PRECISION X(N), Y(N)

          3. Description

          Given a sequence of n complex data values z , for j=0,1,...,n-1,
                                                     j
          this routine calculates their discrete Fourier transform defined
          by:

                            n-1
                    ^    1  --       (   2(pi)jk)
                    z = --- >  z *exp(-i -------), k=0,1,...,n-1.
                     k      --  j    (      n   )
                        \/n j=0

                                      1
          (Note the scale factor of  --- in this definition.)
                                       

                                     \/n

          To compute the inverse discrete Fourier transform defined by:

                                   n-1
                           ^    1  --       (   2(pi)jk)
                           w = --- >  z *exp(+i -------),
                            k      --  j    (      n   )
                               \/n j=0

          this routine should be preceded and followed by calls of C06GCF
                                                           ^
          to form the complex conjugates of the z  and the z .
                                                 j          k

          The routine uses the fast Fourier transform (FFT) algorithm
          (Brigham [1]). There are some restrictions on the value of n (see
          Section 5).

          4. References

          [1]   Brigham E O (1973) The Fast Fourier Transform. Prentice-
                Hall.

          5. Parameters

           1:  X(N) -- DOUBLE PRECISION array                  Input/Output
               On entry: if X is declared with bounds (0:N-1) in the (sub)
               program from which C06ECF is called, then X(j) must contain
               x , the real part of z , for j=0,1,...,n-1. On exit: the
                j                    j
               real parts a  of the components of the discrete Fourier
                           k
               transform. If X is declared with bounds (0:N-1) in the (sub)
               program from which C06ECF is called, then a  is contained in
                                                          k
               X(k), for k=0,1,...,n-1.

           2:  Y(N) -- DOUBLE PRECISION array                  Input/Output
               On entry: if Y is declared with bounds (0:N-1) in the (sub)
               program from which C06ECF is called, then Y(j) must contain
               y , the imaginary part of z , for j=0,1,...,n-1. On exit:
                j                         j
               the imaginary parts b  of the components of the discrete
                                    k
               Fourier transform. If Y is declared with bounds (0:N-1) in
               the (sub)program from which C06ECF is called, then b  is
                                                                   k
               contained in Y(k), for k=0,1,...,n-1.

           3:  N -- INTEGER                                           Input
               On entry: the number of data values, n. The largest prime
               factor of N must not exceed 19, and the total number of
               prime factors of N, counting repetitions, must not exceed
               20. Constraint: N > 1.

           4:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               At least one of the prime factors of N is greater than 19.

          IFAIL= 2
               N has more than 20 prime factors.

          IFAIL= 3
               N <= 1.

          7. Accuracy

          Some indication of accuracy can be obtained by performing a
          subsequent inverse transform and comparing the results with the
          original sequence (in exact arithmetic they would be identical).

          8. Further Comments

          The time taken by the routine is approximately proportional to
          n*logn, but also depends on the factorization of n. The routine
          is somewhat faster than average if the only prime factors of n
          are 2, 3 or 5; and fastest of all if n is a power of 2.

          On the other hand, the routine is particularly slow if n has
          several unpaired prime factors, i.e., if the 'square-free' part
          of n has several factors. For such values of n, routine C06FCF(*)
          (which requires an additional n real elements of workspace) is
          considerably faster.

          9. Example

          This program reads in a sequence of complex data values and
          prints their discrete Fourier transform.

          It then performs an inverse transform using C06GCF and C06ECF,
          and prints the sequence so obtained alongside the original data
          values.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXc06ekf}{nagc.ht}
{ Circular convolution or correlation of two real vectors}
\begin{chunk}{nagc.ht}
\begin{page}{manpageXXc06ekf}{NAG Documentation: c06ekf}
\beginscroll
\begin{verbatim}



     C06EKF(3NAG)      Foundation Library (12/10/92)      C06EKF(3NAG)



          C06 -- Summation of Series                                 C06EKF
                  C06EKF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          C06EKF calculates the circular convolution or correlation of two
          real vectors of period n. No extra workspace is required.

          2. Specification

                 SUBROUTINE C06EKF (JOB, X, Y, N, IFAIL)
                 INTEGER          JOB, N, IFAIL
                 DOUBLE PRECISION X(N), Y(N)

          3. Description

          This routine computes:

          if JOB =1, the discrete convolution of x and y, defined by:

                                  n-1        n-1
                                  --         --
                              z = >  x y   = >  x   y ;
                               k  --  j k-j  --  k-j j
                                  j=0        j=0

          if JOB =2, the discrete correlation of x and y defined by:

                                       n-1
                                       --
                                   w = >  x y   .
                                    k  --  j k+j
                                       j=0

          Here x and y are real vectors, assumed to be periodic, with
          period n, i.e., x =x    =x     =...; z and w are then also
                           j  j+-n  j+-2n
          periodic with period n.

          Note: this usage of the terms 'convolution' and 'correlation' is
          taken from Brigham [1]. The term 'convolution' is sometimes used
          to denote both these computations.

             ^  ^  ^     ^
          If x, y, z and w are the discrete Fourier transforms of these
          sequences,

                        n-1
                ^    1  --       (   2(pi)jk)
          i.e., x = --- >  x *exp(-i -------), etc,
                 k      --  j    (      n   )
                    \/n j=0

                ^      ^ ^
          then  z =\/n.x y
                 k      k k

                       

                ^      ^ ^
          and   w =\/n.x y
                 k      k k

          (the bar denoting complex conjugate).

          This routine calls the same auxiliary routines as C06EAF and
          C06EBF to compute discrete Fourier transforms, and there are some
          restrictions on the value of n.

          4. References

          [1]   Brigham E O (1973) The Fast Fourier Transform. Prentice-
                Hall.

          5. Parameters

           1:  JOB -- INTEGER                                         Input
               On entry: the computation to be performed:
                                    n-1
                                    --
                    if JOB = 1, z = >  x y    (convolution);
                                 k  --  j k-j
                                    j=0

                                    n-1
                                    --
                    if JOB = 2, w = >  x y    (correlation).
                                 k  --  j k+j
                                    j=0
               Constraint: JOB = 1 or 2.

           2:  X(N) -- DOUBLE PRECISION array                  Input/Output
               On entry: the elements of one period of the vector x. If X
               is declared with bounds (0:N-1) in the (sub)program from
               which C06EKF is called, then X(j) must contain x , for
                                                               j
               j=0,1,...,n-1. On exit: the corresponding elements of the
               discrete convolution or correlation.

           3:  Y(N) -- DOUBLE PRECISION array                  Input/Output
               On entry: the elements of one period of the vector y. If Y
               is declared with bounds (0:N-1) in the (sub)program from
               which C06EKF is called, then Y(j) must contain y , for
                                                               j
               j=0,1,...,n-1. On exit: the discrete Fourier transform of
               the convolution or correlation returned in the array X; the
               transform is stored in Hermitian form, exactly as described
               in the document  C06EAF.

           4:  N -- INTEGER                                           Input
               On entry: the number of values, n, in one period of the
               vectors X and Y. The largest prime factor of N must not
               exceed 19, and the total number of prime factors of N,
               counting repetitions, must not exceed 20. Constraint: N > 1.

           5:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               At least one of the prime factors of N is greater than 19.

          IFAIL= 2
               N has more than 20 prime factors.

          IFAIL= 3
               N <= 1.

          IFAIL= 4
               JOB /= 1 or 2.

          7. Accuracy

          The results should be accurate to within a small multiple of the
          machine precision.

          8. Further Comments

          The time taken by the routine is approximately proportional to
          n*logn, but also depends on the factorization of n. The routine
          is faster than average if the only prime factors are 2, 3 or 5;
          and fastest of all if n is a power of 2.

          The routine is particularly slow if n has several unpaired prime
          factors, i.e., if the 'square free' part of n has several
          factors. For such values of n, routine C06FKF(*) is considerably
          faster (but requires an additional workspace of n elements).

          9. Example

          This program reads in the elements of one period of two real
          vectors x and y and prints their discrete convolution and
          correlation (as computed by C06EKF). In realistic computations
          the number of data values would be much larger.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXc06fpf}{nagc.ht}
{ Discrete Fourier transforms of m sequences}
\begin{chunk}{nagc.ht}
\begin{page}{manpageXXc06fpf}{NAG Documentation: c06fpf}
\beginscroll
\begin{verbatim}



     C06FPF(3NAG)      Foundation Library (12/10/92)      C06FPF(3NAG)



          C06 -- Summation of Series                                 C06FPF
                  C06FPF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          C06FPF computes the discrete Fourier transforms of m sequences,
          each containing n real data values. This routine is designed to
          be particularly efficient on vector processors.

          2. Specification

                 SUBROUTINE C06FPF (M, N, X, INIT, TRIG, WORK, IFAIL)
                 INTEGER          M, N, IFAIL
                 DOUBLE PRECISION X(M*N), TRIG(2*N), WORK(M*N)
                 CHARACTER*1      INIT

          3. Description

                                                   p
          Given m sequences of n real data values x , for j=0,1,...,n-1;
                                                   j
          p=1,2,...,m, this routine simultaneously calculates the Fourier
          transforms of all the sequences defined by:

                     n-1
             ^p   1  --  p    (   2(pi)jk)
             z = --- >  x *exp(-i -------), k=0,1,...,n-1; p=1,2,...,m.
              k      --  j    (      n   )
                 \/n j=0

                                   1
          (Note the scale factor  --- in this definition.)
                                    

                                  \/n

                                 ^p
          The transformed values z  are complex, but for each value of p
                                  k
              ^p                                 ^p
          the z  form a Hermitian sequence (i.e.,z    is the complex
               k                                  n-k
                       ^p
          conjugate of z ), so they are completely determined by mn real
                        k
          numbers (see also the Chapter Introduction).

          The discrete Fourier transform is sometimes defined using a
          positive sign in the exponential term:

                                   n-1
                           ^p   1  --  p    (   2(pi)jk)
                           z = --- >  x *exp(+i -------).
                            k      --  j    (      n   )
                               \/n j=0

          To compute this form, this routine should be followed by a call
                                                          ^p
          to C06GQF to form the complex conjugates of the z .
                                                           k

          The routine uses a variant of the fast Fourier transform (FFT)
          algorithm (Brigham [1]) known as the Stockham self-sorting
          algorithm, which is described in Temperton [2]. Special coding is
          provided for the factors 2, 3, 4, 5 and 6. This routine is
          designed to be particularly efficient on vector processors, and
          it becomes especially fast as M, the number of transforms to be
          computed in parallel, increases.

          4. References

          [1]   Brigham E O (1973) The Fast Fourier Transform. Prentice-
                Hall.

          [2]   Temperton C (1983) Fast Mixed-Radix Real Fourier Transforms.
                J. Comput. Phys. 52 340--350.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: the number of sequences to be transformed, m.
               Constraint: M >= 1.

           2:  N -- INTEGER                                           Input
               On entry: the number of real values in each sequence, n.
               Constraint: N >= 1.

           3:  X(M,N) -- DOUBLE PRECISION array                Input/Output
               On entry: the data must be stored in X as if in a two-
               dimensional array of dimension (1:M,0:N-1); each of the m
               sequences is stored in a row of the array. In other words,
               if the data values of the pth sequence to be transformed are
                           p
               denoted by x , for j=0,1,...,n-1, then the mn elements of
                           j
               the array X must contain the values
                    1  2      m   1  2       m      1    2        m
                   x ,x ,...,x , x ,x ,..., x ,...,x   ,x   ,...,x   .
                    0  0      0   1  1       1      n-1  n-1      n-1
               On exit: the m discrete Fourier transforms stored as if in
               a two-dimensional array of dimension (1:M,0:N-1). Each of
               the m transforms is stored in a row of the array in
               Hermitian form, overwriting the corresponding original
               sequence. If the n components of the discrete Fourier
                         ^p                 p   p                       p
               transform z  are written as a +ib , then for 0<=k<=n/2, a
                          k                 k   k                       k
                                                               p
               is contained in X(p,k), and for 1<=k<=(n-1)/2, b  is
                                                               k
               contained in X(p,n-k). (See also Section 2.1.2 of the
               Chapter Introduction.)

           4:  INIT -- CHARACTER*1                                    Input
               On entry: if the trigonometric coefficients required to
               compute the transforms are to be calculated by the routine
               and stored in the array TRIG, then INIT must be set equal to
               'I' (Initial call).

               If INIT contains 'S' (Subsequent call), then the routine
               assumes that trigonometric coefficients for the specified
               value of n are supplied in the array TRIG, having been
               calculated in a previous call to one of C06FPF, C06FQF or
               C06FRF.

               If INIT contains 'R' (Restart then the routine assumes that
               trigonometric coefficients for the particular value of n are
               supplied in the array TRIG, but does not check that C06FPF,
               C06FQF or C06FRF have previously been called. This option
               allows the TRIG array to be stored in an external file, read
               in and re-used without the need for a call with INIT equal
               to 'I'. The routine carries out a simple test to check that
               the current value of n is consistent with the array TRIG.
               Constraint: INIT = 'I', 'S' or 'R'.

           5:  TRIG(2*N) -- DOUBLE PRECISION array             Input/Output
               On entry: if INIT = 'S' or 'R', TRIG must contain the
               required coefficients calculated in a previous call of the
               routine. Otherwise TRIG need not be set. On exit: TRIG
               contains the required coefficients (computed by the routine
               if INIT = 'I').

           6:  WORK(M*N) -- DOUBLE PRECISION array                Workspace

           7:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).


          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry M < 1.

          IFAIL= 2
               N < 1.

          IFAIL= 3
               INIT is not one of 'I', 'S' or 'R'.

          IFAIL= 4
               INIT = 'S', but none of C06FPF, C06FQF or C06FRF has
               previously been called.

          IFAIL= 5
               INIT = 'S' or 'R', but the array TRIG and the current value
               of N are inconsistent.

          7. Accuracy

          Some indication of accuracy can be obtained by performing a
          subsequent inverse transform and comparing the results with the
          original sequence (in exact arithmetic they would be identical).

          8. Further Comments

          The time taken by the routine is approximately proportional to
          nm*logn, but also depends on the factors of n. The routine is
          fastest if the only prime factors of n are 2, 3 and 5, and is
          particularly slow if n is a large prime, or has large prime
          factors.

          9. Example

          This program reads in sequences of real data values and prints
          their discrete Fourier transforms (as computed by C06FPF). The
          Fourier transforms are expanded into full complex form using
          C06GSF and printed. Inverse transforms are then calculated by
          calling C06GQF followed by C06FQF showing that the original
          sequences are restored.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXc06fqf}{nagc.ht}
{ Discrete Fourier transforms of m Hermitian sequences}
\begin{chunk}{nagc.ht}
\begin{page}{manpageXXc06fqf}{NAG Documentation: c06fqf}
\beginscroll
\begin{verbatim}



     C06FQF(3NAG)      Foundation Library (12/10/92)      C06FQF(3NAG)



          C06 -- Summation of Series                                 C06FQF
                  C06FQF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          C06FQF computes the discrete Fourier transforms of m Hermitian
          sequences, each containing n complex data values. This routine is
          designed to be particularly efficient on vector processors.

          2. Specification

                 SUBROUTINE C06FQF (M, N, X, INIT, TRIG, WORK, IFAIL)
                 INTEGER          M, N, IFAIL
                 DOUBLE PRECISION X(M*N), TRIG(2*N), WORK(M*N)
                 CHARACTER*1      INIT

          3. Description

                                                                p
          Given m Hermitian sequences of n complex data values z , for
                                                                j
          j=0,1,...,n-1; p=1,2,...,m, this routine simultaneously
          calculates the Fourier transforms of all the sequences defined
          by:

                     n-1
             ^p   1  --  p    (   2(pi)jk)
             x = --- >  z *exp(-i -------), k=0,1,...,n-1; p=1,2,...,m.
              k      --  j    (      n   )
                 \/n j=0

                                   1
          (Note the scale factor  --- in this definition.)
                                    

                                  \/n

          The transformed values are purely real (see also the Chapter
          Introduction).

          The discrete Fourier transform is sometimes defined using a
          positive sign in the exponential term

                                   n-1
                           ^p   1  --  p    (   2(pi)jk)
                           x = --- >  z *exp(+i -------).
                            k      --  j    (      n   )
                               \/n j=0

          To compute this form, this routine should be preceded by a call
                                                          ^p
          to C06GQF to form the complex conjugates of the z .
                                                           j

          The routine uses a variant of the fast Fourier transform (FFT)
          algorithm (Brigham [1]) known as the Stockham self-sorting
          algorithm, which is described in Temperton [2]. Special code is
          included for the factors 2, 3, 4, 5 and 6. This routine is
          designed to be particularly efficient on vector processors, and
          it becomes especially fast as m, the number of transforms to be
          computed in parallel, increases.

          4. References

          [1]   Brigham E O (1973) The Fast Fourier Transform. Prentice-
                Hall.

          [2]   Temperton C (1983) Fast Mixed-Radix Real Fourier Transforms.
                J. Comput. Phys. 52 340--350.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: the number of sequences to be transformed, m.
               Constraint: M >= 1.

           2:  N -- INTEGER                                           Input
               On entry: the number of data values in each sequence, n.
               Constraint: N >= 1.

           3:  X(M,N) -- DOUBLE PRECISION array                Input/Output
               On entry: the data must be stored in X as if in a two-
               dimensional array of dimension (1:M,0:N-1); each of the m
               sequences is stored in a row of the array in Hermitian form.
                                     p                 p   p
               If the n data values z  are written as x +iy , then for
                                     j                 j   j
                           p
               0<=j<=n/2, x  is contained in X(p,j), and for 1<=j<=(n-1)/2,
                           j
                p
               y  is contained in X(p,n-j). (See also Section 2.1.2 of the
                j
               Chapter Introduction.) On exit: the components of the m
               discrete Fourier transforms, stored as if in a two-
               dimensional array of dimension (1:M,0:N-1). Each of the m
               transforms is stored as a row of the array, overwriting the
               corresponding original sequence. If the n components of the
                                                         ^p
               discrete Fourier transform are denoted by x , for
                                                          k
               k=0,1,...,n-1, then the mn elements of the array X contain
               the values
                   ^1 ^2     ^m  ^1 ^2      ^m     ^1   ^2       ^m
                   x ,x ,...,x , x ,x ,..., x ,...,x   ,x   ,...,x   .
                    0  0      0   1  1       1      n-1  n-1      n-1

           4:  INIT -- CHARACTER*1                                    Input
               On entry: if the trigonometric coefficients required to
               compute the transforms are to be calculated by the routine
               and stored in the array TRIG, then INIT must be set equal to
               'I' (Initial call).

               If INIT contains 'S' (Subsequent call), then the routine
               assumes that trigonometric coefficients for the specified
               value of n are supplied in the array TRIG, having been
               calculated in a previous call to one of C06FPF, C06FQF or
               C06FRF.

               If INIT contains 'R' (Restart), then the routine assumes
               that trigonometric coefficients for the particular value of
               N are supplied in the array TRIG, but does not check that
               C06FPF, C06FQF or C06FRF have previously been called. This
               option allows the TRIG array to be stored in an external
               file, read in and re-used without the need for a call with
               INIT equal to 'I'. The routine carries out a simple test to
               check that the current value of n is compatible with the
               array TRIG. Constraint: INIT = 'I', 'S' or 'R'.

           5:  TRIG(2*N) -- DOUBLE PRECISION array             Input/Output
               On entry: if INIT = 'S' or 'R', TRIG must contain the
               required coefficients calculated in a previous call of the
               routine. Otherwise TRIG need not be set. On exit: TRIG
               contains the required coefficients (computed by the routine
               if INIT = 'I').

           6:  WORK(M*N) -- DOUBLE PRECISION array                Workspace

           7:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry M < 1.

          IFAIL= 2
               On entry N < 1.

          IFAIL= 3
               On entry INIT is not one of 'I', 'S' or 'R'.

          IFAIL= 4
               On entry INIT = 'S', but none of C06FPF, C06FQF and C06FRF
               has previously been called.

          IFAIL= 5
               On entry INIT = 'S' or 'R', but the array TRIG and the
               current value of n are inconsistent.

          7. Accuracy

          Some indication of accuracy can be obtained by performing a
          subsequent inverse transform and comparing the results with the
          original sequence (in exact arithmetic they would be identical).

          8. Further Comments

          The time taken by the routine is approximately proportional to
          nm*logn, but also depends on the factors of n. The routine is
          fastest if the only prime factors of n are 2, 3 and 5, and is
          particularly slow if n is a large prime, or has large prime
          factors.

          9. Example

          This program reads in sequences of real data values which are
          assumed to be Hermitian sequences of complex data stored in
          Hermitian form. The sequences are expanded into full complex form
          using C06GSF and printed. The discrete Fourier transforms are
          then computed (using C06FQF) and printed out. Inverse transforms
          are then calculated by calling C06FPF followed by C06GQF showing
          that the original sequences are restored.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXc06frf}{nagc.ht}
{ Discrete Fourier transforms of m complex sequences}
\begin{chunk}{nagc.ht}
\begin{page}{manpageXXc06frf}{NAG Documentation: c06frf}
\beginscroll
\begin{verbatim}



     C06FRF(3NAG)      Foundation Library (12/10/92)      C06FRF(3NAG)



          C06 -- Summation of Series                                 C06FRF
                  C06FRF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          C06FRF computes the discrete Fourier transforms of m sequences,
          each containing n complex data values. This routine is designed
          to be particularly efficient on vector processors.

          2. Specification

                 SUBROUTINE C06FRF (M, N, X, Y, INIT, TRIG, WORK, IFAIL)
                 INTEGER          M, N, IFAIL
                 DOUBLE PRECISION X(M*N), Y(M*N), TRIG(2*N), WORK(2*M*N)
                 CHARACTER*1      INIT

          3. Description

                                                      p
          Given m sequences of n complex data values z , for j=0,1,...,n-1;
                                                      j
          p=1,2,...,m, this routine simultaneously calculates the Fourier
          transforms of all the sequences defined by:

                     n-1
             ^p   1  --  p    (   2(pi)jk)
             z = --- >  z *exp(-i -------), k=0,1,...,n-1; p=1,2,...,m.
              k      --  j    (      n   )
                 \/n j=0

                                   1
          (Note the scale factor  --- in this definition.)
                                    

                                  \/n

          The discrete Fourier transform is sometimes defined using a
          positive sign in the exponential term

                                   n-1
                           ^p   1  --  p    (   2(pi)jk)
                           z = --- >  z *exp(+i -------).
                            k      --  j    (      n   )
                               \/n j=0

          To compute this form, this routine should be preceded and
          followed by a call of C06GCF to form the complex conjugates of
               p         ^p
          the z  and the z .
               j          k

          The routine uses a variant of the fast Fourier transform (FFT)
          algorithm (Brigham [1]) known as the Stockham self-sorting
          algorithm, which is described in Temperton [2]. Special code is
          provided for the factors 2, 3, 4, 5 and 6. This routine is
          designed to be particularly efficient on vector processors, and
          it becomes especially fast as m, the number of transforms to be
          computed in parallel, increases.

          4. References

          [1]   Brigham E O (1973) The Fast Fourier Transform. Prentice-
                Hall.

          [2]   Temperton C (1983) Self-sorting Mixed-radix Fast Fourier
                Transforms. J. Comput. Phys. 52 1--23.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: the number of sequences to be transformed, m.
               Constraint: M >= 1.

           2:  N -- INTEGER                                           Input
               On entry: the number of complex values in each sequence, n.
               Constraint: N >= 1.

           3:  X(M,N) -- DOUBLE PRECISION array                Input/Output

           4:  Y(M,N) -- DOUBLE PRECISION array                Input/Output
               On entry: the real and imaginary parts of the complex data
               must be stored in X and Y respectively as if in a two-
               dimensional array of dimension (1:M,0:N-1); each of the m
               sequences is stored in a row of each array. In other words,
               if the real parts of the pth sequence to be transformed are
                           p
               denoted by x , for j=0,1,...,n-1, then the mn elements of
                           j
               the array X must contain the values
                    1  2      m   1  2      m       1    2        m
                   x ,x ,...,x , x ,x ,...,x ,..., x   ,x   ,...,x   .
                    0  0      0   1  1      1       n-1  n-1      n-1
               On exit: X and Y are overwritten by the real and imaginary
               parts of the complex transforms.

           5:  INIT -- CHARACTER*1                                    Input
               On entry: if the trigonometric coefficients required to
               compute the transforms are to be calculated by the routine
               and stored in the array TRIG, then INIT must be set equal to
               'I' (Initial call).

               If INIT contains 'S' (Subsequent call), then the routine
               assumes that trigonometric coefficients for the specified
               value of n are supplied in the array TRIG, having been
               calculated in a previous call to one of C06FPF, C06FQF or
               C06FRF.

               If INIT contains 'R' (Restart) then the routine assumes that
               trigonometric coefficients for the particular value of n are
               supplied in the array TRIG, but does not check that C06FPF,
               C06FQF or C06FRF have previously been called. This option
               allows the TRIG array to be stored in an external file, read
               in and re-used without the need for a call with INIT equal
               to 'I'. The routine carries out a simple test to check that
               the current value of n is compatible with the array TRIG.
               Constraint: INIT = 'I', 'S' or 'R'.

           6:  TRIG(2*N) -- DOUBLE PRECISION array             Input/Output
               On entry: if INIT = 'S' or 'R', TRIG must contain the
               required coefficients calculated in a previous call of the
               routine. Otherwise TRIG need not be set. On exit: TRIG
               contains the required coefficients (computed by the routine
               if INIT = 'I').

           7:  WORK(2*M*N) -- DOUBLE PRECISION array              Workspace

           8:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry M < 1.

          IFAIL= 2
               On entry N < 1.

          IFAIL= 3
               On entry INIT is not one of 'I', 'S' or 'R'.

          IFAIL= 4
               On entry INIT = 'S', but none of C06FPF, C06FQF and C06FRF
               has previously been called.

          IFAIL= 5
               On entry INIT = 'S' or 'R', but the array TRIG and the
               current value of n are inconsistent.

          7. Accuracy

          Some indication of accuracy can be obtained by performing a
          subsequent inverse transform and comparing the results with the
          original sequence (in exact arithmetic they would be identical).

          8. Further Comments

          The time taken by the routine is approximately proportional to
          nm*logn, but also depends on the factors of n. The routine is
          fastest if the only prime factors of n are 2, 3 and 5, and is
          particularly slow if n is a large prime, or has large prime
          factors.

          9. Example

          This program reads in sequences of complex data values and prints
          their discrete Fourier transforms (as computed by C06FRF).
          Inverse transforms are then calculated using C06GCF and C06FRF
          and printed out, showing that the original sequences are
          restored.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXc06fuf}{nagc.ht}
{ Discrete Fourier transform of bivariate complex data}
\begin{chunk}{nagc.ht}
\begin{page}{manpageXXc06fuf}{NAG Documentation: c06fuf}
\beginscroll
\begin{verbatim}



     C06FUF(3NAG)      Foundation Library (12/10/92)      C06FUF(3NAG)



          C06 -- Summation of Series                                 C06FUF
                  C06FUF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          C06FUF computes the two-dimensional discrete Fourier transform of
          a bivariate sequence of complex data values. This routine is
          designed to be particularly efficient on vector processors.

          2. Specification

                 SUBROUTINE C06FUF (M, N, X, Y, INIT, TRIGM, TRIGN, WORK,
                1                   IFAIL)
                 INTEGER          M, N, IFAIL
                 DOUBLE PRECISION X(M*N), Y(M*N), TRIGM(2*M), TRIGN(2*N),
                1                 WORK(2*M*N)
                 CHARACTER*1      INIT

          3. Description

          This routine computes the two-dimensional discrete Fourier
          transform of a bivariate sequence of complex data values z    ,
                                                                    j j
                                                                     1 2
          where j =0,1,...,m-1, j =0,1,...,n-1.
                 1               2

          The discrete Fourier transform is here defined by:

                            m-1  n-1          (       ( j k   j k ))
                ^       1   --   --           (       (  1 1   2 2))
                z    = ---- >    >   z    *exp(-2(pi)i( ----+ ----)),
                            --   --   j j     (       (  m     n  ))
                 k k   \/mn j =0 j =0  1 2
                  1 2        1    2

          where k =0,1,...,m-1, k =0,1,...,n-1.
                 1               2

                                      1
          (Note the scale factor of  ---- in this definition.)
                                       

                                     \/mn

          To compute the inverse discrete Fourier transform, defined with
          exp(+2(pi)i(...)) in the above formula instead of exp(-
          2(pi)i(...)), this routine should be preceded and followed by
          calls of C06GCF to form the complex conjugates of the data values
          and the transform.

          This routine calls C06FRF to perform multiple one-dimensional
          discrete Fourier transforms by the fast Fourier transform (FFT)
          algorithm in Brigham [1]. It is designed to be particularly
          efficient on vector processors.

          4. References

          [1]   Brigham E O (1973) The Fast Fourier Transform. Prentice-
                Hall.

          [2]   Temperton C (1983) Self-sorting Mixed-radix Fast Fourier
                Transforms. J. Comput. Phys. 52 1--23.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: the number of rows, m, of the arrays X and Y.
               Constraint: M >= 1.

           2:  N -- INTEGER                                           Input
               On entry: the number of columns, n, of the arrays X and Y.
               Constraint: N >= 1.

           3:  X(M,N) -- DOUBLE PRECISION array                Input/Output

           4:  Y(M,N) -- DOUBLE PRECISION array                Input/Output
               On entry: the real and imaginary parts of the complex data
               values must be stored in arrays X and Y respectively. If X
               and Y are regarded as two-dimensional arrays of dimension
               (0:M-1,0:N-1), then X(j ,j ) and Y(j ,j ) must contain the
                                      1  2         1  2
               real and imaginary parts of z    . On exit: the real and
                                            j j
                                             1 2
               imaginary parts respectively of the corresponding elements
               of the computed transform.

           5:  INIT -- CHARACTER*1                                    Input
               On entry: if the trigonometric coefficients required to
               compute the transforms are to be calculated by the routine
               and stored in the arrays TRIGM and TRIGN, then INIT must be
               set equal to 'I', (Initial call).

               If INIT contains 'S', (Subsequent call), then the routine
               assumes that trigonometric coefficients for the specified
               values of m and n are supplied in the arrays TRIGM and
               TRIGN, having been calculated in a previous call to the
               routine.

               If INIT contains 'R', (Restart), then the routine assumes
               that trigonometric coefficients for the particular values of
               m and n are supplied in the arrays TRIGM and TRIGN, but does
               not check that the routine has previously been called. This
               option allows the TRIGM and TRIGN arrays to be stored in an
               external file, read in and re-used without the need for a
               call with INIT equal to 'I'. The routine carries out a
               simple test to check that the current values of m and n are
               compatible with the arrays TRIGM and TRIGN. Constraint: INIT
               = 'I', 'S' or 'R'.

           6:  TRIGM(2*M) -- DOUBLE PRECISION array            Input/Output

           7:  TRIGN(2*N) -- DOUBLE PRECISION array            Input/Output
               On entry: if INIT = 'S' or 'R',TRIGM and TRIGN must contain
               the required coefficients calculated in a previous call of
               the routine. Otherwise TRIGM and TRIGN need not be set.

               If m=n the same array may be supplied for TRIGM and TRIGN.
               On exit: TRIGM and TRIGN contain the required coefficients
               (computed by the routine if INIT = 'I').

           8:  WORK(2*M*N) -- DOUBLE PRECISION array              Workspace

           9:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry M < 1.

          IFAIL= 2
               On entry N < 1.

          IFAIL= 3
               On entry INIT is not one of 'I', 'S' or 'R'.

          IFAIL= 4
               On entry INIT = 'S', but C06FUF has not previously been
               called.

          IFAIL= 5
               On entry INIT = 'S' or 'R', but at least one of the arrays
               TRIGM and TRIGN is inconsistent with the current value of M
               or N.

          7. Accuracy

          Some indication of accuracy can be obtained by performing a
          subsequent inverse transform and comparing the results with the
          original sequence (in exact arithmetic they would be identical).

          8. Further Comments

          The time taken by the routine is approximately proportional to
          mn*log(mn), but also depends on the factorization of the
          individual dimensions m and n. The routine is somewhat faster
          than average if their only prime factors are 2, 3 or 5; and
          fastest of all if they are powers of 2.

          9. Example

          This program reads in a bivariate sequence of complex data values
          and prints the two-dimensional Fourier transform. It then
          performs an inverse transform and prints the sequence so
          obtained, which may be compared to the original data values.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXc06gbf}{nagc.ht}{ Summation of Series}
\begin{chunk}{nagc.ht}
\begin{page}{manpageXXc06gbf}{NAG Documentation: c06gbf}
\beginscroll
\begin{verbatim}



     C06GBF(3NAG)      Foundation Library (12/10/92)      C06GBF(3NAG)



          C06 -- Summation of Series                                 C06GBF
                  C06GBF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          C06GBF forms the complex conjugate of a Hermitian sequence of n
          data values.

          2. Specification

                 SUBROUTINE C06GBF (X, N, IFAIL)
                 INTEGER          N, IFAIL
                 DOUBLE PRECISION X(N)

          3. Description

          This is a utility routine for use in conjunction with C06EAF,
          C06EBF, C06FAF(*) or C06FBF(*) to calculate inverse discrete
          Fourier transforms (see the Chapter Introduction).

          4. References

          None.

          5. Parameters

           1:  X(N) -- DOUBLE PRECISION array                  Input/Output
               On entry: if the data values z  are written as x +iy  and
                                             j                 j   j
               if X is declared with bounds (0:N-1) in the (sub)program
               from which C06GBF is called, then for 0<=j<=n/2, X(j) must
               contain x (=x   ), while for n/2<j<=n-1, X(j) must contain
                        j   n-j
               -y (=y   ). In other words, X must contain the Hermitian
                 j   n-j
               sequence in Hermitian form. (See also Section 2.1.2 of the
               Chapter Introduction). On exit: the imaginary parts y  are
                                                                    j
               negated. The real parts x  are not referenced.
                                        j

           2:  N -- INTEGER                                           Input
               On entry: the number of data values, n. Constraint: N >= 1.

           3:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               N < 1.

          7. Accuracy

          Exact.

          8. Further Comments

          The time taken by the routine is negligible.

          9. Example

          This program reads in a sequence of real data values, calls
          C06EAF followed by C06GBF to compute their inverse discrete
          Fourier transform, and prints this after expanding it from
          Hermitian form into a full complex sequence.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXc06gcf}{nagc.ht}
{ Complex conjugate of a sequence of n data values}
\begin{chunk}{nagc.ht}
\begin{page}{manpageXXc06gcf}{NAG Documentation: c06gcf}
\beginscroll
\begin{verbatim}



     C06GCF(3NAG)      Foundation Library (12/10/92)      C06GCF(3NAG)



          C06 -- Summation of Series                                 C06GCF
                  C06GCF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          C06GCF forms the complex conjugate of a sequence of n data
          values.

          2. Specification

                 SUBROUTINE C06GCF (Y, N, IFAIL)
                 INTEGER          N, IFAIL
                 DOUBLE PRECISION Y(N)

          3. Description

          This is a utility routine for use in conjunction with C06ECF or
          C06FCF(*) to calculate inverse discrete Fourier transforms (see
          the Chapter Introduction).

          4. References

          None.

          5. Parameters

           1:  Y(N) -- DOUBLE PRECISION array                  Input/Output
               On entry: if Y is declared with bounds (0:N-1) in the (sub)
               program which C06GCF is called, then Y(j) must contain the
               imaginary part of the jth data value, for 0<=j<=n-1. On
               exit: these values are negated.

           2:  N -- INTEGER                                           Input
               On entry: the number of data values, n. Constraint: N >= 1.

           3:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               N < 1.

          7. Accuracy

          Exact.

          8. Further Comments

          The time taken by the routine is negligible.

          9. Example

          This program reads in a sequence of complex data values and
          prints their inverse discrete Fourier transform as computed by
          calling C06GCF, followed by C06ECF and C06GCF again.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXc06gqf}{ngac.ht}
{ Complex conjugates of m Hermitian sequences}
\begin{chunk}{nagc.ht}
\begin{page}{manpageXXc06gqf}{NAG Documentation: c06gqf}
\beginscroll
\begin{verbatim}



     C06GQF(3NAG)      Foundation Library (12/10/92)      C06GQF(3NAG)



          C06 -- Summation of Series                                 C06GQF
                  C06GQF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          C06GQF forms the complex conjugates of m Hermitian sequences,
          each containing n data values.

          2. Specification

                 SUBROUTINE C06GQF (M, N, X, IFAIL)
                 INTEGER          M, N, IFAIL
                 DOUBLE PRECISION X(M*N)

          3. Description

          This is a utility routine for use in conjunction with C06FPF and
          C06FQF to calculate inverse discrete Fourier transforms (see the
          Chapter Introduction).

          4. References

          None.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: the number of Hermitian sequences to be
               conjugated, m. Constraint: M >= 1.

           2:  N -- INTEGER                                           Input
               On entry: the number of data values in each Hermitian
               sequence, n. Constraint: N >= 1.

           3:  X(M,N) -- DOUBLE PRECISION array                Input/Output
               On entry: the data must be stored in array X as if in a
               two-dimensional array of dimension (1:M,0:N-1); each of the
               m sequences is stored in a row of the array in Hermitian
                                           p                 p   p
               form. If the n data values z  are written as x +iy , then
                                           j                 j   j
                               p
               for 0<=j<=n/2, x  is contained in X(p,j), and for 1<=j<=(n-
                               j
                      p
               1)/2, y  is contained in X(p,n-j). (See also Section 2.1.2
                      j
               of the Chapter Introduction.) On exit: the imaginary parts
                p                              p
               y  are negated. The real parts x  are not referenced.
                j                              j

           4:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry M < 1.

          IFAIL= 2
               On entry N < 1.

          7. Accuracy

          Exact.

          8. Further Comments

          None.

          9. Example

          This program reads in sequences of real data values which are
          assumed to be Hermitian sequences of complex data stored in
          Hermitian form. The sequences are expanded into full complex form
          using C06GSF and printed. The sequences are then conjugated
          (using C06GQF) and the conjugated sequences are expanded into
          complex form using C06GSF and printed out.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXc06gsf}{nagc.ht}
{ Form real and imaginary parts of m Hermitian sequences}
\begin{chunk}{nagc.ht}
\begin{page}{manpageXXc06gsf}{NAG Documentation: c06gsf}
\beginscroll
\begin{verbatim}



     C06GSF(3NAG)      Foundation Library (12/10/92)      C06GSF(3NAG)



          C06 -- Summation of Series                                 C06GSF
                  C06GSF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          C06GSF takes m Hermitian sequences, each containing n data
          values, and forms the real and imaginary parts of the m
          corresponding complex sequences.

          2. Specification

                 SUBROUTINE C06GSF (M, N, X, U, V, IFAIL)
                 INTEGER          M, N, IFAIL
                 DOUBLE PRECISION X(M*N), U(M*N), V(M*N)

          3. Description

          This is a utility routine for use in conjunction with C06FPF and
          C06FQF (see the Chapter Introduction).

          4. References

          None.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: the number of Hermitian sequences, m, to be
               converted into complex form. Constraint: M >= 1.

           2:  N -- INTEGER                                           Input
               On entry: the number of data values, n, in each sequence.
               Constraint: N >= 1.

           3:  X(M,N) -- DOUBLE PRECISION array                       Input
               On entry: the data must be stored in X as if in a two-
               dimensional array of dimension (1:M,0:N-1); each of the m
               sequences is stored in a row of the array in Hermitian form.
                                     p                 p   p
               If the n data values z  are written as x +iy , then for
                                     j                 j   j
                           p
               0<=j<=n/2, x  is contained in X(p,j), and for 1<=j<=(n-1)/2,
                           j
                p
               y  is contained in X(p,n-j). (See also Section 2.1.2 of the
                j
               Chapter Introduction.)

           4:  U(M,N) -- DOUBLE PRECISION array                      Output

           5:  V(M,N) -- DOUBLE PRECISION array                      Output
               On exit: the real and imaginary parts of the m sequences of
               length n, are stored in U and V respectively, as if in two-
               dimensional arrays of dimension (1:M,0:N-1); each of the m
               sequences is stored as if in a row of each array. In other
               words, if the real parts of the pth sequence are denoted by
                p
               x , for j=0,1,...,n-1 then the mn elements of the array U
                j
               contain the values
                     1  2      m   1  2      m       1    2        m
                    x ,x ,...,x , x ,x ,...,x ,..., x   ,x   ,...,x
                     0  0      0   1  1      1       n-1  n-1      n-1

           6:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry M < 1.

          IFAIL= 2
               On entry N < 1.

          7. Accuracy

          Exact.

          8. Further Comments

          None.

          9. Example

          This program reads in sequences of real data values which are
          assumed to be Hermitian sequences of complex data stored in
          Hermitian form. The sequences are then expanded into full complex
          form using C06GSF and printed.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\section{nagd.ht}
\pagetitle{manpageXXd01}{nagd.ht}{ Quadrature}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd01}{NAG Documentation: d01}
\beginscroll
\begin{verbatim}



     D01(3NAG)         Foundation Library (12/10/92)         D01(3NAG)



          D01 -- Quadrature                             Introduction -- D01
                                    Chapter D01
                                    Quadrature

          1. Scope of the Chapter

          This chapter provides routines for the numerical evaluation of
          definite integrals in one or more dimensions and for evaluating
          weights and abscissae of integration rules.

          2. Background to the Problems

          The routines in this chapter are designed to estimate:

          (a)   the value of a one-dimensional definite integral of the
                form:
                                        b
                                        /
                                        |f(x)dx                         (1)
                                        /
                                        a
                where f(x) is defined by the user, either at a set of
                points (x ,f(x )), for i=1,2,...,n where a=x <x <...<x =b,
                         i    i                             1  2      n
                or in the form of a function; and the limits of integration
                a,b may be finite or infinite.

                Some methods are specially designed for integrands of the
                form
                                    f(x)=w(x)g(x)                       (2)
                which contain a factor w(x), called the weight-function, of
                a specific form. These methods take full account of any
                peculiar behaviour attributable to the w(x) factor.

          (b)   the value of a multi-dimensional definite integral of the
                form:
                             /
                             | f(x ,x ,...,x )dx ...dx dx               (3)
                             /    1  2      n   n     2  1
                             R
                              n
                where f(x ,x ,...,x ) is a function defined by the user and
                         1  2      n
                R  is some region of n-dimensional space.
                 n

                The simplest form of R  is the n-rectangle defined by:
                                      n
                               a <=x <=b ,  i=1,2,...,n                 (4)
                                i   i   i
                where a  and b  are constants. When a  and b  are functions
                       i      i                      i      i
                of x  (j<i), the region can easily be transformed to the
                    j
                rectangular form (see Davis and Rabinowitz [1] page 266).
                Some of the methods described incorporate the
                transformation procedure.

          2.1. One-dimensional Integrals

          To estimate the value of a one-dimensional integral, a quadrature
          rule uses an approximation in the form of a weighted sum of
          integrand values, i.e.,

                              b         N
                              /         --
                              |f(x)dx~= >  w f(x ).                     (5)
                              /         --  i   i
                              a         i=1

          The points x  within the interval [a,b] are known as the
                      i
          abscissae, and the w  are known as the weights.
                              i

          More generally, if the integrand has the form (2), the
          corresponding formula is

                            b             N
                            /             --
                            |w(x)g(x)dx~= >  w g(x ).                   (6)
                            /             --  i   i
                            a             i=1

          If the integrand is known only at a fixed set of points, these
          points must be used as the abscissae, and the weighted sum is
          calculated using finite-difference methods. However, if the
          functional form of the integrand is known, so that its value at
          any abscissa is easily obtained, then a wide variety of
          quadrature rules are available, each characterised by its choice
          of abscissae and the corresponding weights.

          The appropriate rule to use will depend on the interval [a,b] -
          whether finite or otherwise - and on the form of any w(x) factor
          in the integrand. A suitable value of N depends on the general
          behaviour of f(x); or of g(x), if there is a w(x) factor present.

          Among possible rules, we mention particularly the Gaussian
          formulae, which employ a distribution of abscissae which is
          optimal for f(x) or g(x) of polynomial form.

          The choice of basic rules constitutes one of the principles on
          which methods for one-dimensional integrals may be classified.
          The other major basis of classification is the implementation
          strategy, of which some types are now presented.

          (a)   Single rule evaluation procedures

                A fixed number of abscissae, N, is used. This number and
                the particular rule chosen uniquely determine the weights
                and abscissae. No estimate is made of the accuracy of the
                result.

          (b)   Automatic procedures

                The number of abscissae, N, within [a,b] is gradually
                increased until consistency is achieved to within a level
                of accuracy (absolute or relative) requested by the user.
                There are essentially two ways of doing this; hybrid forms
                of these two methods are also possible:
                (i)   whole interval procedures (non-adaptive)

                      A series of rules using increasing values of N are
                      successively applied over the whole interval [a,b].
                      It is clearly more economical if abscissae already
                      used for a lower value of N can be used again as part
                      of a higher-order formula. This principle is known as
                       optimal extension. There is no overlap between the
                      abscissae used in Gaussian formulae of different
                      orders. However, the Kronrod formulae are designed to
                      give an optimal (2N+1)-point formula by adding (N+1)
                      points to an N-point Gauss formula. Further
                      extensions have been developed by Patterson.

                (ii)  adaptive procedures

                      The interval [a,b] is repeatedly divided into a
                      number of sub-intervals, and integration rules are
                      applied separately to each sub-interval. Typically,
                      the subdivision process will be carried further in
                      the neighbourhood of a sharp peak in the integrand,
                      than where the curve is smooth. Thus, the
                      distribution of abscissae is adapted to the shape of
                      the integrand.

                      Subdivision raises the problem of what constitutes an
                      acceptable accuracy in each sub-interval. The usual
                      global acceptability criterion  demands that the sum
                      of the absolute values of the error estimates in the
                      sub-intervals should meet the conditions required of
                      the error over the whole interval. Automatic
                      extrapolation over several levels of subdivision may
                      eliminate the effects of some types of singularities.

          An ideal general-purpose method would be an automatic method
          which could be used for a wide variety of integrands, was
          efficient (i.e., required the use of as few abscissae as
          possible), and was reliable (i.e., always gave results within the
          requested accuracy). Complete reliability is unobtainable, and
          generally higher reliability is obtained at the expense of
          efficiency, and vice versa.  It must therefore be emphasised that
          the automatic routines in this chapter cannot be assumed to be
          100% reliable. In general, however, the reliability is very high.

          2.2. Multi-dimensional Integrals

          A distinction must be made between cases of moderately low
          dimensionality (say, up to 4 or 5 dimensions), and those of
          higher dimensionality. Where the number of dimensions is limited,
          a one-dimensional method may be applied to each dimension,
          according to some suitable strategy, and high accuracy may be
          obtainable (using product rules). However, the number of
          integrand evaluations rises very rapidly with the number of
          dimensions, so that the accuracy obtainable with an acceptable
          amount of computational labour is limited; for example a product
                                                                      9
          of 3-point rules in 20 dimensions would require more than 10
          integrand evaluations. Special techniques such as the Monte Carlo
          methods can be used to deal with high dimensions.

          (a)   Products of one-dimensional rules

                Using a two-dimensional integral as an example, we have
                         b  b                   [ b          ]
                          1  2             N    [  2         ]
                         /  /              --   [ /          ]
                         |  | f(x,y)dydx~= >  w [ | f(x ,y)dy]          (7)
                         /  /              --  i[ /    i     ]
                         a  a              i=1  [ a          ]
                          1  2                  [  2         ]

                         b  b
                          1  2             N   N
                         /  /              --  --
                         |  | f(x,y)dydx~= >   >  w v f(x ,y )          (8)
                         /  /              --  --  i j   i  j
                         a  a              i=1 j=1
                          1  2
                where (w ,x ) and (v ,y ) are the weights and abscissae of
                        i  i        i  i
                the rules used in the respective dimensions.

                A different one-dimensional rule may be used for each
                dimension, as appropriate to the range and any weight
                function present, and a different strategy may be used, as
                appropriate to the integrand behaviour as a function of
                each independent variable.

                For a rule-evaluation strategy in all dimensions, the
                formula (8) is applied in a straightforward manner. For
                automatic strategies (i.e., attempting to attain a
                requested accuracy), there is a problem in deciding what
                accuracy must be requested in the inner integral(s).
                Reference to formula (7) shows that the presence of a
                limited but random error in the y-integration for different
                values of x  can produce a 'jagged' function of x, which
                           i
                may be difficult to integrate to the desired accuracy and
                for this reason products of automatic one-dimensional
                routines should be used with caution (see also Lyness [3]).

          (b)   Monte Carlo methods

                These are based on estimating the mean value of the
                integrand sampled at points chosen from an appropriate
                statistical distribution function. Usually a variance
                reducing procedure is incorporated to combat the
                fundamentally slow rate of convergence of the rudimentary
                form of the technique. These methods can be effective by
                comparison with alternative methods when the integrand
                contains singularities or is erratic in some way, but they
                are of quite limited accuracy.

          (c)   Number theoretic methods

                These are based on the work of Korobov and Conroy and
                operate by exploiting implicitly the properties of the
                Fourier expansion of the integrand. Special rules,
                constructed from so-called optimal coefficients, give a
                particularly uniform distribution of the points throughout
                n-dimensional space and from their number theoretic
                properties minimize the error on a prescribed class of
                integrals. The method can be combined with the Monte Carlo
                procedure.

          (d)   Sag-Szekeres method

                By transformation this method seeks to induce properties
                into the integrand which make it accurately integrable by
                the trapezoidal rule. The transformation also allows
                effective control over the number of integrand evaluations.

          (e)   Automatic adaptive procedures

                An automatic adaptive strategy in several dimensions
                normally involves division of the region into subregions,
                concentrating the divisions in those parts of the region
                where the integrand is worst behaved. It is difficult to
                arrange with any generality for variable limits in the
                inner integral(s). For this reason, some methods use a
                region where all the limits are constants; this is called a
                hyper-rectangle. Integrals over regions defined by variable
                or infinite limits may be handled by transformation to a
                hyper-rectangle. Integrals over regions so irregular that
                such a transformation is not feasible may be handled by
                surrounding the region by an appropriate hyper-rectangle
                and defining the integrand to be zero outside the desired
                region. Such a technique should always be followed by a
                Monte Carlo method for integration.

                The method used locally in each subregion produced by the
                adaptive subdivision process is usually one of three types:
                Monte Carlo, number theoretic or deterministic.
                Deterministic methods are usually the most rapidly
                convergent but are often expensive to use for high
                dimensionality and not as robust as the other techniques.

          2.3. References

          Comprehensive reference:

          [1]   Davis P J and Rabinowitz P (1975) Methods of Numerical
                Integration. Academic Press.

          Special topics:

          [2]   Gladwell I (1986) Vectorisation of one dimensional
                quadrature codes. Techincal Report. TR7/86  NAG.

          [3]   Lyness J N (1983) When not to use an automatic quadrature
                routine. SIAM Review. 25 63--87.

          [4]   Piessens R, De Doncker-Kapenga E, Uberhuber C and Kahaner D
                (1983) QUADPACK, A Subroutine Package for Automatic
                Integration. Springer-Verlag.

          [5]   Sobol I M (1974) The Monte Carlo Method. The University of
                Chicago Press.

          [6]   Stroud A H (1971) Approximate Calculation of Multiple
                Integrals. Prentice-Hall.

          3. Recommendations on Choice and Use of Routines

          The following three sub-sections consider in turn routines for:
          one-dimensional integrals over a finite interval, and over a
          semi-infinite or an infinite interval; and multi-dimensional
          integrals. Within each sub-section, routines are classified by
          the type of method, which ranges from simple rule evaluation to
          automatic adaptive algorithms. The recommendations apply
          particularly when the primary objective is simply to compute the
          value of one or more integrals, and in these cases the automatic
          adaptive routines are generally the most convenient and reliable,
          although also the most expensive in computing time.

          Note however that in some circumstances it may be counter-
          productive to use an automatic routine. If the results of the
          quadrature are to be used in turn as input to a further
          computation (e.g. an 'outer' quadrature or an optimization
          problem), then this further computation may be adversely affected
          by the 'jagged performance profile' of an automatic routine; a
          simple rule-evaluation routine may provide much better overall
          performance. For further guidance, the article Lyness [3] is
          recommended.

          3.1. One-dimensional Integrals over a Finite Interval

          (a)   Integrand defined as a set of points

                If f(x) is defined numerically at four or more points, then
                the Gill-Miller finite difference method (D01GAF) should be
                used. The interval of integration is taken to coincide with
                the range of x-values of the points supplied. It is in the
                nature of this problem that any routine may be unreliable.
                In order to check results independently and so as to
                provide an alternative technique the user may fit the
                integrand by Chebyshev series using E02ADF and then use
                routines E02AJF and E02AKF to evaluate its integral (which
                need not be restricted to the range of the integration
                points, as is the case for D01GAF). A further alternative
                is to fit a cubic spline to the data using E02BAF and then
                to evaluate its integral using E02BDF.

          (b)   Integrand defined as a function

                If the functional form of f(x) is known, then one of the
                following approaches should be taken. They are arranged in
                the order from most specific to most general, hence the
                first applicable procedure in the list will be the most
                efficient.  However, if the user does not wish to make any
                assumptions about the integrand, the most reliable routine
                to use will be D01AJF, although this will in general be
                less efficient for simple integrals.
                (i)   Rule-evaluation routines

                      If f(x) is known to be sufficiently well-behaved
                      (more precisely, can be closely approximated by a
                      polynomial of moderate degree), a Gaussian routine
                      with a suitable number of abscissae may be used.

                      D01BBF may be used if it is required to examine the
                      weights and abscissae. In this case, the user should
                      write the code for the evaluation of quadrature
                      summation (6).

                (ii)  Automatic adaptive routines

                      Firstly, several routines are available for
                      integrands of the form w(x)g(x) where g(x) is a '
                      smooth' function (i.e., has no singularities, sharp
                      peaks or violent oscillations in the interval of
                      integration) and w(x) is a weight function of one of
                      the following forms:

                                   (alpha)     (beta)          k          l
                      if w(x)=(b-x)       (x-a)      (log(b-x)) (log(x-a))

                      where k,l=0 or 1, (alpha),(beta)>-1: use D01APF;

                      if w(x)=1/(x-c): use D01AQF (this integral is called
                      the Hilbert transform of g);

                      if w(x)=cos((omega)x) or sin((omega)x): use D01ANF
                      (this routine can also handle certain types of
                      singularities in g(x)).

                      Secondly, there are some routines for general f(x).
                      If f(x) is known to be free of singularities, though
                      it may be oscillatory, D01AKF may be used.

                      The most powerful of the finite interval integration
                      routine is D01AJF (which can cope with singularities
                      of several types). It may be used if none of the more
                      specific situations described above applies. D01AJF
                      is very reliable, particularly where the integrand
                      has singularities other than at an end-point, or has
                      discontinuities or cusps, and is therefore
                      recommended where the integrand is known to be badly-
                      behaved, or where its nature is completely unknown.

                      Most of the routines in this chapter require the user
                      to supply a function or subroutine to evaluate the
                      integrand at a single point.

                      If f(x) has singularities of certain types,
                      discontinuities or sharp peaks  occurring at known
                      points, the integral should be evaluated separately
                      over each of the subranges or D01ALF may be used.

          3.2. One-dimensional Integrals over a Semi-infinite or Infinite
               Interval

          (a)   Integrand defined as a set of points

                If f(x) is defined numerically at four or more points, and
                the portion of the integral lying outside the range of the
                points supplied may be neglected, then the Gill-Miller
                finite difference method, D01GAF, should be used.

          (b)   Integrand defined as a function
                (i)   Rule evaluation routines

                      If f(x) behaves approximately like a polynomial in x,
                      apart from a weight function of the form
                       -(beta)x
                      e                    (beta)>0 (semi-infinite interval,
                                                     lower limit finite);

                       -(beta)x
                 or   e                    (beta)<0 (semi-infinite interval,
                                                     upper limit finite);

                                          2
                        -(beta)(x-(alpha))
                 or    e                   (beta)>0 (infinite interval);

                               or if f(x) behaves approximately like a
                                                  -1
                               polynomial in (x+B)   (semi-infinite range);
                               then the Gaussian routines may be used.

                               D01BBF may be used if it is required to
                               examine the weights and abscissae. In this
                               case, the user should write the code for the
                               evaluation of quadrature summation (6).

                (ii)  Automatic adaptive routines

                      D01AMF may be used, except for integrands which decay
                      slowly towards an infinite end-point, and oscillate
                      in sign over the entire range. For this class, it may
                      be possible to calculate the integral by integrating
                      between the zeros and invoking some extrapolation
                      process.

                      D01ASF may be used for integrals involving weight
                      functions of the form cos((omega)x) and sin((omega)x)
                      over a semi-infinite interval (lower limit finite).

                      The following alternative procedures are mentioned
                      for completeness, though their use will rarely be
                      necessary:
                      (1)   If the integrand decays rapidly towards an
                            infinite end-point, a finite cut-off may be
                            chosen, and the finite range methods applied.

                      (2)   If the only irregularities occur in the finite
                            part (apart from a singularity at the finite
                            limit, with which D01AMF can cope), the range
                            may be divided, with D01AMF used on the
                            infinite part.

                      (3)   A transformation to finite range may be
                            employed, e.g.
                                             1-t
                                          x= ---  or x=-log t
                                              t            e
                            will transform (0,infty) to (1,0) while for
                            infinite ranges we have
                                   +infty        infty
                                   /             /
                                   |     f(x)dx= |    [f(x)+f(-x)]dx.
                                   /             /
                                   -infty        0
                            If the integrand behaves badly on (-infty,0)
                            and well on (0,infty) or vice versa it is
                            better to compute it as
                                       0             infty
                                       /             /
                                       |     f(x)dx+ |    f(x)dx.
                                       /             /
                                       -infty        0
                            This saves computing unnecessary function
                            values in the semi-infinite range where the
                            function is well behaved.

          3.3. Multi-dimensional Integrals

          A number of techniques are available in this area and the choice
          depends to a large extent on the dimension and the required
          accuracy. It can be advantageous to use more than one technique
          as a confirmation of accuracy particularly for high dimensional
          integrations. Many of the routines incorporate the transformation
          procedure REGION which allows general product regions to be
          easily dealt with in terms of conversion to the standard n-cube
          region.

          (a)   Products of one-dimensional rules (suitable for up to about
                5 dimensions)

                If f(x ,x ,...,x ) is known to be a sufficiently well-
                      1  2      n
                behaved function of each variable x , apart possibly from
                                                   i
                weight functions of the types provided, a product of
                Gaussian rules may be used. These are provided by D01BBF.
                In this case, the user should write the code for the
                evaluation of quadrature summation (6). Rules for finite,
                semi-infinite and infinite ranges are included.

                The one-dimensional routines may also be used recursively.
                For example, the two-dimensional integral
                                       b  b
                                        1  2
                                       /  /
                                    I= |  | f(x,y)dydx
                                       /  /
                                       a  a
                                        1  2
                may be expressed as
                                          b
                                           1
                                          /
                                       I= | F(x)dx,
                                          /
                                          a
                                           1
                where
                                           b
                                            2
                                           /
                                     F(x)= | f(x,y)dy.
                                           /
                                           a
                                            2
                The user segment to evaluate F(x) will call the integration
                routine for the y-integration, which will call another user
                segment for f(x,y) as a function of y (x being effectively
                a constant). Note that, as Fortran is not a recursive
                language,  a different library integration routine must be
                used for each dimension. Apart from this restriction, the
                full range of one-dimensional routines are available, for
                finite/infinite intervals, constant/variable limits, rule
                evaluation/automatic strategies etc.

          (b)   Automatic routines (D01GBF and D01FCF)

                Both routines are for integrals of the form
                         b  b     b
                          1  2     n
                         /  /     /
                         |  | ... | f(x ,x ,...,x )dx dx   ...dx .
                         /  /     /    1  2      n   n  n-1     1
                         a  a     a
                          1  2     n
                D01GBF is an adaptive Monte Carlo routine. This routine is
                       usually slow and not recommended for high accuracy
                       work. It is a robust routine that can often be used
                       for low accuracy results with highly irregular
                       integrands or when n is large.

                D01FCF is an adaptive deterministic routine. Convergence is
                       fast for well-behaved integrands. Highly accurate
                       results can often be obtained for n between 2 and 5,
                       using significantly fewer integrand evaluations than
                       would be required by D01GBF. The routine will
                       usually work when the integrand is mildly singular
                       and for n<=10 should be used before D01GBF. If it is
                       known in advance that the integrand is highly
                       irregular, it is best to compare results from at
                       least two different routines.

          There are many problems for which one or both of the routines
          will require large amounts of computing time to obtain even
          moderately accurate results. The amount of computing time is
          controlled by the number of integrand evaluations allowed by the
          user, and users should set this parameter carefully, with
          reference to the time available and the accuracy desired.


          3.4. Decision Trees

          (i) One-dimensional integrals over a finite interval. (If in
          doubt, follow the downward branch.)



                   Please see figure in printed Reference Manual


          (ii) One-dimensional integrals over a semi-infinite or infinite
          interval. (If in doubt, follow the downward branch.)



                   Please see figure in printed Reference Manual


          D01 -- Quadrature                                 Contents -- D01
          Chapter D01

          Quadrature

          D01AJF  1-D quadrature, adaptive, finite interval, strategy due
                  to Piessens and de Doncker, allowing for badly-behaved
                  integrands

          D01AKF  1-D quadrature, adaptive, finite interval, method
                  suitable for oscillating functions

          D01ALF  1-D quadrature, adaptive, finite interval, allowing for
                  singularities at user-specified break-points

          D01AMF  1-D quadrature, adaptive, infinite or semi-infinite
                  interval

          D01ANF  1-D quadrature, adaptive, finite interval, weight
                  function cos((omega)x) or sin((omega)x)

          D01APF  1-D quadrature, adaptive, finite interval, weight
                  function with end-point singularities of algebraico-
                  logarithmic type

          D01AQF  1-D quadrature, adaptive, finite interval, weight
                  function 1/(x-c), Cauchy principal value (Hilbert
                  transform)

          D01ASF  1-D quadrature, adaptive, semi-infinite interval, weight
                  function cos((omega)x) or sin((omega)x)

          D01BBF  Weights and abscissae for Gaussian quadrature rules

          D01FCF  Multi-dimensional adaptive quadrature over hyper-
                  rectangle

          D01GAF  1-D quadrature, integration of function defined by data
                  values, Gill-Miller method

          D01GBF  Multi-dimensional quadrature over hyper-rectangle, Monte
                  Carlo method

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd01ajf}{nagd.ht}
{ Approximation of the integral over a finite interval}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd01ajf}{NAG Documentation: d01ajf}
\beginscroll
\begin{verbatim}



     D01AJF(3NAG)      Foundation Library (12/10/92)      D01AJF(3NAG)



          D01 -- Quadrature                                          D01AJF
                  D01AJF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          D01AJF is a general-purpose integrator which calculates an
          approximation to the integral of a function f(x) over a finite
          interval [a,b]:

                                        b
                                        /
                                     I= |f(x)dx.
                                        /
                                        a

          2. Specification

                 SUBROUTINE D01AJF (F, A, B, EPSABS, EPSREL, RESULT,
                1                   ABSERR, W, LW, IW, LIW, IFAIL)
                 INTEGER          LW, IW(LIW), LIW, IFAIL
                 DOUBLE PRECISION F, A, B, EPSABS, EPSREL, RESULT, ABSERR, W
                1                 (LW)
                 EXTERNAL         F

          3. Description

          D01AJF is based upon the QUADPACK routine QAGS (Piessens et al
          [3]). It is an adaptive routine, using the Gauss 10-point and
          Kronrod 21-point rules. The algorithm, described by de Doncker
          [1], incorporates a global acceptance criterion (as defined by
          Malcolm and Simpson [2]) together with the (epsilon)-algorithm
          (Wynn [4]) to perform extrapolation. The local error estimation
          is described by Piessens et al [3].

          The routine is suitable as a general purpose integrator, and can
          be used when the integrand has singularities, especially when
          these are of algebraic or logarithmic type.

          D01AJF requires the user to supply a function to evaluate the
          integrand at a single point.

          The routine D01ATF(*) uses an identical algorithm but requires
          the user to supply a subroutine to evaluate the integrand at an
          array of points. Therefore D01ATF(*) will be more efficient if
          the evaluation can be performed in vector mode on a vector-
          processing machine.

          4. References

          [1]   De Doncker E (1978) An Adaptive Extrapolation Algorithm for
                Automatic Integration. Signum Newsletter. 13 (2) 12--18.

          [2]   Malcolm M A and Simpson R B (1976) Local Versus Global
                Strategies for Adaptive Quadrature. ACM Trans. Math. Softw.
                1 129--146.

          [3]   Piessens R, De Doncker-Kapenga E, Uberhuber C and Kahaner D
                (1983) QUADPACK, A Subroutine Package for Automatic
                Integration. Springer-Verlag.

          [4]   Wynn P (1956) On a Device for Computing the e (S )
                                                             m  n
                Transformation. Math. Tables Aids Comput. 10 91--96.

          5. Parameters

           1:  F -- DOUBLE PRECISION FUNCTION, supplied by the user.
                                                         External Procedure
               F must return the value of the integrand f at a given point.

               Its specification is:

                      DOUBLE PRECISION FUNCTION F (X)
                      DOUBLE PRECISION X

                1:  X -- DOUBLE PRECISION                             Input
                    On entry: the point at which the integrand f must be
                    evaluated.
               F must be declared as EXTERNAL in the (sub)program from
               which D01AJF is called. Parameters denoted as Input
               must not be changed by this procedure.

           2:  A -- DOUBLE PRECISION                                  Input
               On entry: the lower limit of integration, a.

           3:  B -- DOUBLE PRECISION                                  Input
               On entry: the upper limit of integration, b. It is not
               necessary that a<b.

           4:  EPSABS -- DOUBLE PRECISION                             Input
               On entry: the absolute accuracy required. If EPSABS is
               negative, the absolute value is used. See Section 7.

           5:  EPSREL -- DOUBLE PRECISION                             Input
               On entry: the relative accuracy required. If EPSREL is
               negative, the absolute value is used. See Section 7.

           6:  RESULT -- DOUBLE PRECISION                            Output
               On exit: the approximation to the integral I.

           7:  ABSERR -- DOUBLE PRECISION                            Output
               On exit: an estimate of the modulus of the absolute error,
               which should be an upper bound for |I-RESULT|.

           8:  W(LW) -- DOUBLE PRECISION array                       Output
               On exit: details of the computation, as described in
               Section 8.

           9:  LW -- INTEGER                                          Input
               On entry:
               the dimension of the array W as declared in the (sub)program
               from which D01AJF is called.
               The value of LW (together with that of LIW below) imposes a
               bound on the number of sub-intervals into which the interval
               of integration may be divided by the routine. The number of
               sub-intervals cannot exceed LW/4. The more difficult the
               integrand, the larger LW should be. Suggested value: a value
               in the range 800 to 2000 is adequate for most problems.
               Constraint: LW >= 4.

          10:  IW(LIW) -- INTEGER array                              Output
               On exit: IW(1) contains the actual number of sub-intervals
               used. The rest of the array is used as workspace.

          11:  LIW -- INTEGER                                         Input
               On entry:
               the dimension of the array IW as declared in the
               (sub)program from which D01AJF is called.
               The number of sub-intervals into which the interval of
               integration may be divided cannot exceed LIW. Suggested
               value: LIW = LW/4. Constraint: LIW >= 1.

          12:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. Users who are
               unfamiliar with this parameter should refer to the Essential
               Introduction for details.

               On exit: IFAIL = 0 unless the routine detects an error or
               gives a warning (see Section 6).

               For this routine, because the values of output parameters
               may be useful even if IFAIL /=0 on exit, users are
               recommended to set IFAIL to -1 before entry. It is then
               essential to test the value of IFAIL on exit.

          6. Error Indicators and Warnings

          Errors or warnings specified by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               The maximum number of subdivisions allowed with the given
               workspace has been reached without the accuracy requirements
               being achieved. Look at the integrand in order to determine
               the integration difficulties. If the position of a local
               difficulty within the interval can be determined (e.g. a
               singularity of the integrand or its derivative, a peak, a
               discontinuity, etc) you will probably gain from splitting up
               the interval at this point and calling the integrator on the
               subranges. If necessary, another integrator, which is
               designed for handling the type of difficulty involved, must
               be used. Alternatively, consider relaxing the accuracy
               requirements specified by EPSABS and EPSREL, or increasing
               the amount of workspace.

          IFAIL= 2
               Round-off error prevents the requested tolerance from being
               achieved. The error may be under-estimated. Consider
               requesting less accuracy.

          IFAIL= 3
               Extremely bad local integrand behaviour causes a very strong
               subdivision around one (or more) points of the interval.

          IFAIL= 4
               The requested tolerance cannot be achieved, because the
               extrapolation does not increase the accuracy satisfactorily;
               the returned result is the best which can be obtained. The
               same advice applies as in the case of IFAIL = 1.

          IFAIL= 5
               The integral is probably divergent, or slowly convergent.
               Please note that divergence can occur with any non-zero
               value of IFAIL.

          IFAIL= 6
               On entry LW < 4,

               or       LIW < 1.

          7. Accuracy

          The routine cannot guarantee, but in practice usually achieves,
          the following accuracy:

                                  |I-RESULT|<=tol,

          where

                           tol=max{|EPSABS|,|EPSREL|*|I|},

          and EPSABS and EPSREL are user-specified absolute and relative
          error tolerance. Moreover it returns the quantity ABSERR which,
          in normal circumstances, satisfies

                              |I-RESULT|<=ABSERR<=tol.

          8. Further Comments

          The time taken by the routine depends on the integrand and the
          accuracy required.

          If IFAIL /= 0 on exit, then the user may wish to examine the
          contents of the array W, which contains the end-points of the
          sub-intervals used by D01AJF along with the integral
          contributions and error estimates over the sub-intervals.

          Specifically, for i=1,2,...,n, let r  denote the approximation to
                                              i
          the value of the integral over the sub-interval [a ,b ] in the
                                                            i  i
          partition of [a,b] and e  be the corresponding absolute error
                                  i
          estimate.

                 b
                  i                       n
                 /                        --
          Then,  | f(x)dx~=r  and RESULT= >  r , unless D01AJF terminates
                 /          i             --  i
                 a                        i=1
                  i
          while testing for divergence of the integral (see Piessens et al
          [3], Section 3.4.3). In this case, RESULT (and ABSERR) are taken
          to be the values returned from the extrapolation process. The
          value of n is returned in IW(1), and the values a , b , e  and r
                                                           i   i   i      i
          are stored consecutively in the array W, that is:

               a =W(i),
                i

               b =W(n+i),
                i

               e =W(2n+i) and
                i

               r =W(3n+i).
                i

          9. Example

          To compute
                              2(pi)
                              /         x sin(30x)
                              |     ----------------dx.
                              /         
                              0        /(  (  x  )2)
                                      / (1-(-----) )
                                    \/  (  (2(pi)) )

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd01akf}{nagd.ht}
{ Adaptive integration over a finite integral}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd01akf}{NAG Documentation: d01akf}
\beginscroll
\begin{verbatim}



     D01AKF(3NAG)      Foundation Library (12/10/92)      D01AKF(3NAG)



          D01 -- Quadrature                                          D01AKF
                  D01AKF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          D01AKF is an adaptive integrator, especially suited to
          oscillating, non-singular integrands, which calculates an
          approximation to the integral of a function f(x) over a finite
          interval [a,b]:

                                        b
                                        /
                                     I= |f(x)dx.
                                        /
                                        a

          2. Specification

                 SUBROUTINE D01AKF (F, A, B, EPSABS, EPSREL, RESULT,
                1                   ABSERR, W, LW, IW, LIW, IFAIL)
                 INTEGER          LW, IW(LIW), LIW, IFAIL
                 DOUBLE PRECISION F, A, B, EPSABS, EPSREL, RESULT, ABSERR, W
                1                 (LW)
                 EXTERNAL         F

          3. Description

          D01AKF is based upon the QUADPACK routine QAG (Piessens et al [3]
          ). It is an adaptive routine, using the Gauss 30-point and
          Kronrod 61-point rules. A 'global' acceptance criterion (as
          defined by Malcolm and Simpson [1]) is used. The local error
          estimation is described in Piessens et al [3].

          Because this routine is based on integration rules of high order,
          it is especially suitable for non-singular oscillating
          integrands.

          D01AKF requires the user to supply a function to evaluate the
          integrand at a single point.

          The routine D01AUF(*) uses an identical algorithm but requires
          the user to supply a subroutine to evaluate the integrand at an
          array of points. Therefore D01AUF(*) will be more efficient if
          the evaluation can be performed in vector mode on a vector-
          processing machine.

          D01AUF(*) also has an additional parameter KEY which allows the
          user to select from six different Gauss-Kronrod rules.

          4. References

          [1]   Malcolm M A and Simpson R B (1976) Local Versus Global
                Strategies for Adaptive Quadrature. ACM Trans. Math. Softw.
                1 129--146.

          [2]   Piessens R (1973) An Algorithm for Automatic Integration.
                Angewandte Informatik. 15 399--401.

          [3]   Piessens R, De Doncker-Kapenga E, Uberhuber C and Kahaner D
                (1983) QUADPACK, A Subroutine Package for Automatic
                Integration. Springer-Verlag.

          5. Parameters

           1:  F -- DOUBLE PRECISION FUNCTION, supplied by the user.
                                                         External Procedure
               F must return the value of the integrand f at a given point.

               Its specification is:

                      DOUBLE PRECISION FUNCTION F (X)
                      DOUBLE PRECISION X

                1:  X -- DOUBLE PRECISION                             Input
                    On entry: the point at which the integrand f must be
                    evaluated.
               F must be declared as EXTERNAL in the (sub)program from
               which D01AKF is called. Parameters denoted as Input
               must not be changed by this procedure.

           2:  A -- DOUBLE PRECISION                                  Input
               On entry: the lower limit of integration, a.

           3:  B -- DOUBLE PRECISION                                  Input
               On entry: the upper limit of integration, b. It is not
               necessary that a<b.

           4:  EPSABS -- DOUBLE PRECISION                             Input
               On entry: the absolute accuracy required. If EPSABS is
               negative, the absolute value is used. See Section 7.

           5:  EPSREL -- DOUBLE PRECISION                             Input
               On entry: the relative accuracy required. If EPSREL is
               negative, the absolute value is used. See Section 7.

           6:  RESULT -- DOUBLE PRECISION                            Output
               On exit: the approximation to the integral I.

           7:  ABSERR -- DOUBLE PRECISION                            Output
               On exit: an estimate of the modulus of the absolute error,
               which should be an upper bound |I-RESULT|.

           8:  W(LW) -- DOUBLE PRECISION array                       Output
               On exit: details of the computation, as described in
               Section 8.

           9:  LW -- INTEGER                                          Input
               On entry: the dimension of W, as declared in the (sub)
               program from which D01AKF is called. The value of LW
               (together with that of LIW below) imposes a bound on the
               number of sub-intervals into which the interval of
               integration may be divided by the routine. The number of
               sub-intervals cannot exceed LW/4. The more difficult the
               integrand, the larger LW should be. Suggested value: a value
               in the range 800 to 2000 is adequate for most problems.
               Constraint: LW >= 4. See IW below.

          10:  IW(LIW) -- INTEGER array                              Output
               On exit: IW(1) contains the actual number of sub-intervals
               used. The rest of the array is used as workspace.

          11:  LIW -- INTEGER                                         Input
               On entry:
               the dimension of the array IW as declared in the
               (sub)program from which D01AKF is called.
               The number of sub-intervals into which the interval of
               integration may be divided cannot exceed LIW. Suggested
               value: LIW = LW/4. Constraint: LIW >= 1.

          12:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. Users who are
               unfamiliar with this parameter should refer to the Essential
               Introduction for details.

               On exit: IFAIL = 0 unless the routine detects an error or
               gives a warning (see Section 6).

               For this routine, because the values of output parameters
               may be useful even if IFAIL /=0 on exit, users are
               recommended to set IFAIL to -1 before entry. It is then
               essential to test the value of IFAIL on exit.

          6. Error Indicators and Warnings

          Errors or warnings specified by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               The maximum number of subdivisions allowed with the given
               workspace has been reached without the accuracy requirements
               being achieved. Look at the integrand in order to determine
               the integration difficulties. Probably another integrator
               which is designed for handling the type of difficulty
               involved must be used. Alternatively, consider relaxing the
               accuracy requirements specified by EPSABS and EPSREL, or
               increasing the amount of workspace.

          IFAIL= 2
               Round-off error prevents the requested tolerance from being
               achieved. Consider  requesting less accuracy.

          IFAIL= 3
               Extremely bad local integrand behaviour causes a very strong
               subdivision around one (or more) points of the interval.
               The same advice applies as in the case of IFAIL = 1.

          IFAIL= 4
               On entry LW < 4,

               or       LIW < 1.

          7. Accuracy

          The routine cannot guarantee, but in practice usually achieves,
          the following accuracy:

                                  |I-RESULT|<=tol,

          where

                           tol=max{|EPSABS|,|EPSREL|*|I|},

          and EPSABS and EPSREL are user-specified absolute and relative
          error tolerances. Moreover it returns the quantity ABSERR which,
          in normal circumstances satisfies

                              |I-RESULT|<=ABSERR<=tol.

          8. Further Comments

          The time taken by the routine depends on the integrand and the
          accuracy required.

          If IFAIL /= 0 on exit, then the user may wish to examine the
          contents of the array W, which contains the end-points of the
          sub-intervals used by D01AKF along with the integral
          contributions and error estimates over these sub-intervals.

          Specifically, for i=1,2,...,n, let r  denote the approximation to
                                              i
          the value of the integral over the sub-interval [a ,b ] in the
                                                            i  i
          partition of [a,b] and e  be the corresponding absolute error
                                  i
                           b
                            i                       n
                           /                        --
          estimate. Then,  | f(x)dx~=r  and RESULT= >  r . The value of n
                           /          i             --  i
                           a                        i=1
                            i
          is returned in IW(1), and the values a , b , e  and r  are stored
                                                i   i   i      i
          consecutively in the array W, that is:

               a =W(i),
                i

               b =W(n+i),
                i

               e =W(2n+i) and
                i

               r =W(3n+i).
                i

          9. Example

          To compute

                                2(pi)
                                /
                                |    x sin(30x) cosx dx.
                                /
                                0

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd01alf}{nagd.ht}
{ Approximate integration with local singular points}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd01alf}{NAG Documentation: d01alf}
\beginscroll
\begin{verbatim}



     D01ALF(3NAG)      Foundation Library (12/10/92)      D01ALF(3NAG)



          D01 -- Quadrature                                          D01ALF
                  D01ALF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          D01ALF is a general purpose integrator which calculates an
          approximation to the integral of a function f(x) over a finite
          interval [a,b]:

                                        b
                                        /
                                     I= |f(x)dx
                                        /
                                        a

          where the integrand may have local singular behaviour at a finite
          number of points within the integration interval.

          2. Specification

                 SUBROUTINE D01ALF (F, A, B, NPTS, POINTS, EPSABS, EPSREL,
                1                   RESULT, ABSERR, W, LW, IW, LIW, IFAIL)
                 INTEGER          NPTS, LW, IW(LIW), LIW, IFAIL
                 DOUBLE PRECISION F, A, B, POINTS(*), EPSABS, EPSREL,
                1                 RESULT, ABSERR, W(LW)
                 EXTERNAL         F

          3. Description

          D01ALF is based upon the QUADPACK routine QAGP (Piessens et al
          [3]). It is very similar to D01AJF, but allows the user to supply
          difficult. It is an adaptive routine, using the Gauss 10-point
          and Kronrod 21-point rules. The algorithm described by de Doncker
          [1], incorporates a global acceptance criterion (as defined by
          Malcolm and Simpson [2]) together with the (epsilon)-algorithm
          (Wynn [4]) to perform extrapolation. The user-supplied 'break-
          points'always occur as the end-points of some sub-interval during
          the adaptive process. The local error estimation is described by
          Piessens et al [3].

          4. References

          [1]   De Doncker E (1978) An Adaptive Extrapolation Algorithm for
                Automatic Integration. Signum Newsletter. 13 (2) 12--18.

          [2]   Malcolm M A and Simpson R B (1976) Local Versus Global
                Strategies for Adaptive Quadrature. ACM Trans. Math. Softw.
                1 129--146.

          [3]   Piessens R, De Doncker-Kapenga E, Uberhuber C and Kahaner D
                (1983) QUADPACK, A Subroutine Package for Automatic
                Integration. Springer-Verlag.

          [4]   Wynn P (1956) On a Device for Computing the e (S )
                                                             m  n
                Transformation. Math. Tables Aids Comput. 10 91--96.

          5. Parameters

           1:  F -- DOUBLE PRECISION FUNCTION, supplied by the user.
                                                    External Procedure
               F must return the value of the integrand f at a given point.

               Its specification is:

                      DOUBLE PRECISION FUNCTION F (X)
                      DOUBLE PRECISION X

                1:  X -- DOUBLE PRECISION                             Input
                    On entry: the point at which the integrand f must be
                    evaluated.
               F must be declared as EXTERNAL in the (sub)program from
               which D01ALF is called. Parameters denoted as Input
               must not be changed by this procedure.

           2:  A -- DOUBLE PRECISION                                  Input
               On entry: the lower limit of integration, a.

           3:  B -- DOUBLE PRECISION                                  Input
               On entry: the upper limit of integration, b. It is not
               necessary that a<b.

           4:  NPTS -- INTEGER                                        Input
               On entry: the number of user-supplied break-points within
               the integration interval. Constraint: NPTS >= 0.

           5:  POINTS(NPTS) -- DOUBLE PRECISION array                 Input
               On entry: the user-specified break-points. Constraint: the
               break-points must all lie within the interval of integration
               (but may be supplied in any order).

           6:  EPSABS -- DOUBLE PRECISION                             Input
               On entry: the absolute accuracy required. If EPSABS is
               negative, the absolute value is used. See Section 7.

           7:  EPSREL -- DOUBLE PRECISION                             Input
               On entry: the relative accuracy required. If EPSREL is
               negative, the absolute value is used. See Section 7.

           8:  RESULT -- DOUBLE PRECISION                             Input
               On entry: the approximation to the integral I.

           9:  ABSERR -- DOUBLE PRECISION                            Output
               On exit: an estimate of the modulus of the absolute error,
               which should be an upper bound for |I-RESULT|.

          10:  W(LW) -- DOUBLE PRECISION array                       Output
               On exit: details of the computation, as described in
               Section 8.

          11:  LW -- INTEGER                                          Input
               On entry:
               the dimension of the array W as declared in the (sub)program
               from which D01ALF is called.
               The value of LW (together with that of LIW below) imposes a
               bound on the number of sub-intervals into which the interval
               of integration may be divided by the routine. The number of
               sub-intervals cannot exceed (LW-2*NPTS-4)/4. The more
               difficult the integrand, the larger LW should be. Suggested
               value: a value in the range 800 to 2000 is adequate for most
               problems. Constraint: LW>=2*NPTS+8.

          12:  IW(LIW) -- INTEGER array                              Output
               On exit: IW(1) contains the actual number of sub-intervals
               used. The rest of the array is used as workspace.

          13:  LIW -- INTEGER                                         Input
               On entry:
               the dimension of the array IW as declared in the
               (sub)program from which D01ALF is called.
               The number of sub-intervals into which the interval of
               integration may be divided cannot exceed (LIW-NPTS-2)/2.
               Suggested value: LIW = LW/2. Constraint: LIW >= NPTS + 4.

          14:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. Users who are
               unfamiliar with this parameter should refer to the Essential
               Introduction for details.

               On exit: IFAIL = 0 unless the routine detects an error or
               gives a warning (see Section 6).

               For this routine, because the values of output parameters
               may be useful even if IFAIL /=0 on exit, users are
               recommended to set IFAIL to -1 before entry. It is then
               essential to test the value of IFAIL on exit.

          6. Error Indicators and Warnings

          Errors or warnings specified by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               The maximum number of subdivisions allowed with the given
               workspace has been reached, without the accuracy
               requirements being achieved. Look at the integrand in order
               to determine the integration difficulties. If the position
               of a local difficulty within the interval can be determined
               (e.g. a singularity of the integrand or its derivative, a
               peak, a discontinuity, etc) it should be supplied to the
               routine as an element of the vector POINTS. If necessary,
               another integrator should be used, which is designed for
               handling the type of difficulty involved. Alternatively,
               consider relaxing the accuracy requirements specified by
               EPSABS and EPSREL, or increasing the amount of workspace.

          IFAIL= 2
               Round-off error prevents the requested tolerance from being
               achieved. The error may be under-estimated. Consider
               requesting less accuracy.

          IFAIL= 3
               Extremely bad local integrand behaviour causes a very strong
               subdivision around one (or more) points of the interval.
               The same advice applies as in the case of IFAIL = 1.

          IFAIL= 4
               The requested tolerance cannot be achieved, because the
               extrapolation does not increase the accuracy satisfactorily;
               the result returned is the best which can be obtained.  The
               same advice applies as in the case IFAIL = 1.

          IFAIL= 5
               The integral is probably divergent, or slowly convergent.
               Please note that divergence can also occur with any other
               non-zero value of IFAIL.

          IFAIL= 6
               The input is invalid: break-points are specified outside the
               integration range, NPTS > LIMIT or NPTS < 0. RESULT and
               ABSERR are set to zero.

          IFAIL= 7
               On entry LW<2*NPTS+8,

               or       LIW<NPTS+4.

          7. Accuracy

          The routine cannot guarantee, but in practice usually achieves,
          the following accuracy:
                                  |I-RESULT|<=tol,

          where

                           tol=max{|EPSABS|,|EPSREL|*|I|},

          and EPSABS and EPSREL are user-specified absolute and relative
          error tolerances. Moreover it returns the quantity ABSERR which,
          in normal circumstances, satisfies

                              |I-RESULT|<=ABSERR<=tol.

          8. Further Comments

          The time taken by the routine depends on the integrand and on the
          accuracy required.

          If IFAIL /= 0 on exit, then the user may wish to examine the
          contents of the array W, which contains the end-points of the
          sub-intervals used by D01ALF along with the integral
          contributions and error estimates over these sub-intervals.

          Specifically, for i=1,2,...,n, let r  denote the approximation to
                                              i
          the value of the integral over the sub-interval [a ,b ] in the
                                                            i  i
          partition of [a,b] and e  be the corresponding absolute error
                                  i
                           b
                            i                       n
                           /                        --
          estimate. Then,  | f(x)dx~=r  and RESULT= >  r  unless D01ALF
                           /          i             --  i
                           a                        i=1
                            i
          terminates while testing for divergence of the integral (see
          Piessens et al [3] Section 3.4.3). In this case, RESULT (and
          ABSERR) are taken to be the values returned from the
          extrapolation process. The value of n is returned in IW(1), and
          the values a , b , e  and r  are stored consecutively in the
                      i   i   i      i
          array W, that is:

               a =W(i),
                i

               b =W(n+i),
                i

               e =W(2n+i) and
                i

               r =W(3n+i).
                i

          9. Example

          To compute

                                    1
                                    /     1
                                    | ---------dx.
                                    /   
                                    0 \/|x-1/7|

          A break-point is specified at x=1/7, at which point the integrand
          is infinite. (For definiteness the function FST returns the value
          0.0 at this point.)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd01amf}{nagd.ht}
{ Approximate integration over a (semi-)infinite interval}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd01amf}{NAG Documentation: d01amf}
\beginscroll
\begin{verbatim}



     D01AMF(3NAG)      Foundation Library (12/10/92)      D01AMF(3NAG)



          D01 -- Quadrature                                          D01AMF
                  D01AMF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          D01AMF calculates an approximation to the integral of a function
          f(x) over an infinite or semi-infinite interval [a,b]:

                                        b
                                        /
                                     I= |f(x)dx
                                        /
                                        a

          2. Specification

                 SUBROUTINE D01AMF (F, BOUND, INF, EPSABS, EPSREL, RESULT,
                1                   ABSERR, W, LW, IW, LIW, IFAIL)
                 INTEGER          INF, LW, IW(LIW), LIW, IFAIL
                 DOUBLE PRECISION F, BOUND, EPSABS, EPSREL, RESULT, ABSERR,
                1                 W(LW)
                 EXTERNAL         F

          3. Description

          D01AMF is based on the QUADPACK routine QAGI (Piessens et al [3])
          [0,1] using one of the identities:

                            a             1
                            /             / (   1-t) 1
                            |     f(x)dx= |f(a- ---) --dt
                            /             / (    t )  2
                            -infty        0          t

                             infty        1
                             /            / (   1-t) 1
                             |    f(x)dx= |f(a+ ---) --dt
                             /            / (    t )  2
                             a            0          t

             infty         infty                1
             /             /                    /[ ( 1-t)  ( -1+t)] 1
             |     f(x)dx= |    (f(x)+f(-x))dx= |[f( ---)+f( ----)] --dt
             /             /                    /[ (  t )  (  t  )]  2
             -infty        0                    0                   t

          where a represents a finite integration limit. An adaptive
          procedure, based on the Gauss seven-point and Kronrod 15-point
          rules, is then employed on the transformed integral. The
          algorithm, described by de Doncker [1], incorporates a global
          acceptance criterion (as defined by Malcolm and Simpson [2])
          together with the (epsilon)-algorithm (Wynn [4]) to perform
          extrapolation. The local error estimation is described by
          Piessens et al [3].

          4. References

          [1]   De Doncker E (1978) An Adaptive Extrapolation Algorithm for
                Automatic Integration. Signum Newsletter. 13 (2) 12--18.

          [2]   Malcolm M A and Simpson R B (1976) Local Versus Global
                Strategies for Adaptive Quadrature. ACM Trans. Math. Softw.
                1 129--146.

          [3]   Piessens R, De Doncker-Kapenga E, Uberhuber C and Kahaner D
                (1983) QUADPACK, A Subroutine Package for Automatic
                Integration. Springer-Verlag.

          [4]   Wynn P (1956) On a Device for Computing the e (S )
                                                             m  n
                Transformation. Math. Tables Aids Comput. 10 91--96.

          5. Parameters

           1:  F -- DOUBLE PRECISION FUNCTION, supplied by the user.
                                                         External Procedure
               On entry: the point at which the integrand f must be
               evaluated.

               Its specification is:

                      DOUBLE PRECISION FUNCTION F (X)
                      DOUBLE PRECISION X

                1:  X -- DOUBLE PRECISION                             Input
                    On entry: the point at which the integrand f must be
                    evaluated.
               F must be declared as EXTERNAL in the (sub)program from
               which D01AMF is called. Parameters denoted as Input
               must not be changed by this procedure.

           2:  BOUND -- DOUBLE PRECISION                              Input
               On entry: the finite limit of the integration range (if
               present). BOUND is not used if the interval is doubly
               infinite.

           3:  INF -- INTEGER                                         Input
               On entry: indicates the kind of integration range:
                    if INF =1, the range is [BOUND, +infty)

                    if INF =-1, the range is (-infty, BOUND]

                    if INF =+2, the range is (-infty, +infty).
                Constraint: INF =-1, 1 or 2.

           4:  EPSABS -- DOUBLE PRECISION                             Input
               On entry: the absolute accuracy required. If EPSABS is
               negative, the absolute value is used. See Section 7.

           5:  EPSREL -- DOUBLE PRECISION                             Input
               On entry: the relative accuracy required. If EPSREL is
               negative, the absolute value is used. See Section 7.

           6:  RESULT -- DOUBLE PRECISION                            Output
               On exit: the approximation to the integral I.

           7:  ABSERR -- DOUBLE PRECISION                            Output
               On exit: an estimate of the modulus of the absolute error,
               which should be an upper bound for |I-RESULT|.

           8:  W(LW) -- DOUBLE PRECISION array                       Output
               On exit: details of the computation, as described in
               Section 8.

           9:  LW -- INTEGER                                          Input
               On entry:
               the dimension of the array W as declared in the (sub)program
               from which D01AMF is called.
               The value of LW (together with that of LIW below) imposes a
               bound on the number of sub-intervals into which the interval
               of integration may be divided by the routine. The number of
               sub-intervals cannot exceed LW/4. The more difficult the
               integrand, the larger LW should be. Suggested value: a value
               in the range 800 to 2000 is adequate for most problems.
               Constraint: LW >= 4.

          10:  IW(LIW) -- INTEGER array                              Output
               On exit: IW(1) contains the actual number of sub-intervals
               used. The rest of the array is used as workspace.

          11:  LIW -- INTEGER                                         Input
               On entry:
               the dimension of the array IW as declared in the
               (sub)program from which D01AMF is called.
               The number of sub-intervals into which the interval of
               integration may be divided cannot exceed LIW. Suggested
               value: LIW = LW/4. Constraint: LIW >= 1.

          12:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. Users who are
               unfamiliar with this parameter should refer to the Essential
               Introduction for details.
               On exit: IFAIL = 0 unless the routine detects an error or
               gives a warning (see Section 6).

               For this routine, because the values of output parameters
               may be useful even if IFAIL /=0 on exit, users are
               recommended to set IFAIL to -1 before entry. It is then
               essential to test the value of IFAIL on exit.

          6. Error Indicators and Warnings

          Errors or warnings specified by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               The maximum number of subdivisions allowed with the given
               workspace has been reached without the requested accuracy
               requirements being achieved. Look at the integrand in order
               to determine the integration difficulties. If the position
               of a local difficulty within the interval can be determined
               (e.g. a singularity of the integrand or its derivative, a
               peak, a discontinuity, etc) you will probably gain from
               splitting up the interval at this point and calling D01AMF
               on the infinite subrange and an appropriate integrator on
               the finite subrange. Alternatively, consider relaxing the
               accuracy requirements specified by EPSABS and EPSREL, or
               increasing the amount of workspace.

          IFAIL= 2
               Round-off error prevents the requested tolerance from being
               achieved. The error may be underestimated. Consider
               requesting less accuracy.

          IFAIL= 3
               Extremely bad local integrand behaviour causes a very strong
               subdivision around one (or more) points of the interval.
               The same advice applies as in the case of IFAIL = 1.

          IFAIL= 4
               The requested tolerance cannot be achieved, because the
               extrapolation does not increase the accuracy satisfactorily;
               the returned result is the best which can be obtained.  The
               same advice applies as in the case of IFAIL = 1.

          IFAIL= 5
               The integral is probably divergent, or slowly convergent. It
               must be noted that divergence can also occur with any other
               non-zero value of IFAIL.

          IFAIL= 6
               On entry LW < 4,

               or       LIW < 1,

               or       INF /= -1, 1 or 2.
               Please note that divergence can occur with any non-zero
               value of IFAIL.

          7. Accuracy

          The routine cannot guarantee, but in practice usually achieves,
          the following accuracy:

                                  |I-RESULT|<=tol,

          where

                           tol=max{|EPSABS|,|EPSREL|*|I|},

          and EPSABS and EPSREL are user-specified absolute and relative
          error tolerances. Moreover it returns the quantity ABSERR, which,
          in normal circumstances, satisfies

                              |I-RESULT|<=ABSERR<=tol.

          8. Further Comments

          The time taken by the routine depends on the integrand and the
          accuracy required.

          If IFAIL /= 0 on exit, then the user may wish to examine the
          contents of the array W, which contains the end-points of the
          sub-intervals used by D01AMF along with the integral
          contributions and error estimates over these sub-intervals.

          Specifically, for i=1,2,...,n, let r  denote the approximation to
                                              i
          the value of the integral over the sub-interval [a ,b ] in the
                                                            i  i
          partition of [a,b] and e  be the corresponding absolute error
                                  i
                           b
                            i                       n
                           /                        --
          estimate. Then,  | f(x)dx~=r  and RESULT= >  r  unless D01AMF
                           /          i             --  i
                           a                        i=1
                            i
          terminates while testing for divergence of the integral (see
          Piessens et al [3] Section 3.4.3). In this case, RESULT (and
          ABSERR) are taken to be the values returned from the
          extrapolation process. The value of n is returned in IW(1), and
          the values a , b , e  and r  are stored consecutively in the
                      i   i   i      i
          array W, that is:

                    a =W(i),b =W(n+i),e =W(2n+i) and r =W(3n+i).
                     i       i         i              i

          Note: that this information applies to the integral transformed
          to (0,1) as described in Section 3, not to the original integral.

          9. Example

          To compute

                                  infty
                                  /        1
                                  |     --------dx.
                                  /            
                                  0     (x+1)\/x

          The exact answer is (pi).

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd01anf}{nagd.ht}
{ Approximate sine or cosine transform over finite interval}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd01anf}{NAG Documentation: d01anf}
\beginscroll
\begin{verbatim}



     D01ANF(3NAG)      Foundation Library (12/10/92)      D01ANF(3NAG)



          D01 -- Quadrature                                          D01ANF
                  D01ANF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          D01ANF calculates an approximation to the sine or the cosine
          transform of a function g over [a,b]:

             b                                  b
             /                                  /
          I= |g(x)||,sin((omega)x)||,dx  or  I= |g(x)||,cos((omega)x)||,dx
             /                                  /
             a                                  a

          (for a user-specified value of (omega)).

          2. Specification

                 SUBROUTINE D01ANF (G, A, B, OMEGA, KEY, EPSABS, EPSREL,
                1                   RESULT, ABSERR, W, LW, IW, LIW, IFAIL)
                 INTEGER          KEY, LW, IW(LIW), LIW, IFAIL
                 DOUBLE PRECISION G, A, B, OMEGA, EPSABS, EPSREL, RESULT,
                1                 ABSERR, W(LW)
                 EXTERNAL         G

          3. Description

          D01ANF is based upon the QUADPACK routine QFOUR (Piessens et al
          [3]). It is an adaptive routine, designed to integrate a function
          of the form g(x)w(x), where w(x) is either sin((omega)x) or
          cos((omega)x). If a sub-interval has length

                                             -l
                                     L=|b-a|2

          then the integration over this sub-interval is performed by means
          of a modified Clenshaw-Curtis procedure (Piessens and Branders
          [2]) if L(omega)>4 and l<=20. In this case a Chebyshev-series
          approximation of degree 24 is used to approximate g(x), while an
          error estimate is computed from this approximation together with
          that obtained using Chebyshev-series of degree 12. If the above
          conditions do not hold then Gauss 7-point and Kronrod 15-point
          rules are used. The algorithm, described in [3], incorporates a
          global acceptance criterion (as defined in Malcolm and Simpson
          [1]) together with the (epsilon)-algorithm Wynn [4] to perform
          extrapolation. The local error estimation is described in [3].

          4. References

          [1]   Malcolm M A and Simpson R B (1976) Local Versus Global
                Strategies for Adaptive Quadrature. ACM Trans. Math. Softw.
                1 129--146.

          [2]   Piessens R and Branders M (1975) Algorithm 002. Computation
                of Oscillating Integrals. J. Comput. Appl. Math. 1 153--164.

          [3]   Piessens R, De Doncker-Kapenga E, Uberhuber C and Kahaner D
                (1983) QUADPACK, A Subroutine Package for Automatic
                Integration. Springer-Verlag.

          [4]   Wynn P (1956) On a Device for Computing the e (S )
                                                             m  n
                Transformation. Math. Tables Aids Comput. 10 91--96.

          5. Parameters

           1:  G -- DOUBLE PRECISION FUNCTION, supplied by the user.
                                                         External Procedure
               G must return the value of the function g at a given point.

               Its specification is:

                      DOUBLE PRECISION FUNCTION G (X)
                      DOUBLE PRECISION X

                1:  X -- DOUBLE PRECISION                             Input
                    On entry: the point at which the function g must be
                    evaluated.
               G must be declared as EXTERNAL in the (sub)program from
               which D01ANF is called. Parameters denoted as Input
               must not be changed by this procedure.

           2:  A -- DOUBLE PRECISION                                  Input
               On entry: the lower limit of integration, a.

           3:  B -- DOUBLE PRECISION                                  Input
               On entry: the upper limit of integration, b. It is not
               necessary that a<b.

           4:  OMEGA -- DOUBLE PRECISION                              Input
               On entry: the parameter (omega) in the weight function of
               the transform.

           5:  KEY -- INTEGER                                         Input
               On entry: indicates which integral is to be computed:
                    if KEY = 1, w(x)=cos((omega)x);

                    if KEY = 2, w(x)=sin((omega)x).
                Constraint: KEY = 1 or 2.

           6:  EPSABS -- DOUBLE PRECISION                             Input
               On entry: the absolute accuracy required. If EPSABS is
               negative, the absolute value is used. See Section 7.

           7:  EPSREL -- DOUBLE PRECISION                             Input
               On entry: the relative accuracy required. If EPSREL is
               negative, the absolute value is used. See Section 7.

           8:  RESULT -- DOUBLE PRECISION                            Output
               On exit: the approximation to the integral I.

           9:  ABSERR -- DOUBLE PRECISION                            Output
               On exit: an estimate of the modulus of the absolute error,
               which should be an upper bound for |I-RESULT|.

          10:  W(LW) -- DOUBLE PRECISION array                       Output
               On exit: details of the computation, as described in
               Section 8.

          11:  LW -- INTEGER                                          Input
               On entry:
               the dimension of the array W as declared in the (sub)program
               from which D01ANF is called.
               The value of LW (together with that of LIW below) imposes a
               bound on the number of sub-intervals into which the interval
               of integration may be divided by the routine. The number of
               sub-intervals cannot exceed LW/4. The more difficult the
               integrand, the larger LW should be. Suggested value: a value
               in the range 800 to 2000 is adequate for most problems.
               Constraint: LW >= 4.

          12:  IW(LIW) -- INTEGER array                              Output
               On exit: IW(1) contains the actual number of sub-intervals
               used. The rest of the array is used as workspace.

          13:  LIW -- INTEGER                                         Input
               On entry:
               the dimension of the array IW as declared in the
               (sub)program from which D01ANF is called.
               The number of sub-intervals into which the interval of
               integration may be divided cannot exceed LIW/2. Suggested
               value: LIW = LW/2. Constraint: LIW >= 2.

          14:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. Users who are
               unfamiliar with this parameter should refer to the Essential
               Introduction for details.

               On exit: IFAIL = 0 unless the routine detects an error or
               gives a warning (see Section 6).

               For this routine, because the values of output parameters
               may be useful even if IFAIL /=0 on exit, users are
               recommended to set IFAIL to -1 before entry. It is then
               essential to test the value of IFAIL on exit.

          6. Error Indicators and Warnings

          Errors or warnings specified by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               The maximum number of subdivisions allowed with the given
               workspace has been reached without the accuracy requested
               being achieved. Look at the integrand in order to determine
               the integration difficulties. If the position of a local
               difficulty within the interval can be determined (e.g. a
               singularity of the integrand or its derivative, a peak, a
               discontinuity, etc) you will probably gain from splitting up
               the interval at this point and calling the integrator on the
               subranges. If necessary, another integrator, which is
               designed for handling the type of difficulty involved, must
               be used. Alternatively consider relaxing the accuracy
               requirements specified by EPSABS and EPSREL, or increasing
               amount of workspace.

          IFAIL= 2
               Round-off error prevents the requested tolerance from being
               achieved. The error may be underestimated. Consider
               requesting less accuracy.

          IFAIL= 3
               Extremely bad local behaviour of g(x) causes a very strong
               subdivision around one (or more) points of the interval.
               The same advice applies as in the case of IFAIL = 1.

          IFAIL= 4
               The requested tolerance cannot be achieved because the
               extrapolation does not increase the accuracy satisfactorily;
               the returned result is the best which can be obtained.  The
               same advice applies as in the case of IFAIL = 1.

          IFAIL= 5
               The integral is probably divergent, or slowly convergent. It
               must be noted that divergence can occur with any non-zero
               value of IFAIL.

          IFAIL= 6
               On entry KEY < 1,

               or       KEY > 2.

          IFAIL= 7
               On entry LW < 4,

               or       LIW < 2.

          7. Accuracy

          The routine cannot guarantee, but in practice usually achieves,
          the following accuracy:

                                  |I-RESULT|<=tol,

          where

                           tol=max{|EPSABS|,|EPSREL|*|I|},

          and EPSABS and EPSREL are user-specified absolute and relative
          tolerances. Moreover it returns the quantity ABSERR, which, in
          normal circumstances, satisfies

                              |I-RESULT|<=ABSERR<=tol.

          8. Further Comments

          The time taken by the routine depends on the integrand and on the
          accuracy required.

          If IFAIL /= 0 on exit, then the user may wish to examine the
          contents of the array W, which contains the end-points of the
          sub-intervals used by D01ANF along with the integral
          contributions and error estimates over these sub-intervals.

          Specifically, for i=1,2,...,n, let r  denote the approximation to
                                              i
          the value of the integral over the sub-interval [a ,b ] in the
                                                            i  i
          partition of [a,b] and e  be the corresponding absolute error
                                  i
                           b
                            i                           n
                           /                            --
          estimate. Then,  | g(x)w(x)dx~=r  and RESULT= >  r  unless D01ANF
                           /              i             --  i
                           a                            i=1
                            i
          terminates while testing for divergence of the integral (see
          Piessens et al [3] Section 3.4.3). In this case, RESULT (and
          ABSERR) are taken to be the values returned from the
          extrapolation process. The value of n is returned in IW(1), and
          the values a , b , e  and r  are stored consecutively in the
                      i   i   i      i
          array W, that is:

               a =W(i),
                i

               b =W(n+i),
                i

               e =W(2n+i) and
                i

               r =W(3n+i).
                i

          9. Example

          To compute

                                 1
                                 /
                                 |ln(x)sin(10(pi)x)dx.
                                 /
                                 0

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd01apf}{nagd.ht}
{ Adaptive integration of weighted function over an interval}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd01apf}{NAG Documentation: d01apf}
\beginscroll
\begin{verbatim}



     D01APF(3NAG)      Foundation Library (12/10/92)      D01APF(3NAG)



          D01 -- Quadrature                                          D01APF
                  D01APF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          D01APF is an adaptive integrator which calculates an
          approximation to the integral of a function g(x)w(x) over a
          finite interval [a,b]:

                                      b
                                      /
                                   I= |g(x)w(x)dx
                                      /
                                      a

          where the weight function w has end-point singularities of
          algebraico-logarithmic type.

          2. Specification

                 SUBROUTINE D01APF (G, A, B, ALFA, BETA, KEY, EPSABS,
                1                   EPSREL, RESULT, ABSERR, W, LW, IW, LIW,
                2                   IFAIL)
                 INTEGER          KEY, LW, IW(LIW), LIW, IFAIL
                 DOUBLE PRECISION G, A, B, ALFA, BETA, EPSABS, EPSREL,
                1                 RESULT, ABSERR, W(LW)
                 EXTERNAL         G

          3. Description

          D01APF is based upon the QUADPACK routine QAWSE (Piessens et al
          [3]) and integrates a function of the form g(x)w(x), where the
          weight function w(x) may have algebraico-logarithmic
          singularities at the end-points a and/or b. The strategy is a
          modification of that in D01AKF. We start by bisecting the
          original interval and applying modified Clenshaw-Curtis
          integration of orders 12 and 24 to both halves. Clenshaw-Curtis
          integration is then used on all sub-intervals which have a or b
          as one of their end-points (Piessens et al [2]). On the other
          sub-intervals Gauss-Kronrod (7-15 point) integration is carried
          out.

          A 'global' acceptance criterion (as defined by Malcolm and
          Simpson [1]) is used. The local error estimation control is
          described by Piessens et al [3].

          4. References

          [1]   Malcolm M A and Simpson R B (1976) Local Versus Global
                Strategies for Adaptive Quadrature. ACM Trans. Math. Softw.
                1 129--146.

          [2]   Piessens R, Mertens I and Branders M (1974) Integration of
                Functions having End-point Singularities. Angewandte
                Informatik. 16 65--68.

          [3]   Piessens R, De Doncker-Kapenga E, Uberhuber C and Kahaner D
                (1983) QUADPACK, A Subroutine Package for Automatic
                Integration. Springer-Verlag.

          5. Parameters

           1:  G -- DOUBLE PRECISION FUNCTION, supplied by the user.
                                                        External Procedure
               G must return the value of the function g at a given point
               X.

               Its specification is:

                      DOUBLE PRECISION FUNCTION G (X)
                      DOUBLE PRECISION X

                1:  X -- DOUBLE PRECISION                             Input
                    On entry: the point at which the function g must be
                    evaluated.
               G must be declared as EXTERNAL in the (sub)program from
               which D01APF is called. Parameters denoted as Input
               must not be changed by this procedure.

           2:  A -- DOUBLE PRECISION                                  Input
               On entry: the lower limit of integration, a.

           3:  B -- DOUBLE PRECISION                                  Input
               On entry: the upper limit of integration, b. Constraint: B
               > A.

           4:  ALFA -- DOUBLE PRECISION                               Input
               On entry: the parameter (alpha) in the weight function.
               Constraint: ALFA>-1.

           5:  BETA -- DOUBLE PRECISION                               Input
               On entry: the parameter (beta) in the weight function.
               Constraint: BETA>-1.

           6:  KEY -- INTEGER                                         Input
               On entry: indicates which weight function is to be used:
                                          (alpha)     (beta)
                    if KEY = 1, w(x)=(x-a)       (b-x)

                                          (alpha)     (beta)
                    if KEY = 2, w(x)=(x-a)       (b-x)      ln(x-a)

                                          (alpha)     (beta)
                    if KEY = 3, w(x)=(x-a)       (b-x)      ln(b-x)

                                          (alpha)     (beta)
                    if KEY = 4, w(x)=(x-a)       (b-x)     ln(x-a)ln(b-x)

               Constraint: KEY = 1, 2, 3 or 4

           7:  EPSABS -- DOUBLE PRECISION                             Input
               On entry: the absolute accuracy required. If EPSABS is
               negative, the absolute value is used. See Section 7.

           8:  EPSREL -- DOUBLE PRECISION                             Input
               On entry: the relative accuracy required. If EPSREL is
               negative, the absolute value is used. See Section 7.

           9:  RESULT -- DOUBLE PRECISION                            Output
               On exit: the approximation to the integral I.

          10:  ABSERR -- DOUBLE PRECISION                            Output
               On exit: an estimate of the modulus of the absolute error,
               which should be an upper bound for |I-RESULT|.

          11:  W(LW) -- DOUBLE PRECISION array                       Output
               On exit: details of the computation, as described in
               Section 8.

          12:  LW -- INTEGER                                          Input
               On entry:
               the dimension of the array W as declared in the (sub)program
               from which D01APF is called.
               The value of LW (together with that of LIW below) imposes a
               bound on the number of sub-intervals into which the interval
               of integration may be divided by the routine. The number of
               sub-intervals cannot exceed LW/4. The more difficult the
               integrand, the larger LW should be. Suggested value: LW =
               800 to 2000 is adequate for most problems. Constraint: LW >=
               8.

          13:  IW(LIW) -- INTEGER array                              Output
               On exit: IW(1) contains the actual number of sub-intervals
               used. The rest of the array is used as workspace.

          14:  LIW -- INTEGER                                         Input
               On entry:
               the dimension of the array IW as declared in the
               (sub)program from which D01APF is called.
               The number of sub-intervals into which the interval of
               integration may be divided cannot exceed LIW. Suggested
               value: LIW = LW/4. Constraint: LIW >= 2.

          15:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. Users who are
               unfamiliar with this parameter should refer to the Essential
               Introduction for details.

               On exit: IFAIL = 0 unless the routine detects an error or
               gives a warning (see Section 6).

               For this routine, because the values of output parameters
               may be useful even if IFAIL /=0 on exit, users are
               recommended to set IFAIL to -1 before entry. It is then
               essential to test the value of IFAIL on exit.

          6. Error Indicators and Warnings

          Errors or warnings specified by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               The maximum number of subdivisions allowed with the given
               workspace has been reached without the accuracy requirements
               being achieved. Look at the integrand in order to determine
               the integration difficulties. If the position of a
               discontinuity or a singularity of algebraico-logarithmic
               type within the interval can be determined, the interval
               must be split up at this point and the integrator called on
               the subranges. If necessary, another integrator, which is
               designed for handling the difficulty involved, must be used.
               Alternatively consider relaxing the accuracy requirements
               specified by EPSABS and EPSREL, or increasing the amount of
               workspace.

          IFAIL= 2
               Round-off error prevents the requested tolerance from being
               achieved. Consider  requesting less accuracy.

          IFAIL= 3
               Extremely bad local integrand behaviour causes a very strong
               subdivision around one (or more) points of the interval.
               The same advice applies as in the case of IFAIL = 1.

          IFAIL= 4
               On entry B <= A,

               or       ALFA <= -1,

               or       BETA <= -1,

               or       KEY < 1,

               or       KEY > 4.

          IFAIL= 5
               On entry LW < 8,

               or       LIW < 2.

          7. Accuracy

          The routine cannot guarantee, but in practice usually achieves,
          the following accuracy:

                                  |I-RESULT|<=tol,

          where

                           tol=max{|EPSABS|,|EPSREL|*|I|},

          and EPSABS and EPSREL are user-specified absolute and relative
          error tolerances.

          Moreover it returns the quantity ABSERR which, in normal
          circumstances, satisfies:

                              |I-RESULT|<=ABSERR<=tol.

          8. Further Comments

          The time taken by the routine depends on the integrand and on the
          accuracy required.

          If IFAIL /= 0 on exit, then the user may wish to examine the
          contents of the array W, which contains the end-points of the
          sub-intervals used by D01APF along with the integral
          contributions and error estimates over these sub-intervals.

          Specifically, for i=1,2,...,n, let r  denote the approximation to
                                              i
          the value of the integral over the sub-interval [a ,b ] in the
                                                            i  i
          partition of [a,b] and e  be the corresponding absolute error
                                  i
                           b
                            i                           n
                           /                            --
          estimate. Then,  | f(x)w(x)dx~=r  and RESULT= >  r . The value of
                           /              i             --  i
                           a                            i=1
                            i
          n is returned in IW(1), and the values a , b , e  and r  are
                                                  i   i   i      i
          stored consecutively in the array W, that is:

               a =W(i),
                i

               b =W(n+i),
                i

               e =W(2n+i),
                i

               r =W(3n+i).
                i

          9. Example

          To compute:

                               1
                               /
                               |ln(x)cos(10(pi)x)dx  and
                               /
                               0

                                    1
                                    / sin(10x)
                                    | --------dx.
                                    /   
                                    0 \/x(1-x)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd01aqf}{nagd.ht}
{ Hilbert transform over finite interval}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd01aqf}{NAG Documentation: d01aqf}
\beginscroll
\begin{verbatim}



     D01AQF(3NAG)      Foundation Library (12/10/92)      D01AQF(3NAG)



          D01 -- Quadrature                                          D01AQF
                  D01AQF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          D01AQF calculates an approximation to the Hilbert transform of a
          function g(x) over [a,b]:

                                        b
                                        / g(x)
                                     I= | ----dx
                                        / x-c
                                        a

          for user-specified values of a, b and c.

          2. Specification

                 SUBROUTINE D01AQF (G, A, B, C, EPSABS, EPSREL, RESULT,
                1                   ABSERR, W, LW, IW, LIW, IFAIL)
                 INTEGER          LW, IW(LIW), LIW, IFAIL
                 DOUBLE PRECISION G, A, B, C, EPSABS, EPSREL, RESULT,
                1                 ABSERR, W(LW)
                 EXTERNAL         G

          3. Description

          D01AQF is based upon the QUADPACK routine QAWC (Piessens et al
          [3]) and integrates a function of the form g(x)w(x), where the
          weight function

                                             1
                                      w(x)= ---
                                            x-c

          is that of the Hilbert transform. (If a<c<b the integral has to
          be interpreted in the sense of a Cauchy principal value.) It is
          an adaptive routine which employs a 'global' acceptance criterion
          (as defined by Malcolm and Simpson [1]). Special care is taken to
          ensure that c is never the end-point of a sub-interval (Piessens
          et al[2]). On each sub-interval (c ,c ) modified Clenshaw-Curtis
                                            1  2
          integration of orders 12 and 24 is performed if c -d<=c<=c +d
                                                           1        2
          where d=(c -c )/20. Otherwise the Gauss 7-point and Kronrod 15-
                    2  1
          point rules are used. The local error estimation is described by
          Piessens et al [3].

          4. References

          [1]   Malcolm M A and Simpson R B (1976) Local Versus Global
                Strategies for Adaptive Quadrature. ACM Trans. Math. Softw.
                1 129--146.

          [2]   Piessens R, Van Roy-Branders M and Mertens I (1976) The
                Automatic Evaluation of Cauchy Principal Value Integrals.
                Angewandte Informatik. 18 31--35.

          [3]   Piessens R, De Doncker-Kapenga E, Uberhuber C and Kahaner D
                (1983) QUADPACK, A Subroutine Package for Automatic
                Integration. Springer-Verlag.

          5. Parameters

           1:  G -- DOUBLE PRECISION FUNCTION, supplied by the user.
                                                         External Procedure
               G must return the value of the function g at a given point.

               Its specification is:

                      DOUBLE PRECISION FUNCTION G (X)
                      DOUBLE PRECISION X

                1:  X -- DOUBLE PRECISION                             Input
                    On entry: the point at which the function g must be
                    evaluated.
               G must be declared as EXTERNAL in the (sub)program from
               which D01AQF is called. Parameters denoted as Input
               must not be changed by this procedure.

           2:  A -- DOUBLE PRECISION                                  Input
               On entry: the lower limit of integration, a.

           3:  B -- DOUBLE PRECISION                                  Input
               On entry: the upper limit of integration, b. It is not
               necessary that a<b.

           4:  C -- DOUBLE PRECISION                                  Input
               On entry: the parameter c in the weight function.
               Constraint: C must not equal A or B.

           5:  EPSABS -- DOUBLE PRECISION                             Input
               On entry: the absolute accuracy required. If EPSABS is
               negative, the absolute value is used. See Section 7.

           6:  EPSREL -- DOUBLE PRECISION                             Input
               On entry: the relative accuracy required. If EPSREL is
               negative, the absolute value is used. See Section 7.

           7:  RESULT -- DOUBLE PRECISION                            Output
               On exit: the approximation to the integral I.

           8:  ABSERR -- DOUBLE PRECISION                            Output
               On exit: an estimate of the modulus of the absolute error,
               which should be an upper bound for |I-RESULT|.

           9:  W(LW) -- DOUBLE PRECISION array                       Output
               On exit: details of the computation, as described in
               Section 8.

          10:  LW -- INTEGER                                          Input
               On entry:
               the dimension of the array W as declared in the (sub)program
               from which D01AQF is called.
               The value of LW (together with that of LIW below) imposes a
               bound on the number of sub-intervals into which the interval
               of integration may be divided by the routine. The number of
               sub-intervals cannot exceed LW/4. The more difficult the
               integrand, the larger LW should be. Suggested value: LW =
               800 to 2000 is adequate for most problems. Constraint: LW >=
               4.

          11:  IW(LIW) -- INTEGER array                              Output
               On exit: IW(1) contains the actual number of sub-intervals
               used. The rest of the array is used as workspace.

          12:  LIW -- INTEGER                                         Input
               On entry:
               the dimension of the array IW as declared in the
               (sub)program from which D01AQF is called.
               The number of sub-intervals into which the interval of
               integration may be divided cannot exceed LIW. Suggested
               value: LIW = LW/4. Constraint: LIW >= 1.

          13:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. Users who are
               unfamiliar with this parameter should refer to the Essential
               Introduction for details.

               On exit: IFAIL = 0 unless the routine detects an error or
               gives a warning (see Section 6).

               For this routine, because the values of output parameters
               may be useful even if IFAIL /=0 on exit, users are
               recommended to set IFAIL to -1 before entry. It is then
               essential to test the value of IFAIL on exit.

          6. Error Indicators and Warnings

          Errors or warnings specified by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               The maximum number of subdivisions allowed with the given
               workspace has been reached without the accuracy requirements
               being achieved. Look at the integrand in order to determine
               the integration difficulties. Another integrator which is
               designed for handling the type of difficulty involved, must
               be used. Alternatively consider relaxing the accuracy
               requirements specified by EPSABS and EPSREL, or increasing
               the workspace.

          IFAIL= 2
               Round-off error prevents the requested tolerance from being
               achieved. Consider  requesting less accuracy.

          IFAIL= 3
               Extremely bad local behaviour of g(x) causes a very strong
               subdivision around one (or more) points of the interval. The
               same advice applies as in the case of IFAIL = 1.

          IFAIL= 4
               On entry C = A or C = B.

          IFAIL= 5
               On entry LW < 4,

               or       LIW < 1.

          7. Accuracy

          The routine cannot guarantee, but in practice usually achieves,
          the following accuracy:

                                  |I-RESULT|<=tol,

          where

                           tol=max{|EPSABS|,|EPSREL|*|I|},

          and EPSABS and EPSREL are user-specified absolute and relative
          error tolerances. Moreover it returns the quantity ABSERR which,
          in normal circumstances satisfies:

                              |I-RESULT|<=ABSERR<=tol.

          8. Further Comments

          The time taken by the routine depends on the integrand and on the
          accuracy required.

          If IFAIL /= 0 on exit, then the user may wish to examine the
          contents of the array W, which contains the end-points of the
          sub-intervals used by D01AQF along with the integral
          contributions and error estimates over these sub-intervals.

          Specifically, for i=1,2,...,n, let r  denote the approximation to
                                              i
          the value of the integral over the sub-interval [a ,b ] in the
                                                            i  i
          partition of [a,b] and e  be the corresponding absolute error
                                  i
                           b
                            i                           n
                           /                            --
          estimate. Then,  | g(x)w(x)dx~=r  and RESULT= >  r . The value of
                           /              i             --  i
                           a                            i=1
                            i
          n is returned in IW(1), and the values a , b , e  and r  are
                                                  i   i   i      i
          stored consecutively in the array W, that is:

               a =W(i),
                i

               b =W(n+i),
                i

               e =W(2n+i) and
                i

               r =W(3n+i).
                i

          9. Example

          To compute the Cauchy principal value of

                                 1
                                 /         dx
                                 |  ----------------.
                                 /    2     2     1
                                 -1 (x +0.01 )(x- -)
                                                  2

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd01asf}{nagd.ht}
{ Approximate Sine or Cosine over [$a$,$\infty$]}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd01asf}{NAG Documentation: d01asf}
\beginscroll
\begin{verbatim}



     D01ASF(3NAG)      Foundation Library (12/10/92)      D01ASF(3NAG)



          D01 -- Quadrature                                          D01ASF
                  D01ASF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          D01ASF calculates an approximation to the sine or the cosine
          transform of a function g over [a,infty):


             infty
             /
          I= |    g(x)||,sin((omega)x)dx  or  I=
             /
             a
           infty
           /
           |    g(x)||,cos((omega)x)dx
           /
           a

          (for a user-specified value of (omega)).

          2. Specification

                 SUBROUTINE D01ASF (G, A, OMEGA, KEY, EPSABS, RESULT,
                1                   ABSERR, LIMLST, LST, ERLST, RSLST,
                2                   IERLST, W, LW, IW, LIW, IFAIL)
                 INTEGER          KEY, LIMLST, LST, IERLST(LIMLST), LW, IW
                1                 (LIW), LIW, IFAIL
                 DOUBLE PRECISION G, A, OMEGA, EPSABS, RESULT, ABSERR, ERLST
                1                 (LIMLST), RSLST(LIMLST), W(LW)
                 EXTERNAL         G

          3. Description

          D01ASF is based upon the QUADPACK routine QAWFE (Piessens et al
          [2]). It is an adaptive routine, designed to integrate a function
          of the form g(x)w(x) over a semi-infinite interval, where w(x) is
          either sin((omega)x) or cos((omega)x). Over successive intervals

                          C =[a+(k-1)c,a+kc],   k=1,2,...,LST
                           k

          integration is performed by the same algorithm as is used by
          D01ANF. The intervals C  are of constant length
                                 k

                    c={2[|(omega)|]+1}(pi)/|(omega)|,  (omega)/=0

          where [|(omega)|] represents the largest integer less than or
          equal to |(omega)|. Since c equals an odd number of half periods,
          the integral contributions over succeeding intervals will
          alternate in sign when the function g is positive and
          monotonically decreasing over [a,infty). The algorithm, described
          by [2], incorporates a global acceptance criterion (as defined by
          Malcolm and Simpson [1]) together with the (epsilon)-algorithm
          (Wynn [3]) to perform extrapolation. The local error estimation
          is described by Piessens et al [2].

          If (omega)=0 and KEY = 1, the routine uses the same algorithm as
          D01AMF (with EPSREL = 0.0).

          In contrast to the other routines in Chapter D01, D01ASF works
          only with a user-specified absolute error tolerance (EPSABS).
          Over the interval C  it attempts to satisfy the absolute accuracy
                             k
          requirement
                                   EPSA =U *EPSABS
                                       k  k
                         k-1
          where U =(1-p)p   , for k=1,2,... and p=0.9.
                 k

          However, when difficulties occur during the integration over the
          kth sub-interval C  such that the error flag IERLST(k) is non-
                            k
          zero, the accuracy requirement over subsequent intervals is
          relaxed. See Piessens et al [2] for more details.

          4. References

          [1]   Malcolm M A and Simpson R B (1976) Local Versus Global
                Strategies for Adaptive Quadrature. ACM Trans. Math. Softw.
                1 129--146.

          [2]   Piessens R, De Doncker-Kapenga E, Uberhuber C and Kahaner D
                (1983) QUADPACK, A Subroutine Package for Automatic
                Integration. Springer-Verlag.

          [3]   Wynn P (1956) On a Device for Computing the e (S )
                                                             m  n
                Transformation. Math. Tables Aids Comput. 10 91--96.

          5. Parameters

           1:  G -- DOUBLE PRECISION FUNCTION, supplied by the user.
                                                         External Procedure
               G must return the value of the function g at a given point.

               Its specification is:

                      DOUBLE PRECISION FUNCTION G (X)
                      DOUBLE PRECISION X

                1:  X -- DOUBLE PRECISION                             Input
                    On entry: the point at which the function g must be
                    evaluated.
               G must be declared as EXTERNAL in the (sub)program from
               which D01ASF is called. Parameters denoted as Input
               must not be changed by this procedure.

           2:  A -- DOUBLE PRECISION                                  Input
               On entry: the lower limit of integration, a.

           3:  OMEGA -- DOUBLE PRECISION                              Input
               On entry: the parameter (omega) in the weight function of
               the transform.

           4:  KEY -- INTEGER                                         Input
               On entry: indicates which integral is to be computed:
                    if KEY = 1, w(x)=cos((omega)x);

                    if KEY = 2, w(x)=sin((omega)x).
                Constraint: KEY = 1 or 2.

           5:  EPSABS -- DOUBLE PRECISION                             Input
               On entry: the absolute accuracy requirement. If EPSABS is
               negative, the absolute value is used. See Section 7.

           6:  RESULT -- DOUBLE PRECISION                            Output
               On exit: the approximation to the integral I.

           7:  ABSERR -- DOUBLE PRECISION                            Output
               On exit: an estimate of the modulus of the absolute error,
               which should be an upper bound for |I-RESULT|.

           8:  LIMLST -- INTEGER                                      Input
               On entry: an upper bound on the number of intervals C
                                                                     k
               needed for the integration. Suggested value: LIMLST = 50 is
               adequate for most problems. Constraint: LIMLST >= 3.

           9:  LST -- INTEGER                                        Output
               On exit: the number of intervals C  actually used for the
                                                  k
               integration.

          10:  ERLST(LIMLST) -- DOUBLE PRECISION array               Output
               On exit: ERLST(k) contains the error estimate corresponding
               to the integral contribution over the interval C , for
                                                               k
               k=1,2,...,LST.

          11:  RSLST(LIMLST) -- DOUBLE PRECISION array               Output
               On exit: RSLST(k) contains the integral contribution over
               the interval C  for k=1,2,...,LST.
                             k

          12:  IERLST(LIMLST) -- INTEGER array                       Output
               On exit: IERLST(k) contains the error flag corresponding to
               RSLST(k), for k=1,2,...,LST. See Section 6.

          13:  W(LW) -- DOUBLE PRECISION array                    Workspace

          14:  LW -- INTEGER                                          Input
               On entry:
               the dimension of the array W as declared in the (sub)program
               from which D01ASF is called.
               The value of LW (together with that of LIW below) imposes a
               bound on the number of sub-intervals into which each
               interval C  may be divided by the routine. The number of
                         k
               sub-intervals cannot exceed LW/4. The more difficult the
               integrand, the larger LW should be. Suggested value: a value
               in the range 800 to 2000 is adequate for most problems.
               Constraint: LW >= 4.

          15:  IW(LIW) -- INTEGER array                              Output
               On exit: IW(1) contains the maximum number of sub-intervals
               actually used for integrating over any of the intervals C .
                                                                        k
               The rest of the array is used as workspace.

          16:  LIW -- INTEGER                                         Input
               On entry:
               the dimension of the array IW as declared in the
               (sub)program from which D01ASF is called.
               The number of sub-intervals into which each interval C  may
                                                                     k
               be divided cannot exceed LIW/2. Suggested value: LIW = LW/2.
               Constraint: LIW >= 2.

          17:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. Users who are
               unfamiliar with this parameter should refer to the Essential
               Introduction for details.

               On exit: IFAIL = 0 unless the routine detects an error or
               gives a warning (see Section 6).

               For this routine, because the values of output parameters
               may be useful even if IFAIL /=0 on exit, users are
               recommended to set IFAIL to -1 before entry. It is then
               essential to test the value of IFAIL on exit.

          6. Error Indicators and Warnings

          Errors or warnings specified by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               The maximum number of subdivisions allowed with the given
               workspace has been reached without the accuracy requirements
               being achieved. Look at the integrand in order to determine
               the integration difficulties. If the position of a local
               difficulty within the interval can be determined (e.g. a
               singularity of the integrand or its derivative, a peak, a
               discontinuity, etc) you will probably gain from splitting up
               the interval at this point and calling D01ASF on the
               infinite subrange and an appropriate integrator on the
               finite subrange. Alternatively, consider relaxing the
               accuracy requirements specified by EPSABS or increasing the
               amount of workspace.

          IFAIL= 2
               Round-off error prevents the requested tolerance from being
               achieved. The error may be underestimated. Consider
               requesting less accuracy.

          IFAIL= 3
               Extremely bad local integrand behaviour causes a very strong
               subdivision around one (or more) points of the interval.
               The same advice applies as in the case of IFAIL = 1.

          IFAIL= 4
               The requested tolerance cannot be achieved, because the
               extrapolation does not increase the accuracy satisfactorily;
               the returned result is the best which can be obtained.  The
               same advice applies as in the case of IFAIL = 1.

          IFAIL= 5
               The integral is probably divergent, or slowly convergent.
               Please note that divergence can occur with any non-zero
               value of IFAIL.

          IFAIL= 6
               On entry KEY < 1,

               or       KEY > 2,

               or       LIMLST < 3.

          IFAIL= 7
               Bad integration behaviour occurs within one or more of the
               intervals C . Location and type of the difficulty involved
                          k
               can be determined from the vector IERLST (see below).

          IFAIL= 8
               Maximum number of intervals C  (= LIMLST) allowed has been
                                            k
               achieved. Increase the value of LIMLST to allow more cycles.

          IFAIL= 9
               The extrapolation table constructed for convergence
               acceleration of the series formed by the integral
               contribution over the intervals C , does not converge to the
                                                k
               required accuracy.

          IFAIL= 10
               On entry LW < 4,

               or       LIW < 2.

          In the cases IFAIL = 7, 8 or 9, additional information about the
          cause of the error can be obtained from the array IERLST, as
          follows:

          IERLST(k)=1
                The maximum number of subdivisions = min(LW/4,LIW/2) has
                been achieved on the kth interval.

          IERLST(k)=2
                Occurrence of round-off error is detected and prevents the
                tolerance imposed on the kth interval from being achieved.

          IERLST(k)=3
                Extremely bad integrand behaviour occurs at some points of
                the kth interval.

          IERLST(k)=4
                The integration procedure over the kth interval does not
                converge (to within the required accuracy) due to round-off
                in the extrapolation procedure invoked on this interval. It
                is assumed that the result on this interval is the best
                which can be obtained.

          IERLST(k)=5
                The integral over the kth interval is probably divergent or
                slowly convergent. It must be noted that divergence can
                occur with any other value of IERLST(k).

          7. Accuracy

          The routine cannot guarantee, but in practice usually achieves,
          the following accuracy:

                                |I-RESULT|<=|EPSABS|,

          where EPSABS is the user-specified absolute error tolerance.
          Moreover, it returns the quantity ABSERR, which, in normal
          circumstances, satisfies

                            |I-RESULT|<=ABSERR<=|EPSABS|.

          8. Further Comments

          None.

          9. Example

          To compute

                               infty
                               /      1
                               |     ---cos((pi)x/2)dx.
                               /       
                               0     \/x

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd01bbf}{nagd.ht}
{ Weights and abscissae for Gaussian quadrature formula}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd01bbf}{NAG Documentation: d01bbf}
\beginscroll
\begin{verbatim}



     D01BBF(3NAG)                 D01BBF                  D01BBF(3NAG)



     D01 -- Quadrature                                          D01BBF
             D01BBF -- NAG Foundation Library Routine Document

     Note: Before using this routine, please read the Users' Note for
     your implementation to check implementation-dependent details.
     The symbol (*) after a NAG routine name denotes a routine that is
     not included in the Foundation Library.

     Note for users via the Axiom system: the interface to this routine
     has been enhanced for use with Axiom and is slightly different to
     that offered in the standard version of the Foundation Library.

     1. Purpose

     D01BBF returns the weights and abscissae appropriate to a
     Gaussian quadrature formula with a specified number of abscissae.
     The formulae provided are Gauss-Legendre, Gauss-Rational, Gauss-
     Laguerre and Gauss-Hermite.

     2. Specification

            SUBROUTINE D01BBF (A, B, ITYPE, N, WEIGHT, ABSCIS, GTYPE,
           1                   IFAIL)
            INTEGER          ITYPE, N, GTYPE, IFAIL
            DOUBLE PRECISION A, B, WEIGHT(N), ABSCIS(N)

     3. Description

     This routine returns the weights and abscissae for use in the
     Gaussian quadrature of a function f(x). The quadrature takes the
     form

                                  n
                                  --
                               S= >  w f(x )
                                  --  i   i
                                  i=1

     where w  are the weights and x  are the abscissae (see Davis and
            i                      i
     Rabinowitz [1], Froberg [2], Ralston [3] or Stroud and Secrest
     [4]).

     Weights and abscissae are available for Gauss-Legendre, Gauss-
     Rational, Gauss-Laguerre and Gauss-Hermite quadrature, and for a
     selection of values of n (see Section 5).

     (a)   Gauss-Legendre Quadrature:
                                       b
                                       /
                                   S~= |f(x)dx
                                       /

                                       a
           where a and b are finite and it will be exact for any
           function of the form
                                       2n-1
                                       --     i
                                 f(x)= >   c x
                                       --   i
                                       i=0

     (b)   Gauss-Rational quadrature:
                infty                           a
                /                               /
            S~= |    f(x)dx  (a+b>0)   or   S~= |     f(x)dx  (a+b<0)
                /                               /
                a                               -infty
           and will be exact for any function of the form
                                          2n-1
                                          --              i
                                          >   c      (x+b)
                            2n+1   c      --   2n+1-i
                            --      i     i=0
                      f(x)= >    ------= ------------------
                            --        i           2n+1
                            i=2  (x+b)       (x+b)

     (c)   Gauss-Laguerre quadrature, adjusted weights option:
                 infty                          a
                 /                              /
             S~= |    f(x)dx  (b>0<)   or   S~= |     f(x)dx  (b<0)
                 /                              /
                 a                              -infty
           and will be exact for any function of the form
                                         2n-1
                                     -bx --     i
                               f(x)=e    >   c x
                                         --   i
                                         i=0

     (d)   Gauss-Hermite quadrature, adjusted weights option:
                                    +infty
                                    /
                                S~= |     f(x)dx
                                    /
                                    -infty
           and will be exact for any function of the form

                                      2 2n-1
                               -b(x-a)  --     i
                         f(x)=e         >   c x   (b>0)
                                        --   i
                                        i=0

     (e)   Gauss-Laguerre quadrature, normal weights option:

               infty                             a
               /     -bx                         /      -bx
           S~= |    e   f(x)dx  (b>0)   or   S~= |     e   f(x)dx
               /                                 /
               a                                 -infty


            (b<0)


           and will be exact for any function of the form
                                       2n-1
                                       --     i
                                 f(x)= >   c x
                                       --   i
                                       i=0

     (f)   Gauss-Hermite quadrature, normal weights option:

                                +infty        2
                                /      -b(x-a)
                            S~= |     e        f(x)dx
                                /
                                -infty
           and will be exact for any function of the form:
                                       2n-1
                                       --     i
                                 f(x)= >   c x
                                       --   i
                                       i=0

     Note: that the Gauss-Legendre abscissae, with a=-1, b=+1, are the
     zeros of the Legendre polynomials; the Gauss-Laguerre abscissae,
     with a=0, b=1, are the zeros of the Laguerre polynomials; and the
     Gauss-Hermite abscissae, with a=0, b=1, are the zeros of the
     Hermite polynomials.

     4. References

     [1]   Davis P J and Rabinowitz P (1967) Numerical Integration.
           Blaisdell Publishing Company. 33--52.

     [2]   Froberg C E (1965) Introduction to Numerical Analysis.
           Addison-Wesley. 181--187.

     [3]   Ralston A (1965) A First Course in Numerical Analysis.
           McGraw-Hill. 87--90.

     [4]   Stroud A H and Secrest D (1966) Gaussian Quadrature
           Formulas. Prentice-Hall.

     5. Parameters

      1:  A -- DOUBLE PRECISION                                  Input

      2:  B -- DOUBLE PRECISION                                  Input
          On entry: the quantities a and b as described in the
          appropriate subsection of Section 3.

      3:  ITYPE -- INTEGER                                       Input
          On entry: indicates the type of weights for Gauss-Laguerre
          or Gauss-Hermite quadrature (see Section 3):

          if ITYPE = 1, adjusted weights will be returned;

          if ITYPE = 0, normal weights will be returned.

          Constraint: ITYPE = 0 or 1.

          For Gauss-Legendre or Gauss-Rational quadrature, this
          parameter is not used.

      4:  N -- INTEGER                                           Input
          On entry: the number of weights and abscissae to be
          returned, n. Constraint: N =
          1,2,3,4,5,6,8,10,12,14,16,20,24,32,48 or 64.

      5:  WEIGHT(N) -- DOUBLE PRECISION array                   Output
          On exit: the N weights. For Gauss-Laguerre and Gauss-
          Hermite quadrature, these will be the adjusted weights if
          ITYPE = 1, and the normal weights if ITYPE = 0.

      6:  ABSCIS(N) -- DOUBLE PRECISION array                   Output
          On exit: the N abscissae.

      7:  GTYPE -- INTEGER                                       Input
          On entry: The value of GTYPE indicates which quadrature
          formula are to be used:
               GTYPE = 0 for Gauss-Legendre weights and abscissae;

               GTYPE = 1 for Gauss-Rational weights and abscissae;

               GTYPE = 2 for Gauss-Laguerre weights and abscissae;

               GTYPE = 3 for Gauss-Hermite weights and abscissae.

      8:  IFAIL -- INTEGER                                Input/Output
          On entry: IFAIL must be set to 0, -1 or 1. For users not
          familiar with this parameter (described in the Essential
          Introduction) the recommended value is 0.

          On exit: IFAIL = 0 unless the routine detects an error (see
          Section 6).

     6. Error Indicators and Warnings

     Errors detected by the routine:

     IFAIL= 1
          The N-point rule is not among those stored. If the soft fail
          option is used, the weights and abscissae returned will be
          those for the largest valid value of N less than the
          requested value, and the excess elements of WEIGHT and
          ABSCIS (i.e., up to the requested N) will be filled with
          zeros.

     IFAIL= 2
          The value of A and/or B is invalid.
               Gauss-Rational: A + B = 0

               Gauss-Laguerre: B = 0

               Gauss-Hermite: B <= 0
          If the soft fail option is used the weights and abscissae
          are returned as zero.

     IFAIL= 3
          Laguerre and Hermite normal weights only: underflow is
          occurring in evaluating one or more of the normal weights.
          If the soft fail option is used, the underflowing weights
          are returned as zero. A smaller value of N must be used; or
          adjusted weights should be used (ITYPE = 1). In the latter
          case, take care that underflow does not occur when
          evaluating the integrand appropriate for adjusted weights.

     IFAIL=4
         GTYPE < 0 or GTYPE > 3

     7. Accuracy

     The weights and abscissae are stored for standard values of A and
     B to full machine accuracy.

     8. Further Comments

     Timing is negligible.

     9. Example

     This example program returns the abscissae and (adjusted) weights
     for the six-point Gauss-Laguerre formula.

     The example program is not reproduced here. The source code for
     all example programs is distributed with the NAG Foundation
     Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd01fcf}{nagd.ht}
{ Multidimensional integrals with finite limits}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd01fcf}{NAG Documentation: d01fcf}
\beginscroll
\begin{verbatim}



     D01FCF(3NAG)      Foundation Library (12/10/92)      D01FCF(3NAG)



          D01 -- Quadrature                                          D01FCF
                  D01FCF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          D01FCF attempts to evaluate a multi-dimensional integral (up to
          15 dimensions), with constant and finite limits, to a specified
          relative accuracy, using an adaptive subdivision strategy.

          2. Specification

                 SUBROUTINE D01FCF (NDIM, A, B, MINPTS, MAXPTS, FUNCTN,
                1                   EPS, ACC, LENWRK, WRKSTR, FINVAL, IFAIL)
                 INTEGER          NDIM, MINPTS, MAXPTS, LENWRK, IFAIL
                 DOUBLE PRECISION A(NDIM), B(NDIM), FUNCTN, EPS, ACC, WRKSTR
                1                 (LENWRK), FINVAL
                 EXTERNAL         FUNCTN

          3. Description

          The routine returns an estimate of a multi-dimensional integral
          over a hyper-rectangle (i.e., with constant limits), and also an
          estimate of the relative error. The user sets the relative
          accuracy required, supplies the integrand as a function
          subprogram (FUNCTN), and also sets the minimum and maximum
          acceptable number of calls to FUNCTN (in MINPTS and MAXPTS).

          The routine operates by repeated subdivision of the hyper-
          rectangular region into smaller hyper-rectangles. In each
          subregion, the integral is estimated using a seventh-degree rule,
          and an error estimate is obtained by comparison with a fifth-
          degree rule which uses a subset of the same points. The fourth
          differences of the integrand along each co-ordinate axis are
          evaluated, and the subregion is marked for possible future
          subdivision in half along that co-ordinate axis which has the
          largest absolute fourth difference.

          If the estimated errors, totalled over the subregions, exceed the
          requested relative error (or if fewer than MINPTS calls to FUNCTN
          have been made), further subdivision is necessary, and is
          performed on the subregion with the largest estimated error, that
          subregion being halved along the appropriate co-ordinate axis.

          The routine will fail if the requested relative error level has
          not been attained by the time MAXPTS calls to FUNCTN have been
          made; or, if the amount LENWRK of working storage is
          insufficient. A formula for the recommended value of LENWRK is
          given in Section 5. If a smaller value is used, and is exhausted
          in the course of execution, the routine switches to a less
          efficient mode of operation; only if this mode also breaks down
          is insufficient storage reported.

          D01FCF is based on the HALF subroutine developed by van Dooren
          and de Ridder [1]. It uses a different basic rule, described by
          Genz and Malik [2].

          4. References

          [1]   Van Dooren P and De Ridder L (1976) An Adaptive Algorithm
                for Numerical Integration over an N-dimensional Cube. J.
                Comput. Appl. Math. 2 207--217.

          [2]   Genz A C and Malik A A (1980) An Adaptive Algorithm for
                Numerical Integration over an N-dimensional Rectangular
                Region. J. Comput. Appl. Math. 6 295--302.

          5. Parameters

           1:  NDIM -- INTEGER                                        Input
               On entry: the number of dimensions of the integral, n.
               Constraint: 2 <= NDIM <= 15.

           2:  A(NDIM) -- DOUBLE PRECISION array                      Input
               On entry: the lower limits of integration, a , for
                                                            i
               i=1,2,...,n.

           3:  B(NDIM) -- DOUBLE PRECISION array                      Input
               On entry: the upper limits of integration, b , for
                                                            i
               i=1,2,...,n.

           4:  MINPTS -- INTEGER                               Input/Output
               On entry: MINPTS must be set to the minimum number of
               integrand evaluations to be allowed. On exit: MINPTS
               contains the actual number of integrand evaluations used by
               D01FCF.

           5:  MAXPTS -- INTEGER                                      Input
               On entry: the maximum number of integrand evaluations to be
               allowed.
               Constraints:
                        MAXPTS >= MINPTS

                        MAXPTS >= (alpha),

                                       NDIM       2
                        where (alpha)=2    +2*NDIM +2*NDIM+1.

           6:  FUNCTN -- DOUBLE PRECISION FUNCTION, supplied by the
          user.
                                                         External Procedure
               FUNCTN must return the value of the integrand f at a given
               point.

               Its specification is:

                      DOUBLE PRECISION FUNCTION FUNCTN (NDIM,Z)
                      INTEGER          NDIM
                      DOUBLE PRECISION Z(NDIM)

                1:  NDIM -- INTEGER                                   Input
                    On entry: the number of dimensions of the integral, n.

                2:  Z(NDIM) -- DOUBLE PRECISION array                 Input
                    On entry: the co-ordinates of the point at which the
                    integrand must be evaluated.
               FUNCTN must be declared as EXTERNAL in the (sub)program
               from which D01FCF is called. Parameters denoted as
               Input must not be changed by this procedure.

           7:  EPS -- DOUBLE PRECISION                                Input
               On entry: the relative error acceptable to the user. When
               the solution is zero or very small relative accuracy may not
               be achievable but the user may still set EPS to a reasonable
               value and check for the error exit IFAIL = 2. Constraint:
               EPS > 0.0.

           8:  ACC -- DOUBLE PRECISION                               Output
               On exit: the estimated relative error in FINVAL.

           9:  LENWRK -- INTEGER                                      Input
               On entry:
               the dimension of the array WRKSTR as declared in the
               (sub)program from which D01FCF is called.
               Suggested value: for maximum efficiency, LENWRK >=
               (NDIM+2)*(1+MAXPTS/(alpha)) (see parameter MAXPTS for
               (alpha)).

               If LENWRK is less than this, the routine will usually run
               less efficiently and may fail. Constraint: LENWRK>=2*NDIM+4.

          10:  WRKSTR(LENWRK) -- DOUBLE PRECISION array           Workspace

          11:  FINVAL -- DOUBLE PRECISION                            Output
               On exit: the best estimate obtained for the integral.

          12:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. Users who are
               unfamiliar with this parameter should refer to the Essential
               Introduction for details.
               On exit: IFAIL = 0 unless the routine detects an error or
               gives a warning (see Section 6).

               For this routine, because the values of output parameters
               may be useful even if IFAIL /=0 on exit, users are
               recommended to set IFAIL to -1 before entry. It is then
               essential to test the value of IFAIL on exit. To suppress
               the output of an error message when soft failure occurs, set
               IFAIL to 1.

          6. Error Indicators and Warnings

          Errors or warnings specified by the routine:

          IFAIL= 1
               On entry NDIM < 2,

               or       NDIM > 15,

               or       MAXPTS is too small,

               or       LENWRK<2*NDIM+4,

               or       EPS <= 0.0.

          IFAIL= 2
               MAXPTS was too small to obtain the required relative
               accuracy EPS. On soft failure, FINVAL and ACC contain
               estimates of the integral and the relative error, but ACC
               will be greater than EPS.

          IFAIL= 3
               LENWRK was too small. On soft failure, FINVAL and ACC
               contain estimates of the integral and the relative error,
               but ACC will be greater than EPS.

          7. Accuracy

          A relative error estimate is output through the parameter ACC.

          8. Further Comments

          Execution time will usually be dominated by the time taken to
          evaluate the integrand FUNCTN, and hence the maximum time that
          could be taken will be proportional to MAXPTS.

          9. Example

          This example program estimates the integral

                                  2
                  1  1  1  1  4z z exp(2z z )
                  /  /  /  /    1 3      1 3
                  |  |  |  |  ---------------dz dz dz dz =0.575364.
                  /  /  /  /             2     4  3  2  1
                  0  0  0  0    (1+z +z )
                                    2  4

          The accuracy requested is one part in 10,000.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd01gaf}{nagd.ht}
{ Third-order finite-difference integration}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd01gaf}{NAG Documentation: d01gaf}
\beginscroll
\begin{verbatim}



     D01GAF(3NAG)      Foundation Library (12/10/92)      D01GAF(3NAG)



          D01 -- Quadrature                                          D01GAF
                  D01GAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          D01GAF integrates a function which is specified numerically at
          four or more points, over the whole of its specified range, using
          third-order finite-difference formulae with error estimates,
          according to a method due to Gill and Miller.

          2. Specification

                 SUBROUTINE D01GAF (X, Y, N, ANS, ER, IFAIL)
                 INTEGER          N, IFAIL
                 DOUBLE PRECISION X(N), Y(N), ANS, ER

          3. Description

          This routine evaluates the definite integral

                                       x
                                        n
                                       /
                                    I= | y(x)dx,
                                       /
                                       x
                                        1

          where the function y is specified at the n-points x ,x ,...,x ,
                                                             1  2      n
          which should be all distinct, and in either ascending or
          descending order. The integral between successive points is
          calculated by a four-point finite-difference formula centred on
          the interval concerned, except in the case of the first and last
          intervals, where four-point forward and backward difference
          formulae respectively are employed. If n is less than 4, the
          routine fails. An approximation to the truncation error is
          integrated and added to the result. It is also returned
          separately to give an estimate of the uncertainty in the result.
          The method is due to Gill and Miller.

          4. References

          [1]   Gill P E and Miller G F (1972) An Algorithm for the
                Integration of Unequally Spaced Data. Comput. J. 15 80--83.

          5. Parameters

           1:  X(N) -- DOUBLE PRECISION array                         Input
               On entry: the values of the independent variable, i.e., the
               x ,x ,...,x . Constraint: either X(1) < X(2) <... < X(N) or
                1  2      n
               X(1) > X(2) >... > X(N).

           2:  Y(N) -- DOUBLE PRECISION array                         Input
               On entry: the values of the dependent variable y  at the
                                                                i
               points x , for i=1,2,...,n.
                       i

           3:  N -- INTEGER                                           Input
               On entry: the number of points, n. Constraint: N >= 4.

           4:  ANS -- DOUBLE PRECISION                               Output
               On exit: the estimate of the integral.

           5:  ER -- DOUBLE PRECISION                                Output
               On exit: an estimate of the uncertainty in ANS.

           6:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               Indicates that fewer than four-points have been supplied to
               the routine.

          IFAIL= 2
               Values of X are neither strictly increasing nor strictly
               decreasing.

          IFAIL= 3
               Two points have the same X-value.

          No error is reported arising from the relative magnitudes of ANS
          and ER on return, due to the difficulty when the true answer is
          zero.

          7. Accuracy

          No accuracy level is specified by the user before calling the
          routine but on return ABS(ER) is an approximation to, but not
          necessarily a bound for, |I-ANS|. If on exit IFAIL > 0, both ANS
          and ER are returned as zero.

          8. Further Comments

          The time taken by the routine depends on the number of points
          supplied, n.

          In their paper, Gill and Miller [1] do not add the quantity ER to
          ANS before return. However, extensive tests have shown that a
          dramatic reduction in the error often results from such addition.
          In other cases, it does not make an improvement, but these tend
          to be cases of low accuracy in which the modified answer is not
          significantly inferior to the unmodified one. The user has the
          option of recovering the Gill-Miller answer by subtracting ER
          from ANS on return from the routine.

          9. Example

          The example program evaluates the integral

                                    1
                                    /  4
                                    | ----dx=(pi)
                                    /    2
                                    0 1+x

          reading in the function values at 21 unequally-spaced points.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd01gbf}{nagd.ht}
{ Monte Carlo integration over hyper-rectangular regions}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd01gbf}{NAG Documentation: d01gbf}
\beginscroll
\begin{verbatim}



     D01GBF(3NAG)      Foundation Library (12/10/92)      D01GBF(3NAG)



          D01 -- Quadrature                                          D01GBF
                  D01GBF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          D01GBF returns an approximation to the integral of a function
          over a hyper-rectangular region, using a Monte Carlo method. An
          approximate relative error estimate is also returned. This
          routine is suitable for low accuracy work.

          2. Specification

                 SUBROUTINE D01GBF (NDIM, A, B, MINCLS, MAXCLS, FUNCTN,
                1                   EPS, ACC, LENWRK, WRKSTR, FINEST, IFAIL)
                 INTEGER          NDIM, MINCLS, MAXCLS, LENWRK, IFAIL
                 DOUBLE PRECISION A(NDIM), B(NDIM), FUNCTN, EPS, ACC, WRKSTR
                1                 (LENWRK), FINEST
                 EXTERNAL         FUNCTN

          3. Description

          D01GBF uses an adaptive Monte Carlo method based on the algorithm
          described by Lautrup [1]. It is implemented for integrals of the
          form:

                       b  b     b
                        1  2     n
                       /  /     /
                       |  | ... | f(x ,x ,...,x )dx ...dx dx .
                       /  /     /    1  2      n   n     2  1
                       a  a     a
                        1  2     n

          Upon entry, unless LENWRK has been set to the minimum value
          10*NDIM, the routine subdivides the integration region into a
          number of equal volume subregions. Inside each subregion the
          integral and the variance are estimated by means of pseudo-random
          sampling. All contributions are added together to produce an
          estimate for the whole integral and total variance. The variance
          along each co-ordinate axis is determined and the routine uses
          this information to increase the density and change the widths of
          the sub-intervals along each axis, so as to reduce the total
          variance. The total number of subregions is then increased by a
          factor of two and the program recycles for another iteration. The
          program stops when a desired accuracy has been reached or too
          many integral evaluations are needed for the next cycle.

          4. References

          [1]   Lautrup B (1971) An Adaptive Multi-dimensional Integration
                Procedure. Proc. 2nd Coll. on Advanced Methods in
                Theoretical Physics, Marseille.

          5. Parameters

           1:  NDIM -- INTEGER                                        Input
               On entry: the number of dimensions of the integral, n.
               Constraint: NDIM >= 1.

           2:  A(NDIM) -- DOUBLE PRECISION array                      Input
               On entry: the lower limits of integration, a , for
                                                           i
               i=1,2,...,n.

           3:  B(NDIM) -- DOUBLE PRECISION array                      Input
               On entry: the upper limits of integration, b , for
                                                           i
               i=1,2,...,n.

           4:  MINCLS -- INTEGER                               Input/Output
               On entry: MINCLS must be set:

               either to the minimum number of integrand evaluations to be
               allowed, in which case MINCLS >= 0;

               or to a negative value. In this case the routine assumes
               that a previous call had been made with the same parameters
               NDIM, A and B and with either the same integrand (in which
               case D01GBF continues calculation) or a similar integrand
               (in which case D01GBF begins the calculation with the
               subdivision used in the last iteration of the previous call)
               . See also WRKSTR. On exit: MINCLS contains the number of
               integrand evaluations actually used by D01GBF.

           5:  MAXCLS -- INTEGER                                      Input
               On entry: the maximum number of integrand evaluations to be
               allowed. In the continuation case this is the number of new
               integrand evaluations to be allowed. These counts do not
               include zero integrand values.
               Constraints:
                        MAXCLS > MINCLS,

                        MAXCLS >= 4*(NDIM+1).

           6:  FUNCTN -- DOUBLE PRECISION FUNCTION, supplied by the user.
                                                         External Procedure
               FUNCTN must return the value of the integrand f at a given
               point.

               Its specification is:

                      DOUBLE PRECISION FUNCTION FUNCTN (NDIM, X)
                      INTEGER          NDIM
                      DOUBLE PRECISION X(NDIM)

                1:  NDIM -- INTEGER                                   Input
                    On entry: the number of dimensions of the integral, n.

                2:  X(NDIM) -- DOUBLE PRECISION array                 Input
                    On entry: the co-ordinates of the point at which the
                    integrand must be evaluated.
               FUNCTN must be declared as EXTERNAL in the (sub)program
               from which D01GBF is called. Parameters denoted as
               Input must not be changed by this procedure.

           7:  EPS -- DOUBLE PRECISION                                Input
               On entry: the relative accuracy required. Constraint: EPS
               >= 0.0.

           8:  ACC -- DOUBLE PRECISION                               Output
               On exit: the estimated relative accuracy of FINEST.

           9:  LENWRK -- INTEGER                                      Input
               On entry:
               the dimension of the array WRKSTR as declared in the
               (sub)program from which D01GBF is called.
               For maximum efficiency, LENWRK should be about
                                              1/NDIM
                             3*NDIM*(MAXCLS/4)      +7*NDIM.
               If LENWRK is given the value 10*NDIM then the subroutine
               uses only one iteration of a crude Monte Carlo method with
               MAXCLS sample points. Constraint: LENWRK >= 10*NDIM.

          10:  WRKSTR(LENWRK) -- DOUBLE PRECISION array        Input/Output
               On entry: if MINCLS<0, WRKSTR must be unchanged from the
               previous call of D01GBF - except that for a new integrand
               WRKSTR(LENWRK) must be set to 0.0. See also MINCLS. On
               exit: WRKSTR contains information about the current sub-
               interval structure which could be used in later calls of
               D01GBF. In particular, WRKSTR(j) gives the number of sub-
               intervals used along the jth co-ordinate axis.

          11:  FINEST -- DOUBLE PRECISION                            Output
               On exit: the best estimate obtained for the integral.

          12:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. Users who are
               unfamiliar with this parameter should refer to the Essential
               Introduction for details.

               On exit: IFAIL = 0 unless the routine detects an error or
               gives a warning (see Section 6).

               For this routine, because the values of output parameters
               may be useful even if IFAIL /=0 on exit, users are
               recommended to set IFAIL to -1 before entry. It is then
               essential to test the value of IFAIL on exit. To suppress
               the output of an error message when soft failure occurs, set
               IFAIL to 1.

          6. Error Indicators and Warnings

          Errors or warnings specified by the routine:

          IFAIL= 1
               On entry NDIM < 1,

               or       MINCLS >= MAXCLS,

               or       LENWRK < 10*NDIM,

               or       MAXCLS < 4*(NDIM+1),

               or       EPS < 0.0.

          IFAIL= 2
               MAXCLS was too small for D01GBF to obtain the required
               relative accuracy EPS. In this case D01GBF returns a value
               of FINEST with estimated relative error ACC, but ACC will be
               greater than EPS. This error exit may be taken before MAXCLS
               non-zero integrand evaluations have actually occurred, if
               the routine calculates that the current estimates could not
               be improved before MAXCLS was exceeded.

          7. Accuracy

          A relative error estimate is output through the parameter ACC.
          The confidence factor is set so that the actual error should be
          less than ACC 90% of the time. If a user desires a higher
          confidence level then a smaller value of EPS should be used.

          8. Further Comments

          The running time for D01GBF will usually be dominated by the time
          used to evaluate the integrand FUNCTN, so the maximum time that
          could be used is approximately proportional to MAXCLS.

          For some integrands, particularly those that are poorly behaved
          in a small part of the integration region, D01GBF may terminate
          with a value of ACC which is significantly smaller than the
          actual relative error. This should be suspected if the returned
          value of MINCLS is small relative to the expected difficulty of
          the integral. Where this occurs, D01GBF should be called again,
          but with a higher entry value of MINCLS (e.g. twice the returned
          value) and the results compared with those from the previous
          call.

          The exact values of FINEST and ACC on return will depend (within
          statistical limits) on the sequence of random numbers generated
          within D01GBF by calls to G05CAF. Separate runs will produce
          identical answers unless the part of the program executed prior
          to calling D01GBF also calls (directly or indirectly) routines
          from Chapter G05, and the series of such calls differs between
          runs. If desired, the user may ensure the identity or difference
          between runs of the results returned by D01GBF, by calling G05CBF
          or G05CCF respectively, immediately before calling D01GBF.

          9. Example

          This example program calculates the integral

                  1  1  1  1  4x x exp(2x x )
                  /  /  /  /    1 3      1 3
                  |  |  |  |  ---------------dx dx dx dx =0.575364.
                  /  /  /  /             2     1  2  3  4
                  0  0  0  0    (1+x +x )
                                    2  4

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd02}{nagd.ht}
{ Ordinary Differential Equations}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd02}{NAG Documentation: d02}
\beginscroll
\begin{verbatim}



     D02(3NAG)         Foundation Library (12/10/92)         D02(3NAG)



          D02 -- Ordinary Differential Equations        Introduction -- D02
                                    Chapter D02
                          Ordinary Differential Equations

          1. Scope of the Chapter

          This chapter is concerned with the numerical solution of ordinary
          differential equations. There are two main types of problem,
          those in which all boundary conditions are specified at one point
          (initial-value problems), and those in which the boundary
          conditions are distributed between two or more points (boundary-
          value problems and eigenvalue problems). Routines are available
          for initial-value problems, two-point boundary-value problems and
          Sturm-Liouville eigenvalue problems.

          2. Background to the Problems

          For most of the routines in this chapter a system of ordinary
          differential equations must be written in the form

                              y'  = f (x,y ,y ,...,y ),
                                1    1    1  2      n

                              y'  = f (x,y ,y ,...,y ),
                                2    2    1  2      n

                                .. ...

                              y'  = f (x,y ,y ,...y ),
                                n    n    1  2     n

          that is the system must be given in first-order form. The n
          dependent variables (also, the solution) y ,y ,...,y  are
                                                    1  2      n
          functions of the independent variable x, and the differential
          equations give expressions for the first derivatives y' =dy /dx
                                                                 i   i
          in terms of x and y ,y ,...,y . For a system of n first-order
                             1  2      n
          equations, n associated boundary conditions are usually required
          to define the solution.

          A more general system may contain derivatives of higher order,
          but such systems can almost always be reduced to the first-order
          form by introducing new variables. For example, suppose we have
          the third-order equation


                                                2
                                z'''+zz''+k(l-z' )=0.

          We write y =z, y =z', y =z'', and the third order equation may
                    1     2      3
          then be written as the system of first-order equations

                                y'  = y
                                  1    2

                                y'  = y
                                  2    3
                                                 2
                                y'  = -y y -k(l-y ).
                                  3     1 3      2

          For this system n = 3 and we require 3 boundary conditions in
          order to define the solution. These conditions must specify
          values of the dependent variables at certain points. For example,
          we have an initial-value problem if the conditions are:

              y   =  0        at x=0
               1

              y   =  0        at x=0
               2

              y   =  0.1      at x=0.
               3

          These conditions would enable us to integrate the equations
          numerically from the point x=0 to some specified end-point. We
          have a boundary-value problem if the conditions are:

              y   =  0        at x=0
               1

              y   =  0        at x=0
               2

              y   =  1        at x=10.
               2

          These conditions would be sufficient to define a solution in the
          range 0<=x<=10, but the problem could not be solved by direct
          integration (see Section 2.2 ). More general boundary conditions
          are permitted in the boundary-value case.

          2.1. Initial-value Problems

          To solve first-order systems, initial values of the dependent
          variables y , for i=1,2,...,n must be supplied at a given point,
                     i
          a. Also a point, b, at which the values of the dependent
          variables are required, must be specified. The numerical solution
          is then obtained by a step-by-step calculation which approximates
          values of the variables y , for i=1,2,...,n at finite intervals
                                   i
          over the required range [a,b]. The routines in this chapter
          adjust the step length automatically to meet specified accuracy
          tolerances. Although the accuracy tests used are reliable over
          each step individually, in general an accuracy requirement cannot
          be guaranteed over a long range. For many problems there may be
          no serious accumulation of error, but for unstable systems small
          perturbations of the solution will often lead to rapid divergence
          of the calculated values from the true values. A simple check for
          stability is to carry out trial calculations with different
          tolerances; if the results differ appreciably the system is
          probably unstable. Over a short range, the difficulty may
          possibly be overcome by taking sufficiently small tolerances, but
          over a long range it may be better to try to reformulate the
          problem.

          A special class of initial-value problems are those for which the
          solutions contain rapidly decaying transient terms. Such problems
          are called stiff; an alternative way of describing them is to say
          that certain eigenvalues of the Jacobian matrix (ddf /ddy ) have
                                                              i    j
          large negative real parts when compared to others. These problems
          require special methods for efficient numerical solution; the
          methods designed for non-stiff problems when applied to stiff
          problems tend to be very slow, because they need small step
          lengths to avoid numerical instability. A full discussion is
          given in Hall and Watt [6] and a discussion of the methods for
          stiff problems is given in Berzins, Brankin and Gladwell [1].

          2.2. Boundary-value Problems

          A full discussion of the design of the methods and codes for
          boundary-value problems is given in Gladwell [4]. In general, a
          system of nonlinear differential equations with boundary
          conditions given at two or more points cannot be guaranteed to
          have a solution. The solution has to be determined iteratively
          (if it exists). Finite-difference equations are set up on a mesh
          of points and estimated values for the solution at the grid
          points are chosen. Using these estimated values as starting
          values a Newton iteration is used to solve the finite-difference
          equations. The accuracy of the solution is then improved by
          deferred corrections or the addition of points to the mesh or a
          combination of both. Good initial estimates of the solution may
          be required in some cases but results may be difficult to compute
          when the solution varies very rapidly over short ranges. A
          discussion is given in Chapters 9 and 11 of Gladwell and Sayers
          [5] and Chapter 4 of Childs et al [2].

          2.3. Eigenvalue Problems

          Sturm-Liouville problems of the form

                             (p(x)y')'+q(x,(lambda))y=0

          with appropriate boundary conditions given at two points, can be
          solved by a Scaled Pruefer method. In this method the
          differential equation is transformed to another which can be
          solved for a specified eigenvalue by a shooting method. A
          discussion is given in Chapter 11 of Gladwell and Sayers [5] and
          a complete description is given in Pryce [7].

          2.6. References

          [1]   Berzins M, Brankin R W and Gladwell I (1987) Design of the
                Stiff Integrators in the NAG Library. Technical Report.
                TR14/87 NAG.

          [2]   (1979) Codes for Boundary-value Problems in Ordinary
                Differential Equations. Lecture Notes in Computer Science.
                (ed Childs B, Scott M, Daniel J W, Denman E and Nelson P) 76
                 Springer-Verlag.

          [3]   Gladwell I (1979) Initial Value Routines in the NAG Library.
                ACM Trans Math Softw. 5 386--400.

          [4]   Gladwell I (1987) The NAG Library Boundary Value Codes.
                Numerical Analysis Report. 134 Manchester University.

          [5]   (1980) Computational Techniques for Ordinary Differential
                Equations. (Gladwell I and Sayers D K) Academic Press.

          [6]   Hall G and Watt J M (eds) (1976) Modern Numerical Methods
                for Ordinary Differential Equations. Clarendon Press.

          [7]   Pryce J D (1986) Error Estimation for Phase-function
                Shooting Methods for Sturm-Liouville Problems. J. Num. Anal.
                6 103--123.

          3. Recommendations on Choice and Use of Routines

          There are no routines which deal directly with COMPLEX equations.
          These may however be transformed to larger systems of real
          equations of the required form. Split each equation into its real
          and imaginary parts and solve for the real and imaginary parts of
          each component of the solution. Whilst this process doubles the
          size of the system and may not always be appropriate it does make
          available for use the full range of routines provided presently.

          3.1. Initial-value Problems

          For simple first-order problems with low accuracy requirements,
          that is problems on a short range of integration, with derivative
          functions f  which are inexpensive to calculate and where only a
                     i
          few correct figures are required, the best routines to use are
          likely to be the Runge-Kutta-Merson (RK) routines, D02BBF and
          D02BHF. For larger problems, over long ranges or with high
          accuracy requirements the variable-order, variable-step Adams
          routine D02CJF should usually be preferred. For stiff equations,
          that is those with rapidly decaying transient solutions, the
          Backward Differentiation Formula (BDF) variable-order, variable-
          step routine D02EJF should be used.

          There are four routines for initial-value problems, two of which
          use the Runge-Kutta-Merson method:

          D02BBF     integrates a system of first order ordinary
                     differential equations over a range with intermediate
                     output and a choice of error control

          D02BHF     integrates a system of first order ordinary
                     differential equations with a choice of error control
                     until a position is determined where a function of the
                     solution is zero.

          one uses an Adams method:

          D02CJF     combines the functionality of D02BBF and D02BHF

          and one uses a BDF method:

          D02EJF     combines the functionality of D02BBF and D02BHF.

          3.2. Boundary-value Problems

          D02GAF may be used for simple boundary-value problems with
          assigned boundary values. The user may find that convergence is
          difficult to achieve using D02GAF since only specifying the
          unknown boundary values and the position of the finite-difference
          mesh is permitted. In such cases the user may use D02RAF which
          permits specification of an initial estimate for the solution at
          all mesh points and allows the calculation to be influenced in
          other ways too. D02RAF is designed to solve a general nonlinear
          two-point boundary value problem with nonlinear boundary
          conditions.

          A routine, D02GBF, is also supplied specifically for the general
          linear two-point boundary-value problem written in a standard

          The user is advised to use interpolation routines from the E01
          Chapter to obtain solution values at points not on the final
          mesh.

          3.3. Eigenvalue Problems

          There is one general purpose routine for eigenvalue problems,
          D02KEF. It may be used to solve regular or singular second-order
          Sturm-Liouville problems on a finite or infinite range.
          Discontinous coefficient functions can be treated and
          eigenfunctions can be computed.


          D02 -- Ordinary Differential Equations            Contents -- D02
          Chapter D02

          Ordinary Differential Equations

          D02BBF  ODEs, IVP, Runge-Kutta-Merson method, over a range,
                  intermediate output

          D02BHF  ODEs, IVP, Runge-Kutta-Merson method, until function of
                  solution is zero

          D02CJF  ODEs, IVP, Adams method, until function of solution is
                  zero, intermediate output

          D02EJF  ODEs, stiff IVP, BDF method, until function of solution
                  is zero, intermediate output

          D02GAF  ODEs, boundary value problem, finite difference technique
                  with deferred correction, simple nonlinear problem

          D02GBF  ODEs, boundary value problem, finite difference technique
                  with deferred correction, general linear problem

          D02KEF  2nd order Sturm-Liouville problem, regular/singular
                  system, finite/infinite range, eigenvalue and
                  eigenfunction, user-specified break-points

          D02RAF  ODEs, general nonlinear boundary value problem, finite
                  difference technique with deferred correction,
                  continuation facility

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd02bbf}{nagd.ht}
{ First-order ODE over an interval with initial conditions}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd02bbf}{NAG Documentation: d02bbf}
\beginscroll
\begin{verbatim}



     D02BBF(3NAG)                 D02BBF                  D02BBF(3NAG)



     D02 -- Ordinary Differential Equations                     D02BBF
             D02BBF -- NAG Foundation Library Routine Document

     Note: Before using this routine, please read the Users' Note for
     your implementation to check implementation-dependent details.
     The symbol (*) after a NAG routine name denotes a routine that is
     not included in the Foundation Library.

     Note for users via the Axiom system: the interface to this routine
     has been enhanced for use with Axiom and is slightly different to
     that offered in the standard version of the Foundation Library.

     1. Purpose

     D02BBF integrates a system of first-order ordinary differential
     equations over an interval with suitable initial conditions,
     using a Runge-Kutta-Merson method, and returns the solution at
     points specified by the user.

     2. Specification

            SUBROUTINE D02BBF (X, XEND, M, N, Y, TOL, IRELAB, RESULT,
           1                   FCN, OUTPUT, W, IFAIL)
            INTEGER          M, N, IRELAB, IFAIL
            DOUBLE PRECISION X, XEND, Y(N), TOL, W(N,7), RESULT(M,N)
            EXTERNAL         FCN, OUTPUT

     3. Description

     The routine integrates a system of ordinary differential
     equations

                    y' =f (x,y ,y ,...,y )  i=1,2,...,n
                      i  i    1  2      n

     from x = X to x = XEND using a Merson form of the Runge-Kutta
     method. The system is defined by a subroutine FCN supplied by the
     user, which evaluates f  in terms of x and y ,y ,...,y , and the
                            i                    1  2      n
     values of y ,y ,...,y  must be given at x = X.
                1  2      n

     The solution is returned via the user-supplied routine OUTPUT at
     a set of points specified by the user. This solution is obtained
     by quintic Hermite interpolation on solution values produced by
     the Runge-Kutta method.

     The accuracy of the integration and, indirectly, the
     interpolation is controlled by the parameters TOL and IRELAB.

     For a description of Runge-Kutta methods and their practical
     implementation see Hall and Watt [1].

     4. References

     [1]   Hall G and Watt J M (eds) (1976) Modern Numerical Methods
           for Ordinary Differential Equations. Clarendon Press.

     5. Parameters

      1:  X -- DOUBLE PRECISION                           Input/Output
          On entry: X must be set to the initial value of the
          independent variable x. On exit: XEND, unless an error has
          occurred, when it contains the value of x at the error.

      2:  XEND -- DOUBLE PRECISION                               Input
          On entry: the final value of the independent variable. If
          XEND < X on entry, integration will proceed in a negative
          direction.

      3:  M -- INTEGER                                           Input
          On entry: the first dimension of the array RESULT.  This
          will usually be equal to the number of points at which the
          solution is required.
          Constraint: M > 0.

      4:  N -- INTEGER                                           Input
          On entry: the number of differential equations.
          Constraint: N > 0.

      5:  Y(N) -- DOUBLE PRECISION array                  Input/Output
          On entry: the initial values of the solution y ,y ,...,y .
                                                         1  2      n
          On exit: the computed values of the solution at the final
          value of X.

      6:  TOL -- DOUBLE PRECISION                         Input/Output
          On entry: TOL must be set to a positive tolerance for
          controlling the error in the integration.

          D02BBF has been designed so that, for most problems, a
          reduction in TOL leads to an approximately proportional
          reduction in the error in the solution at XEND. The relation
          between changes in TOL and the error at intermediate output
          points is less clear, but for TOL small enough the error at
          intermediate output points should also be approximately
          proportional to TOL. However, the actual relation between
          TOL and the accuracy achieved cannot be guaranteed. The user
          is strongly recommended to call D02BBF with more than one
          value for TOL and to compare the results obtained to
          estimate their accuracy. In the absence of any prior
          knowledge, the user might compare the results obtained by
                                      -p             -p-1
          calling D02BBF with TOL=10.0   and TOL=10.0     if p correct
          decimal digits in the solution are required. Constraint: TOL
          > 0.0. On exit: normally unchanged. However if the range X
          to XEND is so short that a small change in TOL is unlikely
          to make any change in the computed solution then, on return,
          TOL has its sign changed. This should be treated as a
          warning that the computed solution is likely to be more
          accurate than would be produced by using the same value of
          TOL on a longer range of integration.

      7:  IRELAB -- INTEGER                                      Input
          On entry: IRELAB determines the type of error control. At
          each step in the numerical solution an estimate of the local
          error, EST, is made. For the current step to be accepted the
          following condition must be satisfied:
          IRELAB = 0
                EST=10.0<=TOL*max{1.0,|y |,|y |,...,|y |};
                                        1    2        n

          IRELAB = 1
                EST <= TOL;

          IRELAB = 2
                EST<=TOL*max{(epsilon),|y |,|y |,...,|y |}, where
                                         1    2        n
                (epsilon) is machine precision.
          If the appropriate condition is not satisfied, the step size
          is reduced and the solution is recomputed on the current
          step.

          If the user wishes to measure the error in the computed
          solution in terms of the number of correct decimal places,
          then IRELAB should be given the value 1 on entry, whereas if
          the error requirement is in terms of the number of correct
          significant digits, then IRELAB should be given the value 2.
          Where there is no preference in the choice of error test
          IRELAB = 0 will result in a mixed error test. Constraint: 0
          <= IRELAB <= 2.

      8:  RESULT(M,N) -- DOUBLE PRECISION array                 Output
          On exit: the computed values of the solution at the points
          given by OUTPUT.

      9:  FCN -- SUBROUTINE, supplied by the user.
                                                    External Procedure
          FCN must evaluate the functions f  (i.e., the derivatives
                                           i
          y' ) for given values of its arguments x,y ,...,y .
            i                                       1      n

          Its specification is:

                 SUBROUTINE FCN (X, Y, F)
                 DOUBLE PRECISION X, Y(n), F(n)

          where n is the actual value of N in the call of D02BBF.

           1:  X -- DOUBLE PRECISION                             Input
               On entry: the value of the argument x.

           2:  Y(*) -- DOUBLE PRECISION array                    Input
               On entry: the value of the argument y , for
                                                     i
               i=1,2,...,n.

           3:  F(*) -- DOUBLE PRECISION array                   Output
               On exit: the value of f , for i=1,2,...,n.
                                       i
          FCN must be declared as EXTERNAL in the (sub)program
          from which D02BBF is called. Parameters denoted as
          Input must not be changed by this procedure.

     10:  OUTPUT -- SUBROUTINE, supplied by the user.
                                                    External Procedure
          OUTPUT allows the user to have access to intermediate values
          of the computed solution at successive points specified by the
          user. These solution values may be returned to the user via
          the array RESULT if desired (this is a non-standard feature
          added for use with the Axiom system).  OUTPUT is initially
          called by D02BBF with XSOL = X (the initial value of x). The
          user must reset XSOL to the next point where OUTPUT is to be
          called, and so on at each call to OUTPUT. If, after a call
          to OUTPUT, the reset point XSOL is beyond XEND, D02BBF will
          integrate to XEND with no further calls to OUTPUT; if a call
          to OUTPUT is required at the point XSOL = XEND, then XSOL
          must be given precisely the value XEND.

          Its specification is:

               SUBROUTINE OUTPUT(XSOL,Y,COUNT,M,N,RESULT)
               DOUBLE PRECISION Y(N),RESULT(M,N),XSOL
               INTEGER M,N,COUNT

           1:  XSOL -- DOUBLE PRECISION                   Input/Output
               On entry: the current value of the independent
               variable x. On exit: the next value of x at which
               OUTPUT is to be called.

           2:  Y(N) -- DOUBLE PRECISION array                    Input
               On entry: the computed solution at the point XSOL.

           3:  COUNT -- INTEGER                           Input/Output
               On entry: Zero if OUTPUT has not been called before, or
               the previous value of COUNT.
               On exit: A new value of COUNT: this can be used to keep
               track of the number of times OUTPUT has been called.

           4:  M -- INTEGER                                      Input
               On entry: The first dimension of RESULT.

           5:  N -- INTEGER                                      Input
               On entry: The dimension of Y.

           6:  RESULT(M,N) -- DOUBLE PRECISION array      Input/Output
               On entry: the previous contents of RESULT.
               On exit: RESULT may be used to return the values of the
               intermediate solutions to the user.

          OUTPUT must be declared as EXTERNAL in the (sub)program
          from which D02BBF is called. Parameters denoted as
          Input must not be changed by this procedure.

     11:  W(N,7) -- DOUBLE PRECISION array                   Workspace

     12:  IFAIL -- INTEGER                                Input/Output
          On entry: IFAIL must be set to 0, -1 or 1. For users not
          familiar with this parameter (described in the Essential
          Introduction) the recommended value is 0.

          On exit: IFAIL = 0 unless the routine detects an error (see
          Section 6).

     6. Error Indicators and Warnings

     Errors detected by the routine:

     IFAIL= 1
          On entry TOL <= 0,

          or       N <= 0,

          or       IRELAB /= 0, 1 or 2.

     IFAIL= 2
          With the given value of TOL, no further progress can be made
          across the integration range from the current point x = X,
          or the dependence of the error on TOL would be lost if
          further progress across the integration range were attempted
          (see Section 8 for a discussion of this error exit). The
          components Y(1),Y(2),...,Y(n) contain the computed values of
          the solution at the current point x = X.

     IFAIL= 3
          TOL is too small for the routine to take an initial step
          (see Section 8). X and Y(1),Y(2),...,Y(n) retain their
          initial values.

     IFAIL= 4
          X = XEND and XSOL /= X after the initial call to OUTPUT.

     IFAIL= 5
          A value of XSOL returned by OUTPUT lies behind the previous
          value of XSOL in the direction of integration.

     IFAIL= 6
          A serious error has occurred in an internal call to
          D02PAF(*). Check all subroutine calls and array dimensions.
          Seek expert help.

     IFAIL= 7
          A serious error has occurred in an internal call to
          D02XAF(*). Check all subroutine calls and array dimensions.
          Seek expert help.

     7. Accuracy

     The accuracy depends on TOL, on the mathematical properties of
     the differential system, on the length of the range of
     integration and on the method. It can be controlled by varying
     TOL but the approximate proportionality of the error to TOL holds
     only for a restricted range of values of TOL. For TOL too large,
     the underlying theory may break down and the result of varying
     TOL may be unpredictable. For TOL too small, rounding errors may
     affect the solution significantly and an error exit with IFAIL =
     2 or IFAIL = 3 is possible.

     At the intermediate output points the same remarks apply. For
     large values of TOL it is possible that the errors at some
     intermediate output points may be much larger than at XEND. In
     any case, it must not be expected that the error will have the
     same size at all output points. At any point, it is a combination
     of the errors arising from the integration of the differential
     equation and the interpolation. The effect of combining these
     errors will vary, though in most cases the integration error will
     dominate.

     The user who requires a more reliable estimate of the accuracy
     achieved than can be obtained by varying TOL, is recommended to
     call D02BDF(*) where both the solution and a global error
     estimate are computed.

     8. Further Comments

     The time taken by the routine depends on the complexity and
     mathematical properties of the system of differential equations
     defined by FCN, on the range, the tolerance and the number of
     calls to OUTPUT. There is also an overhead of the form a+b*n
     where a and b are machine-dependent computing times.

     If the routine fails with IFAIL = 3, then it can be called again
     with a larger value of TOL (if this has not already been tried).
     If the accuracy requested is really needed and cannot be obtained
     with this routine, the system may be very stiff (see below) or so
     badly scaled that it cannot be solved to the required accuracy.

     If the routine fails with IFAIL = 2, it is probable that it has
     been called with a value of TOL which is so small that the
     solution cannot be obtained on the range X to XEND. This can
     happen for well-behaved systems and very small values of TOL. The
     user should, however, consider whether there is a more
     fundamental difficulty. For example:

     (a)   in the region of a singularity (infinite value) of the
           solution, the routine will usually stop with IFAIL = 2,
           unless overflow occurs first. If overflow occurs using
           D02BBF, D02PAF(*) can be used instead to trap the
           increasing solution before overflow occurs. In any case,
           numerical integration cannot be continued through a
           singularity, and analytic treatment should be considered;

     (b)   for 'stiff' equations, where the solution contains rapidly
           decaying components, the routine will use very small steps
           in x (internally to D02BBF) to preserve stability. This
           will usually exhibit itself by making the computing time
           excessively long, or occasionally by an exit with IFAIL =
           2. Merson's method is not efficient in such cases, and the
           user should try using D02EBF(*) (Backward Differentiation
           Formula). To determine whether a problem is stiff,
           D02BDF(*) may be used.

     For well-behaved systems with no difficulties such as stiffness
     or singularities, the Merson method should work well for low
     accuracy calculations (three or four figures). For higher
     accuracy calculations or where FCN is costly to evaluate,
     Merson's method may not be appropriate and a computationally less
     expensive method may be D02CBF(*) which uses an Adams method.

     Users with problems for which D02BBF is not sufficiently general
     should consider using D02PAF(*) with D02XAF(*). D02PAF(*) is a
     more general Merson routine with many facilities including more
     general error control options and several criteria for
     interrupting the calculations. D02XAF(*) interpolates on values
     produced by D02PAF(*).

     9. Example

     To integrate the following equations (for a projectile)

                                y'=tan(phi)

                           -0.032tan(phi)   0.02v
                       v'= --------------- --------
                                 v         cos(phi)


                                      -0.032
                              (phi)'= ------
                                         2
                                        v

     over an interval X = 0.0 to XEND = 8.0, starting with values
     y=0.0, v=0.5 and (phi)=(pi)/5 and printing the solution at steps
     of 1.0. We write y=Y(1), v=Y(2) and (phi)=Y(3), and we set
     TOL=1.0E-4 and TOL=1.0E-5 in turn so that we may compare the
     solutions. The value of (pi) is obtained by using X01AAF(*).

     Note the careful construction of routine OUT to ensure that the
     value of XEND is printed.

     The example program is not reproduced here. The source code for
     all example programs is distributed with the NAG Foundation
     Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd02bhf}{nagd.ht}
{ First-order ODE with initial conditions and user function}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd02bhf}{NAG Documentation: d02bhf}
\beginscroll
\begin{verbatim}



     D02BHF(3NAG)      Foundation Library (12/10/92)      D02BHF(3NAG)



          D02 -- Ordinary Differential Equations                     D02BHF
                  D02BHF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          D02BHF integrates a system of first-order ordinary differential
          equations over an interval with suitable initial conditions,
          using a Runge-Kutta-Merson method, until a user-specified
          function of the solution is zero.

          2. Specification

                 SUBROUTINE D02BHF (X, XEND, N, Y, TOL, IRELAB, HMAX, FCN,
                1                   G, W, IFAIL)
                 INTEGER          N, IRELAB, IFAIL
                 DOUBLE PRECISION X, XEND, Y(N), TOL, HMAX, G, W(N,7)
                 EXTERNAL         FCN, G

          3. Description

          The routine advances the solution of a system of ordinary
          differential equations

                        y' =f (x,y ,y ,...,y ),  i=1,2,...,n,
                          i  i    1  2      n

          from x = X towards x = XEND using a Merson form of the Runge-
          Kutta method. The system is defined by a subroutine FCN supplied
          by the user, which evaluates f  in terms of x and y ,y ,...,y
                                        i                    1  2      n
          (see Section 5), and the values of y ,y ,...,y  must be given at
                                              1  2      n
          x = X.

          As the integration proceeds, a check is made on the function
          g(x,y) specified by the user, to determine an interval where it
          changes sign. The position of this sign change is then determined
          accurately by interpolating for the solution and its derivative.
          It is assumed that g(x,y) is a continuous function of the
          variables, so that a solution of g(x,y) = 0 can be determined by
          searching for a change in sign in g(x,y).

          The accuracy of the integration and, indirectly, of the
          determination of the position where g(x,y) = 0, is controlled by
          the parameter TOL.

          For a description of Runge-Kutta methods and their practical
          implementation see Hall and Watt [1].

          4. References

          [1]   Hall G and Watt J M (eds) (1976) Modern Numerical Methods
                for Ordinary Differential Equations. Clarendon Press.

          5. Parameters

           1:  X -- DOUBLE PRECISION                           Input/Output
               On entry: X must be set to the initial value of the
               independent variable x. On exit: the point where g(x,y) = 0.
               0 unless an error has occurred, when it contains the value
               of x at the error. In particular, if g(x,y)/=0.0 anywhere on
               the range X to XEND, it will contain XEND on exit.

           2:  XEND -- DOUBLE PRECISION                               Input
               On entry: the final value of the independent variable x.

               If XEND < X on entry, integration proceeds in a negative
               direction.

           3:  N -- INTEGER                                           Input
               On entry: the number of differential equations, n.
               Constraint: N > 0.

           4:  Y(N) -- DOUBLE PRECISION array                  Input/Output
               On entry: the initial values of the solution y ,y ,...,y .
                                                             1  2      n
               On exit: the computed values of the solution at the final
               point x = X.

           5:  TOL -- DOUBLE PRECISION                         Input/Output
               On entry: TOL must be set to a positive tolerance for
               controlling the error in the integration and in the
               determination of the position where g(x,y) = 0.0.

               D02BHF has been designed so that, for most problems, a
               reduction in TOL leads to an approximately proportional
               reduction in the error in the solution obtained in the
               integration. The relation between changes in TOL and the
               error in the determination of the position where g(x,y) = 0.
               0 is less clear, but for TOL small enough the error should
               be approximately proportional to TOL. However, the actual
               relation between TOL and the accuracy cannot be guaranteed.
               The user is strongly recommended to call D02BHF with more
               than one value for TOL and to compare the results obtained
               to estimate their accuracy. In the absence of any prior
               knowledge the user might compare results obtained by calling
                                   -p             -p-1
               D02BHF with TOL=10.0   and TOL=10.0     if p correct decimal
               digits in the solution are required. Constraint: TOL > 0.0.

               On exit: normally unchanged. However if the range from x = X
               to the position where g(x,y) = 0.0 (or to the final value of
               x if an error occurs) is so short that a small change in TOL
               is unlikely to make any change in the computed solution,
               then TOL is returned with its sign changed. To check results
               returned with TOL < 0.0, D02BHF should be called again with
               a positive value of TOL whose magnitude is considerably
               smaller than that of the previous call.

           6:  IRELAB -- INTEGER                                      Input
               On entry: IRELAB determines the type of error control. At
               each step in the numerical solution an estimate of the local
               error, EST, is made. For the current step to be accepted the
               following condition must be satisfied:
               IRELAB = 0
                     EST<=TOL*max{1.0,|y |,|y |,...,|y |};
                                        1    2        n

               IRELAB = 1
                     EST <= TOL;

               IRELAB = 2
                     EST<=TOL*max{(epsilon),|y |,|y |,...,|y |},
                                              1    2        n

                     where (epsilon) is machine precision.
               If the appropriate condition is not satisfied, the step size
               is reduced and the solution recomputed on the current step.

               If the user wishes to measure the error in the computed
               solution in terms of the number of correct decimal places,
               then IRELAB should be given the value 1 on entry, whereas if
               the error requirement is in terms of the number of correct
               significant digits, then IRELAB should be given the value 2.
               Where there is no preference in the choice of error test,
               IRELAB = 0 will result in a mixed error test. It should be
               borne in mind that the computed solution will be used in
               evaluating g(x,y). Constraint: 0 <= IRELAB <= 2.

           7:  HMAX -- DOUBLE PRECISION                               Input
               On entry: if HMAX = 0.0, no special action is taken.

               If HMAX /= 0.0, a check is made for a change in sign of
               g(x,y) at steps not greater than |HMAX|. This facility
               should be used if there is any chance of 'missing' the
               change in sign by checking too infrequently. For example, if
               two changes of sign of g(x,y) are expected within a distance
               h, say, of each other, then a suitable value for HMAX might
               be HMAX = h/2. If only one change of sign in g(x,y) is
               expected on the range X to XEND, then the choice HMAX = 0.0
               is most appropriate.

           8:  FCN -- SUBROUTINE, supplied by the user.
                                                         External Procedure
               FCN must evaluate the functions f  (i.e., the derivatives
                                                i
               y' ) for given values of its arguments x,y ,...,y .
                 i                                       1      n

               Its specification is:

                      SUBROUTINE FCN (X, Y, F)
                      DOUBLE PRECISION X, Y(n), F(n)

                1:  X -- DOUBLE PRECISION                             Input
                    On entry: the value of the argument x.

                2:  Y(*) -- DOUBLE PRECISION array                    Input
                    On entry: the value of the argument y , for
                                                         i
                    i=1,2,...,n.

                3:  F(*) -- DOUBLE PRECISION array                   Output
                    On exit: the value of f , for i=1,2,...,n.
                                           i
               FCN must be declared as EXTERNAL in the (sub)program
               from which D02BHF is called. Parameters denoted as
               Input must not be changed by this procedure.

           9:  G -- DOUBLE PRECISION FUNCTION, supplied by the user.
                                                    External Procedure
               G must evaluate the function g(x,y) at a specified point.

               Its specification is:

                      DOUBLE PRECISION FUNCTION G (X, Y)
                      DOUBLE PRECISION X, Y(n)
               where n is the actual value of N in the call of D02BHF.

                1:  X -- DOUBLE PRECISION                             Input
                    On entry: the value of the independent variable x.

                2:  Y(*) -- DOUBLE PRECISION array                    Input
                    On entry: the value of y , for i=1,2,...,n.
                                             i
               G must be declared as EXTERNAL in the (sub)program from
               which D02BHF is called. Parameters denoted as Input
               must not be changed by this procedure.

          10:  W(N,7) -- DOUBLE PRECISION array                   Workspace

          11:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               On entry TOL <= 0.0,

               or       N <= 0,

               or       IRELAB /= 0, 1 or 2.

          IFAIL= 2
               With the given value of TOL, no further progress can be made
               across the integration range from the current point x = X,
               or dependence of the error on TOL would be lost if further
               progress across the integration range were attempted (see
               Section 8 for a discussion of this error exit). The
               components Y(1),Y(2),...,Y(n) contain the computed values of
               the solution at the current point x = X. No point at which
               g(x,y) changes sign has been located up to the point x = X.

          IFAIL= 3
               TOL is too small for the routine to take an initial step
               (see Section 8). X and Y(1),Y(2),...,Y(n) retain their
               initial values.

          IFAIL= 4
               At no point in the range X to XEND did the function g(x,y)
               change sign. It is assumed that g(x,y) = 0.0 has no
               solution.

          IFAIL= 5
               A serious error has occurred in an internal call to
               C05AZF(*). Check all subroutine calls and array dimensions.
               Seek expert help.

          IFAIL= 6
               A serious error has occurred in an internal call to
               D02PAF(*). Check all subroutine calls and array dimensions.
               Seek expert help.

          IFAIL= 7
               A serious error has occurred in an internal call to
               D02XAF(*). Check all subroutine calls and array dimensions.
               Seek expert help.

          7. Accuracy

          The accuracy depends on TOL, on the mathematical properties of
          the differential system, on the position where g(x,y) = 0.0 and
          on the method. It can be controlled by varying TOL but the
          approximate proportionality of the error to TOL holds only for a
          restricted range of values of TOL. For TOL too large, the
          underlying theory may break down and the result of varying TOL
          may be unpredictable. For TOL too small, rounding error may
          affect the solution significantly and an error exit with IFAIL =
          2 or IFAIL = 3 is possible.

          The accuracy may also be restricted by the properties of g(x,y).
          The user should try to code G without introducing any unnecessary
          cancellation errors.

          8. Further Comments

          The time taken by the routine depends on the complexity and
          mathematical properties of the system of differential equations
          defined by FCN, the complexity of G, on the range, the position
          of the solution and the tolerance. There is also an overhead of
          the form a+b*n where a and b are machine-dependent computing
          times.

          For some problems it is possible that D02BHF will return IFAIL =
          4 because of inaccuracy of the computed values Y, leading to
          inaccuracy in the computed values of g(x,y) used in the search
          for the solution of g(x,y) = 0.0. This difficulty can be overcome
          by reducing TOL sufficiently, and if necessary, by choosing HMAX
          sufficiently small. If possible, the user should choose XEND well
          beyond the expected point where g(x,y) = 0.0; for example make
          |XEND-X| about 50 larger than the expected range. As a simple
          check, if, with XEND fixed, a change in TOL does not lead to a
          significant change in Y at XEND, then inaccuracy is not a likely
          source of error.

          If the routine fails with IFAIL = 3, then it could be called
          again with a larger value of TOL if this has not already been
          tried. If the accuracy requested is really needed and cannot be
          obtained with this routine, the system may be very stiff (see
          below) or so badly scaled that it cannot be solved to the
          required accuracy.

          If the routine fails with IFAIL = 2, it is likely that it has
          been called with a value of TOL which is so small that a solution
          cannot be obtained on the range X to XEND. This can happen for
          well-behaved systems and very small values of TOL. The user
          should, however, consider whether there is a more fundamental
          difficulty. For example:

          (a)   in the region of a singularity (infinite value) of the
                solution, the routine will usually stop with IFAIL = 2,
                unless overflow occurs first. If overflow occurs using
                D02BHF, D02PAF(*) can be used instead to trap the
                increasing solution, before overflow occurs. In any case,
                numerical integration cannot be continued through a
                singularity, and analytical treatment should be considered;

          (b)   for 'stiff' equations, where the solution contains rapidly
                decaying components, the routine will compute in very small
                steps in x (internally to D02BHF) to preserve stability.
                This will usually exhibit itself by making the computing
                time excessively long, or occasionally by an exit with
                IFAIL = 2. Merson's method is not efficient in such cases,
                and the user should try D02EHF(*) which uses a Backward
                Differentiation Formula method. To determine whether a
                problem is stiff, D02BDF(*) may be used.

          For well-behaved systems with no difficulties such as stiffness
          or singularities, the Merson method should work well for low
          accuracy calculations (three or four figures). For high accuracy
          calculations or where FCN is costly to evaluate, Merson's method
          may not be appropriate and a computationally less expensive
          method may be D02CHF(*) which uses an Adams method.

          For problems for which D02BHF is not sufficiently general, the
          user should consider D02PAF(*). D02PAF(*) is a more general
          Merson routine with many facilities including more general error
          control options and several criteria for interrupting the
          calculations. D02PAF(*) can be combined with the rootfinder
          C05AZF(*) and the interpolation routine D02XAF(*) to solve
          equations involving y ,y ,...,y  and their derivatives.
                               1  2      n

          D02BHF can also be used to solve an equation involving x,
          y ,y ,...,y  and the derivatives of y ,y ,...,y . For example in
           1  2      n                         1  2      n
          Section 9, D02BHF is used to find a value of X > 0.0 where Y(1) =
          0.0. It could instead be used to find a turning-point of y  by
                                                                    1
          replacing the function g(x,y) in the program by:

                DOUBLE PRECISION FUNCTION G(X,Y)
                DOUBLE PRECISION X,Y(3),F(3)
                CALL FCN(X,Y,F)
                G = F(1)
                RETURN
                END

          This routine is only intended to locate the first zero of g(x,y).
          If later zeros are required, users are strongly advised to
          construct their own more general root finding routines as
          discussed above.

          9. Example

          To find the value X > 0.0 at which y=0.0, where y, v, (phi) are
          defined by

                                     y'=tan(phi)

                                -0.032tan(phi)   0.02v
                            v'= --------------- --------
                                      v         cos(phi)

                                            0.032
                                   (phi)'=- -----
                                              2
                                             v

          and where at X = 0.0 we are given y=0.5, v=0.5 and (phi)=(pi)/5.
          We write y=Y(1), v=Y(2) and (phi)=Y(3) and we set TOL=1.0E-4 and
          TOL=1.0E-5 in turn so that we can compare the solutions. We
          expect the solution X ~= 7.3 and so we set XEND = 10.0 to avoid
          determining the solution of y=0.0 too near the end of the range
          of integration. The value of (pi) is obtained by using X01AAF(*).


          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd02cjf}{nagd.ht}
{ First-order ODE with variable-order, variable-step}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd02cjf}{NAG Documentation: d02cjf}
\beginscroll
\begin{verbatim}



     D02CJF(3NAG)                 D02CJF                  D02CJF(3NAG)



     D02 -- Ordinary Differential Equations                     D02CJF
             D02CJF -- NAG Foundation Library Routine Document

     Note: Before using this routine, please read the Users' Note for
     your implementation to check implementation-dependent details.
     The symbol (*) after a NAG routine name denotes a routine that is
     not included in the Foundation Library.

     Note for users via the Axiom system: the interface to this routine
     has been enhanced for use with Axiom and is slightly different to
     that offered in the standard version of the Foundation Library.

     1. Purpose

     D02CJF integrates a system of first-order ordinary differential
     equations over a range with suitable initial conditions, using a
     variable-order, variable-step Adams method until a user-specified
     function, if supplied, of the solution is zero, and returns the
     solution at points specified by the user, if desired.

     2. Specification

            SUBROUTINE D02CJF (X, XEND, M, N, Y, FCN, TOL, RELABS,
           1                   RESULT, OUTPUT, G, W, IFAIL)
            INTEGER          M, N, IFAIL
            DOUBLE PRECISION X, XEND, Y(N), TOL, G, W(28+21*N), RESULT(M,N)
            CHARACTER*1      RELABS
            EXTERNAL         FCN, OUTPUT, G

     3. Description

     The routine advances the solution of a system of ordinary
     differential equations

                   y' =f (x,y ,y ,...,y ),  i=1,2,...,n,
                     i  i    1  2      n

     from x = X to x = XEND using a variable-order, variable-step
     Adams method. The system is defined by a subroutine FCN supplied
     by the user, which evaluates f  in terms of x and y ,y ,...,y .
                                   i                    1  2      n
     The initial values of y ,y ,...,y  must be given at x = X.
                            1  2      n

     The solution is returned via the user-supplied routine OUTPUT at
     points specified by the user, if desired: this solution is
                  1
     obtained by C  interpolation on solution values produced by the
     method. As the integration proceeds a check can be made on the
     user-specified function g(x,y) to determine an interval where it
     changes sign. The position of this sign change is then determined
                    1
     accurately by C  interpolation to the solution. It is assumed
     that g(x,y) is a continuous function of the variables, so that a
     solution of g(x,y)=0.0 can be determined by searching for a
     change in sign in g(x,y). The accuracy of the integration, the
     interpolation and, indirectly, of the determination of the
     position where g(x,y)=0.0, is controlled by the parameters TOL
     and RELABS.

     For a description of Adams methods and their practical
     implementation see Hall and Watt [1].

     4. References

     [1]   Hall G and Watt J M (eds) (1976) Modern Numerical Methods
           for Ordinary Differential Equations. Clarendon Press.

     5. Parameters

      1:  X -- DOUBLE PRECISION                           Input/Output
          On entry: the initial value of the independent variable x.
          Constraint: X /= XEND. On exit: if g is supplied by the
          user, it contains the point where g(x,y)=0.0, unless
          g(x,y)/=0.0 anywhere on the range X to XEND, in which case,
          X will contain XEND. If g is not supplied by the user it
          contains XEND, unless an error has occurred, when it
          contains the value of x at the error.

      2:  XEND -- DOUBLE PRECISION                               Input
          On entry: the final value of the independent variable. If
          XEND < X, integration proceeds in the negative direction.
          Constraint: XEND /= X.

      3:  M -- INTEGER                                           Input
          On entry: the first dimension of the array RESULT.  This
          will usually be equal to the number of points at which the
          solution is required.
          Constraint: M > 0.

      4:  N -- INTEGER                                           Input
          On entry: the number of differential equations.
          Constraint: N >= 1.

      5:  Y(N) -- DOUBLE PRECISION array                  Input/Output
          On entry: the initial values of the solution y ,y ,...,y
                                                         1  2      n
          at x = X. On exit: the computed values of the solution at
          the final point x = X.

      6:  FCN -- SUBROUTINE, supplied by the user.
                                                    External Procedure
          FCN must evaluate the functions f  (i.e., the derivatives
                                           i
          y' ) for given values of their arguments x,y ,y ,...,y .
            i                                         1  2      n

          Its specification is:

                 SUBROUTINE FCN (X, Y, F)
                 DOUBLE PRECISION X, Y(n), F(n)
          where n is the actual value of N in the call of D02CJF.

           1:  X -- DOUBLE PRECISION                             Input
               On entry: the value of the independent variable x.

           2:  Y(*) -- DOUBLE PRECISION array                    Input
               On entry: the value of the variable y , for
                                                     i
               i=1,2,...,n.

           3:  F(*) -- DOUBLE PRECISION array                   Output
               On exit: the value of f , for i=1,2,...,n.
                                       i
          FCN must be declared as EXTERNAL in the (sub)program
          from which D02CJF is called. Parameters denoted as
          Input must not be changed by this procedure.

      7:  TOL -- DOUBLE PRECISION                                Input
          On entry: a positive tolerance for controlling the error in
          the integration. Hence TOL affects the determination of the
          position where g(x,y)=0.0, if g is supplied.

          D02CJF has been designed so that, for most problems, a
          reduction in TOL leads to an approximately proportional
          reduction in the error in the solution. However, the actual
          relation between TOL and the accuracy achieved cannot be
          guaranteed. The user is strongly recommended to call D02CJF
          with more than one value for TOL and to compare the results
          obtained to estimate their accuracy. In the absence of any
          prior knowledge, the user might compare the results obtained
                                         -p             -p-1
          by calling D02CJF with TOL=10.0   and TOL=10.0     where p
          correct decimal digits are required in the solution.
          Constraint: TOL > 0.0.

      8:  RELABS -- CHARACTER*1                                  Input
          On entry: the type of error control. At each step in the
          numerical solution an estimate of the local error, EST, is
          made. For the current step to be accepted the following
          condition must be satisfied:
                           ______________________________
                          / n
                         /  --                          2
                 EST=   /   >  (e /((tau) *|y |+(tau) )) <=1.0
                       /    --   i       r   i       a
                     \/     i=1
          where (tau)  and (tau)  are defined by
                     r          a
               RELABS   (tau)    (tau)
                             r        a

               'M'      TOL      TOL

               'A'      0.0      TOL

               'R'      TOL      (epsilon)

               'D'      TOL      TOL
          where (epsilon) is a small machine-dependent number and e
                                                                   i
          is an estimate of the local error at y , computed
                                                i
          internally. If the appropriate condition is not satisfied,
          the step size is reduced and the solution is recomputed on
          the current step. If the user wishes to measure the error in
          the computed solution in terms of the number of correct
          decimal places, then RELABS should be set to 'A' on entry,
          whereas if the error requirement is in terms of the number
          of correct significant digits, then RELABS should be set to
          'R'. If the user prefers a mixed error test, then RELABS
          should be set to 'M', otherwise if the user has no
          preference, RELABS should be set to the default 'D'. Note
          that in this case 'D' is taken to be 'M'. Constraint: RELABS
          = 'M', 'A', 'R', 'D'.

      9:  RESULT(M,N) -- DOUBLE PRECISION array                 Output
          On exit: the computed values of the solution at the points
          given by OUTPUT.

     10:  OUTPUT -- SUBROUTINE, supplied by the user.
                                                    External Procedure
          OUTPUT allows the user to have access to intermediate values
          of the computed solution at successive points specified by the
          user. These solution values may be returned to the user via
          the array RESULT if desired (this is a non-standard feature
          added for use with the Axiom system).  OUTPUT is initially
          called by D02CJF with XSOL = X (the initial value of x). The
          user must reset XSOL to the next point where OUTPUT is to be
          called, and so on at each call to OUTPUT. If, after a call
          to OUTPUT, the reset point XSOL is beyond XEND, D02CJF will
          integrate to XEND with no further calls to OUTPUT; if a call
          to OUTPUT is required at the point XSOL = XEND, then XSOL
          must be given precisely the value XEND.

          Its specification is:

               SUBROUTINE OUTPUT(XSOL,Y,COUNT,M,N,RESULT)
               DOUBLE PRECISION Y(N),RESULT(M,N),XSOL
               INTEGER M,N,COUNT

           1:  XSOL -- DOUBLE PRECISION                   Input/Output
               On entry: the current value of the independent
               variable x. On exit: the next value of x at which
               OUTPUT is to be called.

           2:  Y(N) -- DOUBLE PRECISION array                    Input
               On entry: the computed solution at the point XSOL.

           3:  COUNT -- INTEGER                           Input/Output
               On entry: Zero if OUTPUT has not been called before, or
               the previous value of COUNT.
               On exit: A new value of COUNT: this can be used to keep
               track of the number of times OUTPUT has been called.

           4:  M -- INTEGER                                      Input
               On entry: The first dimension of RESULT.

           5:  N -- INTEGER                                      Input
               On entry: The dimension of Y.

           6:  RESULT(M,N) -- DOUBLE PRECISION array      Input/Output
               On entry: the previous contents of RESULT.
               On exit: RESULT may be used to return the values of the
               intermediate solutions to the user.

          OUTPUT must be declared as EXTERNAL in the (sub)program
          from which D02CJF is called. Parameters denoted as
          Input must not be changed by this procedure.

     11:  G -- DOUBLE PRECISION FUNCTION, supplied by the user.
                                               External Procedure
          G must evaluate the function g(x,y) for specified values x,y
          . It specifies the function g for which the first position x
          where g(x,y)=0 is to be found.

          If the user does not require the root finding option, the
          actual argument G  mustbe the dummy routine D02CJW. (D02CJW
          is included in the NAG Foundation Library and so need not be
          supplied by the user).

          Its specification is:

                 DOUBLE PRECISION FUNCTION G (X, Y)
                 DOUBLE PRECISION X, Y(n)
          where n is the actual value of N in the call of D02CJF.

           1:  X -- DOUBLE PRECISION                             Input
               On entry: the value of the independent variable x.

           2:  Y(*) -- DOUBLE PRECISION array                    Input
               On entry: the value of the variable y , for
                                                    i
               i=1,2,...,n.
          G must be declared as EXTERNAL in the (sub)program from
          which D02CJF is called. Parameters denoted as Input
          must not be changed by this procedure.

     12:  W(28+21*N) -- DOUBLE PRECISION array               Workspace

     13:  IFAIL -- INTEGER                                Input/Output
          On entry: IFAIL must be set to 0, -1 or 1. For users not
          familiar with this parameter (described in the Essential
          Introduction) the recommended value is 0.

          On exit: IFAIL = 0 unless the routine detects an error (see
          Section 6).

     6. Error Indicators and Warnings

     Errors detected by the routine:

     If on entry IFAIL = 0 or -1, explanatory error messages are
     output on the current error message unit (as defined by X04AAF).

     IFAIL= 1
          On entry TOL <= 0.0,

          or       N <= 0,

          or       RELABS /= 'M', 'A', 'R' or 'D'.

          or       X = XEND.

     IFAIL= 2
          With the given value of TOL, no further progress can be made
          across the integration range from the current point x = X.
          (See Section 8 for a discussion of this error exit.) The
          components Y(1),Y(2),...,Y(N) contain the computed values of
          the solution at the current point x = X. If the user has
          supplied g, then no point at which g(x,y) changes sign has
          been located up to the point x = X.

     IFAIL= 3
          TOL is too small for D02CJF to take an initial step. X and Y
          (1),Y(2),...,Y(N) retain their initial values.

     IFAIL= 4
          XSOL has not been reset or XSOL lies behind X in the
          direction of integration, after the initial call to OUTPUT,
          if the OUTPUT option was selected.

     IFAIL= 5
          A value of XSOL returned by OUTPUT has not been reset or
          lies behind the last value of XSOL in the direction of
          integration, if the OUTPUT option was selected.

     IFAIL= 6
          At no point in the range X to XEND did the function g(x,y)
          change sign, if g was supplied. It is assumed that g(x,y)=0
          has no solution.

     IFAIL= 7
          A serious error has occurred in an internal call. Check all
          subroutine calls and array sizes. Seek expert help.

     7. Accuracy

     The accuracy of the computation of the solution vector Y may be
     controlled by varying the local error tolerance TOL. In general,
     a decrease in local error tolerance should lead to an increase in
     accuracy. Users are advised to choose RELABS = 'M' unless they
     have a good reason for a different choice.

     If the problem is a root-finding one, then the accuracy of the
     root determined will depend on the properties of g(x,y). The user
     should try to code G without introducing any unnecessary
     cancellation errors.

     8. Further Comments

     If more than one root is required then D02QFF(*) should be used.

     If the routine fails with IFAIL = 3, then it can be called again
     with a larger value of TOL if this has not already been tried. If
     the accuracy requested is really needed and cannot be obtained
     with this routine, the system may be very stiff (see below) or so
     badly scaled that it cannot be solved to the required accuracy.

     If the routine fails with IFAIL = 2, it is probable that it has
     been called with a value of TOL which is so small that a solution
     cannot be obtained on the range X to XEND. This can happen for
     well-behaved systems and very small values of TOL. The user
     should, however, consider whether there is a more fundamental
     difficulty. For example:

     (a)   in the region of a singularity (infinite value) of the
           solution, the routine will usually stop with IFAIL = 2,
           unless overflow occurs first. Numerical integration cannot
           be continued through a singularity, and analytic treatment
           should be considered;

     (b)   for 'stiff' equations where the solution contains rapidly
           decaying components, the routine will use very small steps
           in x (internally to D02CJF) to preserve stability. This
           will exhibit itself by making the computing time
           excessively long, or occasionally by an exit with IFAIL =
           2. Adams methods are not efficient in such cases, and the
           user should try D02EJF.

     9. Example

     We illustrate the solution of four different problems. In each
     case the differential system (for a projectile) is

                                y'=tan(phi)

                           -0.032tan(phi)   0.02v
                       v'= --------------- --------
                                 v         cos(phi)

                                      -0.032
                              (phi)'= ------
                                         2
                                        v

     over an interval X = 0.0 to XEND = 10.0 starting with values
     y=0.5, v=0.5 and (phi)=(pi)/5. We solve each of the following
     problems with local error tolerances 1.0E-4 and 1.0E-5.

     (i)   To integrate to x=10.0 producing output at intervals of 2.0
           until a point is encountered where y=0.0.

     (ii)  As (i) but with no intermediate output.

     (iii) As (i) but with no termination on a root-finding condition.

     (iv)  As (i) but with no intermediate output and no root-finding
           termination condition.

     The example program is not reproduced here. The source code for
     all example programs is distributed with the NAG Foundation
     Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd02ejf}{nagd.ht}
{ Stiff First-order ODE with variable order and step}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd02ejf}{NAG Documentation: d02ejf}
\beginscroll
\begin{verbatim}



     D02EJF(3NAG)                 D02EJF                  D02EJF(3NAG)



     D02 -- Ordinary Differential Equations                     D02EJF
             D02EJF -- NAG Foundation Library Routine Document

     Note: Before using this routine, please read the Users' Note for
     your implementation to check implementation-dependent details.
     The symbol (*) after a NAG routine name denotes a routine that is
     not included in the Foundation Library.

     Note for users via the Axiom system: the interface to this routine
     has been enhanced for use with Axiom and is slightly different to
     that offered in the standard version of the Foundation Library.

     1. Purpose

     D02EJF integrates a stiff system of first-order ordinary
     differential equations over an interval with suitable initial
     conditions, using a variable-order, variable-step method
     implementing the Backward Differentiation Formulae (BDF), until a
     user-specified function, if supplied, of the solution is zero,
     and returns the solution at points specified by the user, if
     desired.

     2. Specification

            SUBROUTINE D02EJF (X, XEND, M, N, Y, FCN, PEDERV, TOL,
           1                   RELABS, OUTPUT, G, W, IW, RESULT, IFAIL)
            INTEGER          M, N, IW, IFAIL
            DOUBLE PRECISION X, XEND, Y(N), TOL, G, W(IW), RESULT(M,N)
            CHARACTER*1      RELABS
            EXTERNAL         FCN, PEDERV, OUTPUT, G

     3. Description

     The routine advances the solution of a system of ordinary
     differential equations

                   y' =f (x,y ,y ,...,y ),  i=1,2,...,n,
                     i  i    1  2      n

     from x = X to x = XEND using a variable-order, variable-step
     method implementing the BDF. The system is defined by a
     subroutine FCN supplied by the user, which evaluates f  in terms
                                                           i
     of x and y ,y ,...,y  (see Section 5). The initial values of
               1  2      n
     y ,y ,...,y  must be given at x = X.
      1  2      n

     The solution is returned via the user-supplied routine OUTPUT at
     points specified by the user, if desired: this solution is
                  1
     obtained by C  interpolation on solution values produced by the
     method. As the integration proceeds a check can be made on the
     user-specified function g(x,y) to determine an interval where it
     changes sign. The position of this sign change is then determined
                    1
     accurately by C  interpolation to the solution. It is assumed
     that g(x,y) is a continuous function of the variables, so that a
     solution of g(x,y) = 0.0 can be determined by searching for a
     change in sign in g(x,y). The accuracy of the integration, the
     interpolation and, indirectly, of the determination of the
     position where g(x,y) = 0.0, is controlled by the parameters TOL
     and RELABS. The Jacobian of the system y'=f(x,y) may be supplied
     in routine PEDERV, if it is available.

     For a description of BDF and their practical implementation see
     Hall and Watt [1].

     4. References

     [1]   Hall G and Watt J M (eds) (1976) Modern Numerical Methods
           for Ordinary Differential Equations. Clarendon Press.

     5. Parameters

      1:  X -- DOUBLE PRECISION                           Input/Output
          On entry: the initial value of the independent variable x.
          Constraint: X /= XEND On exit: if G is supplied by the user,
          X contains the point where g(x,y) = 0.0, unless g(x,y) /= 0.
          0 anywhere on the range X to XEND, in which case, X will
          contain XEND. If G is not supplied X contains XEND, unless
          an error has occured, when it contains the value of x at the
          error.

      2:  XEND -- DOUBLE PRECISION                               Input
          On entry: the final value of the independent variable. If
          XEND < X, integration proceeds in the negative direction.
          Constraint: XEND /= X.

      3:  M -- INTEGER                                           Input
          On entry: the first dimension of the array RESULT.  This
          will usually be equal to the number of points at which the
          solution is required.
          Constraint: M > 0.

      4:  N -- INTEGER                                           Input
          On entry: the number of differential equations, n.
          Constraint: N >= 1.

      5:  Y(N) -- DOUBLE PRECISION array                  Input/Output
          On entry: the initial values of the solution y ,y ,...,y
                                                        1  2      n
          at x = X. On exit: the computed values of the solution at
          the final point x = X.

      6:  FCN -- SUBROUTINE, supplied by the user.
                                                    External Procedure
          FCN must evaluate the functions f  (i.e., the derivatives
                                           i
          y' ) for given values of their arguments x,y ,y ,...,y .
            i                                         1  2      n

          Its specification is:

                 SUBROUTINE FCN (X, Y, F)
                 DOUBLE PRECISION X, Y(n), F(n)
          where n is the actual value of N in the call of D02EJF.

           1:  X -- DOUBLE PRECISION                             Input
               On entry: the value of the independent variable x.

           2:  Y(*) -- DOUBLE PRECISION array                    Input
               On entry: the value of the variable y , for
                                                    i
               i=1,2,...,n.

           3:  F(*) -- DOUBLE PRECISION array                   Output
               On exit: the value of f , for i=1,2,...,n.
                                      i
          FCN must be declared as EXTERNAL in the (sub)program
          from which D02EJF is called. Parameters denoted as
          Input must not be changed by this procedure.

      7:  PEDERV -- SUBROUTINE, supplied by the user.
                                                    External Procedure
          PEDERV must evaluate the Jacobian of the system (that is,
                                   ddf
                                      i
          the partial derivatives  ----) for given values of the
                                   ddy
                                      j
          variables x,y ,y ,...,y .
                       1  2      n

          Its specification is:

                 SUBROUTINE PEDERV (X, Y, PW)
                 DOUBLE PRECISION X, Y(n), PW(n,n)
          where n is the actual value of N in the call of D02EJF.

           1:  X -- DOUBLE PRECISION                             Input
               On entry: the value of the independent variable x.

           2:  Y(*) -- DOUBLE PRECISION array                    Input
               On entry: the value of the variable y , for
                                                    i
               i=1,2,...,n.

           3:  PW(n,*) -- DOUBLE PRECISION array                Output
                                       ddf
                                          i
               On exit: the value of  ----, for i,j=1,2,...,n.
                                       ddy
                                          j
          If the user does not wish to supply the Jacobian, the
          actual argument PEDERV must be the dummy routine D02EJY
          . (D02EJY is included in the NAG Foundation Library and
          so need not be supplied by the user. The name may be
          implementation dependent: see the User's Note for your
          implementation for details).
          PEDERV must be declared as EXTERNAL in the (sub)program
          from which D02EJF is called. Parameters denoted as
          Input must not be changed by this procedure.

      8:  TOL -- DOUBLE PRECISION                         Input/Output
          On entry: TOL must be set to a positive tolerance for
          controlling the error in the integration. Hence TOL affects
          the determination of the position where g(x,y) = 0.0, if G
          is supplied.

          D02EJF has been designed so that, for most problems, a
          reduction in TOL leads to an approximately proportional
          reduction in the error in the solution. However, the actual
          relation between TOL and the accuracy achieved cannot be
          guaranteed. The user is strongly recommended to call D02EJF
          with more than one value for TOL and to compare the results
          obtained to estimate their accuracy. In the absence of any
          prior knowledge, the user might compare the results obtained
                                       -p           -p-1
          by calling D02EJF with TOL=10   and TOL=10     if p correct
          decimal digits are required in the solution. Constraint: TOL
          > 0.0. On exit: normally unchanged. However if the range X
          to XEND is so short that a small change in TOL is unlikely
          to make any change in the computed solution, then, on
          return, TOL has its sign changed.

      9:  RELABS -- CHARACTER*1                                  Input
          On entry: the type of error control. At each step in the
          numerical solution an estimate of the local error, EST, is
          made. For the current step to be accepted the following
          condition must be satisfied:
                          ________________________________
                         /   n
                        /  1 --                          2
                EST=   /   - >  (e /((tau) *|y |+(tau) )) <=1.0
                      /    n --   i       r   i       a
                    \/       i=1
          where (tau)  and (tau)  are defined by
                     r          a
               RELABS   (tau)    (tau)
                             r        a

               'M'      TOL      TOL

               'A'      0.0      TOL

               'R'      TOL      (epsilon)

               'D'      TOL      (epsilon)
          where (epsilon) is a small machine-dependent number and e
                                                                   i
          is an estimate of the local error at y , computed
                                                i
          internally. If the appropriate condition is not satisfied,
          the step size is reduced and the solution is recomputed on
          the current step. If the user wishes to measure the error in
          the computed solution in terms of the number of correct
          decimal places, then RELABS should be set to 'A' on entry,
          whereas if the error requirement is in terms of the number
          of correct significant digits, then RELABS should be set to
          'R'. If the user prefers a mixed error test, then RELABS
          should be set to 'M', otherwise if the user has no
          preference, RELABS should be set to the default 'D'. Note
          that in this case 'D' is taken to be 'R'. Constraint: RELABS
          = 'A', 'M', 'R' or 'D'.

     10:  OUTPUT -- SUBROUTINE, supplied by the user.
                                                    External Procedure
          OUTPUT allows the user to have access to intermediate values
          of the computed solution at successive points specified by the
          user. These solution values may be returned to the user via
          the array RESULT if desired (this is a non-standard feature
          added for use with the Axiom system).  OUTPUT is initially
          called by D02EJF with XSOL = X (the initial value of x). The
          user must reset XSOL to the next point where OUTPUT is to be
          called, and so on at each call to OUTPUT. If, after a call
          to OUTPUT, the reset point XSOL is beyond XEND, D02EJF will
          integrate to XEND with no further calls to OUTPUT; if a call
          to OUTPUT is required at the point XSOL = XEND, then XSOL
          must be given precisely the value XEND.

          Its specification is:

               SUBROUTINE OUTPUT(XSOL,Y,COUNT,M,N,RESULT)
               DOUBLE PRECISION Y(N),RESULT(M,N),XSOL
               INTEGER M,N,COUNT

           1:  XSOL -- DOUBLE PRECISION                   Input/Output
               On entry: the current value of the independent
               variable x. On exit: the next value of x at which
               OUTPUT is to be called.

           2:  Y(N) -- DOUBLE PRECISION array                    Input
               On entry: the computed solution at the point XSOL.

           3:  COUNT -- INTEGER                           Input/Output
               On entry: Zero if OUTPUT has not been called before, or
               the previous value of COUNT.
               On exit: A new value of COUNT: this can be used to keep
               track of the number of times OUTPUT has been called.

           4:  M -- INTEGER                                      Input
               On entry: The first dimension of RESULT.

           5:  N -- INTEGER                                      Input
               On entry: The dimension of Y.

           6:  RESULT(M,N) -- DOUBLE PRECISION array      Input/Output
               On entry: the previous contents of RESULT.
               On exit: RESULT may be used to return the values of the
               intermediate solutions to the user.

          OUTPUT must be declared as EXTERNAL in the (sub)program
          from which D02EJF is called. Parameters denoted as
          Input must not be changed by this procedure.

     11:  G -- DOUBLE PRECISION FUNCTION, supplied by the user.
                                                    External Procedure
          G must evaluate the function g(x,y) for specified values x,y
          . It specifies the function g for which the first position x
          where g(x,y) = 0 is to be found.

          Its specification is:

                 DOUBLE PRECISION FUNCTION G (X, Y)
                 DOUBLE PRECISION X, Y(n)
          where n is the actual value of N in the call of D02EJF.

           1:  X -- DOUBLE PRECISION                             Input
               On entry: the value of the independent variable x.

           2:  Y(*) -- DOUBLE PRECISION array                    Input
               On entry: the value of the variable y , for
                                                    i
               i=1,2,...,n.
          If the user does not require the root finding option,
          the actual argument G must be the dummy routine D02EJW.
          (D02EJW is included in the NAG Foundation Library and
          so need not be supplied by the user).
          G must be declared as EXTERNAL in the (sub)program from
          which D02EJF is called. Parameters denoted as Input
          must not be changed by this procedure.

     12:  W(IW) -- DOUBLE PRECISION array                    Workspace

     13:  IW -- INTEGER                                          Input
          On entry:
          the dimension of the array W as declared in the (sub)program
          from which D02EJF is called.
          Constraint: IW>=(12+N)*N+50.

     14:  RESULT(M,N) -- DOUBLE PRECISION array                 Output
          On exit: the computed values of the solution at the points
          given by OUTPUT.

     15:  IFAIL -- INTEGER                                Input/Output
          On entry: IFAIL must be set to 0, -1 or 1. For users not
          familiar with this parameter (described in the Essential
          Introduction) the recommended value is 0.

          On exit: IFAIL = 0 unless the routine detects an error (see
          Section 6).

     6. Error Indicators and Warnings

     Errors detected by the routine:

     If on entry IFAIL = 0 or -1, explanatory error messages are
     output on the current error message unit (as defined by X04AAF).

     IFAIL= 1
          On entry TOL <= 0.0,

          or       X = XEND,

          or       N <= 0,

          or       RELABS /= 'M', 'A', 'R', 'D'.

          or       IW<(12+N)*N+50.

     IFAIL= 2
          With the given value of TOL, no further progress can be made
          across the integration range from the current point x = X.
          (See Section 5 for a discussion of this error test.) The
          components Y(1),Y(2),...,Y(n) contain the computed values of
          the solution at the current point x = X. If the user has
          supplied G, then no point at which g(x,y) changes sign has
          been located up to the point x = X.

     IFAIL= 3
          TOL is too small for D02EJF to take an initial step. X and Y
          (1),Y(2),...,Y(n) retain their initial values.

     IFAIL= 4
          XSOL lies behind X in the direction of integration, after
          the initial call to OUTPUT, if the OUTPUT option was
          selected.

     IFAIL= 5
          A value of XSOL returned by OUTPUT lies behind the last
          value of XSOL in the direction of integration, if the OUTPUT
          option was selected.

     IFAIL= 6
          At no point in the range X to XEND did the function g(x,y)
          change sign, if G was supplied. It is assumed that g(x,y) =
          0 has no solution.

     IFAIL= 7
          A serious error has occurred in an internal call to
          C05AZF(*). Check all subroutine calls and array dimensions.
          Seek expert help.

     IFAIL= 8
          A serious error has occurred in an internal call to
          D02XKF(*). Check all subroutine calls and array dimensions.
          Seek expert help.

     IFAIL= 9
          A serious error has occurred in an internal call to
          D02NMF(*). Check all subroutine calls and array dimensions.
          Seek expert help.

     7. Accuracy

     The accuracy of the computation of the solution vector Y may be
     controlled by varying the local error tolerance TOL. In general,
     a decrease in local error tolerance should lead to an increase in
     accuracy. Users are advised to choose RELABS = 'R' unless they
     have a good reason for a different choice. It is particularly
     appropriate if the solution decays.

     If the problem is a root-finding one, then the accuracy of the
                                              ddg      ddg
     root determined will depend strongly on  --- and  ----, for
                                              ddx      ddy
                                                          i
     i=1,2,...,n. Large values for these quantities may imply large
     errors in the root.

     8. Further Comments

     If more than one root is required, then to determine the second
     and later roots D02EJF may be called again starting a short
     distance past the previously determined roots. Alternatively the
     user may construct his own root finding code using D02QDF(*) (or
     the routines of the subchapter D02M-D02N), D02XKF(*) and
     C05AZF(*).

     If it is easy to code, the user should supply the routine PEDERV.
     However, it is important to be aware that if PEDERV is coded
     incorrectly, a very inefficient integration may result and
     possibly even a failure to complete the integration (IFAIL = 2).

     9. Example

     We illustrate the solution of five different problems. In each
     case the differential system is the well-known stiff Robertson
     problem.

                                      4
                         a'= -0.04a-10 bc
                                      4        7 2
                         b'=  0.04a-10 bc -3*10 b
                                               7 2
                         c'=               3*10 b

     with initial conditions a=1.0, b=c=0.0 at x=0.0. We solve each of
     the following problems with local error tolerances 1.0E-3 and 1.0
     E-4.

     (i)   To integrate to x=10.0 producing output at intervals of 2.0
           until a point is encountered where a=0.9. The Jacobian is
           calculated numerically.

     (ii)  As (i) but with the Jacobian calculated analytically.

     (iii) As (i) but with no intermediate output.

     (iv)  As (i) but with no termination on a root-finding condition.

     (v)   Integrating the equations as in (i) but with no
           intermediate output and no root-finding termination
           condition.

     The example program is not reproduced here. The source code for
     all example programs is distributed with the NAG Foundation
     Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd02gaf}{nagd.ht}{ Two-point boundary-value ODE}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd02gaf}{NAG Documentation: d02gaf}
\beginscroll
\begin{verbatim}



     D02GAF(3NAG)      Foundation Library (12/10/92)      D02GAF(3NAG)



          D02 -- Ordinary Differential Equations                     D02GAF
                  D02GAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          D02GAF solves the two-point boundary-value problem with assigned
          boundary values for a system of ordinary differential equations,
          using a deferred correction technique and a Newton iteration.

          2. Specification

                 SUBROUTINE D02GAF (U, V, N, A, B, TOL, FCN, MNP, X, Y, NP,
                1                   W, LW, IW, LIW, IFAIL)
                 INTEGER          N, MNP, NP, LW, IW(LIW), LIW, IFAIL
                 DOUBLE PRECISION U(N,2), V(N,2), A, B, TOL, X(MNP), Y
                1                 (N,MNP), W(LW)
                 EXTERNAL         FCN

          3. Description

          D02GAF solves a two-point boundary-value problem for a system of
          n differential equations in the interval [a,b]. The system is
          written in the form

                      y' =f (x,y ,y ,...,y ) , i=1,2,...,n              (1)
                        i  i    1  2      n

          and the derivatives are evaluated by a subroutine FCN supplied by
          the user. Initially, n boundary values of the variables y  must
                                                                   i
          be specified (assigned), some at a and some at b. The user also
          supplies estimates of the remaining n boundary values and all the
          boundary values are used in constructing an initial approximation
          to the solution. This approximate solution is corrected by a
          finite-difference technique with deferred correction allied with
          a Newton iteration to solve the finite-difference equations. The
          technique used is described fully in Pereyra [1]. The Newton
                                                ddf
                                                   i
          iteration requires a Jacobian matrix  ---- and this is calculated
                                                ddy
                                                   j
          by numerical differentiation using an algorithm described in
          Curtis et al [2].

          The user supplies an absolute error tolerance and may also supply
          an initial mesh for the construction of the finite-difference
          equations (alternatively a default mesh is used). The algorithm
          constructs a solution on a mesh defined by adding points to the
          initial mesh. This solution is chosen so that the error is
          everywhere less than the user's tolerance and so that the error
          is approximately equidistributed on the final mesh. The solution
          is returned on this final mesh.

          If the solution is required at a few specific points then these
          should be included in the initial mesh. If on the other hand the
          solution is required at several specific points then the user
          should use the interpolation routines provided in Chapter E01 if
          these points do not themselves form a convenient mesh.

          4. References

          [1]   Pereyra V (1979) PASVA3: An Adaptive Finite-Difference
                Fortran Program for First Order Nonlinear, Ordinary Boundary
                Problems. Codes for Boundary Value Problems in Ordinary
                Differential Equations. Lecture Notes in Computer Science.
                (ed B Childs, M Scott, J W Daniel, E Denman and P Nelson) 76
                Springer-Verlag.

          [2]   Curtis A R, Powell M J D and Reid J K (1974) On the
                Estimation of Sparse Jacobian Matrices. J. Inst. Maths
                Applics. 13 117--119.

          5. Parameters

           1:  U(N,2) -- DOUBLE PRECISION array                       Input
               On entry: U(i,1) must be set to the known (assigned) or
               estimated values of y  at a and U(i,2) must be set to the
                                    i
               known or estimated values of y  at b, for i=1,2,...,n.
                                             i

           2:  V(N,2) -- DOUBLE PRECISION array                       Input
               On entry: V(i,j) must be set to 0.0 if U(i,j) is a known
               (assigned) value and to 1.0 if U(i,j) is an estimated value,
               i=1,2,...,n; j=1,2. Constraint: precisely N of the V(i,j)
               must be set to 0.0, i.e., precisely N of the U(i,j) must be
               known values, and these must not be all at a or all at b.

           3:  N -- INTEGER                                           Input
               On entry: the number of equations. Constraint: N >= 2.

           4:  A -- DOUBLE PRECISION                                  Input
               On entry: the left-hand boundary point, a.

           5:  B -- DOUBLE PRECISION                                  Input
               On entry: the right-hand boundary point, b. Constraint: B >
               A.

           6:  TOL -- DOUBLE PRECISION                                Input
               On entry: a positive absolute error tolerance. If
                                    a=x <x <...<x  =b
                                       1  2      NP
               is the final mesh, z (x ) is the jth component of the
                                   j  i
               approximate solution at x , and y (x) is the jth component
                                        i       j
               of the true solution of equation (1) (see Section 3) and the
               boundary conditions, then, except in extreme cases, it is
               expected that
                   |z (x )-y (x )|<=TOL , i=1,2,...,NP;j=1,2,...,n      (2)
                     j  i   j  i
                Constraint: TOL > 0.0.

           7:  FCN -- SUBROUTINE, supplied by the user.
                                                         External Procedure
               FCN must evaluate the functions f  (i.e., the derivatives
                                                i
               y' ) at the general point x.
                 i

               Its specification is:

                      SUBROUTINE FCN (X, Y, F)
                      DOUBLE PRECISION X, Y(n), F(n)
               where n is the actual value of N in the call of D02GAF.

                1:  X -- DOUBLE PRECISION                             Input
                    On entry: the value of the argument x.

                2:  Y(*) -- DOUBLE PRECISION array                    Input
                    On entry: the value of the argument y , for
                                                         i
                    i=1,2,...,n.

                3:  F(*) -- DOUBLE PRECISION array                   Output
                    On exit: the values of f , for i=1,2,...,n.
                                            i
               FCN must be declared as EXTERNAL in the (sub)program
               from which D02GAF is called. Parameters denoted as
               Input must not be changed by this procedure.

           8:  MNP -- INTEGER                                         Input
               On entry: the maximum permitted number of mesh points.
               Constraint: MNP >= 32.

           9:  X(MNP) -- DOUBLE PRECISION array                Input/Output
               On entry: if NP >= 4 (see NP below), the first NP elements
               must define an initial mesh. Otherwise the elements of X
               need not be set. Constraint:
                          A=X(1)<X(2)<...<X(NP)=B for NP>=4             (3)
               On exit: X(1),X(2),...,X(NP) define the final mesh (with
               the returned value of NP) satisfying the relation (3).

          10:  Y(N,MNP) -- DOUBLE PRECISION array                    Output
               On exit: the approximate solution z (x ) satisfying (2), on
                                                  j  i
               the final mesh, that is
                        Y(j,i)=z (x ) , i=1,2,...,NP;j=1,2,...,n,
                                j  i
               where NP is the number of points in the final mesh.

               The remaining columns of Y are not used.

          11:  NP -- INTEGER                                   Input/Output
               On entry: determines whether a default or user-supplied
               mesh is used. If NP = 0, a default value of 4 for NP and a
               corresponding equispaced mesh X(1),X(2),...,X(NP) are used.
               If NP >= 4, then the user must define an initial mesh using
               the array X as described. Constraint: NP = 0 or 4 <= NP <=
               MNP. On exit: the number of points in the final (returned)
               mesh.

          12:  W(LW) -- DOUBLE PRECISION array                    Workspace

          13:  LW -- INTEGER                                          Input
               On entry: the length of the array W as declared in the
                                                            2         2
               calling (sub)program. Constraint: LW>=MNP*(3N +6N+2)+4N +4N

          14:  IW(LIW) -- INTEGER array                           Workspace

          15:  LIW -- INTEGER                                         Input
               On entry: the length of the array IW as declared in the
                                                                  2
               calling (sub)program. Constraint: LIW>=MNP*(2N+1)+N +4N+2.

          16:  IFAIL -- INTEGER                                Input/Output
               For this routine, the normal use of IFAIL is extended to
               control the printing of error and warning messages as well
               as specifying hard or soft failure (see the Essential
               Introduction).

               Before entry, IFAIL must be set to a value with the decimal
               expansion cba, where each of the decimal digits c, b and a
               must have a value of 0 or 1.
               a=0   specifies hard failure, otherwise soft failure;

               b=0   suppresses error messages, otherwise error messages
                     will be printed (see Section 6);

               c=0   suppresses warning messages, otherwise warning
                     messages will be printed (see Section 6).
               The recommended value for inexperienced users is 110 (i.e.,
               hard failure with all messages printed).

               Unless the routine detects an error (see Section 6), IFAIL
               contains 0 on exit.

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               One or more of the parameters N, TOL, NP, MNP, LW or LIW has
               been incorrectly set, or B <= A, or the condition (3) on X
               is not satisfied, or the number of known boundary values
               (specified by V) is not N.

          IFAIL= 2
               The Newton iteration has failed to converge. This could be
               due to there being too few points in the initial mesh or to
               the initial approximate solution being too inaccurate. If
               this latter reason is suspected the user should use
               subroutine D02RAF instead. If the warning 'Jacobian matrix
               is singular' is printed this could be due to specifying zero
               estimated boundary values and these should be varied. This
               warning could also be printed in the unlikely event of the
               Jacobian matrix being calculated inaccurately. If the user
               cannot make changes to prevent the warning then subroutine
               D02RAF should be used.

          IFAIL= 3
               The Newton iteration has reached round-off level. It could
               be, however, that the answer returned is satisfactory. This
               error might occur if too much accuracy is requested.

          IFAIL= 4
               A finer mesh is required for the accuracy requested; that is
               MNP is not large enough.

          IFAIL= 5
               A serious error has occurred in a call to D02GAF. Check all
               array subscripts and subroutine parameter lists in calls to
               D02GAF. Seek expert help.

          7. Accuracy

          The solution returned by the routine will be accurate to the
          user's tolerance as defined by the relation (2) except in extreme
          circumstances. If too many points are specified in the initial
          mesh, the solution may be more accurate than requested and the
          error may not be approximately equidistributed.

          8. Further Comments

          The time taken by the routine depends on the difficulty of the
          problem, the number of mesh points used (and the number of
          different meshes used), the number of Newton iterations and the
          number of deferred corrections.

          The user is strongly recommended to set IFAIL to obtain self-
          explanatory error messages, and also monitoring information about
          the course of the computation. The user may select the channel
          numbers on which this output is to appear by calls of X04AAF (for
          error messages) or X04ABF (for monitoring information) - see
          Section 9 for an example. Otherwise the default channel numbers
          will be used, as specified in the implementation document.

          A common cause of convergence problems in the Newton iteration is
          the user specifying too few points in the initial mesh. Although
          the routine adds points to the mesh to improve accuracy it is
          unable to do so until the solution on the initial mesh has been
          calculated in the Newton iteration.

          If the user specifies zero known and estimated boundary values,
          the routine constructs a zero initial approximation and in many
          cases the Jacobian is singular when evaluated for this
          approximation, leading to the breakdown of the Newton iteration.

          The user may be unable to provide a sufficiently good choice of
          initial mesh and estimated boundary values, and hence the Newton
          iteration may never converge. In this case the continuation
          facility provided in D02RAF is recommended.

          In the case where the user wishes to solve a sequence of similar
          problems, the final mesh from solving one case is strongly
          recommended as the initial mesh for the next.

          9. Example

          We solve the differential equation

                                                    2
                              y'''=-yy''-(beta)(1-y' )

          with boundary conditions

                                    y(0)=y'(0)=0,

                                      y'(10)=1

          for (beta)=0.0 and (beta)=0.2 to an accuracy specified by TOL=1.0
          E-3. We solve first the simpler problem with (beta)=0.0 using an
          equispaced mesh of 26 points and then we solve the problem with
          (beta)=0.2 using the final mesh from the first problem.

          Note the call to X04ABF prior to the call to D02GAF.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd02gbf}{nagd.ht}
{ Two-point boundary value ODE with deferred correction}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd02gbf}{NAG Documentation: d02gbf}
\beginscroll
\begin{verbatim}



     D02GBF(3NAG)      Foundation Library (12/10/92)      D02GBF(3NAG)



          D02 -- Ordinary Differential Equations                     D02GBF
                  D02GBF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          D02GBF solves a general linear two-point boundary value problem
          for a system of ordinary differential equations using a deferred
          correction technique.

          2. Specification

                 SUBROUTINE D02GBF (A, B, N, TOL, FCNF, FCNG, C, D, GAM,
                1                   MNP, X, Y, NP, W, LW, IW, LIW, IFAIL)
                 INTEGER          N, MNP, NP, LW, IW(LIW), LIW, IFAIL
                 DOUBLE PRECISION A, B, TOL, C(N,N), D(N,N), GAM(N), X(MNP),
                1                 Y(N,MNP), W(LW)
                 EXTERNAL         FCNF, FCNG

          3. Description

          D02GBF solves the linear two-point boundary value problem for a
          system of n ordinary differential equations in the interval

          [a,b]. The system is written in the form

                                 y'=F(x)y+g(x)                          (1)

          and the boundary conditions are written in the form

                              Cy(a)+Dy(b)=(gamma)                       (2)

          Here F(x), C and D are n by n matrices, and g(x) and (gamma) are
          n-component vectors. The approximate solution to (1) and (2) is
          found using a finite-difference method with deferred correction.
          The algorithm is a specialisation of that used in subroutine
          D02RAF which solves a nonlinear version of (1) and (2). The
          nonlinear version of the algorithm is described fully in Pereyra
          [1].

          The user supplies an absolute error tolerance and may also supply
          an initial mesh for the construction of the finite-difference
          equations (alternatively a default mesh is used). The algorithm
          constructs a solution on a mesh defined by adding points to the
          initial mesh. This solution is chosen so that the error is
          everywhere less than the user's tolerance and so that the error
          is approximately equidistributed on the final mesh. The solution
          is returned on this final mesh.

          If the solution is required at a few specific points then these
          should be included in the initial mesh. If, on the other hand,
          the solution is required at several specific points, then the
          user should use the interpolation routines provided in Chapter
          E01 if these points do not themselves form a convenient mesh.

          4. References

          [1]   Pereyra V (1979) PASVA3: An Adaptive Finite-Difference
                Fortran Program for First Order Nonlinear, Ordinary Boundary
                Problems. Codes for Boundary Value Problems in Ordinary
                Differential Equations. Lecture Notes in Computer Science.
                (ed B Childs, M Scott, J W Daniel, E Denman and P Nelson) 76
                Springer-Verlag.

          5. Parameters

           1:  A -- DOUBLE PRECISION                                  Input
               On entry: the left-hand boundary point, a.

           2:  B -- DOUBLE PRECISION                                  Input
               On entry: the right-hand boundary point, b. Constraint: B >
               A.

           3:  N -- INTEGER                                           Input
               On entry: the number of equations; that is n is the order of
               system (1). Constraint: N >= 2.

           4:  TOL -- DOUBLE PRECISION                                Input
               On entry: a positive absolute error tolerance. If
                                    a=x <x <...<x  =b
                                       1  2      NP
               is the final mesh, z(x) is the approximate solution from
               D02GBF and y(x) is the true solution of equations (1) and
               (2) then, except in extreme cases, it is expected that
                                    ||z-y||<=TOL                        (3)
               where
                           ||u||=max       max        |u (x )|.
                                    1<=i<=N   1<=j<=NP  i  j
               Constraint: TOL > 0.0.

           5:  FCNF -- SUBROUTINE, supplied by the user.
                                                         External Procedure
               FCNF must evaluate the matrix F(x) in (1) at a general point
               x.

               Its specification is:

                      SUBROUTINE FCN (X, F)
                      DOUBLE PRECISION X, F(n,n)
               where n is the actual value of N in the call of D02GBF.

                1:  X -- DOUBLE PRECISION                             Input
                    On entry: the value of the independent variable x.

                2:  F(n,n) -- DOUBLE PRECISION array                 Output
                    On exit: the (i,j)th element of the matrix F(x), for
                    i,j=1,2,...,n. (See Section 9 for an example.)
               FCN must be declared as EXTERNAL in the (sub)program
               from which D02GBF is called. Parameters denoted as
               Input must not be changed by this procedure.

           6:  FCNG -- SUBROUTINE, supplied by the user.
                                                         External Procedure
               FCNG must evaluate the vector g(x) in (1) at a general point
               x.

               Its specification is:

                      SUBROUTINE FCNG (X, G)
                      DOUBLE PRECISION X, G(n)
               where n is the actual value of N in the call of D02GBF.

                1:  X -- DOUBLE PRECISION                             Input
                    On entry: the value of the independent variable x.

                2:  G(*) -- DOUBLE PRECISION array                   Output
                    On exit: the ith element of the vector g(x), for
                    i=1,2,...,n. (See Section Section 9 for an example.)
               FCNG must be declared as EXTERNAL in the (sub)program
               from which D02GBF is called. Parameters denoted as
               Input must not be changed by this procedure.

           7:  C(N,N) -- DOUBLE PRECISION array                Input/Output

           8:  D(N,N) -- DOUBLE PRECISION array                Input/Output

           9:  GAM(N) -- DOUBLE PRECISION array                Input/Output
               On entry: the arrays C and D must be set to the matrices C
               and D in (2). GAM must be set to the vector (gamma) in (2).
               On exit: the rows of C and D and the components of GAM are
               re-ordered so that the boundary conditions are in the order:
                 (i)   conditions on y(a) only;

                 (ii)  condition involving y(a) and y(b); and

                 (iii) conditions on y(b) only.

               The routine will be slightly more efficient if the arrays C,
               D and GAM are ordered in this way before entry, and in this
               event they will be unchanged on exit.

               Note that the problems (1) and (2) must be of boundary value
               type, that is neither C nor D may be identically zero. Note
               also that the rank of the matrix [C,D] must be n for the
               problem to be properly posed. Any violation of these
               conditions will lead to an error exit.

          10:  MNP -- INTEGER                                         Input
               On entry: the maximum permitted number of mesh points.
               Constraint: MNP >= 32.

          11:  X(MNP) -- DOUBLE PRECISION array                Input/Output
               On entry: if NP >= 4 (see NP below), the first NP elements
               must define an initial mesh. Otherwise the elements of x
               need not be set. Constraint:
                         A=X(1)<X(2)<...<X(NP)=B, for NP>=4.            (4)
               On exit: X(1),X(2),...,X(NP) define the final mesh (with the
               returned value of NP) satisfying the relation (4).

          12:  Y(N,MNP) -- DOUBLE PRECISION array                    Output
               On exit: the approximate solution z(x) satisfying (3), on
               the final mesh, that is
                         Y(j,i)=z (x ) , i=1,2,...,NP;j=1,2,...,n
                                 j  i
               where NP is the number of points in the final mesh.

               The remaining columns of Y are not used.

          13:  NP -- INTEGER                                   Input/Output
               On entry: determines whether a default mesh or user-supplied
               mesh is used. If NP = 0, a default value of 4 for NP and a
               corresponding equispaced mesh X(1),X(2),...,X(NP) are used.
               If NP >= 4, then the user must define an initial mesh X as
               in (4) above. On exit: the number of points in the final
               (returned) mesh.

          14:  W(LW) -- DOUBLE PRECISION array                    Workspace

          15:  LW -- INTEGER                                          Input
               On entry: the length of the array W, Constraint:
                          2         2
               LW>=MNP*(3N +5N+2)+3N +5N.

          16:  IW(LIW) -- INTEGER array                           Workspace

          17:  LIW -- INTEGER                                         Input
               On entry: the length of the array IW. Constraint:
               LIW>=MNP*(2N+1)+N.

          18:  IFAIL -- INTEGER                                Input/Output
               For this routine, the normal use of IFAIL is extended to
               control the printing of error and warning messages as well
               as specifying hard or soft failure (see the Essential
               Introduction).

               Before entry, IFAIL must be set to a value with the decimal
               expansion cba, where each of the decimal digits c, b and a
               must have a value of 0 or 1.
               a=0   specifies hard failure, otherwise soft failure;

               b=0   suppresses error messages, otherwise error messages
                     will be printed (see Section 6);

               c=0   suppresses warning messages, otherwise warning
                     messages will be printed (see Section 6).
               The recommended value for inexperienced users is 110 (i.e.,
               hard failure with all messages printed).

               Unless the routine detects an error (see Section 6), IFAIL
               contains 0 on exit.

          6. Error Indicators and Warnings

          Errors detected by the routine:

          For each error, an explanatory error message is output on the
          current error message unit (as defined by X04AAF), unless
          suppressed by the value of IFAIL on entry.

          IFAIL= 1
               One or more of the parameters N, TOL, NP, MNP, LW or LIW is
               incorrectly set, B <= A or the condition (4) on X is not
               satisfied.

          IFAIL= 2
               There are three possible reasons for this error exit to be
               taken:
                 (i)  one of the matrices C or D is identically zero (that
                      is the problem is of initial value and not boundary
                      value type). In this case, IW(1) = 0 on exit;

                 (ii) a row of C and the corresponding row of D are
                      identically zero (that is the boundary conditions are
                      rank deficient). In this case, on exit IW(1) contains
                      the index of the first such row encountered; and

                 (iii more than n of the columns of the n by 2n matrix [C,D
                 )    ] are identically zero (that is the boundary
                      conditions are rank deficient). In this case, on exit
                      IW(1) contains minus the number of non-identically
                      zero columns.

          IFAIL= 3
               The routine has failed to find a solution to the specified
               accuracy. There are a variety of possible reasons including:
                 (i)   the boundary conditions are rank deficient, which may
                       be indicated by the message that the Jacobian is
                       singular. However this is an unlikely explanation for
                       the error exit as all rank deficient boundary
                       conditions should lead instead to error exits with
                       either IFAIL = 2 or IFAIL = 5; see also (iv) below;

                 (ii)  not enough mesh points are permitted in order to
                       attain the required accuracy. This is indicated by NP
                       = MNP on return from a call to D02GBF. This
                       difficulty may be aggravated by a poor initial choice
                       of mesh points;

                 (iii) the accuracy requested cannot be attained on the
                       computer being used; and

                 (iv)  an unlikely combination of values of F(x) has led to
                       a singular Jacobian. The error should not persist if
                       more mesh points are allowed.

          IFAIL= 4
               A serious error has occurred in a call to D02GBF. Check all
               array subscripts and subroutine parameter lists in calls to
               D02GBF. Seek expert help.

          IFAIL= 5
               There are two possible reasons for this error exit which
               occurs when checking the rank of the boundary conditions by
               reduction to a row echelon form:
                    (i) at least one row of the n by 2n matrix [C,D] is a
                    linear combination of the other rows and hence the
                    boundary conditions are rank deficient. The index of
                    the first such row encountered is given by IW(1) on
                    exit; and

                    (ii) as (i) but the rank deficiency implied by this
                    error exit has only been determined up to a numerical
                    tolerance. Minus the index of the first such row
                    encountered is given by IW(1) on exit.
               In case (ii) above there is some doubt as to the rank
               deficiency of the boundary conditions. However even if the
               boundary conditions are not rank deficient they are not
               posed in a suitable form for use with this routine.

               For example, if
                                                          ((gamma) )
                        (1 0        )     (1 0)           (       1)
                      C=(1 (epsilon)) , D=(1 0) , (gamma)=((gamma) )
                                                          (       2)
               and (epsilon) is small enough, this error exit is likely to
               be taken. A better form for the boundary conditions in this
               case would be
                                           ((gamma)                       )
                                           (       1                      )
                 (1 0)     (1 0)           (         -1                   )
               C=(0 1) , D=(0 0) , (gamma)=((epsilon)  ((gamma) -(gamma) ))
                                           (                   2        1 )

          7. Accuracy

          The solution returned by the routine will be accurate to the
          user's tolerance as defined by the relation (3) except in extreme
          circumstances. If too many points are specified in the initial
          mesh, the solution may be more accurate than requested and the
          error may not be approximately equidistributed.

          8. Further Comments

          The time taken by the routine depends on the difficulty of the
          problem, the number of mesh points (and meshes) used and the
          number of deferred corrections.

          The user is strongly recommended to set IFAIL to obtain self-
          explanatory error messages, and also monitoring information about
          the course of the computation. The user may select the channel
          numbers on which this output is to appear by calls of X04AAF (for
          error messages) or X04ABF (for monitoring information) - see
          Section 9 for an example. Otherwise the default channel numbers
          will be used, as specified in the implementation document.

          In the case where the user wishes to solve a sequence of similar
          problems, the use of the final mesh from one case is strongly
          recommended as the initial mesh for the next.

          9. Example

          We solve the problem (written as a first order system)

                                  (epsilon)y''+y'=0

          with boundary conditions

                                   y(0)=0,  y(1)=1

                                    -1                 -2
          for the cases (epsilon)=10   and (epsilon)=10   using the default
          initial mesh in the first case, and the final mesh of the first
          case as initial mesh for the second (more difficult) case. We
          give the solution and the error at each mesh point to illustrate
          the accuracy of the method given the accuracy request TOL=1.0E-3.

          Note the call to X04ABF prior to the call to D02GBF.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd02kef}{nagd.ht}
{ Eignevalue of regular singular 2nd-order Sturm-Liouville}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd02kef}{NAG Documentation: d02kef}
\beginscroll
\begin{verbatim}



D02KEF(3NAG)                 D02KEF                  D02KEF(3NAG)



     D02 -- Ordinary Differential Equations                     D02KEF
             D02KEF -- NAG Foundation Library Routine Document

     Note: Before using this routine, please read the Users' Note for
     your implementation to check implementation-dependent details.
     The symbol (*) after a NAG routine name denotes a routine that is
     not included in the Foundation Library.

     1. Purpose

     D02KEF finds a specified eigenvalue of a regular singular second-
     order Sturm-Liouville system on a finite or infinite range, using
     a Pruefer transformation and a shooting method. It also reports
     values of the eigenfunction and its derivatives. Provision is
     made for discontinuities in the coefficient functions or their
     derivatives.

     2. Specification

            SUBROUTINE D02KEF (XPOINT, M, MATCH, COEFFN, BDYVAL, K,
           1                   TOL, ELAM, DELAM, HMAX, MAXIT, MAXFUN,
           2                   MONIT, REPORT, IFAIL)
            INTEGER          M, MATCH, K, MAXIT, MAXFUN, IFAIL
            DOUBLE PRECISION XPOINT(M), TOL, ELAM, DELAM, HMAX(2,M)
            EXTERNAL         COEFFN, BDYVAL, MONIT, REPORT

     3. Description

     D02KEF has essentially the same purpose as D02KDF(*) with minor
     modifications to enable values of the eigenfunction to be
     obtained after convergence to the eigenvalue has been achieved.

                                           ~~~~~~~~
     It first finds a specified eigenvalue (lambda) of a Sturm-
     Liouville system defined by a self-adjoint differential equation
     of the second-order

                     (p(x)y')'+q(x;(lambda))y=0, a<x<b

     together with the appropriate boundary conditions at the two
     (finite or infinite) end-points a and b. The functions p and q,
     which are real-valued, must be defined by a subroutine COEFFN.
     The boundary conditions must be defined by a subroutine BDYVAL,
     and, in the case of a singularity at a or b, take the form of an
     asymptotic formula for the solution near the relevant end-point.

                                      ~~~~~~~~
     When the final estimate (lambda)=(lambda) of the eigenvalue has
     been found, the routine integrates the differential equation once
     more with that value of (lambda), and with initial conditions
     chosen so that the integral

                       b
                       /    2    ddq
                    S= |y(x)  ----------(x;(lambda))dx
                       /      dd(lambda)
                       a

     is approximately one. When q(x;(lambda)) is of the form
     (lambda)w(x)+q(x), which is the most common case, S represents
     the square of the norm of y induced by the inner product

                                 b
                                 /
                          <f,g>= |f(x)g(x)w(x)dx,
                                 /
                                 a

     with respect to which the eigenfunctions are mutually orthogonal.
     This normalisation of y is only approximate, but experience shows
     that S generally differs from unity by only one or two per cent.

     During this final integration the REPORT routine supplied by the
     user is called at each integration mesh point x. Sufficient
     information is returned to permit the user to compute y(x) and
     y'(x) for printing or plotting. For reasons described in Section
     8.2, D02KEF passes across to REPORT, not y and y', but the Pru
     efer variables (beta), (phi) and (rho) on which the numerical
     method is based. Their relationship to y and y' is given by the
     equations


              ______   ( (rho))   ( (phi))
     p(x)y'=\/(beta)exp( -----)cos( -----);
                       (   2  )   (   2  )

                1       ( (rho))   ( (phi))
          y= --------exp( -----)sin( -----).
               ______   (   2  )   (   2  )
             \/(beta)

     For the theoretical basis of the numerical method to be valid,
     the following conditions should hold on the coefficient
     functions:

     (a)   p(x) must be non-zero and of one sign throughout the
           interval (a,b); and,

               ddq
     (b)    ---------- must be of one sign throughout (a,b) for all
            dd(lambda)
           relevant values of (lambda), and must not be identically
           zero as x varies, for any (lambda).

     Points of discontinuity in the functions p and q or their
     derivatives are allowed, and should be included as 'break-points'
     in the array XPOINT.

     A good account of the theory of Sturm-Liouville systems, with
     some description of Pruefer transformations, is given in Birkhoff
     and Rota [4], Chapter X. An introduction for the user of Pruefer
     transformations for the numerical solution of eigenvalue problems
     arising from physics and chemistry is Bailey [2].

     The scaled Pruefer method is fairly recent, and is described in a
     short note by Pryce [6] and in some detail in the technical
     report [5].

     4. References

     [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
           Functions. Dover Publications.

     [2]   Bailey P B (1966) Sturm-Liouville Eigenvalues via a Phase
           Function. SIAM J. Appl. Math . 14 242--249.

     [3]   Banks D O and Kurowski I (1968) Computation of Eigenvalues
           of Singular Sturm-Liouville Systems. Math. Computing. 22
           304--310.

     [4]   Birkhoff G and Rota G C (1962) Ordinary Differential
           Equations. Ginn & Co., Boston and New York.

     [5]   Pryce J D (1981) Two codes for Sturm-Liouville problems.
           Technical Report CS-81-01. Dept of Computer Science, Bristol
           University .

     [6]   Pryce J D and Hargrave B A (1977) The Scale Pruefer Method
           for one-parameter and multi-parameter eigenvalue problems in
           ODEs. Inst. Math. Appl., Numerical Analysis Newsletter. 1(3)

     5. Parameters

      1:  XPOINT(M) -- DOUBLE PRECISION array                    Input
          On entry: the points where the boundary conditions computed
          by BDYVAL are to be imposed, and also any break-points,
          i.e., XPOINT(1) to XPOINT(m) must contain values x ,...,x
                                                            1      m
          such that
                             x <=x <x <...<x   <=x
                              1   2  3      m-1   m
          with the following meanings:
          (a)   x  and x  are the left and right end-points, a and b,
                 1      m
                of the domain of definition of the Sturm-Liouville
                system if these are finite. If either a or b is
                infinite, the corresponding value x  or x  may be a
                                                   1     m
                more-or-less arbitrarily 'large' number of appropriate
                sign.

          (b)   x  and x    are the Boundary Matching Points (BMP's),
                 2      m-1
                that is the points at which the left and right
                boundary conditions computed in BDYVAL are imposed.

                If the left-hand end-point is a regular point then the
                user should set x =x (=a), while if it is a singular
                                 2  1
                point the user must set x >x . Similarly x   =x (=b)
                                         2  1             m-1  m
                if the right-hand end-point is regular, and x   <x  if
                                                             m-1  m
                it is singular.

          (c)   The remaining m-4 points x ,...,x   , if any, define
                                          3      m-2
                `break-points' which divide the interval [x ,x   ]
                                                           2  m-1
                into m-3 sub-intervals
                           i =[x ,x ],...,i   =[x   ,x   ]
                            1   2  3       m-3   m-2  m-1
                Numerical integration of the differential equation is
                stopped and restarted at each break-point. In simple
                cases no break-points are needed. However if p(x) or
                q(x;(lambda)) are given by different formulae in
                different parts of the range, then integration is more
                efficient if the range is broken up by break-points in
                the appropriate way. Similarly points where any jumps
                occur in p(x) or q(x;(lambda)), or in their
                derivatives up to the fifth order, should appear as
                break-points.
          Constraint: X(1) <= X(2) < ... < X(M-1) <= X(M).

      2:  M -- INTEGER                                           Input
          On entry: the number of points in the array XPOINT.
          Constraint: M >= 4.

      3:  MATCH -- INTEGER                                Input/Output
          On entry: MATCH must be set to the index of the 'break-point
          ' to be used as the matching point (see Section 8.3). If
          MATCH is set to a value outside the range [2,m-1] then a
          default value is taken, corresponding to the break-point
          nearest the centre of the interval [XPOINT(2),XPOINT(m-1)].
          On exit: the index of the break-point actually used as the
          matching point.

      4:  COEFFN -- SUBROUTINE, supplied by the user.
                                               External Procedure
          COEFFN must compute the values of the coefficient functions
          p(x) and q(x;(lambda)) for given values of x and (lambda).
          Section 3 states conditions which p and q must satisfy.

          Its specification is:

                 SUBROUTINE COEFFN (P, Q, DQDL, X, ELAM, JINT)
                 DOUBLE PRECISION P, Q, DQDL, X, ELAM
                 INTEGER          JINT

           1:  P -- DOUBLE PRECISION                            Output
               On exit: the value of p(x) for the current value of x.

           2:  Q -- DOUBLE PRECISION                            Output
               On exit: the value of q(x;(lambda)) for the current
               value of x and the current trial value of (lambda).

           3:  DQDL -- DOUBLE PRECISION                         Output
                                         ddq
               On exit: the value of  ----------(x;(lambda)) for the
                                      dd(lambda)
               current value of x and the current trial value of
               (lambda). However DQDL is only used in error estimation
               and an approximation (say to within 20%) will suffice.

           4:  X -- DOUBLE PRECISION                             Input
               On entry: the current value of x.

           5:  ELAM -- DOUBLE PRECISION                          Input
               On entry: the current trial value of the eigenvalue
               parameter (lambda).

           6:  JINT -- INTEGER                                   Input
               On entry: the index j of the sub-interval i  (see
                                                          j
               specification of XPOINT) in which x lies.
          See Section 8.4 and Section 9 for examples.

          COEFFN must be declared as EXTERNAL in the (sub)program
          from which D02KEF is called. Parameters denoted as
          Input must not be changed by this procedure.

      5:  BDYVAL -- SUBROUTINE, supplied by the user.
                                               External Procedure
          BDYVAL must define the boundary conditions. For each end-
          point, BDYVAL must return (in YL or YR) values of y(x) and
          p(x)y'(x) which are consistent with the boundary conditions
          at the end-points; only the ratio of the values matters.
          Here x is a given point (XL or XR) equal to, or close to,
          the end-point.

          For a regular end-point (a, say), x=a; and a boundary
          condition of the form
                                c y(a)+c y'(a)=0
                                 1      2
          can be handled by returning constant values in YL, e.g.
          YL(1)=c  and YL(2)=-c p(a).
                 2             1

          For a singular end-point however, YL(1) and YL(2) will in
          general be functions of XL and ELAM, and YR(1) and YR(2)
          functions of XR and ELAM, usually derived analytically from
          a power-series or asymptotic expansion. Examples are given
          in Section 8.5 Section 9.

          Its specification is:

                 SUBROUTINE BDYVAL (XL, XR, ELAM, YL, YR))
                 DOUBLE PRECISION XL, XR, ELAM, YL(3), YR(3)

           1:  XL -- DOUBLE PRECISION                            Input
               On entry: if a is a regular end-point of the system (so
               that a=x =x ), then XL contains a. If a is a singular
                       1  2
               point (so that a<=x <x ), then XL contains a point x
                                  1  2
               such that x <x<=x ).
                          1     2

           2:  XR -- DOUBLE PRECISION                            Input
               On entry: if b is a regular end-point of the system (so
               that x   =x =b), then XR contains b. If b is a singular
                     m-1  m
               point (so that x   <x <=b), then XR contains a point x
                               m-1  m
               such that x   <=x<x .
                          m-1     m

           3:  ELAM -- DOUBLE PRECISION                          Input
               On entry: the current trial value of (lambda).

           4:  YL(3) -- DOUBLE PRECISION array                  Output
               On exit: YL(1) and YL(2) should contain values of y(x)
               and p(x)y'(x) respectively (not both zero) which are
               consistent with the boundary condition at the left-hand
               end-point, given by x = XL. YL(3) should not be set.

           5:  YR(3) -- DOUBLE PRECISION array                  Output
               On exit: YR(1) and YR(2) should contain values of y(x)
               and p(x)y'(x) respectively (not both zero) which are
               consistent with the boundary condition at the right-
               hand end-point, given by x = XR. YR(3) should not be
               set.

          BDYVAL must be declared as EXTERNAL in the (sub)program
          from which D02KEF is called. Parameters denoted as
          Input must not be changed by this procedure.

      6:  K -- INTEGER                                           Input
          On entry: the index k of the required eigenvalue when the
          eigenvalues are ordered
          (lambda) <(lambda) <(lambda) <...<(lambda) <....
                  0         1         2             k
          Constraint: K >= 0.

      7:  TOL -- DOUBLE PRECISION                                Input
          On entry: the tolerance parameter which determines the
          accuracy of the computed eigenvalue. The error estimate held
          in DELAM on exit satisfies the mixed absolute/relative error
          test
                        DELAM<=TOL*max(1.0,|ELAM|)                 (*)
          where ELAM is the final estimate of the eigenvalue. DELAM is
          usually somewhat smaller than the right-hand side of (*) but
          not several orders of magnitude smaller. Constraint: TOL >
          0.0.

      8:  ELAM -- DOUBLE PRECISION                        Input/Output
                                                          ~~~~~~~~
          On entry: an initial estimate of the eigenvalue (lambda).
          On exit: the final computed estimate, whether or not an
          error occurred.

      9:  DELAM -- DOUBLE PRECISION                       Input/Output
          On entry: an indication of the scale of the problem in the
          (lambda)-direction. DELAM holds the initial 'search step'
          (positive or negative). Its value is not critical but the
          first two trial evaluations are made at ELAM and ELAM +
          DELAM, so the routine will work most efficiently if the
          eigenvalue lies between these values. A reasonable choice
          (if a closer bound is not known) is half the distance
          between adjacent eigenvalues in the neighbourhood of the one
          sought. In practice, there will often be a problem, similar
          to the one in hand but with known eigenvalues, which will
          help one to choose initial values for ELAM and DELAM.

          If DELAM = 0.0 on entry, it is given the default value of
          0.25*max(1.0,|ELAM|). On exit: with IFAIL = 0, DELAM holds
          an estimate of the absolute error in the computed
                               ~~~~~~~~
          eigenvalue, that is |(lambda)-ELAM|~=DELAM. (In Section 8.2
          we discuss the assumptions under which this is true.) The
          true error is rarely more than twice, or less than a tenth,
          of the estimated error.

          With IFAIL /= 0, DELAM may hold an estimate of the error, or
          its initial value, depending on the value of IFAIL. See
          Section 6 for further details.

     10:  HMAX(2,M) -- DOUBLE PRECISION array             Input/Output
          On entry: HMAX(1,j) a maximum step size to be used by the
          differential equation code in the jth sub-interval i  (as
                                                              j
          described in the specification of parameter XPOINT), for
          j=1,2,...,m-3. If it is zero the routine generates a maximum
          step size internally.

          It is recommended that HMAX(1,j) be set to zero unless the
          coefficient functions p and q have features (such as a
          narrow peak) within the jth sub-interval that could be '
          missed' if a long step were taken. In such a case HMAX(1,j)
          should be set to about half the distance over which the
          feature should be observed. Too small a value will increase
          the computing time for the routine. See Section 8 for
          further suggestions.

          The rest of the array is used as workspace. On exit: HMAX(
          1,m-1) and HMAX(1,m) contain the sensitivity coefficients
          (sigma) ,(sigma) , described in Section 8.6. Other entries
                 l        r
          contain diagnostic output in case of an error (see Section 6
          ).

     11:  MAXIT -- INTEGER                                Input/Output
          On entry: a bound on n , the number of root-finding
                                r
          iterations allowed, that is the number of trial values of
          (lambda) that are used. If MAXIT <= 0, no such bound is
          assumed. (See also under MAXFUN.) Suggested value: MAXIT =
          0. On exit: MAXIT will have been decreased by the number of
          iterations actually performed, whether or not it was
          positive on entry.

     12:  MAXFUN -- INTEGER                                      Input
          On entry: a bound on n , the number of calls to COEFFN made
                                f
          in any one root-finding iteration. If MAXFUN <= 0, no such
          bound is assumed. Suggested value: MAXFUN = 0.

          MAXFUN and MAXIT may be used to limit the computational cost
          of a call to D02KEF, which is roughly proportional to n *n .
                                                                 r  f

     13:  MONIT -- SUBROUTINE, supplied by the user.
                                               External Procedure
          MONIT is called by D02KEF at the end of each root-finding
          iteration and allows the user to monitor the course of the
          computation by printing out the parameters (see Section 8
          for an example).
          If no monitoring is required, the dummy subroutine D02KAY
          may be used. (D02KAY is included in the NAG Foundation
          Library).

          Its specification is:

                 SUBROUTINE MONIT (MAXIT, IFLAG, ELAM, FINFO)
                 INTEGER          MAXIT, IFLAG
                 DOUBLE PRECISION ELAM, FINFO(15)

           1:  MAXIT -- INTEGER                                  Input
               On entry: the current value of the parameter MAXIT of
               D02KEF; this is decreased by one at each iteration.

           2:  IFLAG -- INTEGER                                  Input
               On entry: IFLAG describes what phase the computation is
               in, as follows:
               IFLAG < 0
                     an error occurred in the computation of the '
                     miss-distance' at this iteration;

                     an error exit from D02KEF with IFAIL =-IFLAG will
                     follow.

               IFLAG = 1
                     the routine is trying to bracket the eigenvalue
                     ~~~~~~~~
                     (lambda).

               IFLAG = 2
                     the routine is converging to the eigenvalue
                     ~~~~~~~~
                     (lambda) (having already bracketed it).

           3:  ELAM -- DOUBLE PRECISION                          Input
               On entry: the current trial value of (lambda).

           4:  FINFO(15) -- DOUBLE PRECISION array               Input
               On entry: information about the behaviour of the
               shooting method, and diagnostic information in the case
               of errors. It should not normally be printed in full if
               no error has occurred (that is, if IFLAG > 0), though
               the first few components may be of interest to the
               user. In case of an error (IFLAG < 0) all the
               components of FINFO should be printed. The contents of
               FINFO are as follows:

               FINFO(1): the current value of the 'miss-distance' or '
               residual' function f((lambda)) on which the shooting
               method is based. FINFO(1) is set to zero if IFLAG < 0.

               FINFO(2): an estimate of the quantity dd(lambda)
               defined as follows. Consider the perturbation in the
               miss-distance f((lambda)) that would result if the
               local error, in the solution of the differential
               equation, were always positive and equal to its maximum
               permitted value. Then dd(lambda) is the perturbation in
               (lambda) that would have the same effect on f((lambda))
               . Thus, at the zero of f((lambda)),|dd(lambda)| is an
               approximate bound on the perturbation of the zero (that
               is the eigenvalue) caused by errors in numerical
               solution. If dd(lambda) is very large then it is
               possible that there has been a programming error in
               COEFFN such that q is independent of (lambda). If this
               is the case, an error exit with IFAIL = 5 should
               follow. FINFO(2) is set to zero if IFLAG < 0.

               FINFO(3): the number of internal iterations, using the
               same value of (lambda) and tighter accuracy tolerances,
               needed to bring the accuracy (that is the value of
               dd(lambda)) to an acceptable value. Its value should
               normally be 1.0, and should almost never exceed 2.0.

               FINFO(4): the number of calls to COEFFN at this
               iteration.

               FINFO(5): the number of successful steps taken by the
               internal differential equation solver at this
               iteration. A step is successful if it is used to
               advance the integration (cf. COUT(8) in specification
               of D02PAF(*)).

               FINFO(6): the number of unsuccessful steps used by the
               internal integrator at this iteration (cf. COUT(9) in
               specification of D02PAF(*)).

               FINFO(7): the number of successful steps at the maximum
               step size taken by the internal integrator at this
               iteration (cf. COUT(3) in specification of D02PAF(*)).

               FINFO(8): is not used.

               FINFO(9) to FINFO(15): set to zero, unless IFLAG < 0 in
               which case they hold the following values describing
               the point of failure:

               FINFO(9): contains the index of the sub-interval where
               failure occurred, in the range 1 to m-3. In case of an
               error in BDYVAL, it is set to 0 or m-2 depending on
               whether the left or right boundary condition caused the
               error.

               FINFO(10): the value f the independent variable x, the
               point at which error occurred. In case of an error in
               BDYVAL, it is set to the value of XL or XR as
               appropriate (see the specification of BDYVAL).

               FINFO(11), FINFO(12), FINFO(13): the current values of
               the Pruefer dependent variables (beta), (phi) and (rho)
               respectively. These are set to zero in case of an error
               in BDYVAL.

               FINFO(14): the local-error tolerance being used by the
               internal integrator at the point of failure. This is
               set to zero in the case of an error in BDYVAL.

               FINFO(15): the last integration mesh point. This is set
               to zero in the case of an error in BDYVAL.
          MONIT must be declared as EXTERNAL in the (sub)program
          from which D02KEF is called. Parameters denoted as
          Input must not be changed by this procedure.

     14:  REPORT -- SUBROUTINE, supplied by the user.
                                               External Procedure
          This routine provides the means by which the user may
          compute the eigenfunction y(x) and its derivative at each
          integration mesh point x. (See Section 8 for an example).

          Its specification is:

                 SUBROUTINE REPORT (X, V, JINT)
                 INTEGER          JINT
                 DOUBLE PRECISION X, V(3)

           1:  X -- DOUBLE PRECISION                             Input
               On entry: the current value of the independent variable
               x. See Section 8.3 for the order in which values of x
               are supplied.

           2:  V(3) -- DOUBLE PRECISION array                    Input
               On entry: V(1), V(2), V(3) hold the current values of
               the Pruefer variables (beta), (phi), (rho)
               respectively.

           3:  JINT -- INTEGER                                   Input
               On entry: JINT indicates the sub-interval between
               break-points in which X lies exactly as for the routine
               COEFFN, except that at the extreme left end-point (when
               x = XPOINT(2)) JINT is set to 0 and at the extreme
               right end-point (when x=x =XPOINT(m-1)) JINT is set to
                                        r
               m-2.
          REPORT must be declared as EXTERNAL in the (sub)program
          from which D02KEF is called. Parameters denoted as
          Input must not be changed by this procedure.

     15:  IFAIL -- INTEGER                                Input/Output
          On entry: IFAIL must be set to 0, -1 or 1. For users not
          familiar with this parameter (described in the Essential
          Introduction) the recommended value is 0.

          On exit: IFAIL = 0 unless the routine detects an error (see
          Section 6).

     6. Error Indicators and Warnings

     Errors detected by the routine:

     IFAIL= 1
          A parameter error. All parameters (except IFAIL) are left
          unchanged. The reason for the error is shown by the value of
          HMAX(2,1) as follows:
          HMAX(2,1) = 1: M < 4;

          HMAX(2,1) = 2: K < 0;

          HMAX(2,1) = 3: TOL <= 0.0;

          HMAX(2,1) = 4: XPOINT(1) to XPOINT(m) are not in ascending
                         order.

                         HMAX(2,2) gives the position i in XPOINT
                         where this was detected.

     IFAIL= 2
          At some call to BDYVAL, invalid values were returned, that
          is, either YL(1) = YL(2) = 0.0, or YR(1) = YR(2) = 0.0 (a
          programming error in BDYVAL). See the last call of MONIT for
          details.

          This error exit will also occur if p(x) is zero at the point
          where the boundary condition is imposed. Probably BDYVAL was
          called with XL equal to a singular end-point a or with XR
          equal to a singular end-point b.

     IFAIL= 3
          At some point between XL and XR the value of p(x) computed
          by COEFFN became zero or changed sign. See the last call of
          MONIT for details.

     IFAIL= 4
          MAXIT > 0 on entry, and after MAXIT iterations the
          eigenvalue had not been found to the required accuracy.

     IFAIL= 5
          The 'bracketing' phase (with parameter IFLAG of MONIT equal
          to 1) failed to bracket the eigenvalue within ten
          iterations. This is caused by an error in formulating the
          problem (for example, q is independent of (lambda)), or by
          very poor initial estimates of ELAM, DELAM.

          On exit ELAM and ELAM + DELAM give the end-points of the
          interval within which no eigenvalue was located by the
          routine.

     IFAIL= 6
          MAXFUN > 0 on entry, and the last iteration was terminated
          because more than MAXFUN calls to COEFFN were used. See the
          last call of MONIT for details.

     IFAIL= 7
          To obtain the desired accuracy the local error tolerance was
          set so small at the start of some sub-interval that the
          differential equation solver could not choose an initial
          step size large enough to make significant progress. See the
          last call of MONIT for diagnostics.

     IFAIL= 8
          At some point inside a sub-interval the step size in the
          differenital equation solver was reduced to a value too
          small to make significant progress (for the same reasons as
          with IFAIL = 7). This could be due to pathological behaviour
          of p(x) and q(x;(lambda)) or to an unreasonable accuracy
          requirement or to the current value of (lambda) making the
          equations 'stiff'. See the last call of MONIT for details.

     IFAIL= 9
          TOL is too small for the problem being solved and the
          machine precision is being used. The final value of ELAM
          should be a very good approximation to the eigenvalue.

     IFAIL= 10
          C05AZF(*), called by D02KEF, has terminated with the error
          exit corresponding to a pole of the residual function
          f((lambda)). This error exit should not occur, but if it
          does, try solving the problem again with a smaller value for
          TOL.

     IFAIL= 11
          A serious error has occurred in an internal call to D02KDY.
          Check all subroutine calls and array dimensions. Seek expert
          help.

     IFAIL= 12
          A serious error has occurred in an internal call to
          C05AZF(*). Check all subroutine calls and array dimensions.
          Seek expert help.

          HMAX(2,1) holds the failure exit number from the routine
          where the failure occurred. In the case of a failure in
          C05AZF(*), HMAX(2,2) holds the value of parameter IND of
          C05AZF(*).

     Note: error exits with IFAIL = 2, 3, 6, 7, 8, 11 are caused by
     being unable to set up or solve the differential equation at some
     iteration, and will be immediately preceded by a call of MONIT
     giving diagnostic information. For other errors, diagnostic
     information is contained in HMAX(2,j), for j=1,2,...,m, where
     appropriate.

     7. Accuracy

     See the discussion in Section 8.2.

     8. Further Comments

     8.1. Timing

     The time taken by the routine depends on the complexity of the
     coefficient functions, whether they or their derivatives are
     rapidly changing, the tolerance demanded, and how many iterations
     are needed to obtain convergence. The amount of work per
     iteration is roughly doubled when TOL is divided by 16. To make
     the most economical use of the routine, one should try to obtain
     good initial values for ELAM and DELAM, and, where appropriate,
     good asymptotic formulae. The boundary matching points should not
     be set unnecessarily close to singular points. The extra time
     needed to compute the eigenfunction is principally the cost of
     one additional integration once the eigenvalue has been found.

     8.2. General Description of the Algorithm

     A shooting method, for differential equation problems containing
     unknown parameters, relies on the construction of a 'miss-
     distance function', which for given trial values of the
     parameters measures how far the conditions of the problem are
     from being met. The problem is then reduced to one of finding the
     values of the parameters for which the miss-distance function is
     zero, that is to a root-finding process. Shooting methods differ
     mainly in how the miss-distance is defined.

     This routine defines a miss-distance f((lambda)) based on the
     rotation around the origin of the point P(x)=(p(x)y'(x),y(x)) in
     the Phase Plane as the solution proceeds from a to b. The
     boundary-conditions define the ray (i.e., two-sided line through
     the origin) on which p(x) should start, and the ray on which it
     should finish. The eigenvalue index k defines the total number of
     half-turns it should make. Numerical solution is actually done by
     matching point x=c. Then f((lambda)) is taken as the angle
     between the rays to the two resulting points P (c) and P (c). A
                                                   a         b
     relative scaling of the py' and y axes, based on the behaviour of
     the coefficient functions p and q, is used to improve the
     numerical behaviour.



              Please see figure in printed Reference Manual

     The resulting function f((lambda)) is monotonic over -
                                             ddq
     infty<(lambda)<infty, increasing if  ---------->0 and decreasing
                                          dd(lambda)
            ddq
     if  ----------<0, with a unique zero at the desired eigenvalue
         dd(lambda)
     ~~~~~~~~
     (lambda). The routine measures f((lambda)) in units of a half-
     turn. This means that as (lambda) increases, f((lambda)) varies
     by about 1 as each eigenvalue is passed. (This feature implies
     that the values of f((lambda)) at successive iterations -
     especially in the early stages of the iterative process - can be
     used with suitable extrapolation or interpolation to help the
     choice of initial estimates for eigenvalues near to the one
     currently being found.)

     The routine actually computes a value for f((lambda)) with
     errors, arising from the local errors of the differential
     equation code and from the asymptotic formulae provided by the
     user if singular points are involved. However, the error estimate
     output in DELAM is usually fairly realistic, in that the actual
            ~~~~~~~~
     error |(lambda)-ELAM| is within an order of magnitude of DELAM.

     We pass the values of (beta), (phi), (rho) across through REPORT
     rather than converting them to values of y, y' inside D02KEF, for
     the following reasons. First, there may be cases where auxiliary
     quantities can be more accurately computed from the Pruefer
     variables than from y and y'. Second, in singular problems on an
     infinite interval y and y' may underflow towards the end of the
     range, whereas the Pruefer variables remain well-behaved. Third,
     with high-order eigenvalues (and therefore highly oscillatory
     eigenfunctions) the eigenfunction may have a complete oscillation
     (or more than one oscillation) between two mesh points, so that
     values of y and y' at mesh points give a very poor representation
     of the curve. The probable behaviour of the Pruefer variables in
     this case is that (beta) and (rho) vary slowly whilst (phi)
     increases quickly: for all three Pruefer variables linear
     interpolation between the values at adjacent mesh points is
     probably sufficiently accurate to yield acceptable intermediate
     values of (beta), (phi), (rho) (and hence of y,y') for graphical
     purposes.

     Similar considerations apply to the exponentially decaying 'tails
     Here (phi) has approximately constant value whilst (rho)
     increases rapidly in the direction of integration, though the
     step length is generally fairly small over such a range.

     If the solution is output through REPORT at x-values which are
     too widely spaced, the step length can be controlled by choosing
     HMAX suitably, or, preferably, by reducing TOL. Both these
     choices will lead to more accurate eigenvalues and eigenfunctions
     but at some computational cost.

     8.3. The Position of the Shooting Matching Point c

     This point is always one of the values x  in array XPOINT. It may
                                             i
     be specified using the parameter MATCH. The default value is
     chosen to be the value of that x ,2<=i<=m-1, that lies closest to
                                     i
     the middle of the interval [x ,x   ]. If there is a tie, the
                                  2  m-1
     rightmost candidate is chosen. In particular if there are no
     break-points then c=x   (=x ) - that is the shooting is from left
                          m-1   3
     to right in this case. A break-point may be inserted purely to
     move c to an interior point of the interval, even though the form
     of the equations does not require it. This often speeds up
     convergence especially with singular problems.

     Note that the shooting method used by the code integrates first
     from the left-hand end x , then from the right-hand end x , to
                             l                                r
     meet at the matching point c in the middle. This will of course
     be reflected in printed or graphical output. The diagram shows a
     possible sequence of nine mesh points (tau)  through (tau)  in
                                                1              9
     the order in which they appear, assuming there are just two sub-
     intervals (so m=5).


                                Figure 1
              Please see figure in printed Reference Manual

     Since the shooting method usually fails to match up the two 'legs
     p(x)y' or both, at the matching point c. The code in fact 'shares
     large jump does not imply an inaccurate eigenvalue, but implies
     either

     (a)   a badly chosen matching point: if q(x;(lambda)) has a '
           humped' shape, c should be chosen near the maximum value of
           q, especially if q is negative at the ends of the interval.

     (b)   An inherently ill-conditioned problem, typically one where
           another eigenvalue is pathologically close to the one being
           sought. In this case it is extremely difficult to obtain an
           accurate eigenfunction.

     In Section 9 below, we find the 11th eigenvalue and corresponding
     eigenfunction of the equation

                                     2
                  y''+((lambda)-x-2/x )y=0  on  0<x<infty

     the boundary conditions being that y should remain bounded as x
     tends to 0 and x tends to infty. The coding of this problem is
     discussed in detail in Section 8.5.

     The choice of matching point c is open. If we choose c=30.0 as in
     the D02KDF(*) example program we find that the exponentially
     increasing component of the solution dominates and we get
     extremely inaccurate values for the eigenfunction (though the
     eigenvalue is determined accurately). The values of the
     eigenfunction calculated with c=30.0 are given schematically in
     Figure 2.


                                Figure 2
              Please see figure in printed Reference Manual

     If we choose c as the maximum of the hump in q(x;(lambda)) (see
     (a) above) we instead obtain the accurate results given in
     Figure 3.


                                Figure 3
              Please see figure in printed Reference Manual

     8.4. Examples of Coding the COEFFN Routine

     Coding COEFFN is straightforward except when break-points are
     needed. The examples below show:

     (a)   a simple case,

     (b)   a case in which discontinuities in the coefficient
           functions or their derivatives necessitate break-points,
           and

     (c)   a case where break-points together with the HMAX parameter
           are an efficient way to deal with a coefficient function
           that is well-behaved except over one short interval.

     Example A

     The modified Bessel equation

                                         2     2
                       x(xy')'+((lambda)x -(nu) )y=0

     Assuming the interval of solution does not contain the origin,
     dividing through by x, we have p(x)=x,
                                 2
     q(x;(lambda))=(lambda)x-(nu) /x. The code could be


           SUBROUTINE COEFFN(P,Q,DQDL,X,ELAM,JINT)
           P = X
           Q = ELAM*X + NU*NU/X
           DQDL = X
           RETURN
           END


     where NU (standing for (nu)) is a real variable that might be
     defined in a DATA statement, or might be in user-declared COMMON
     so that its value could be set in the main program.

     Example B

     The Schroedinger equation

                          y''+((lambda)+q(x))y=0

                { 2
                {x -10 (|x|<=4),
     where q(x)={6/|x| (|x|>4),

     over some interval 'approximating to (-infty,infty)', say [-20,
     20]. Here we need break-points at +- 4, forming three sub-
     intervals i =[-20,-4], i =[-4,4],i =[4,20]. The code could be
                1            2         3


           SUBROUTINE COEFFN(P,Q,DQDL,X,ELAM,JINT)
           IF (JINT.EQ.2) THEN
             Q = ELAM + X*X - 10.0E0
           ELSE
             Q = ELAM + 6.0E0/ABS(X)
           ENDIF
           P = 1.0E0
           DQDL = 1.0E0
           RETURN
           END


     The array XPOINT would contain the values x , -20.0, -4.0, +4.0,
                                                1
     +20.0, x  and m would be 6. The choice of appropriate values for
             6
     x  and x  depends on the form of the asymptotic formula computed
      1      6
     by BDYVAL and the technique is discussed in the next subsection.

     Example C

                                     2
                                -100x

               y''+(lambda)(1-2e      )y=0, over -10<=x<=10

     Here q(x;(lambda)) is nearly constant over the range except for a
     sharp inverted spike over approximately -0.1<=x<=0.1. There is a
     danger that the routine will build up to a large step size and '
     step over' the spike without noticing it. By using break-points -
     say at +- 0.5 - one can restrict the step size near the spike
     without impairing the efficiency elsewhere.

     The code for COEFFN could be


           SUBROUTINE COEFFN(P,Q,DQDL,X,ELAM,JINT)
           P = 1.0E0
           DQDL = 1.0E0 - 2.0E0*EXP(-100.0E0*X*X)
           Q = ELAM*DQDL
           RETURN
           END


     XPOINT might contain -0.0, -10.0, -0.5, 0.5, 10.0, 10.0 (assuming
     +- 10 are regular points) and m would be 6. HMAX(1,j), j=1,2,3
     might contain 0.0, 0.1 and 0.0.

     8.5. Examples of Boundary Conditions at Singular Points

     Quoting from Bailey [2] page 243: 'Usually... the differential
     equation has two essentially different types of solution near a
     singular point, and the boundary condition there merely serves to
     distinguish one kind from the other. This is the case in all the
     standard examples of mathematical physics.'

     In most cases the behaviour of the ratio p(x)y'/y near the point
     is quite different for the two types of solution. Essentially
     what the user provides through his BDYVAL routine is an
     approximation to this ratio, valid as x tends to the singular
     point (SP).

     The user must decide (a) how accurate to make this approximation
     or asymptotic formula, for example how many terms of a series to
     use, and (b) where to place the boundary matching point (BMP) at
     which the numerical solution of the differential equation takes
     over from the asymptotic formula. Taking the BMP closer to the SP
     will generally improve the accuracy of the asymptotic formula,
     but will make the computation more expensive as the Pruefer
     differential equations generally become progressively more ill-
     behaved as the SP is approached. The user is strongly recommended
     to experiment with placing the BMPs. In many singular problems
     quite crude asymptotic formulae will do. To help the user avoid
     needlessly accurate formulae, D02KEF outputs two 'sensitivity
     coefficients' (sigma) ,(sigma)  which estimate how much the
                          l        r
     errors at the BMP's affect the computed eigenvalue. They are
     described in detail below, see Section 8.6.

     Example of coding BDYVAL:

     The example below illustrates typical situations:

                      (            2 )
                  y''+((lambda)-x- --)y=0, for 0<x<infty
                      (             2)
                      (            x )

     the boundary conditions being that y should remain bounded as x
     tends to 0 and x tends to infty.

                                                             2
     At the end x=0 there is one solution that behaves like x  and
                                -1
     another that behaves like x  . For the first of these solutions
     p(x)y'/y is asymptotically 2/x while for the second it is
     asymptotically -1/x. Thus the desired ratio is specified by
     setting

                          YL(1)=x and YL(2)=2.0.

     At the end x=infty the equation behaves like Airy's equation
     shifted through (lambda), i.e., like y''-ty=0 where t=x-(lambda),
     so again there are two types of solution. The solution we require
     behaves as

                                (  2 3/2) 4 _
                             exp(- -t   )/\/t
                                (  3    )

     and the other as

                                (  2 3/2) 4 _
                             exp(+ -t   )/\/t
                                (  3    )

                                                _
     once, the desired solution has p(x)y'/y~-\/t so that we could set
                              __________
     YR(1) = 1.0 and YR(2)=-\/x-(lambda). The complete subroutine
     might thus be


           SUBROUTINE BDYVAL(XL,XR,ELAM,YL,YR)
           real XL, XR, ELAM, YL(3), YR(3)
           YL(1) = XL
           YL(2) = 2.0E0
           YR(1) = 1.0E0
           YR(2) = -SQRT(XR - ELAM)
           RETURN
           END


     Clearly for this problem it is essential that any value given by
     D02KEF to XR is well to the right of the value of ELAM, so that
     the user must vary the right-hand BMP with the eigenvalue index k
                                k
     function Ai(x), so there is no problem in estimating ELAM.

     More accurate asymptotic formulae are easily found - near x=0 by
     the standard Frobenius method, and near x=infty by using standard
     asymptotics for Ai(x), Ai'(x) (see [1], p. 448). For example, by
     the Frobenius method the solution near x=0 has the expansion

                              2           2
                           y=x (c +c x+c x +...)
                                 0  1   2

     with

                                                c   -(lambda)c
                        (lambda)     1           n-3          n-2
         c =1,c =0,c =- --------,c = --,...,c = -----------------
          0    1    2      10     3  18      n       n(n+3)

     This yields

                                   2         2
                                2- -(lambda)x +...
                       p(x)y'      5
                       ------= --------------------.
                         y      (   (lambda) 2    )
                               x(1- --------x +...)
                                (      10         )

     8.6. The Sensitivity Parameters (sigma)  and (sigma)
                                            l            r

     The sensitivity parameters (sigma) ,(sigma)  (held in HMAX(1,m-1)
                                       l        r
     and HMAX(1,m) on output) estimate the effect of errors in the
     boundary conditions. For sufficiently small errors (Delta)y,
     (Delta)py' in y and py' respectively, the relations

           (Delta)(lambda)~=(y.(Delta)py'-py'.(Delta)y) (sigma)
                                                       l       l

           (Delta)(lambda)~=(y.(Delta)py'-py'.(Delta)y) (sigma)
                                                       r       r

     are satisfied where the subscripts l, r denote errors committed
     at left- and right-hand BMP's respectively, and (Delta)(lambda)
     denotes the consequent error in the computed eigenvalue.

     8.7. Missed Zeros

     This is a pitfall to beware of at a singular point. If the BMP is
     chosen so far from the SP that a zero of the desired
     eigenfunction lies in between them, then the routine will fail to
     number of zeros of its eigenfunction, the result will be that:

     (a)   The wrong eigenvalue will be computed for the given index k
           - in fact some (lambda)     will be found where k'>=1.
                                  k+k'

     (b)   The same index k can cause convergence to any of several
           eigenvalues depending on the initial values of ELAM and
           DELAM.

     It is up to the user to take suitable precautions - for instance
     by varying the position of the BMP's in the light of his
     knowledge of the asymptotic behaviour of the eigenfunction at
     different eigenvalues.

     9. Example

     To find the 11th eigenvalue and eigenfunction of the example of
     Section 8.5, using the simple asymptotic formulae for the
     boundary conditions.

     Comparison of the results from this example program with the
     corresponding results from D02KDF(*) example program shows that
     similar output is produced from the routine MONIT, followed by
     the eigenfunction values from REPORT, and then a further line of
     information from MONIT (corresponding to the integration to find
     the eigenfunction). Final information is printed within the
     example program exactly as with D02KDF(*).

                                                   3 _
     Note the discrepancy at the matching point c(=\/4 , the maximum
     of q(x;(lambda)), in this case) between the solutions obtained by
     integrations from left and right end-points.

     The example program is not reproduced here. The source code for
     all example programs is distributed with the NAG Foundation
     Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd02raf}{nagd.ht}
{ Two-point boundary-value ODE equation systems}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd02raf}{NAG Documentation: d02raf}
\beginscroll
\begin{verbatim}



     D02RAF(3NAG)      Foundation Library (12/10/92)      D02RAF(3NAG)



          D02 -- Ordinary Differential Equations                     D02RAF
                  D02RAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          D02RAF solves the two-point boundary-value problem with general
          boundary conditions for a system of ordinary differential
          equations, using a deferred correction technique and Newton
          iteration.

          2. Specification

                 SUBROUTINE D02RAF (N, MNP, NP, NUMBEG, NUMMIX, TOL, INIT,
                1                   X, Y, IY, ABT, FCN, G, IJAC, JACOBF,
                2                   JACOBG, DELEPS, JACEPS, JACGEP, WORK,
                3                   LWORK, IWORK, LIWORK, IFAIL)
                 INTEGER          N, MNP, NP, NUMBEG, NUMMIX, INIT, IY,
                1                 IJAC, LWORK, IWORK(LIWORK), LIWORK, IFAIL
                 DOUBLE PRECISION TOL, X(MNP), Y(IY,MNP), ABT(N), DELEPS,
                1                 WORK(LWORK)
                 EXTERNAL         FCN, G, JACOBF, JACOBG, JACEPS, JACGEP

          3. Description

          D02RAF solves a two-point boundary-value problem for a system of
          n ordinary differential equations in the interval (a,b) with b>a.
          The system is written in the form

                      y '=f (x,y ,y ,...,y ) , i=1,2,...,n              (1)
                       i   i    1  2      n

          and the derivatives f  are evaluated by a subroutine FCN supplied
                               i
          by the user. With the differential equations (1) must be given a
          system of n (nonlinear) boundary conditions

                            g (y(a),y(b))=0 , i=1,2,...,n
                             i

          where

                                                     T
                         y(x)=[y (x),y (x),...,y (x)] .                 (2)
                                1     2         n

          The functions g  are evaluated by a subroutine G supplied by the
                         i
          user. The solution is computed using a finite-difference
          technique with deferred correction allied to a Newton iteration
          to solve the finite-difference equations. The technique used is
          described fully in Pereyra [1].

          The user must supply an absolute error tolerance and may also
          supply an initial mesh for the finite-difference equations and an
          initial approximate solution (alternatively a default mesh and
          approximation are used). The approximate solution is corrected
          using Newton iteration and deferred correction. Then, additional
          points are added to the mesh and the solution is recomputed with
          the aim of making the error everywhere less than the user's
          tolerance and of approximately equidistributing the error on the
          final mesh. The solution is returned on this final mesh.

          If the solution is required at a few specific points then these
          should be included in the initial mesh. If, on the other hand,
          the solution is required at several specific points then the user
          should use the interpolation routines provided in Chapter E01 if
          these points do not themselves form a convenient mesh.

          The Newton iteration requires Jacobian matrices

                          ( ddf )  (  ddg   )     (  ddg   )
                          (    i)  (     i  )     (     i  )
                          ( ----), ( -------) and ( -------).
                          ( ddy )  ( ddy (a))     ( ddy (b))
                          (    j)  (    j   )     (    j   )

          These may be supplied by the user through subroutines JACOBF for
          ( ddf )
          (    i)
          ( ----) and JACOBG for the others. Alternatively the Jacobians
          ( ddy )
          (    j)
          may be calculated by numerical differentiation using the
          algorithm described in Curtis et al [2].

          For problems of the type (1) and (2) for which it is difficult to
          determine an initial approximation from which the Newton
          iteration will converge, a continuation facility is provided. The
          user must set up a family of problems

                y'=f(x,y,(epsilon)),   g(y(a),y(b),(epsilon))=0,        (3)

                                T
          where f=[f ,f ,...,f ]  etc, and where (epsilon) is a
                    1  2      n
          continuation parameter. The choice (epsilon)=0 must give a
          problem (3) which is easy to solve and (epsilon)=1 must define
          the problem whose solution is actually required. The routine
          solves a sequence of problems with (epsilon) values

                   0=(epsilon) <(epsilon) <...<(epsilon) =1.            (4)
                              1          2              p

          The number p and the values (epsilon)  are chosen by the routine
                                               i
          so that each problem can be solved using the solution of its
                                                                  ddf
          predecessor as a starting approximation. Jacobians  -----------
                                                              dd(epsilon)
                   ddg
          and  ----------- are required and they may be supplied by the
               dd(epsilon)
          user via routines JACEPS and JACGEP respectively or may be
          computed by numerical differentiation.

          4. References

          [1]   Pereyra V (1979) PASVA3: An Adaptive Finite-Difference
                Fortran Program for First Order Nonlinear, Ordinary Boundary
                Problems. Codes for Boundary Value Problems in Ordinary
                Differential Equations. Lecture Notes in Computer Science.
                (ed B Childs, M Scott, J W Daniel, E Denman and P Nelson) 76
                Springer-Verlag.

          [2]   Curtis A R, Powell M J D and Reid J K (1974) On the
                Estimation of Sparse Jacobian Matrices. J. Inst. Maths
                Applics. 13 117--119.

          5. Parameters

           1:  N -- INTEGER                                           Input
               On entry: the number of differential equations, n.
               Constraint: N > 0.

           2:  MNP -- INTEGER                                         Input
               On entry: MNP must be set to the maximum permitted number
               of points in the finite-difference mesh. If LWORK or LIWORK
               (see below) is too small then internally MNP will be
               replaced by the maximum permitted by these values. (A
               warning message will be output if on entry IFAIL is set to
               obtain monitoring information.) Constraint: MNP >= 32.

           3:  NP -- INTEGER                                   Input/Output
               On entry: NP must be set to the number of points to be used
               in the initial mesh. Constraint: 4 <= NP <= MNP. On exit:
               the number of points in the final mesh.

           4:  NUMBEG -- INTEGER                                      Input
               On entry: the number of left-hand boundary conditions (that
               is the number involving y(a) only). Constraint: 0 <= NUMBEG
               < N.

           5:  NUMMIX -- INTEGER                                      Input
               On entry: the number of coupled boundary conditions (that
               is the number involving both y(a) and y(b)). Constraint: 0
               <= NUMMIX <= N - NUMBEG.

           6:  TOL -- DOUBLE PRECISION                                Input
               On entry: a positive absolute error tolerance. If
                                    a=x <x <...<x  =b
                                       1  2      NP
               is the final mesh, z (x ) is the jth component of the
                                   j  i
               approximate solution at x , and y (x) is the jth component
                                        i       j
               of the true solution of (1) and (2), then, except in extreme
               circumstances, it is expected that
                 |z (x )-y (x )|<=TOL , i=1,2,...,NP ; j=1,2,...,n.     (5)
                   j  i   j  i
                Constraint: TOL > 0.0.

           7:  INIT -- INTEGER                                        Input
               On entry: indicates whether the user wishes to supply an
               initial mesh and approximate solution (INIT /= 0) or whether
               default values are to be used, (INIT = 0).

           8:  X(MNP) -- DOUBLE PRECISION array                Input/Output
               On entry: the user must set X(1) = a and X(NP) = b. If INIT
               = 0 on entry a default equispaced mesh will be used,
               otherwise the user must specify a mesh by setting X(i)=x ,
                                                                       i
               for i = 2,3,...NP-1. Constraints:
                      X(1) < X(NP), if INIT = 0,

                      X(1) < X(2) <... < X(NP), if INIT /= 0.
               On exit: X(1),X(2),...,X(NP) define the final mesh (with
               the returned value of NP) and X(1) = a and X(NP) = b.

           9:  Y(IY,MNP) -- DOUBLE PRECISION array             Input/Output
               On entry: if INIT = 0, then Y need not be set.

               If INIT /= 0, then the array Y must contain an initial
               approximation to the solution such that Y(j,i) contains an
               approximation to
                           y (x ) , i=1,2,...,NP ; j=1,2,...,n.
                            j  i
               On exit: the approximate solution z (x ) satisfying (5) on
                                                  j  i
               the final mesh, that is
                       Y(j,i)=z (x ) , i=1,2,...,NP ; j=1,2,...,n,
                               j  i
               where NP is the number of points in the final mesh. If an
               error has occurred then Y contains the latest approximation
               to the solution. The remaining columns of Y are not used.

          10:  IY -- INTEGER                                          Input
               On entry:
               the first dimension of the array Y as declared in the
               (sub)program from which D02RAF is called.
               Constraint: IY >= N.

          11:  ABT(N) -- DOUBLE PRECISION array                      Output
               On exit: ABT(i), for i=1,2,...,n, holds the largest
               estimated error (in magnitude) of the ith component of the
               solution over all mesh points.

          12:  FCN -- SUBROUTINE, supplied by the user.
                                                         External Procedure
               FCN must evaluate the functions f  (i.e., the derivatives
                                                i
               y' ) at a general point x for a given value of (epsilon),
                 i
               the continuation parameter (see Section 3).

               Its specification is:

                      SUBROUTINE FCN (X, EPS, Y, F, N)
                      INTEGER          N
                      DOUBLE PRECISION X, EPS, Y(N), F(N)

                1:  X -- DOUBLE PRECISION                             Input
                    On entry: the value of the argument x.

                2:  EPS -- DOUBLE PRECISION                           Input
                    On entry: the value of the continuation parameter,
                    (epsilon). This is 1 if continuation is not being used.

                3:  Y(N) -- DOUBLE PRECISION array                    Input
                    On entry: the value of the argument y , for
                                                         i
                    i=1,2,...,n.

                4:  F(N) -- DOUBLE PRECISION array                   Output
                    On exit: the values of f , for i=1,2,...,n.
                                            i

                5:  N -- INTEGER                                      Input
                    On entry: the number of equations.
               FCN must be declared as EXTERNAL in the (sub)program
               from which D02RAF is called. Parameters denoted as
               Input must not be changed by this procedure.

          13:  G -- SUBROUTINE, supplied by the user.
                                                    External Procedure
               G must evaluate the boundary conditions in equation (3) and
               place them in the array BC.

               Its specification is:

                      SUBROUTINE G (EPS, YA, YB, BC, N)
                      INTEGER          N
                      DOUBLE PRECISION EPS, YA(N), YB(N), BC(N)

                1:  EPS -- DOUBLE PRECISION                           Input
                    On entry: the value of the continuation parameter,
                    (epsilon). This is 1 if continuation is not being used.

                2:  YA(N) -- DOUBLE PRECISION array                   Input
                    On entry: the value y (a), for i=1,2,...,n.
                                         i

                3:  YB(N) -- DOUBLE PRECISION array                   Input
                    On entry: the value y (b), for i=1,2,...,n.
                                         i

                4:  BC(N) -- DOUBLE PRECISION array                  Output
                    On exit: the values g (y(a),y(b),(epsilon)), for
                                         i
                    i=1,2,...,n. These must be ordered as follows:
                      (i)   first, the conditions involving only y(a) (see
                            NUMBEG description above);

                      (ii)  next, the NUMMIX coupled conditions involving
                            both y(a) and y(b) (see NUMMIX description
                            above); and,

                      (iii) finally, the conditions involving only y(b) (N-
                            NUMBEG-NUMMIX).

                5:  N -- INTEGER                                      Input
                    On entry: the number of equations, n.
               G must be declared as EXTERNAL in the (sub)program from
               which D02RAF is called. Parameters denoted as Input
               must not be changed by this procedure.

          14:  IJAC -- INTEGER                                   Input
               On entry: indicates whether or not the user is supplying
               Jacobian evaluation routines. If IJAC /= 0 then the user
               must supply routines JACOBF and JACOBG and also, when
               continuation is used, routines JACEPS and JACGEP. If IJAC =
               0 numerical differentiation is used to calculate the
               Jacobian and the routines D02GAZ, D02GAY, D02GAZ and D02GAX
                                                 ( ddf )
                                                 (    i)
               JACOBF must evaluate the Jacobian ( ----) for i,j=1,2,...,n,
                                                 ( ddy )
                                                 (    j)
               given x and y , for j=1,2,...,n.
                            j

               Its specification is:

                      SUBROUTINE JACOBF (X, EPS, Y, F, N)
                      INTEGER          N
                      DOUBLE PRECISION X, EPS, Y(N), F(N,N)

                1:  X -- DOUBLE PRECISION                             Input
                    On entry: the value of the argument x.

                2:  EPS -- DOUBLE PRECISION                           Input
                    On entry: the value of the continuation parameter
                    (epsilon). This is 1 if continuation is not being used.

                3:  Y(N) -- DOUBLE PRECISION array                    Input
                    On entry: the value of the argument y , for
                                                         i
                    i=1,2,...,n.

                4:  F(N,N) -- DOUBLE PRECISION array                 Output
                                                                  ddf
                                                                     i
                    On exit: F(i,j) must be set to the value of   ----,
                                                                  ddy
                                                                     j
                    evaluated at the point (x,y), for i,j=1,2,...,n.

                5:  N -- INTEGER                                      Input
                    On entry: the number of equations, n.
               JACOBF must be declared as EXTERNAL in the (sub)program
               from which D02RAF is called. Parameters denoted as
               Input must not be changed by this procedure.

          16:  JACOBG -- SUBROUTINE, supplied by the user.
                                                         External Procedure
                                                  (  ddg   )     (  ddg   )
                                                  (     i  )     (     i  )
               JACOBG must evaluate the Jacobians ( -------) and ( -------)
                                                  ( ddy (a))     ( ddy (b))
                                                  (    j   )     (    j   )
               The ordering of the rows of AJ and BJ must correspond to
               the ordering of the boundary conditions described in the
               specification of subroutine G above.

               Its specification is:

                      SUBROUTINE JACOBG (EPS, YA, YB, AJ, BJ, N)
                      INTEGER          N
                      DOUBLE PRECISION EPS, YA(N), YB(N), AJ(N,N), BJ
                     1                 (N,N)

                1:  EPS -- DOUBLE PRECISION                           Input
                    On entry: the value of the continuation parameter,
                    (epsilon). This is 1 if continuation is not being used.

                2:  YA(N) -- DOUBLE PRECISION array                   Input
                    On entry: the value y (a), for i=1,2,...,n.
                                          i

                3:  YB(N) -- DOUBLE PRECISION array                   Input
                    On entry: the value y (b), for i=1,2,...,n.
                                         i

                4:  AJ(N,N) -- DOUBLE PRECISION array                Output
                                                                ddg
                                                                   i
                    On exit: AJ(i,j) must be set to the value  -------,
                                                               ddy (a)
                                                                  j
                    for i,j=1,2,...,n.

                5:  BJ(N,N) -- DOUBLE PRECISION array                Output
                                                                ddg
                                                                   i
                    On exit: BJ(i,j) must be set to the value  -------,
                                                               ddy (b)
                                                                  j
                    for i,j=1,2...,n.

                6:  N -- INTEGER                                      Input
                    On entry: the number of equations, n.
               JACOBG must be declared as EXTERNAL in the (sub)program
               from which D02RAF is called. Parameters denoted as
               Input must not be changed by this procedure.

          17:  DELEPS -- DOUBLE PRECISION                      Input/Output
               On entry: DELEPS must be given a value which specifies
               whether continuation is required. If DELEPS <= 0.0 or DELEPS
               >= 1.0 then it is assumed that continuation is not required.
               If 0.0 < DELEPS < 1.0 then it is assumed that continuation
               is required unless DELEPS < square root of machine precision
               when an error exit is taken. DELEPS is used as the increment
               (epsilon) -(epsilon)  (see (4)) and the choice DELEPS = 0.1
                        2          1
               is recommended. On exit: an overestimate of the increment
               (epsilon) -(epsilon)    (in fact the value of the increment
                        p          p-1
               which would have been tried if the restriction (epsilon) =1
                                                                       p
               had not been imposed). If continuation was not requested
               then DELEPS = 0.0.

               If continuation is not requested then the parameters JACEPS
               and JACGEP may be replaced by dummy actual parameters in the
               call to D02RAF. (D02GAZ and D02GAX respectively may be used
               as the dummy parameters.)

          18:  JACEPS -- SUBROUTINE, supplied by the user.
                                                         External Procedure
                                                       ddf
                                                          i
               JACEPS must evaluate the derivative  ----------- given x and
                                                    dd(epsilon)
               y if continuation is being used.

               Its specification is:

                      SUBROUTINE JACEPS (X, EPS, Y, F, N)
                      INTEGER          N
                      DOUBLE PRECISION X, EPS, Y(N), F(N)

                1:  X -- DOUBLE PRECISION                             Input
                    On entry: the value of the argument x.

                2:  EPS -- DOUBLE PRECISION                           Input
                    On entry: the value of the continuation parameter,
                    (epsilon).

                3:  Y(N) -- DOUBLE PRECISION array                    Input
                    On entry: the solution values y  at the point x, for
                                                   i
                    i=1,2,...,n.

                4:  F(N) -- DOUBLE PRECISION array                   Output
                                                             ddf
                                                                i
                    On exit: F(i) must contain the value  ----------- at
                                                          dd(epsilon)
                    the point (x,y), for i=1,2,...,n.

                5:  N -- INTEGER                                      Input
                    On entry: the number of equations, n.
               JACEPS must be declared as EXTERNAL in the (sub)program
               from which D02RAF is called. Parameters denoted as
               Input must not be changed by this procedure.

          19:  JACGEP -- SUBROUTINE, supplied by the user.
                                                         External Procedure
                                                        ddg
                                                           i
               JACGEP must evaluate the derivatives  ----------- if
                                                     dd(epsilon)
               continuation is being used.

               Its specification is:

                      SUBROUTINE JACGEP (EPS, YA, YB, BCEP, N)
                      INTEGER          N
                      DOUBLE PRECISION EPS, YA(N), YB(N), BCEP(N)

                1:  EPS -- DOUBLE PRECISION                           Input
                    On entry: the value of the continuation parameter,
                    (epsilon).

                2:  YA(N) -- DOUBLE PRECISION array                   Input
                    On entry: the value of y (a), for i=1,2,...,n.
                                            i

                3:  YB(N) -- DOUBLE PRECISION array                   Input
                    On entry: the value of y (b), for i=1,2,...,n.
                                            i

                4:  BCEP(N) -- DOUBLE PRECISION array                Output
                    On exit: BCEP(i) must contain the value of
                        ddg
                           i
                     -----------, for i=1,2,...,n.
                     dd(epsilon)

                5:  N -- INTEGER                                      Input
                    On entry: the number of equations, n.
               JACGEP must be declared as EXTERNAL in the (sub)program
               from which D02RAF is called. Parameters denoted as
               Input must not be changed by this procedure.

          20:  WORK(LWORK) -- DOUBLE PRECISION array              Workspace

          21:  LWORK -- INTEGER                                       Input
               On entry:
               the dimension of the array WORK as declared in the
               (sub)program from which D02RAF is called.
                                         2         2
               Constraint: LWORK>=MNP*(3N +6N+2)+4N +3N.

          22:  IWORK(LIWORK) -- INTEGER array                     Workspace

          23:  LIWORK -- INTEGER                                      Input
               On entry:
               the dimension of the array IWORK as declared in the
               (sub)program from which D02RAF is called.
               Constraints:
                    LIWORK>=MNP*(2*N+1)+N, if IJAC /= 0,

                                         2
                    LIWORK>=MNP*(2*N+1)+N +4*N+2, if IJAC = 0.

          24:  IFAIL -- INTEGER                                Input/Output
               For this routine, the normal use of IFAIL is extended to
               control the printing of error and warning messages as well
               as specifying hard or soft failure (see the Essential
               Introduction).

               Before entry, IFAIL must be set to a value with the decimal
               expansion cba, where each of the decimal digits c, b and a
               must have a value of 0 or 1.
               a=0   specifies hard failure, otherwise soft failure;

               b=0   suppresses error messages, otherwise error messages
                     will be printed (see Section 6);

               c=0   suppresses warning messages, otherwise warning
                     messages will be printed (see Section 6).
               The recommended value for inexperienced users is 110 (i.e.,
               hard failure with all messages printed).

               Unless the routine detects an error (see Section 6), IFAIL
               contains 0 on exit.

          6. Error Indicators and Warnings

          Errors detected by the routine:

          For each error, an explanatory error message is output on the
          current error message unit (as defined by X04AAF), unless
          suppressed by the value of IFAIL on entry.

          IFAIL= 1
               One or more of the parameters N, MNP, NP, NUMBEG, NUMMIX,
               TOL, DELEPS, LWORK or LIWORK has been incorrectly set, or X
               (1) >= X(NP) or the mesh points X(i) are not in strictly
               ascending order.

          IFAIL= 2
               A finer mesh is required for the accuracy requested; that is
               MNP is not large enough. This error exit normally occurs
               when the problem being solved is difficult (for example,
               there is a boundary layer) and high accuracy is requested. A
               poor initial choice of mesh points will make this error exit
               more likely.

          IFAIL= 3
               The Newton iteration has failed to converge. There are
               several possible causes for this error:
               (i)   faulty coding in one of the Jacobian calculation
                     routines;

               (ii)  if IJAC = 0 then inaccurate Jacobians may have been
                     calculated numerically (this is a very unlikely
                     cause); or,

               (iii) a poor initial mesh or initial approximate solution
                     has been selected either by the user or by default or
                     there are not enough points in the initial mesh.
                     Possibly, the user should try the continuation
                     facility.

          IFAIL= 4
               The Newton iteration has reached round-off error level. It
               could be however that the answer returned is satisfactory.
               The error is likely to occur if too high an accuracy is
               requested.

          IFAIL= 5
               The Jacobian calculated by JACOBG (or the equivalent matrix
               calculated by numerical differentiation) is singular. This
               may occur due to faulty coding of JACOBG or, in some
               circumstances, to a zero initial choice of approximate
               solution (such as is chosen when INIT = 0).

          IFAIL= 6
               There is no dependence on (epsilon) when continuation is
               being used. This can be due to faulty coding of JACEPS or
               JACGEP or, in some circumstances, to a zero initial choice
               of approximate solution (such as is chosen when INIT = 0).

          IFAIL= 7
               DELEPS is required to be less than machine precision for
               continuation to proceed. It is likely that either the
               problem (3) has no solution for some value near the current
               value of (epsilon) (see the advisory print out from D02RAF)
               or that the problem is so difficult that even with
               continuation it is unlikely to be solved using this routine.
               If the latter cause is suspected then using more mesh points
               initially may help.

          IFAIL= 8
               Indicates that a serious error has occurred in a call to
               D02RAF. Check all array subscripts and subroutine parameter
               lists in calls to D02RAF. Seek expert help.

          IFAIL= 9
               Indicates that a serious error has occurred in a call to
               D02RAR. Check all array subscripts and subroutine parameter
               lists in calls to D02RAF. Seek expert help.

          7. Accuracy

          The solution returned by the routine will be accurate to the
          user's tolerance as defined by the relation (5) except in extreme
          circumstances. The final error estimate over the whole mesh for
          each component is given in the array ABT. If too many points are
          specified in the initial mesh, the solution may be more accurate
          than requested and the error may not be approximately
          equidistributed.

          8. Further Comments

          There are too many factors present to quantify the timing. The
          time taken by the routine is negligible only on very simple
          problems.

          The user is strongly recommended to set IFAIL to obtain self-
          explanatory error messages, and also monitoring information about
          the course of the computation.

          In the case where the user wishes to solve a sequence of similar
          problems, the use of the final mesh and solution from one case as
          the initial mesh is strongly recommended for the next.

          9. Example

          We solve the differential equation

                                                      2
                            y'''=-yy''-2(epsilon)(1-y' )

          with (epsilon)=1 and boundary conditions

                               y(0)=y'(0)=0,  y'(10)=1

          to an accuracy specified by TOL=1.0E-4. The continuation facility
          is used with the continuation parameter (epsilon) introduced as
          in the differential equation above and with DELEPS = 0.1
          initially. (The continuation facility is not needed for this
          problem and is used here for illustration.)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd03}{nagd.ht}{ Partial differential equations}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd03}{NAG Documentation: d03}
\beginscroll
\begin{verbatim}



     D03(3NAG)         Foundation Library (12/10/92)         D03(3NAG)



          D03 -- Partial Differential Equations         Introduction -- D03
                                    Chapter D03
                          Partial Differential Equations

          1. Scope of the Chapter

          This chapter is concerned with the solution of partial
          differential equations.

          2. Background to the Problems

          The definition of a partial differential equation problem
          includes not only the equation itself but also the domain of
          interest and appropriate subsidiary conditions. Indeed, partial
          differential equations are usually classified as elliptic,
          hyperbolic or parabolic according to the form of the equation and
          the form of the subsidiary conditions which must be assigned to
          produce a well-posed problem. Ultimately it is hoped that this
          chapter will contain routines for the solution of equations of
          each of these types together with automatic mesh generation
          routines and other utility routines particular to the solution of
          partial differential equations. The routines in this chapter will
          often call upon routines from the Linear Algebra Chapter F04 --
          Simultaneous Linear Equations.

          The classification of partial differential equations is easily
          described in the case of linear equations of the second order in
          two independent variables, i.e., equations of the form

                        au  +2bu  +cu  +du +eu +fu+g=0,                 (1)
                          xx    xy   yy   x   y

          where a, b, c, d, e, f and g are functions of x and y only.
          Equation (1) is called elliptic, hyperbolic or parabolic
                           2
          according as ac-b  is positive, negative or zero. Useful
          definitions of the concepts of elliptic, hyperbolic and parabolic
          character can also be given for differential equations in more
          than two independent variables, for systems and for nonlinear
          differential equations.

          For elliptic equations, of which Laplace's equation

                                   u  +u  =0                            (2)
                                    xx  yy

          is the simplest example of second order, the subsidiary
          conditions take the form of boundary conditions, i.e., conditions
          which provide information about the solution at all points of a
          closed boundary. For example, if equation (2) holds in a plane
          domain D bounded by a contour C, a solution u may be sought
          subject to the condition

                                   u=f  on C,                           (3)

          where f is a given function. The condition (3) is known as a
          Dirichlet boundary condition. Equally common is the Neumann
          boundary condition

                                  u'=g  on C,                           (4)

          which is one form of a more general condition

                                 u'+fu=g  on C,                         (5)

          where u' denotes the derivative of u normal to the contour C and
          f and g are given functions. Provided that f and g satisfy
          certain restrictions, condition (5) yields a well-posed  boundary
          value problem  for Laplace's equation. In the case of the Neumann
          problem, one further piece of information, e.g. the value of u at
          a particular point, is necessary for uniqueness of the solution.
          Boundary conditions similar to the above are applicable to more
          general second order elliptic equations, whilst two such
          conditions are required for equations of fourth order.

          For hyperbolic equations, the wave equation

                                   u  -u  =0                            (6)
                                    tt  xx

          is the simplest example of second order. It is equivalent to a
          first order system

                               u -v =0,  v -u =0.                       (7)
                                t  x      t  x

          The subsidiary conditions may take the form of initial
          conditions, i.e., conditions which provide information about the
          solution at points on a suitable open boundary. For example, if
          equation (6) is satisfied for t>0, a solution u may be sought
          such that

                          u(x,0)=f(x),  u (x,0)=g(x),                   (8)
                                         t

          where f and g are given functions. This is an example of an
          initial value problem, sometimes known as Cauchy's problem.

          For parabolic equations, of which the heat conduction equation

                                    u -u  =0                            (9)
                                     t  xx

          is the simplest example, the subsidiary conditions always include
          some of initial type and may also include some of boundary type.
          For example, if equation (9) is satisfied for t>0 and 0<x<1, a
          solution u may be sought such that

                             u(x,0)=f(x),  0<x<1,                      (10)

          and

                          u(0,t)=0,  u(1,t)=1,  t>0.                   (11)

          This is an example of a mixed  initial/boundary value problem.

          For all types of partial differential equations, finite
          difference methods (Mitchell and Griffiths [5]) and finite
          element methods (Wait and Mitchell [9]) are the most common means
          of solution and such methods obviously feature prominently either
          in this chapter or in the companion NAG Finite Element Library.
          Many of the utility routines in this chapter are concerned with
          the solution of the large sparse systems of equations which arise
          from the finite difference and finite element methods.

          Alternative methods of solution are often suitable for special
          classes of problems. For example, the method of characteristics
          is the most common for hyperbolic equations involving time and
          one space dimension (Smith [7]). The method of lines (see Mikhlin
          and Smolitsky [4]) may be used to reduce a parabolic equation to
          a (stiff) system of ordinary differential equations, which may be
          solved by means of routines from Chapter D02 -- Ordinary
          Differential Equations. Similarly, integral equation or boundary
          element methods (Jaswon and Symm [3]) are frequently used for
          elliptic equations. Typically, in the latter case, the solution
          of a boundary value problem is represented in terms of certain
          boundary functions by an integral expression which satisfies the
          differential equation throughout the relevant domain. The
          boundary functions are obtained by applying the given boundary
          conditions to this representation. Implementation of this method
          necessitates discretisation of only the boundary of the domain,
          the dimensionality of the problem thus being effectively reduced
          by one. The boundary conditions yield a full system of
          simultaneous equations, as opposed to the sparse systems yielded
          by the finite difference and finite element methods, but the full
          system is usually of much lower order. Solution of this system
          yields the boundary functions, from which the solution of the
          problem may be obtained, by quadrature, as and where required.

          2.1. References

          [1]   Ames W F (1977) Nonlinear Partial Differential Equations in
                Engineering. Academic Press (2nd Edition).

          [2]   Berzins M (1990) Developments in the NAG Library Software
                for Parabolic Equations. Scientific Software Systems. (ed J
                C Mason and M G Cox) Chapman and Hall. 59--72.

          [3]   Jaswon M A and Symm G T (1977) Integral Equation Methods in
                Potential Theory and Elastostatics. Academic Press.

          [4]   Mikhlin S G and Smolitsky K L (1967) Approximate Methods for
                the Solution of Differential and Integral Equations.
                Elsevier.

          [5]   Mitchell A R and Griffiths D F (1980) The Finite Difference
                Method in Partial Differential Equations. Wiley.

          [6]   Richtmyer R D and Morton K W (1967) Difference Methods for
                Initial-value Problems. Interscience (2nd Edition).

          [7]   Smith G D (1985) Numerical Solution of Partial Differential
                Equations: Finite Difference Methods. Oxford University
                Press (3rd Edition).

          [8]   Swarztrauber P N and Sweet R A (1979) Efficient Fortran
                Subprograms for the Solution of Separable Elliptic Partial
                Differential Equations. ACM Trans. Math. Softw. 5 352--364.

          [9]   Wait R and Mitchell A R (1985) Finite Element Analysis and
                Application. Wiley.

          3. Recommendations on Choice and Use of Routines

          The choice of routine will depend first of all upon the type of
          partial differential equation to be solved. At present no special
          allowances are made for problems with boundary singularities such
          as may arise at corners of domains or at points where boundary
          conditions change. For such problems results should be treated
          with caution.

          Users may wish to construct their own partial differential
          equation solution software for problems not solvable by the
          routines described in Sections 3.1 to 3.4 below. In such cases
          users can employ appropriate routines from the Linear Algebra
          Chapters to solve the resulting linear systems; see Section 3.5
          for further details.

          3.1. Elliptic Equations

          The routine D03EDF solves a system of seven-point difference
          equations in a rectangular grid (in two dimensions), using the
          multigrid iterative method. The equations are supplied by the
          user, and the seven-point form allows cross-derivative terms to
          be represented (see Mitchell and Griffiths [5]). The method is
          particularly efficient for large systems of equations with
          diagonal dominance.

          The routine D03EEF discretises a second-order equation on a two-
          dimensional rectangular region using finite differences and a
          seven-point molecule. The routine allows for cross-derivative
          terms, Dirichlet, Neumann or mixed boundary conditions, and
          either central or upwind differences. The resulting seven-
          diagonal difference equations are in a form suitable for passing
          directly to the multigrid routine D03EDF, although other solution
          methods could easily be used.

          The routine D03FAF, based on the routine HW3CRT from FISHPACK
          (Swarztrauber and Sweet [8]), solves the Helmholtz equation in a
          three-dimensional cuboidal region, with any combination of
          Dirichlet, Neumann or periodic boundary conditions. The method
          used is based on the fast Fourier transform algorithm, and is
          likely to be particularly efficient on vector-processing
          machines.

          3.2. Hyperbolic Equations

          There are no routines available yet for the solution of these
          equations.

          3.3. Parabolic Equations

          There are no routines available yet for the solution of these
          equations.

          But problems in two space dimensions plus time may be treated as
          a succession of elliptic equations [1], [6] using appropriate
          D03E- routines or one may use codes from the NAG Finite Element
          Library.

          3.4. Utility Routines

          There are no utility routines available yet, but routines are
          available in the Linear Algebra Chapters for the direct and
          iterative solution of linear equations. Here we point to some of
          the routines that may be of use in solving the linear systems
          that arise from finite difference or finite element
          approximations to partial differential equation solutions.
          Chapters F01 and F04 should be consulted for further information
          and for the routine documents. Decision trees for the solution of
          linear systems are given in Section 3.5 of the F04 Chapter
          Introduction.

          The following routines allow the direct solution of symmetric
          positive-definite systems:

              Band               F04ACF

              Variable band      F01MCF and F04MCF
              (skyline)

              Tridiagonal        F04FAF

              Sparse             F01MAF* and F04MAF

          (* the parameter DROPTL should be set to zero for F01MAF to give
          a direct solution)

          and the following routines allow the iterative solution of
          symmetric positive-definite systems:

              Sparse (incomplete F01MAF and F04MBF
              Cholesky)

              Sparse (conjugate  F04MBF
              gradient)

          The latter routine above allows the user to supply a pre-
          conditioner and also allows the solution of indefinite symmetric
          systems.

          The following routines allow the direct solution of unsymmetric
          systems:

              Band               F01LBF and F04LDF

              Almost block-      F01LHF and F04LHF
              diagonal

              Tridiagonal        F01LEF and F04LEF or F04EAF

              Sparse             F01BRF (and F01BSF) and F04AXF

          and the following routine allows the iterative solution of
          unsymmetric systems:

              Sparse             F04QAF

          The above routine allows the user to supply a pre-conditioner and
          also allows the solution of least-squares systems.

          3.5. Index

          Elliptic equations
               equations on rectangular grid (seven-point 2-D        D03EDF
               molecule)
               discretisation on rectangular grid (seven-point 2-D   D03EEF
               molecule)
               Helmholtz's equation in three dimensions              D03FAF



          D03 -- Partial Differential Equations             Contents -- D03
          Chapter D03

          Partial Differential Equations

          D03EDF  Elliptic PDE, solution of finite difference equations by
                  a multigrid technique

          D03EEF  Discretize a 2nd order elliptic PDE on a rectangle

          D03FAF  Elliptic PDE, Helmholtz equation, 3-D Cartesian co-
                  ordinates

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd03edf}{nagd.ht}
{ Discrete elliptic PDE on rectangular region}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd03edf}{NAG Documentation: d03edf}
\beginscroll
\begin{verbatim}



     D03EDF(3NAG)      Foundation Library (12/10/92)      D03EDF(3NAG)



          D03 -- Partial Differential Equations                      D03EDF
                  D03EDF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          D03EDF solves seven-diagonal systems of linear equations which
          arise from the discretization of an elliptic partial differential
          equation on a rectangular region. This routine uses a multigrid
          technique.

          2. Specification

                 SUBROUTINE D03EDF (NGX, NGY, LDA, A, RHS, UB, MAXIT, ACC,
                1                   US, U, IOUT, NUMIT, IFAIL)
                 INTEGER          NGX, NGY, LDA, MAXIT, IOUT, NUMIT, IFAIL
                 DOUBLE PRECISION A(LDA,7), RHS(LDA), UB(NGX*NGY), ACC, US
                1                 (LDA), U(LDA)

          3. Description

          D03EDF solves, by multigrid iteration, the seven-point scheme

           6            7
          A   u       +A   u
           i,j i-1,j+1  i,j i,j+1

            3           4        5
          +A   u      +A   u   +A   u
            i,j i-1,j   i,j ij   i,j i+1,j

                        1          2
                      +A   u     +A   u        =f  ,
                        i,j i,j-1  i,j i+1,j-1  ij

                                               i=1,2,...,n ; j=1,2,...,n ,
                                                          x             y

          which arises from the discretization of an elliptic partial
          differential equation of the form


          (alpha)(x,y)U  +(beta)(x,y)U  +(gamma)(x,y)U  +(delta)(x,y)U
                       xx             xy              yy              x

          +(epsilon)(x,y)U +(phi)(x,y)U=(psi)(x,y)
                          y

          and its boundary conditions, defined on a rectangular region.
          This we write in matrix form as

                                        Au=f

          The algorithm is described in separate reports by Wesseling [2],
          [3] and McCarthy [1].

          Systems of linear equations, matching the seven-point stencil
          defined above, are solved by a multigrid iteration. An initial
          estimate of the solution must be provided by the user. A zero
          guess may be supplied if no better approximation is available.

          A 'smoother' based on incomplete Crout decomposition is used to
          eliminate the high frequency components of the error. A
          restriction operator is then used to map the system on to a
          sequence of coarser grids. The errors are then smoothed and
          prolongated (mapped onto successively finer grids). When the
          finest cycle is reached, the approximation to the solution is
          corrected. The cycle is repeated for MAXIT iterations or until
          the required accuracy, ACC, is reached.

          D03EDF will automatically determine the number l of possible
          coarse grids, 'levels' of the multigrid scheme, for a particular
          problem. In other words, D03EDF determines the maximum integer l
          so that n  and n  can be expressed in the form
                   x      y

                        l-1          l-1
                   n =m2   +1,  n =n2   +1,  with  m>=2 and n>=2.
                    x            y

          It should be noted that the rate of convergence improves
          significantly with the number of levels used (see McCarthy [1]),
          so that n  and n  should be carefully chosen so that n -1 and
                   x      y                                     x
                                         l
          n -1 have factors of the form 2 , with l as large as possible.
           y
          For good convergence the integer l should be at least 2.

          D03EDF has been found to be robust in application, but being an
          iterative method the problem of divergence can arise. For a
          strictly diagonally dominant matrix A

                                   4           k
                                    ij   --     ij
                                 |A   |> >   |A   |
                                         --
                                         k/=4

          no such problem is foreseen. The diagonal dominance of A is not a
          necessary condition, but should this condition be strongly
          violated then divergence may occur. The quickest test is to try
          the routine.

          4. References

          [1]   McCarthy G J (1983) Investigation into the Multigrid Code
                MGD1. Report AERE-R 10889. Harwell.

          [2]   Wesseling P (1982) MGD1 - A Robust and Efficient Multigrid
                Method. Multigrid Methods. Lecture Notes in Mathematics. 960
                Springer-Verlag. 614--630.

          [3]   Wesseling P (1982) Theoretical Aspects of a Multigrid
                Method. SIAM J. Sci. Statist. Comput. 3 387--407.

          5. Parameters

           1:  NGX -- INTEGER                                         Input
               On entry: the number of interior grid points in the x-
               direction, n . NGX-1 should preferably be divisible by as
                           x
               high a power of 2 as possible. Constraint: NGX >= 3.

           2:  NGY -- INTEGER                                         Input
               On entry: the number of interior grid points in the y-
               direction, n . NGY-1 should preferably be divisible by as
                           y
               high a power of 2 as possible. Constraint: NGY >= 3.

           3:  LDA -- INTEGER                                         Input
               On entry: the first dimension of the array A as declared in
               the (sub)program from which D03EDF is called, which must
               also be a lower bound for the dimensions of the arrays RHS,
               US and U. It is always sufficient to set
               LDA>=(4*(NGX+1)*(NGY+1))/3, but slightly smaller values may
               be permitted, depending on the values of NGX and NGY. If on
               entry, LDA is too small, an error message gives the minimum
               permitted value. (LDA must be large enough to allow space
               for the coarse-grid approximations).

           4:  A(LDA,7) -- DOUBLE PRECISION array              Input/Output
                                                           k
               On entry: A(i+(j-1)*NGX,k) must be set to  A  ,   for i =
                                                           ij
               1,2,...,NGX; j = 1,2,...,NGY and k = 1,2,...,7. On exit: A
               is overwritten.

           5:  RHS(LDA) -- DOUBLE PRECISION array              Input/Output
               On entry: RHS(i+(j-1)*NGX) must be set to f  , for i =
                                                           ij
               1,2,...,NGX; j = 1,2,...,NGY. On exit: the first NGX*NGY
               elements are unchanged and the rest of the array is used as
               workspace.

           6:  UB(NGX*NGY) -- DOUBLE PRECISION array           Input/Output
               On entry: UB(i+(j-1)*NGX) must be set to the initial
               estimate for the solution u  . On exit: the corresponding
                                          ij
               component of the residual r=f-Au.

           7:  MAXIT -- INTEGER                                       Input
               On entry: the maximum permitted number of multigrid
               iterations. If MAXIT = 0, no multigrid iterations are
               performed, but the coarse-grid approximations and incomplete
               Crout decompositions are computed, and may be output if IOUT
               is set accordingly. Constraint: MAXIT >= 0.

           8:  ACC -- DOUBLE PRECISION                                Input
               On entry: the required tolerance for convergence of the
               residual 2-norm:
                                              

                                             / NGX*NGY
                                            /  --         2
                                 ||r|| =   /   >      (r )
                                      2   /    --       k
                                        \/     k=1
               where r=f-Au and u is the computed solution. Note that the
               norm is not scaled by the number of equations. The routine
               will stop after fewer than MAXIT iterations if the residual
               2-norm is less than the specified tolerance. (If MAXIT > 0,
               at least one iteration is always performed.)

               If on entry ACC = 0.0, then the machine precision is used as
               a default value for the tolerance; if ACC > 0.0, but ACC is
               less than the machine precision, then the routine will stop
               when the residual 2-norm is less than the machine precision
               and IFAIL will be set to 4. Constraint: ACC >= 0.0.

           9:  US(LDA) -- DOUBLE PRECISION array                     Output
               On exit: the residual 2-norm, stored in element US(1).

          10:  U(LDA) -- DOUBLE PRECISION array                      Output
               On exit: the computed solution u   is returned in U(i+(j-
                                                ij
               1)*NGX), for i = 1,2,...,NGX; j = 1,2,...,NGY.

          11:  IOUT -- INTEGER                                        Input
               On entry: controls the output of printed information to the
               advisory message unit as returned by X04ABF:
               IOUT = 0
                     No output.

               IOUT = 1
                     The solution u  , for i = 1,2,...,NGX; j = 1,2,...
                                   ij
                     ,NGY.

               IOUT = 2
                     The residual 2-norm after each iteration, with the
                     reduction factor over the previous iteration.

               IOUT = 3
                     As for IOUT = 1 and IOUT = 2.

               IOUT = 4
                     As for IOUT = 3, plus the final residual (as returned
                     in UB).

               IOUT = 5
                     As for IOUT = 4, plus the initial elements of A and
                     RHS.

               IOUT = 6
                     As for IOUT = 5, plus the Galerkin coarse grid
                     approximations.

               IOUT = 7
                     As for IOUT = 6, plus the incomplete Crout
                     decompositions.

               IOUT = 8
                     As for IOUT = 7, plus the residual after each
                     iteration.
               The elements A(p,k), the Galerkin coarse grid approximations
               and the incomplete Crout decompositions are output in the
               format:
                    Y-index = j

                    X-index = i A(p,1) A(p,2) A(p,3) A(p,4) A(p,5) A(p,6)
                    A(p,7)

                    where p=i+(j-1)*NGX, i = 1,2,...,NGX and j = 1,2,...
                    ,NGY.
               The vectors U(p), UB(p), RHS(p) are output in matrix form
               with NGY rows and NGX columns. Where NGX > 10, the NGX
               values for a given j-value are produced in rows of 10.
               Values of IOUT > 4 may yield considerable amounts of output.
               Constraint: 0 <= IOUT <= 8.

          12:  NUMIT -- INTEGER                                      Output
               On exit: the number of iterations performed.

          13:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry NGX < 3,

               or       NGY < 3,

               or       LDA is too small,

               or       ACC < 0.0,

               or       MAXIT < 0,

               or       IOUT < 0,

               or       IOUT > 8.

          IFAIL= 2
               MAXIT iterations have been performed with the residual 2-
               norm decreasing at each iteration but the residual 2-norm
               has not been reduced to less than the specified tolerance
               (see ACC). Examine the progress of the iteration by setting
               IOUT >= 2.

          IFAIL= 3
               As for IFAIL = 2, except that at one or more iterations the
               residual 2-norm did not decrease. It is likely that the
               method fails to converge for the given matrix A.

          IFAIL= 4
               On entry ACC is less than the machine precision. The routine
               terminated because the residual norm is less than the
               machine precision.

          7. Accuracy

          See ACC (Section 5).

          8. Further Comments

          The rate of convergence of this routine is strongly dependent
          upon the number of levels, l, in the multigrid scheme, and thus
          the choice of NGX and NGY is very important. The user is advised
          to experiment with different values of NGX and NGY to see the
          effect they have on the rate of convergence; for example, using a
                                    6
          value such as NGX = 65 (=2 +1) followed by NGX = 64 (for which l
          = 1).

          9. Example

          The program solves the elliptic partial differential equation

                        U  -(alpha)U  +U  =-4,   (alpha)=1.7
                         xx         xy  yy

          on the unit square 0<=x,y<=1, with boundary conditions

                           {x=0, (0<=y<=1)
                    U=0 on {y=0, (0<=x<=1) U=1 on x=1,  0<=y<=1.
                           {y=1, (0<=x<=1)

          For the equation to be elliptic, (alpha) must be less than 2.

          The equation is discretized on a square grid with mesh spacing h
          in both directions using the following approximations:



                   Please see figure in printed Reference Manual

                                       1
                                 U  ~= --(U -2U +U )
                                  xx    2  E   O  W
                                       h

                                       1
                                 U  ~= --(U -2U +U )
                                  yy    2  N   O  S
                                       h

                                1
                         U  ~= ---(U -U  +U -2U +U -U  +U ).
                          xy     2  N  NW  E   O  W  SE  S
                               2h

          Thus the following equations are solved:


              1                      1
              -(alpha)u        + (1- -(alpha))u
              2        i-1,j+1       2         i,j+1

               1                                           1

          +(1- -(alpha))u      + (-4+(alpha))u       + (1- -(alpha))u
               2         i-1,j                ij           2         i+1,j

                                     1                  1
                               + (1- -(alpha))u      +  -(alpha)u
                                     2         i,j-1    2        i+1,j-1

                    2
                =-4h

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd03eef}{nagd.ht}
{ Discrete 2nd-order elliptic PDE on rectangular regions}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd03eef}{NAG Documentation: d03eef}
\beginscroll
\begin{verbatim}



     D03EEF(3NAG)      Foundation Library (12/10/92)      D03EEF(3NAG)



          D03 -- Partial Differential Equations                      D03EEF
                  D03EEF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          D03EEF discretizes a second order elliptic partial differential
          equation (PDE) on a rectangular region.

          2. Specification

                 SUBROUTINE D03EEF (XMIN, XMAX, YMIN, YMAX, PDEF, BNDY,
                1                   NGX, NGY, LDA, A, RHS, SCHEME, IFAIL)
                 INTEGER          NGX, NGY, LDA, IFAIL
                 DOUBLE PRECISION XMIN, XMAX, YMIN, YMAX, A(LDA,7), RHS(LDA)
                 CHARACTER*1      SCHEME
                 EXTERNAL         PDEF, BNDY

          3. Description

          D03EEF discretizes a second order linear elliptic partial
          differential equation of the form


                         2                 2                  2
                       dd U              dd U               dd U
          (alpha)(x,y) ----+(beta)(x,y) ------+(gamma)(x,y) ----
                         2              ddxddy                2
                       dd x                                 dd y

                        ddU                ddU
          +(delta)(x,y) ---+(epsilon)(x,y) ---+(phi)(x,y)U=(psi)(x,y)   (1)
                        ddx                ddy


          on a rectangular region

                                      x <=x<=x
                                       A      B

                                      y <=y<=y
                                       A      B

          subject to boundary conditions of the form

                                             ddU
                              a(x,y)U+b(x,y) ---=c(x,y)
                                             ddn

                 ddU
          where  --- denotes the outward pointing normal derivative on the
                 ddn
          boundary. Equation (1) is said to be elliptic if

                                                              2
                      4(alpha)(x,y)(gamma)(x,y)>=((beta)(x,y))

          for all points in the rectangular region. The linear equations
          produced are in a form suitable for passing directly to the
          multigrid routine D03EDF.

          The equation is discretized on a rectangular grid, with n  grid
                                                                   x
          points in the x-direction and n  grid points in the y-direction.
                                         y
          The grid spacing used is therefore

                                  h =(x -x )/(n -1)
                                   x   B  A    x

                                  h =(y -y )/(n -1)
                                   y   B  A    y

          and the co-ordinates of the grid points (x ,y ) are
                                                    i  j

                            x =x +(i-1)h ,  i=1,2,...,n ,
                             i  A       x              x

                            y =y +(j-1)h ,  j=1,2,...,n .
                             j  A       y              y

          At each grid point (x ,y ) six neighbouring grid points are used
                               i  j
          to approximate the partial differential equation, so that the
          equation is discretized on the following seven-point stencil:



                   Please see figure in printed Reference Manual

          For convenience the approximation u   to the exact solution
                                             ij
          U(x ,y ) is denoted by u , and the neighbouring approximations
             i  j                 O
          are labelled according to points of the compass as shown. Where
          numerical labels for the seven points are required, these are
          also shown above.

          The following approximations are used for the second derivatives:

                 2
               dd U   1
               ----~= --(u -2u +u )
                 2     2  E   O  W
               dd x   h
                       x

                 2
               dd U   1
               ----~= --(u -2u +u )
                 2     2  N   O  S
               dd y   h
                       y

                  2
                dd U    1
               ------~= -----(u -u  +u -2u +u -u  +u ).
               ddxddy 2h h   N  NW  E   O  W  SE  S
                        x y

          Two possible schemes may be used to approximate the first
          derivatives:

          Central Differences

               ddU     1
               ---~=  ---(u -u )
               ddx    2h   W  E
                        x

               ddU     1
               ---~=  ---(u -u )
               ddy    2h   N  S
                        y

          Upwind Differences

               ddU    1
               ---~=  --(u -u )if (delta)(x,y)>0
               ddx    h   E  O
                       x

               ddU    1
               ---~=  --(u -u )if (delta)(x,y)<0
               ddx    h   O  W
                       x

               ddU    1
               ---~=  --(u -u )if (epsilon)(x,y)>0
               ddy    h   N  O
                       y

               ddU    1
               ---~=  --(u -u )if (epsilon)(x,y)<0.
               ddy    h   O  S
                       y

          Central differences are more accurate than upwind differences,
          but upwind differences may lead to a more diagonally dominant
          matrix for those problems where the coefficients of the first
          derivatives are significantly larger than the coefficients of the
          second derivatives.

          The approximations used for the first derivatives may be written
          in a more compact form as follows:

               ddU     1
               ---~=  ---((k -1)u -2k u +(k +1)u )
               ddx    2h (  x    W   x O   x    E)
                        x

               ddU     1
               ---~=  ---((k -1)u -2k u +(k +1)u )
               ddy    2h (  y    S   y O   y    N)
                        y

          where k =sign (delta) and k =sign (epsilon) for upwind
                 x                   y
          differences, and k =k =0 for central differences.
                            x  y

          At all points in the rectangular domain, including the boundary,
          the coefficients in the partial differential equation are
          evaluated by calling the user-supplied subroutine PDEF, and
          applying the approximations. This leads to a seven-diagonal
          system of linear equations of the form:

              6            7
             A  u        +A  u
              ij i-1,j+1   ij i,j+1
               3          4       5
             +A  u      +A  u   +A  u
               ij i-1,j   ij ij   ij i+1,j
                 1          2
               +A  u      +A  u        =f  , i=1,2,...,n ;j=1,2,...,n ,
                 ij i,j-1   ij i+1,j-1   ij             x            y

          where the coefficients are given by

           1                 1                   1                   1
          A  =(beta)(x ,y )----- +(gamma)(x ,y )-- +(epsilon)(x ,y )---(k -1)
           ij         i  j 2h h            i  j  2             i  j 2h   y
                             x y                h                     y
                                                 y
           2                   1
          A  =-(beta)(x ,y ) -----
           ij          i  j  2h h
                               x y

           3                 1                  1                   1
          A  =(alpha)(x ,y ) --+(beta)(x ,y ) -----+(delta)(x ,y ) ---(k -1)
           ij          i  j   2         i  j  2h h           i  j  2h   x
                             h                  x y                  x
                              x

           4                  2                  1                   2
          A  =-(alpha)(x ,y ) -- -(beta)(x ,y ) ---- -(gamma)(x ,y ) --
           ij           i  j   2          i  j  h h            i  j   2
                              h                  x y                 h
                               x                                      y

                              k                    k
                               y                    y
              -(delta)(x ,y ) -- -(epsilon)(x ,y ) -- -(phi)(x ,y )
                        i  j  h              i  j  h          i  j
                               x                    y

           5                 1                  1                   1
          A  =(alpha)(x ,y ) --+(beta)(x ,y ) -----+(delta)(x ,y ) ---(k +1)
           ij          i  j   2         i  j  2h h           i  j  2h   x
                             h                  x y                  x
                              x

           6                   1
          A  =-(beta)(x ,y ) -----
           ij          i  j  2h h
                               x y

           7                 1                  1                   1
          A  =(beta)(x ,y )-----+(gamma)(x ,y )--+(epsilon)(x ,y )---(k +1)
           ij         i  j 2h h           i  j  2             i j 2h   y
                             x y               h                    y
                                                y

          f  =(psi)(x ,y )
           ij        i  j

          These equations then have to be modified to take account of the
          boundary conditions. These may be Dirichlet (where the solution
          is given), Neumann (where the derivative of the solution is
          given), or mixed (where a linear combination of solution and
          derivative is given).

          If the boundary conditions are Dirichlet, there are an infinity
          of possible equations which may be applied:

                           (mu)u  =(mu)f   , (mu)/=0.                   (2)
                                ij      ij

          If D03EDF is used to solve the discretized equations, it turns
          out that the choice of (mu) can have a dramatic effect on the
          rate of convergence, and the obvious choice (mu)=1 is not the
          best. Some choices may even cause the multigrid method to fail
          altogether. In practice it has been found that a value of the
          same order as the other diagonal elements of the matrix is best,
          and the following value has been found to work well in practice:

                                       ( { 2   2 }  4 )
                             (mu)=min  (-{ --+ --},A  ).
                                     ij( {  2   2}  ij)
                                       ( { h   h }    )
                                       ( {  x   y}    )

          If the boundary conditions are either mixed or Neumann (i.e., B
          /= 0 on return from the user-supplied subroutine BNDY), then one
          of the points in the seven-point stencil lies outside the domain.
          In this case the normal derivative in the boundary conditions is
          used to eliminate the 'fictitious' point, u       :
                                                     outside

                           ddU   1
                           ---~= --(u       -u      ).                  (3)
                           ddn   2h  outside  inside

          It should be noted that if the boundary conditions are Neumann
          and (phi)(x,y)==0, then there is no unique solution. The routine
          returns with IFAIL = 5 in this case, and the seven-diagonal
          matrix is singular.

          The four corners are treated separately. The user-supplied
          subroutine BNDY is called twice, once along each of the edges
          meeting at the corner. If both boundary conditions at this point
          are Dirichlet and the prescribed solution values agree, then this
          value is used in an equation of the form (2). If the prescribed
          solution is discontinuous at the corner, then the average of the
          two values is used. If one boundary condition is Dirichlet and
          the other is mixed, then the value prescribed by the Dirichlet
          condition is used in an equation of the form given above.
          Finally, if both conditions are mixed or Neumann, then two '
          fictitious' points are eliminated using two equations of the form
          (3).

          It is possible that equations for which the solution is known at
          all points on the boundary, have coefficients which are not
          defined on the boundary. Since this routine calls the user-
          supplied subroutine PDEF at all points in the domain, including
          boundary points, arithmetic errors may occur in the user's
          routine PDEF which this routine cannot trap. If the user has an
          equation with Dirichlet boundary conditions (i.e., B = 0 at all
          points on the boundary), but with PDE coefficients which are
          singular on the boundary, then D03EDF could be called directly
          only using interior grid points with the user's own
          discretization.

          After the equations have been set up as described above, they are
          checked for diagonal dominance. That is to say,

                     4     --    k
                   |A  | > >   |A  |,  i=1,2,...,n ; j=1,2,...,n .
                     ij    --    ij               x             y
                           k/=4

          If this condition is not satisfied then the routine returns with
          IFAIL = 6. The multigrid routine D03EDF may still converge in
          this case, but if the coefficients of the first derivatives in
          the partial differential equation are large compared with the
          coefficients of the second derivative, the user should consider
          using upwind differences (SCHEME = 'U').

          Since this routine is designed primarily for use with D03EDF,
          this document should be read in conjunction with the document for
          that routine.

          4. References

          [1]   Wesseling P (1982) MGD1 - A Robust and Efficient Multigrid
                Method. Multigrid Methods. Lecture Notes in Mathematics. 960
                Springer-Verlag. 614--630.

          5. Parameters

           1:  XMIN -- DOUBLE PRECISION                               Input

           2:  XMAX -- DOUBLE PRECISION                               Input
               On entry: the lower and upper x co-ordinates of the
               rectangular region respectively, x  and x . Constraint: XMIN
                                                 A      B
               < XMAX.

           3:  YMIN -- DOUBLE PRECISION                               Input

           4:  YMAX -- DOUBLE PRECISION                               Input
               On entry: the lower and upper y co-ordinates of the
               rectangular region respectively, y  and y . Constraint: YMIN
                                                 A      B
               < YMAX.

           5:  PDEF -- SUBROUTINE, supplied by the user.
                                                         External Procedure
               PDEF must evaluate the functions (alpha)(x,y), (beta)(x,y),
               (gamma)(x,y), (delta)(x,y), (epsilon)(x,y), (phi)(x,y) and
               (psi)(x,y) which define the equation at a general point
               (x,y).

               Its specification is:

                      SUBROUTINE PDEF (X, Y, ALPHA, BETA, GAMMA,
                     1                 DELTA, EPSLON, PHI, PSI)
                      DOUBLE PRECISION X, Y, ALPHA, BETA, GAMMA, DELTA,
                     1                 EPSLON, PHI, PSI

                1:  X -- DOUBLE PRECISION                             Input

                2:  Y -- DOUBLE PRECISION                             Input
                    On entry: the x and y co-ordinates of the point at
                    which the coefficients of the partial differential
                    equation are to be evaluated. 8

                3:  ALPHA -- DOUBLE PRECISION                        Output

                4:  BETA -- DOUBLE PRECISION                         Output

                5:  GAMMA -- DOUBLE PRECISION                        Output

                6:  DELTA -- DOUBLE PRECISION                        Output

                7:  EPSLON -- DOUBLE PRECISION                       Output

                8:  PHI -- DOUBLE PRECISION                          Output

                9:  PSI -- DOUBLE PRECISION                          Output
                    On exit: ALPHA, BETA, GAMMA, DELTA, EPSLON, PHI and PSI
                    must be set to the values of (alpha)(x,y), (beta)(x,y),
                    (gamma)(x,y), (delta)(x,y), (epsilon)(x,y), (phi)(x,y)
                    and (psi)(x,y) respectively at the point specified by X
                    and Y.
               PDEF must be declared as EXTERNAL in the (sub)program
               from which D03EEF is called. Parameters denoted as
               Input must not be changed by this procedure.

           6:  BNDY -- SUBROUTINE, supplied by the user.
                                                         External Procedure
               BNDY must evaluate the functions a(x,y), b(x,y), and c(x,y)
               involved in the boundary conditions.

               Its specification is:

                      SUBROUTINE BNDY (X, Y, A, B, C, IBND)
                      INTEGER          IBND
                      DOUBLE PRECISION X, Y, A, B, C

                1:  X -- DOUBLE PRECISION                             Input

                2:  Y -- DOUBLE PRECISION                             Input
                    On entry: the x and y co-ordinates of the point at
                    which the boundary conditions are to be evaluated.

                3:  A -- DOUBLE PRECISION                            Output

                4:  B -- DOUBLE PRECISION                            Output

                5:  C -- DOUBLE PRECISION                            Output
                    On exit: A, B and C must be set to the values of the
                    functions appearing in the boundary conditions.

                6:  IBND -- INTEGER                                   Input
                    On entry: specifies on which boundary the point (X,Y)
                    lies. IBND = 0, 1, 2 or 3 according as the point lies
                    on the bottom, right, top or left boundary.
               BNDY must be declared as EXTERNAL in the (sub)program
               from which D03EEF is called. Parameters denoted as
               Input must not be changed by this procedure.

           7:  NGX -- INTEGER                                         Input

           8:  NGY -- INTEGER                                         Input
               On entry: the number of interior grid points in the x- and y
               -directions respectively, n  and n . If the seven-diagonal
                                          x      y
               equations are to be solved by D03EDF, then NGX-1 and NGY-1
               should preferably be divisible by as high a power of 2 as
               possible. Constraint: NGX >= 3, NGY >= 3.

           9:  LDA -- INTEGER                                         Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which D03EEF is called.
               Constraint: if only the seven-diagonal equations are
               required, then LDA >= NGX*NGY. If a call to this routine is
               to be followed by a call to D03EDF to solve the seven-
               diagonal linear equations, LDA >= (4*(NGX+1)*(NGY+1))/3.

               Note: this routine only checks the former condition. D03EDF,
               if called, will check the latter condition.

          10:  A(LDA,7) -- DOUBLE PRECISION array                    Output
               On exit: A(i,j), for i=1,2,...,NGX*NGY; j = 1,2,...,7,
               contains the seven-diagonal linear equations produced by the
               discretization described above. If LDA > NGX*NGY, the
               remaining elements are not referenced by the routine, but if
               LDA >= (4*(NGX+1)*(NGY+1))/3 then the array A can be passed
               directly to D03EDF, where these elements are used as
               workspace.

          11:  RHS(LDA) -- DOUBLE PRECISION array                    Output
               On exit: the first NGX*NGY elements contain the right-hand
               sides of the seven-diagonal linear equations produced by the
               discretization described above. If LDA > NGX*NGY, the
               remaining elements are not referenced by the routine, but if
               LDA >= (4*(NGY+1)*(NGY+1))/3 then the array RHS can be
               passed directly to D03EDF, where these elements are used as
               workspace.

          12:  SCHEME -- CHARACTER*1                                  Input
               On entry: the type of approximation to be used for the first
               derivatives which occur in the partial differential
               equation.

               If SCHEME = 'C', then central differences are used.

               If SCHEME = 'U', then upwind differences are used.
               Constraint: SCHEME = 'C' or 'U'.

               Note: generally speaking, if at least one of the
               coefficients multiplying the first derivatives (DELTA or
               EPSLON as returned by PDEF) are large compared with the
               coefficients multiplying the second derivatives, then upwind
               differences may be more appropriate. Upwind differences are
               less accurate than central differences, but may result in
               more rapid convergence for strongly convective equations.
               The easiest test is to try both schemes.

          13:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. Users who are
               unfamiliar with this parameter should refer to the Essential
               Introduction for details.

               On exit: IFAIL = 0 unless the routine detects an error or
               gives a warning (see Section 6).

               For this routine, because the values of output parameters
               may be useful even if IFAIL /=0 on exit, users are
               recommended to set IFAIL to -1 before entry. It is then
               essential to test the value of IFAIL on exit.

          6. Error Indicators and Warnings

          Errors or warnings specified by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry XMIN >= XMAX,

               or       YMIN >= YMAX,

               or       NGX < 3,

               or       NGY < 3,

               or       LDA < NGX*NGY,

               or       SCHEME is not one of 'C' or 'U'.

          IFAIL= 2
               At some point on the boundary there is a derivative in the
               boundary conditions (B /= 0 on return from a BNDY) and there
                                                                     2
                                                                   dd U
               is a non-zero coefficient of the mixed derivative  ------
                                                                  ddxddy
               (BETA /= 0 on return from PDEF).

          IFAIL= 3
               A null boundary has been specified, i.e., at some point both
               A and B are zero on return from a call to BNDY.

          IFAIL= 4
                                                                    2
               The equation is not elliptic, i.e., 4*ALPHA*GAMMA<BETA  after
               a call to PDEF. The discretization has been completed, but
               the convergence of D03EDF cannot be guaranteed.

          IFAIL= 5
               The boundary conditions are purely Neumann (only the
               derivative is specified) and there is, in general, no unique
               solution.

          IFAIL= 6
               The equations were not diagonally dominant. (See Section 3).

          7. Accuracy

          Not applicable.

          8. Further Comments

          If this routine is used as a pre-processor to the multigrid
          routine D03EDF it should be noted that the rate of convergence of
          that routine is strongly dependent upon the number of levels in
          the multigrid scheme, and thus the choice of NGX and NGY is very
          important.

          9. Example

          The program solves the elliptic partial differential equation

                             2     2
                           dd U  dd U   { ddU  ddU}
                           ----+ ----+50{ ---+ ---}=f(x,y)
                              2     2   { ddx  ddy}
                           ddx   ddy

          on the unit square 0<=x, y<=1, with boundary conditions

                ddU
                --- given on x=0 and y=0,
                ddn

               U given on x=1 and y=1.

          The function f(x,y) and the exact form of the boundary conditions
          are derived from the exact solution U(x,y)=sinxsiny.

          The equation is first solved using central differences. Since the
          coefficients of the first derivatives are large, the linear
          equations are not diagonally dominated, and convergence is slow.
          The equation is solved a second time with upwind differences,
          showing that convergence is more rapid, but the solution is less
          accurate.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXd03faf}{nagd.ht}{ Helmholtz equation in 3 dimensions}
\begin{chunk}{nagd.ht}
\begin{page}{manpageXXd03faf}{NAG Documentation: d03faf}
\beginscroll
\begin{verbatim}



     D03FAF(3NAG)      Foundation Library (12/10/92)      D03FAF(3NAG)



          D03 -- Partial Differential Equations                      D03FAF
                  D03FAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          D03FAF solves the Helmholtz equation in Cartesian co-ordinates in
          three dimensions using the standard seven-point finite difference
          approximation. This routine is designed to be particularly
          efficient on vector processors.

          2. Specification

                 SUBROUTINE D03FAF (XS, XF, L, LBDCND, BDXS, BDXF, YS, YF,
                1                   M, MBDCND, BDYS, BDYF, ZS, ZF, N,
                2                   NBDCND, BDZS, BDZF, LAMBDA, LDIMF,
                3                   MDIMF, F, PERTRB, W, LWRK, IFAIL)
                 INTEGER          L, LBDCND, M, MBDCND, N, NBDCND, LDIMF,
                1                 MDIMF, LWRK, IFAIL
                 DOUBLE PRECISION XS, XF, BDXS(MDIMF,N+1), BDXF(MDIMF,N+1),
                1                 YS, YF, BDYS(LDIMF,N+1), BDYF(LDIMF,N+1),
                2                 ZS, ZF, BDZS(LDIMF,M+1), BDZF(LDIMF,M+1),
                3                 LAMBDA, F(LDIMF,MDIMF,N+1), PERTRB, W
                4                 (LWRK)

          3. Description

          D03FAF solves the three-dimensional Helmholtz equation in
          cartesian co-ordinates:

                           2     2     2
                         dd u  dd u  dd u
                         ----+ ----+ ----+(lambda)u=f(x,y,z)
                           2     2     2
                         dd x  dd y  dd z

          This subroutine forms the system of linear equations resulting
          from the standard seven-point finite difference equations, and
          then solves the system using a method based on the fast Fourier
          transform (FFT) described by Swarztrauber [1]. This subroutine is
          based on the routine HW3CRT from FISHPACK (see Swarztrauber and
          Sweet [2]).

          More precisely, the routine replaces all the second derivatives
          by second-order central difference approximations, resulting in a
          block tridiagonal system of linear equations. The equations are
          modified to allow for the prescribed boundary conditions. Either
          the solution or the derivative of the solution may be specified
          on any of the boundaries, or the solution may be specified to be
          periodic in any of the three dimensions. By taking the discrete
          Fourier transform in the x- and y-directions, the equations are
          reduced to sets of tridiagonal systems of equations. The Fourier
          transforms required are computed using the multiple FFT routines
          found in Chapter C06 of the NAG Fortran Library.

          4. References

          [1]   Swarztrauber P N (1984) Fast Poisson Solvers. Studies in
                Numerical Analysis. (ed G H Golub) Mathematical Association
                of America.

          [2]   Swarztrauber P N and Sweet R A (1979) Efficient Fortran
                Subprograms for the Solution of Separable Elliptic Partial
                Differential Equations. ACM Trans. Math. Softw. 5 352--364.

          5. Parameters

           1:  XS -- DOUBLE PRECISION                                 Input
               On entry: the lower bound of the range of x, i.e., XS <= x
               <= XF. Constraint: XS < XF.

           2:  XF -- DOUBLE PRECISION                                 Input
               On entry: the upper bound of the range of x, i.e., XS <= x
               <= XF. Constraint: XS < XF.

           3:  L -- INTEGER                                           Input
               On entry: the number of panels into which the interval
               (XS,XF) is subdivided. Hence, there will be L+1 grid points
               in the x-direction given by x =XS+(i-1)*(delta)x, for
                                            i
               i=1,2,...,L+1, where (delta)x=(XF-XS)/L is the panel width.
               Constraint: L >= 5.

           4:  LBDCND -- INTEGER                                      Input
               On entry: indicates the type of boundary conditions at x =
               XS and x = XF.
               LBDCND = 0
                     if the solution is periodic in x, i.e.,
                     u(XS,y,z)=u(XF,y,z).

               LBDCND = 1
                     if the solution is specified at x = XS and x = XF.

               LBDCND = 2
                     if the solution is specified at x = XS and the
                     derivative of the solution with respect to x is
                     specified at x = XF.

               LBDCND = 3
                     if the derivative of the solution with respect to x is
                     specified at x = XS and x = XF.

               LBDCND = 4
                     if the derivative of the solution with respect to x is
                     specified at x = XS and the solution is specified at x
                     = XF.
                Constraint: 0 <= LBDCND <= 4.

           5:  BDXS(MDIMF,N+1) -- DOUBLE PRECISION array              Input
               On entry: the values of the derivative of the solution with
               respect to x at x = XS. When LBDCND = 3 or 4, BDXS
               (j,k)=u (XS,y ,z ), for j=1,2,...,M+1; k=1,2,...,N+1.
                      x     j  k

               When LBDCND has any other value, BDXS is not referenced.

           6:  BDXF(MDIMF,N+1) -- DOUBLE PRECISION array              Input
               On entry: the values of the derivative of the solution with
               respect to x at x = XF. When LBDCND = 2 or 3, BDXF(j,k) =
               u (XF,y ,z ), for j=1,2,...,M+1; k=1,2,...,N+1.
                x     i  k

               When LBDCND has any other value, BDXF is not referenced.

           7:  YS -- DOUBLE PRECISION                                 Input
               On entry: the lower bound of the range of y, i.e., YS <= y
               <= YF. Constraint: YS < YF.

           8:  YF -- DOUBLE PRECISION                                 Input
               On entry: the upper bound of the range of y, i.e., YS <= y
               <= YF. Constraint: YS < YF.

           9:  M -- INTEGER                                           Input
               On entry: the number of panels into which the interval
               (YS,YF) is subdivided. Hence, there will be M+1 grid points
               in the y-direction given by y  = YS + (j-1)*(delta)y for
                                            j
               j=1,2,...,M+1, where (delta)y=(YF-YS)/M is the panel width.
               Constraint: M >= 5.

          10:  MBDCND -- INTEGER                                      Input
               On entry: indicates the type of boundary conditions at y =
               YS and y = YF.
               MBDCND = 0
                     if the solution is periodic in y, i.e.,
                     u(x,YF,z)=u(x,YS,z).

               MBDCND = 1
                     if the solution is specified at y = YS and y = YF.

               MBDCND = 2
                     if the solution is specified at y = YS and the
                     derivative of the solution with respect to y is
                     specified at y = YF.

               MBDCND = 3
                     if the derivative of the solution with respect to y is
                     specified at y = YS and y = YF.

               MBDCND = 4
                     if the derivative of the solution with respect to y is
                     specified at y = YS and the solution is specified at y
                     = YF.
                Constraint: 0 <= MBDCND <= 4.

          11:  BDYS(LDIMF,N+1) -- DOUBLE PRECISION array              Input
               On entry: the values of the derivative of the solution with
               respect to y at y = YS. When MBDCND = 3 or 4, BDYS
               (i,k)=u (x ,y ,z ), for i=1,2,...,L+1; k=1,2,...,N+1.
                      y  i  s  k

               When MBDCND has any other value, BDYS is not referenced.

          12:  BDYF(LDIMF,N+1) -- DOUBLE PRECISION array              Input
               On entry: the values of the derivative of the solution with
               respect to y at y = YF. When MBDCND = 2 or 3, BDYF
               (i,k)=u (x ,YF,z ), for i=1,2,...,L+1; k=1,2,...,N+1.
                      y  i     k

               When MBDCND has any other value, BDYF is not referenced.

          13:  ZS -- DOUBLE PRECISION                                 Input
               On entry: the lower bound of the range of z, i.e., ZS <= z
               <= ZF. Constraint: ZS < ZF.

          14:  ZF -- DOUBLE PRECISION                                 Input
               On entry: the upper bound of the range of z, i.e., ZS <= z
               <= ZF. Constraint: ZS < ZF.

          15:  N -- INTEGER                                           Input
               On entry: the number of panels into which the interval
               (ZS,ZF) is subdivided. Hence, there will be N+1 grid points
               in the z-direction given by z =ZS+(k-1)*(delta)z, for
                                            k
               k=1,2,...,N+1, where (delta)z=(ZF-ZS)/N is the panel width.
               Constraint: N >= 5.

          16:  NBDCND -- INTEGER                                      Input
               On entry: specifies the type of boundary conditions at z =
               ZS and z = ZF.
               NBDCND = 0
                     if the solution is periodic in z, i.e.,
                     u(x,y,ZF)=u(x,y,ZS).

               NBDCND = 1
                     if the solution is specified at z = ZS and z = ZF.

               NBDCND = 2
                     if the solution is specified at z = ZS and the
                     derivative of the solution with respect to z is
                     specified at z = ZF.

               NBDCND = 3
                     if the derivative of the solution with respect to z is
                     specified at z = ZS and z = ZF.

               NBDCND = 4
                     if the derivative of the solution with respect to z is
                     specified at z = ZS and the solution is specified at z
                     = ZF.
                Constraint: 0 <= NBDCND <= 4.

          17:  BDZS(LDIMF,M+1) -- DOUBLE PRECISION array              Input
               On entry: the values of the derivative of the solution with
               respect to z at z = ZS. When NBDCND = 3 or 4, BDZS
               (i,j)=u (x ,y ,ZS)=u(x,y,z), for i=1,2,...,L+1;
                      z  i  j
               j=1,2,...,M+1.

               When NBDCND has any other value, BDZS is not referenced.

          18:  BDZF(LDIMF,M+1) -- DOUBLE PRECISION array              Input
               On entry: the values of the derivative of the solution with
               respect to z at z = ZF. When NBDCND = 2 or 3, BDZF
               (i,j)=u (x ,y ,ZF)=u(x,y,z), for i=1,2,...,L+1;
                      z  i  j
               j=1,2,...,M+1.

               When NBDCND has any other value, BDZF is not referenced.

          19:  LAMBDA -- DOUBLE PRECISION                             Input
               On entry: the constant (lambda) in the Helmholtz equation.
               For certain positive values of (lambda) a solution to the
               differential equation may not exist, and close to these
               values the solution of the discretized problem will be
               extremely ill-conditioned. If (lambda)>0, then D03FAF will
               set IFAIL to 3, but will still attempt to find a solution.
               However, since in general the values of (lambda) for which
               no solution exists cannot be predicted a priori, the user is
               advised to treat any results computed with (lambda)>0 with
               great caution.

          20:  LDIMF -- INTEGER                                       Input
               On entry:
               the first dimension of the arrays F, BDYS, BDYF, BDZS and
               BDZF as declared in the (sub)program from which D03FAF is
               called.
               Constraint: LDIMF >= L + 1.

          21:  MDIMF -- INTEGER                                       Input
               On entry: the second dimension of the array F and
               the first dimension of the arrays BDXS and BDXF as declared
               in the (sub)program from which D03FAF is called.
               Constraint: MDIMF >= M + 1.

          22:  F(LDIMF,MDIMF,N+1) -- DOUBLE PRECISION array    Input/Output
               On entry: the values of the right-side of the Helmholtz
               equation and boundary values (if any).

               F(i,j,k)=f(x ,y ,z ) i=2,3,...,L, j=2,3,...,M and k
                           i  j  k
               =2,3,...,N.

               On the boundaries F is defined by
               LBDCND    F(1,j,k)  F(L+1,j,k)

               0         f(XS,y ,z )f(XS,y ,z )
                               j  k      j  k

               1         u(XS,y ,z )u(XF,y ,z )
                               j  k      j  k

               2         u(XS,y ,z )f(XF,y ,z )  j=1,2,...,M+1
                               j  k      j  k

               3         f(XS,y ,z )f(XF,y ,z )  k=1,2,...,N+1
                               j  k      j  k

               4         f(XS,y ,z )u(XF,y ,z )
                               j  k      j  k



               MBDCND    F(i,1,k)  F(
                                   i,M+1,k)

               0         f(x ,YS,z )f(x ,YS,z )
                            i     k   i     k

               1         u(x ,YS,z )u(x ,YF,z )
                            i     k   i     k

               2         u(x ,YS,z )f(x ,YF,z )  i=1,2,...,L+1
                            i     k   i     k

               3         f(x ,YS,z )f(x ,YF,z )  k=1,2,...,N+1
                            i     k   i     k

               4         f(x ,YS,z )u(x ,YF,z )
                            i     k   i     k



               NBDCND    F(i,j,1)  F(i,j,N+1
                                   )

               0         f(x ,y ,ZS)f(x ,y ,ZS)
                            i  j      i  j

               1         u(x ,y ,ZS)u(x ,y ,ZF)
                            i  j      i  j

               2         u(x ,y ,ZS)f(x ,y ,ZF)  i=1,2,...,L+1
                            i  j      i  j

               3         f(x ,y ,ZS)f(x ,y ,ZF)  j=1,2,...,M+1
                            i  j      i  j

               4         f(x ,y ,ZS)u(x ,y ,ZF)
                            i  j      i  j
               Note: if the table calls for both the solution u and the
               right-hand side f on a boundary, then the solution must be
               specified. On exit: F contains the solution u(i,j,k) of the
               finite difference approximation for the grid point (
               x ,y ,z ) for i=1,2,...,L+1, j=1,2,...,M+1 and k=1,2,...,N+1.
                i  j  k

          23:  PERTRB -- DOUBLE PRECISION                            Output
               On exit: PERTRB = 0, unless a solution to Poisson's
               equation ((lambda)=0) is required with a combination of
               periodic or derivative boundary conditions (LBDCND, MBDCND
               and NBDCND = 0 or 3). In this case a solution may not exist.
               PERTRB is a constant, calculated and subtracted from the
               array F, which ensures that a solution exists. D03FAF then
               computes this solution, which is a least-squares solution to
               the original approximation. This solution is not unique and
               is unnormalised. The value of PERTRB should be small
               compared to the right-hand side F, otherwise a solution has
               been obtained to an essentially different problem. This
               comparison should always be made to insure that a meaningful
               solution has been obtained.

          24:  W(LWRK) -- DOUBLE PRECISION array                  Workspace

          25:  LWRK -- INTEGER                                        Input
               On entry:
               the dimension of the array W as declared in the (sub)program
               from which D03FAF is called.
               LRWK>=2*(N+1)*max(L,M)+3*L+3*M+4*N+6 is an upper bound on
               the required size of W. If LWRK is too small, the routine
               exits with IFAIL = 2, and if on entry IFAIL = 0 or IFAIL = -
               1, a message is output giving the exact value of LWRK
               required to solve the current problem.

          26:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. Users who are
               unfamiliar with this parameter should refer to the Essential
               Introduction for details.

               On exit: IFAIL = 0 unless the routine detects an error or
               gives a warning (see Section 6).

               For this routine, because the values of output parameters
               may be useful even if IFAIL /=0 on exit, users are
               recommended to set IFAIL to -1 before entry. It is then
               essential to test the value of IFAIL on exit.

          6. Error Indicators and Warnings

          Errors or warnings specified by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry XS >= XF,

               or       L < 5,

               or       LBDCND < 0,

               or       LBDCND > 4,

               or       YS >= YF,

               or       M < 5,

               or       MBDCND < 0,

               or       MBDCND > 4,

               or       ZS >= ZF,

               or       N < 5,

               or       NBDCND < 0,

               or       NBDCND > 4,

               or       LDIMF < L + 1 > 0,

               or       MDIMF < M + 1.

          IFAIL= 2
               On entry LWRK is too small.

          IFAIL= 3
               On entry (lambda) > 0.

          7. Accuracy

          None.

          8. Further Comments

          The execution time is roughly proportional to
          L*M*N*(log L+log M+5), but also depends on input parameters
                    2     2
          LBDCND and MBDCND.

          9. Example

          The example solves the Helmholz equation

                           2     2     2
                         dd u  dd u  dd u
                         ----+ ----+ ----+(lambda)u=f(x,y,z)
                            2     2     2
                         ddx   ddy   ddz

                                               (pi)
          for (x,y,z)is in [0,1]*[0,2(pi)]*[0, ----] where (lambda)=-2, and
                                                2
          f(x,y,z) is derived from the exact solution

                                          4
                                u(x,y,z)=x sin(y)cos(z).

          The equation is subject to the following boundary conditions,
          again derived from the exact solution given above.

               u(0,y,z) and u(1,y,z) are prescribed (i.e., LBDCND = 1).

               u(x,0,z)=u(x,2(pi),z) (i.e., MBDCND = 0).

                                    (pi)
               u(x,y,0) and u (x,y, ----) are prescribed (i.e. NBDCND = 2).
                             x       2

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\section{nage.ht}
\pagetitle{manpageXXe01}{nage.ht}{ Interpolation}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe01}{NAG Documentation: e01}
\beginscroll
\begin{verbatim}



     E01(3NAG)         Foundation Library (12/10/92)         E01(3NAG)



          E01 -- Interpolation                          Introduction -- E01
                                    Chapter E01
                                   Interpolation

          1. Scope of the Chapter

          This chapter is concerned with the interpolation of a function of
          one or two variables. When provided with the value of the
          function (and possibly one or more of its lowest-order
          derivatives) at each of a number of values of the variable(s),
          the routines provide either an interpolating function or an
          interpolated value. For some of the interpolating functions,
          there are supporting routines to evaluate, differentiate or
          integrate them.

          2. Background to the Problems

          In motivation and in some of its numerical processes, this
          chapter has much in common with Chapter E02 (Curve and Surface
          Fitting). For this reason, we shall adopt the same terminology
          and refer to dependent variable and independent variable(s)
          instead of function and variable(s). Where there is only one
          independent variable, we shall denote it by x and the dependent
          variable by y. Thus, in the basic problem considered in this
          chapter, we are given a set of distinct values x ,x ,...,x  of x
                                                          1  2      m
          and a corresponding set of values y ,y ,...,y  of y, and we shall
                                             1  2      m
          describe the problem as being one of interpolating the data
          points (x ,y ), rather than interpolating a function. In modern
                   r  r
          usage, however, interpolation can have either of two rather
          different meanings, both relevant to routines in this chapter.
          They are

          (a) the determination of a function of x which takes the value y
                                                                          r
              at x=x , for r=1,2,...,m (an interpolating function or
                    r
              interpolant),

          (b) the determination of the value (interpolated value or
              interpolate) of an interpolating function at any given value,
                  ^
              say x, of x within the range of the x  (so as to estimate the
                                                   r
                       ^
              value at x of the function underlying the data).

          The latter is the older meaning, associated particularly with the
          use of mathematical tables. The term 'function underlying the
          data', like the other terminology described above, is used so as
          to cover situations additional to those in which the data points
          have been computed from a known function, as with a mathematical
          table. In some contexts, the function may be unknown, perhaps
          representing the dependency of one physical variable on another,
          say temperature upon time.

          Whether the underlying function is known or unknown, the object
          of interpolation will usually be to approximate it to acceptable
          accuracy by a function which is easy to evaluate anywhere in some
          range of interest. Piecewise polynomials such as cubic splines
          (see Section 2.2 of the E02 Chapter Introduction for definitions
          of terms in this case), being easy to evaluate and also capable
          of approximating a wide variety of functions, are the types of
          function mostly used in this chapter as interpolating functions.

          Piecewise polynomials also, to a large extent, avoid the well-
          known problem of large unwanted fluctuations which can arise when
          interpolating a data set with a simple polynomial. Fluctuations
          can still arise but much less frequently and much less severely
          than with simple polynomials. Unwanted fluctuations are avoided
          altogether by a routine using piecewise cubic polynomials having
          only first derivative continuity. It is designed especially for
          monotonic data, but for other data still provides an interpolant
          which increases, or decreases, over the same intervals as the
          data.

          The concept of interpolation can be generalised in a number of
          ways. For example, we may be required to estimate the value of
                                             ^
          the underlying function at a value x outside the range of the
          data. This is the process of extrapolation. In general, it is a
          good deal less accurate than interpolation and is to be avoided
          whenever possible.

          Interpolation can also be extended to the case of two independent
          variables. We shall denote these by x and y, and the dependent
          variable by f. Methods used depend markedly on whether or not the
          data values of f are given at the intersections of a rectangular
          mesh in the (x,y)-plane. If they are, bicubic splines (see
          Section 2.3.2 of the E02 Chapter Introduction) are very suitable
          and usually very effective for the problem. For other cases,
          perhaps where the f values are quite arbitrarily scattered in the
          (x,y)-plane, polynomials and splines are not at all appropriate
          and special forms of interpolating function have to be employed.
          Many such forms have been devised and two of the most successful
          are in routines in this chapter. They both have continuity in
          first, but not higher, derivatives.

          2.1. References

          [1]   Froberg C E (1970) Introduction to Numerical Analysis.
                Addison-Wesley (2nd Edition).

          [2]   Dahlquist G and Bjork A (1974) Numerical Methods. Prentice-
                Hall.

          3. Recommendations on Choice and Use of Routines

          3.1. General

          Before undertaking interpolation, in other than the simplest
          cases, the user should seriously consider the alternative of
          using a routine from Chapter E02 to approximate the data by a
          polynomial or spline containing significantly fewer coefficients
          than the corresponding interpolating function. This approach is
          much less liable to produce unwanted fluctuations and so can
          often provide a better approximation to the function underlying
          the data.

          When interpolation is employed to approximate either an
          underlying function or its values, the user will need to be
          satisfied that the accuracy of approximation achieved is
          adequate. There may be a means for doing this which is particular
          to the application, or the routine used may itself provide a
          means. In other cases, one possibility is to repeat the
          interpolation using one or more extra data points, if they are
          available, or otherwise one or more fewer, and to compare the
          results. Other possibilities, if it is an interpolating function
          which is determined, are to examine the function graphically, if
          that gives sufficient accuracy, or to observe the behaviour of
          the differences in a finite-difference table, formed from
          evaluations of the interpolating function at equally-spaced
          values of x over the range of interest. The spacing should be
          small enough to cause the typical size of the differences to
          decrease as the order of difference increases.

          3.2. One Independent Variable

          E01BAF computes an interpolating cubic spline, using a particular
          choice for the set of knots which has proved generally
          satisfactory in practice. If the user wishes to choose a
          different set, a cubic spline routine from Chapter E02, namely
          E02BAF, may be used in its interpolating mode, setting NCAP7 = M+
          4 and all elements of the parameter W to unity. These routines
          provide the interpolating function in B-spline form (see Section
          2.2.2 in the E02 Chapter Introduction). Routines for evaluating,
          differentiating and integrating this form are discussed in
          Section 3.7 of the E02 Chapter Introduction.

          The cubic spline does not always avoid unwanted fluctuations,
          especially when the data show a steep slope close to a region of
          small slope, or when the data inadequately represent the
          underlying curve. In such cases, E01BEF can be very useful. It
          derives a piecewise cubic polynomial (with first derivative
          continuity) which, between any adjacent pair of data points,
          either increases all the way, or decreases all the way (or stays
          constant). It is especially suited to data which are monotonic
          over their whole range.

          In this routine, the interpolating function is represented simply
          by its value and first derivative at the data points. Supporting
          routines compute its value and first derivative elsewhere, as
          well as its definite integral over an arbitary interval.

          3.3. Two Independent Variables

          3.3.1.  Data on a rectangular mesh

          Given the value f   of the dependent variable f at the point
                           qr
          (x ,y ) in the plane of the independent variables x and y, for
            q  r
          each q=1,2,...,m and r=1,2,...,n (so that the points (x ,y ) lie
                                                                 q  r
          at the m*n intersections of a rectangular mesh), E01DAF computes
          an interpolating bicubic spline, using a particular choice for
          each of the spline's knot-set. This choice, the same as in E01BAF
          , has proved generally satisfactory in practice. If, instead, the
          user wishes to specify his own knots, a routine from Chapter E02,
          namely E02DAF, may be adapted (it is more cumbersome for the
          purpose, however, and much slower for larger problems). Using m
          and n in the above sense, the parameter M must be set to m*n, PX
          and PY must be set to m+4 and n+4 respectively and all elements
          of W should be set to unity. The recommended value for EPS is
          zero.

          3.3.2.  Arbitrary data

          As remarked at the end of Section 2, special types of
          interpolating are required for this problem, which can often be
          difficult to solve satisfactorily. Two of the most successful are
          employed in E01SAF and E01SEF, the two routines which (with their
          respective evaluation routines E01SBF and E01SFF) are provided
          for the problem. Definitions can be found in the routine
          documents. Both interpolants have first derivative continuity and
          are 'local', in that their value at any point depends only on
          data in the immediate neighbourhood of the point. This latter
          feature is necessary for large sets of data to avoid prohibitive
          computing time.

          The relative merits of the two methods vary with the data and it
          is not possible to predict which will be the better in any
          particular case.

          3.4. Index

          Derivative, of interpolant from E01BEF                     E01BGF

          Evaluation, of interpolant
               from E01BEF                                           E01BFF
               from E01SAF                                           E01SBF
               from E01SEF                                           E01SFF
          Extrapolation, one variable                                E01BEF
          Integration (definite) of interpolant from E01BEF          E01BHF
          Interpolated values, one variable, from interpolant from   E01BFF
          E01BEF
                                                                     E01BGF
          Interpolated values, two variables,
               from interpolant from E01SAF                          E01SBF
               from interpolant from E01SEF                          E01SFF
          Interpolating function, one variable,
               cubic spline                                          E01BAF
               other piecewise polynomial                            E01BEF
          Interpolating function, two variables
               bicubic spline                                        E01DAF
               other piecewise polynomial                            E01SAF
               modified Shepard method                               E01SEF


          E01 -- Interpolation                              Contents -- E01
          Chapter E01

          Interpolation

          E01BAF  Interpolating functions, cubic spline interpolant, one
                  variable

          E01BEF  Interpolating functions, monotonicity-preserving,
                  piecewise cubic Hermite, one variable

          E01BFF  Interpolated values, interpolant computed by E01BEF,
                  function only, one variable,

          E01BGF  Interpolated values, interpolant computed by E01BEF,
                  function and 1st derivative, one variable

          E01BHF  Interpolated values, interpolant computed by E01BEF,
                  definite integral, one variable

          E01DAF  Interpolating functions, fitting bicubic spline, data on
                  rectangular grid

          E01SAF  Interpolating functions, method of Renka and Cline, two
                  variables

          E01SBF  Interpolated values, evaluate interpolant computed by
                  E01SAF, two variables

          E01SEF  Interpolating functions, modified Shepard's method, two
                  variables

          E01SFF  Interpolated values, evaluate interpolant computed by
                  E01SEF, two variables

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe01baf}{nage.ht}{ Cubic spline interpolant}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe01baf}{NAG Documentation: e01baf}
\beginscroll
\begin{verbatim}



     E01BAF(3NAG)      Foundation Library (12/10/92)      E01BAF(3NAG)



          E01 -- Interpolation                                       E01BAF
                  E01BAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E01BAF determines a cubic spline interpolant to a given set of
          data.

          2. Specification

                 SUBROUTINE E01BAF (M, X, Y, LAMDA, C, LCK, WRK, LWRK,
                1                   IFAIL)
                 INTEGER          M, LCK, LWRK, IFAIL
                 DOUBLE PRECISION X(M), Y(M), LAMDA(LCK), C(LCK), WRK(LWRK)

          3. Description

          This routine determines a cubic spline s(x), defined in the range
          x <=x<=x , which interpolates (passes exactly through) the set of
           1      m
          data points (x ,y ), for i=1,2,...,m, where m>=4 and x <x <...<x
                        i  i                                    1  2      m
          end conditions are not imposed. The spline interpolant chosen has
          m-4 interior knots (lambda) ,(lambda) ,...,(lambda) , which are
                                     5         6             m
          set to the values of x ,x ,...,x    respectively. This spline is
                                3  4      m-2
          represented in its B-spline form (see Cox [1]):

                                        m
                                        --
                                  s(x)= >  c N (x),
                                        --  i i
                                        i=1

          where N (x) denotes the normalised B-Spline of degree 3, defined
                 i
          upon the knots (lambda) ,(lambda)   ,...,(lambda)   , and c
                                 i         i+1             i+4       i
          denotes its coefficient, whose value is to be determined by the
          routine.

          The use of B-splines requires eight additional knots (lambda) ,
                                                                       1
          (lambda) , (lambda) , (lambda) , (lambda)   , (lambda)   ,
                  2          3          4          m+1          m+2
          (lambda)    and (lambda)    to be specified; the routine sets the
                  m+3             m+4
          first four of these to x  and the last four to x .
                                  1                       m

          The algorithm for determining the coefficients is as described in
          [1] except that QR factorization is used instead of LU
          decomposition. The implementation of the algorithm involves
          setting up appropriate information for the related routine E02BAF
          followed by a call of that routine. (For further details of
          E02BAF, see the routine document.)

          Values of the spline interpolant, or of its derivatives or
          definite integral, can subsequently be computed as detailed in
          Section 8.

          4. References

          [1]   Cox M G (1975) An Algorithm for Spline Interpolation. J.
                Inst. Math. Appl. 15 95--108.

          [2]   Cox M G (1977) A Survey of Numerical Methods for Data and
                Function Approximation. The State of the Art in Numerical
                Analysis. (ed D A H Jacobs) Academic Press. 627--668.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: m, the number of data points. Constraint: M >= 4.

           2:  X(M) -- DOUBLE PRECISION array                         Input
               On entry: X(i) must be set to x , the ith data value of the
                                              i
               independent variable x, for i=1,2,...,m. Constraint: X(i) <
               X(i+1), for i=1,2,...,M-1.

           3:  Y(M) -- DOUBLE PRECISION array                         Input
               On entry: Y(i) must be set to y , the ith data value of the
                                              i
               dependent variable y, for i=1,2,...,m.

           4:  LAMDA(LCK) -- DOUBLE PRECISION array                  Output
               On exit: the value of (lambda) , the ith knot, for
                                             i
               i=1,2,...,m+4.

           5:  C(LCK) -- DOUBLE PRECISION array                      Output
               On exit: the coefficient c  of the B-spline N (x), for
                                         i                  i
               i=1,2,...,m. The remaining elements of the array are not
               used.

           6:  LCK -- INTEGER                                         Input
               On entry:
               the dimension of the arrays LAMDA and C as declared in the
               (sub)program from which E01BAF is called.
               Constraint: LCK >= M + 4.

           7:  WRK(LWRK) -- DOUBLE PRECISION array                Workspace

           8:  LWRK -- INTEGER                                        Input
               On entry:
               the dimension of the array WRK as declared in the
               (sub)program from which E01BAF is called.
               Constraint: LWRK>=6*M+16.

           9:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               On entry M < 4,

               or       LCK<M+4,

               or       LWRK<6*M+16.

          IFAIL= 2
               The X-values fail to satisfy the condition

               X(1) < X(2) < X(3) <... < X(M).

          7. Accuracy

          The rounding errors incurred are such that the computed spline is
          an exact interpolant for a slightly perturbed set of ordinates
          y +(delta)y . The ratio of the root-mean-square value of the
           i         i
          (delta)y  to that of the y  is no greater than a small multiple
                  i                 i
          of the relative machine precision.

          8. Further Comments

          The time taken by the routine is approximately proportional to m.

          All the x  are used as knot positions except x  and x   . This
                   i                                    2      m-1
          choice of knots (see Cox [2]) means that s(x) is composed of m-3
          cubic arcs as follows. If m=4, there is just a single arc space
          spanning the whole interval x  to x . If m>=5, the first and last
                                       1     4
          arcs span the intervals x  to x  and x    to x  respectively.
                                   1     3      m-2     m
          Additionally if m>=6, the ith arc, for i=2,3,...,m-4 spans the
          interval x    to x   .
                    i+1     i+2

          After the call

                 CALL E01BAF (M, X, Y, LAMDA, C, LCK, WRK, LWRK, IFAIL)

          the following operations may be carried out on the interpolant
          s(x).

          The value of s(x) at x = XVAL can be provided in the real
          variable SVAL by the call

                 CALL E02BBF (M+4, LAMDA, C, XVAL, SVAL, IFAIL)

          The values of s(x) and its first three derivatives at x = XVAL
          can be provided in the real array SDIF of dimension 4, by the
          call

                 CALL E02BCF (M+4, LAMDA, C, XVAL, LEFT, SDIF, IFAIL)

          Here LEFT must specify whether the left- or right-hand value of
          the third derivative is required (see E02BCF for details).

          The value of the integral of s(x) over the range x  to x  can be
                                                            1     m
          provided in the real variable SINT by

                 CALL E02BDF (M+4, LAMDA, C, SINT, IFAIL)

          9. Example

          The example program sets up data from 7 values of the exponential
          function in the interval 0 to 1. E01BAF is then called to compute
          a spline interpolant to these data.

          The spline is evaluated by E02BBF, at the data points and at
          points halfway between each adjacent pair of data points, and the
                                           x
          spline values and the values of e  are printed out.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe01bef}{nage.ht}
{ Monoticity-preserving piecewise cubic Hermite interpolant}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe01bef}{NAG Documentation: e01bef}
\beginscroll
\begin{verbatim}



     E01BEF(3NAG)      Foundation Library (12/10/92)      E01BEF(3NAG)



          E01 -- Interpolation                                       E01BEF
                  E01BEF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E01BEF computes a monotonicity-preserving piecewise cubic Hermite
          interpolant to a set of data points.

          2. Specification

                 SUBROUTINE E01BEF (N, X, F, D, IFAIL)
                 INTEGER          N, IFAIL
                 DOUBLE PRECISION X(N), F(N), D(N)

          3. Description

          This routine estimates first derivatives at the set of data
          points (x ,f ), for r=1,2,...,n, which determine a piecewise
                   r  r
          cubic Hermite interpolant to the data, that preserves
          monotonicity over ranges where the data points are monotonic. If
          the data points are only piecewise monotonic, the interpolant
          will have an extremum at each point where monotonicity switches
          direction. The estimates of the derivatives are computed by a
          formula due to Brodlie, which is described in Fritsch and Butland
          [1], with suitable changes at the boundary points.

          The routine is derived from routine PCHIM in Fritsch [2].

          Values of the computed interpolant, and of its first derivative
          and definite integral, can subsequently be computed by calling
          E01BFF, E01BGF and E01BHF, as described in Section 8

          4. References

          [1]   Fritsch F N and Butland J (1984) A Method for Constructing
                Local Monotone Piecewise Cubic Interpolants. SIAM J. Sci.
                Statist. Comput. 5 300--304.

          [2]   Fritsch F N (1982) PCHIP Final Specifications. Report UCID-
                30194. Lawrence Livermore National Laboratory.

          5. Parameters

           1:  N -- INTEGER                                           Input
               On entry: n, the number of data points. Constraint: N >= 2.

           2:  X(N) -- DOUBLE PRECISION array                         Input
               On entry: X(r) must be set to x , the rth value of the
                                              r
               independent variable (abscissa), for r=1,2,...,n.
               Constraint: X(r) < X(r+1).

           3:  F(N) -- DOUBLE PRECISION array                         Input
               On entry: F(r) must be set to f , the rth value of the
                                              r
               dependent variable (ordinate), for r=1,2,...,n.

           4:  D(N) -- DOUBLE PRECISION array                        Output
               On exit: estimates of derivatives at the data points. D(r)
               contains the derivative at X(r).

           5:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry N < 2.

          IFAIL= 2
               The values of X(r), for r=1,2,...,N, are not in strictly
               increasing order.

          7. Accuracy

          The computational errors in the array D should be negligible in
          most practical situations.

          8. Further Comments

          The time taken by the routine is approximately proportional to n.

          The values of the computed interpolant at the points PX(i), for
          i=1,2,...,M, may be obtained in the real array PF, of length at
          least M, by the call:


                  CALL E01BFF(N,X,F,D,M,PX,PF,IFAIL)

          where N, X and F are the input parameters to E01BEF and D is the
          output parameter from E01BEF.

          The values of the computed interpolant at the points PX(i), for i
          = 1,2,...,M, together with its first derivatives, may be obtained
          in the real arrays PF and PD, both of length at least M, by the
          call:

                  CALL E01BGF(N,X,F,D,M,PX,PF,PD,IFAIL)

          where N, X, F and D are as described above.

          The value of the definite integral of the interpolant over the
          interval A to B can be obtained in the real variable PINT by the
          call:

                  CALL E01BHF(N,X,F,D,A,B,PINT,IFAIL)

          where N, X, F and D are as described above.

          9. Example

          This example program reads in a set of data points, calls E01BEF
          to compute a piecewise monotonic interpolant, and then calls
          E01BFF to evaluate the interpolant at equally spaced points.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe01bff}{nage.ht}{ Piecewise cubic Hermite interpolant}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe01bff}{NAG Documentation: e01bff}
\beginscroll
\begin{verbatim}



     E01BFF(3NAG)      Foundation Library (12/10/92)      E01BFF(3NAG)



          E01 -- Interpolation                                       E01BFF
                  E01BFF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E01BFF evaluates a piecewise cubic Hermite interpolant at a set
          of points.

          2. Specification

                 SUBROUTINE E01BFF (N, X, F, D, M, PX, PF, IFAIL)
                 INTEGER          N, M, IFAIL
                 DOUBLE PRECISION X(N), F(N), D(N), PX(M), PF(M)

          3. Description

          This routine evaluates a piecewise cubic Hermite interpolant, as
          computed by E01BEF, at the points PX(i), for i=1,2,...,m. If any
          point lies outside the interval from X(1) to X(N), a value is
          extrapolated from the nearest extreme cubic, and a warning is
          returned.

          The routine is derived from routine PCHFE in Fritsch [1].

          4. References

          [1]   Fritsch F N (1982) PCHIP Final Specifications. Report UCID-
                30194. Lawrence Livermore National Laboratory.

          5. Parameters

           1:  N -- INTEGER                                           Input

           2:  X(N) -- DOUBLE PRECISION array                         Input

           3:  F(N) -- DOUBLE PRECISION array                         Input

           4:  D(N) -- DOUBLE PRECISION array                         Input
               On entry: N, X, F and D must be unchanged from the previous
               call of E01BEF.

           5:  M -- INTEGER                                           Input
               On entry: m, the number of points at which the interpolant
               is to be evaluated. Constraint: M >= 1.

           6:  PX(M) -- DOUBLE PRECISION array                        Input
               On entry: the m values of x at which the interpolant is to
               be evaluated.

           7:  PF(M) -- DOUBLE PRECISION array                       Output
               On exit: PF(i) contains the value of the interpolant
               evaluated at the point PX(i), for i=1,2,...,m.

           8:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry N < 2.

          IFAIL= 2
               The values of X(r), for r = 1,2,...,N, are not in strictly
               increasing order.

          IFAIL= 3
               On entry M < 1.

          IFAIL= 4
               At least one of the points PX(i), for i = 1,2,...,M, lies
               outside the interval [X(1),X(N)], and extrapolation was
               performed at all such points. Values computed at such points
               may be very unreliable.

          7. Accuracy

          The computational errors in the array PF should be negligible in
          most practical situations.

          8. Further Comments

          The time taken by the routine is approximately proportional to
          the number of evaluation points, m. The evaluation will be most
          efficient if the elements of PX are in non-decreasing order (or,
          more generally, if they are grouped in increasing order of the
          intervals [X(r-1),X(r)]). A single call of E01BFF with m>1 is
          more efficient than several calls with m=1.

          9. Example

          This example program reads in values of N, X, F and D, and then
          calls E01BFF to evaluate the interpolant at equally spaced
          points.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe01bgf}{nage.ht}
{ Piecewise cubic Hermite interpolant and 1st deriv}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe01bgf}{NAG Documentation: e01bgf}
\beginscroll
\begin{verbatim}



     E01BGF(3NAG)      Foundation Library (12/10/92)      E01BGF(3NAG)



          E01 -- Interpolation                                       E01BGF
                  E01BGF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E01BGF evaluates a piecewise cubic Hermite interpolant and its
          first derivative at a set of points.

          2. Specification

                 SUBROUTINE E01BGF (N, X, F, D, M, PX, PF, PD, IFAIL)
                 INTEGER          N, M, IFAIL
                 DOUBLE PRECISION X(N), F(N), D(N), PX(M), PF(M), PD(M)

          3. Description

          This routine evaluates a piecewise cubic Hermite interpolant, as
          computed by E01BEF, at the points PX(i), for i=1,2,...,m. The
          first derivatives at the points are also computed. If any point
          lies outside the interval from X(1) to X(N), values of the
          interpolant and its derivative are extrapolated from the nearest
          extreme cubic, and a warning is returned.

          If values of the interpolant only, and not of its derivative, are
          required, E01BFF should be used.

          The routine is derived from routine PCHFD in Fritsch [1].

          4. References

          [1]   Fritsch F N (1982) PCHIP Final Specifications. Report UCID-
                30194. Lawrence Livermore National Laboratory.

          5. Parameters

           1:  N -- INTEGER                                           Input

           2:  X(N) -- DOUBLE PRECISION array                         Input

           3:  F(N) -- DOUBLE PRECISION array                         Input

           4:  D(N) -- DOUBLE PRECISION array                         Input
               On entry: N, X, F and D must be unchanged from the previous
               call of E01BEF.

           5:  M -- INTEGER                                           Input
               On entry: m, the number of points at which the interpolant
               is to be evaluated. Constraint: M >= 1.

           6:  PX(M) -- DOUBLE PRECISION array                        Input
               On entry: the m values of x at which the interpolant is to
               be evaluated.

           7:  PF(M) -- DOUBLE PRECISION array                       Output
               On exit: PF(i) contains the value of the interpolant
               evaluated at the point PX(i), for i=1,2,...,m.

           8:  PD(M) -- DOUBLE PRECISION array                       Output
               On exit: PD(i) contains the first derivative of the
               interpolant evaluated at the point PX(i), for i=1,2,...,m.

           9:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry N < 2.

          IFAIL= 2
               The values of X(r), for r = 1,2,...,N, are not in strictly
               increasing order.

          IFAIL= 3
               On entry M < 1.

          IFAIL= 4
               At least one of the points PX(i), for i = 1,2,...,M, lies
               outside the interval [X(1),X(N)], and extrapolation was
               performed at all such points. Values computed at these
               points may be very unreliable.

          7. Accuracy

          The computational errors in the arrays PF and PD should be
          negligible in most practical situations.

          8. Further Comments

          The time taken by the routine is approximately proportional to
          the number of evaluation points, m. The evaluation will be most
          efficient if the elements of PX are in non-decreasing order (or,
          more generally, if they are grouped in increasing order of the
          intervals [X(r-1),X(r)]). A single call of E01BGF with m>1 is
          more efficient than several calls with m=1.

          9. Example

          This example program reads in values of N, X, F and D, and calls
          E01BGF to compute the values of the interpolant and its
          derivative at equally spaced points.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe01bhf}{nage.ht}
{ Definite integral of piecewise cubic Hermite interpolant}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe01bhf}{NAG Documentation: e01bhf}
\beginscroll
\begin{verbatim}



     E01BHF(3NAG)      Foundation Library (12/10/92)      E01BHF(3NAG)



          E01 -- Interpolation                                       E01BHF
                  E01BHF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E01BHF evaluates the definite integral of a piecewise cubic
          Hermite interpolant over the interval [a,b].

          2. Specification

                 SUBROUTINE E01BHF (N, X, F, D, A, B, PINT, IFAIL)
                 INTEGER          N, IFAIL
                 DOUBLE PRECISION X(N), F(N), D(N), A, B, PINT

          3. Description

          This routine evaluates the definite integral of a piecewise cubic
          Hermite interpolant, as computed by E01BEF, over the interval
          [a,b].

          If either a or b lies outside the interval from X(1) to X(N)
          computation of the integral involves extrapolation and a warning
          is returned.

          The routine is derived from routine PCHIA in Fritsch [1].

          4. References

          [1]   Fritsch F N (1982) PCHIP Final Specifications. Report UCID-
                30194. Lawrence Livermore National Laboratory .

          5. Parameters

           1:  N -- INTEGER                                           Input

           2:  X(N) -- DOUBLE PRECISION array                         Input

           3:  F(N) -- DOUBLE PRECISION array                         Input

           4:  D(N) -- DOUBLE PRECISION array                         Input
               On entry: N, X, F and D must be unchanged from the previous
               call of E01BEF.

           5:  A -- DOUBLE PRECISION                                  Input

           6:  B -- DOUBLE PRECISION                                  Input
               On entry: the interval [a,b] over which integration is to
               be performed.

           7:  PINT -- DOUBLE PRECISION                              Output
               On exit: the value of the definite integral of the
               interpolant over the interval [a,b].

           8:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry N < 2.

          IFAIL= 2
               The values of X(r), for r = 1,2,...,N, are not in strictly
               increasing order.

          IFAIL= 3
               On entry at least one of A or B lies outside the interval [X
               (1),X(N)], and extrapolation was performed to compute the
               integral. The value returned is therefore unreliable.

          7. Accuracy

          The computational error in the value returned for PINT should be
          negligible in most practical situations.

          8. Further Comments

          The time taken by the routine is approximately proportional to
          the number of data points included within the interval [a,b].

          9. Example

          This example program reads in values of N, X, F and D. It then
          reads in pairs of values for A and B, and evaluates the definite
          integral of the interpolant over the interval [A,B] until end-of-
          file is reached.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe01daf}{nage.ht}{ Bicubic spline interpolated surface}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe01daf}{NAG Documentation: e01daf}
\beginscroll
\begin{verbatim}



     E01DAF(3NAG)      Foundation Library (12/10/92)      E01DAF(3NAG)



          E01 -- Interpolation                                       E01DAF
                  E01DAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E01DAF computes a bicubic spline interpolating surface through a
          set of data values, given on a rectangular grid in the x-y plane.

          2. Specification

                 SUBROUTINE E01DAF (MX, MY, X, Y, F, PX, PY, LAMDA, MU, C,
                1                   WRK, IFAIL)
                 INTEGER          MX, MY, PX, PY, IFAIL
                 DOUBLE PRECISION X(MX), Y(MY), F(MX*MY), LAMDA(MX+4), MU(MX
                1                 +4), C(MX*MY), WRK((MX+6)*(MY+6))

          3. Description

          This routine determines a bicubic spline interpolant to the set
          of data points (x ,y ,f   ), for q=1,2,...,m ; r=1,2,...,m . The
                           q  r  q,r                  x             y
          spline is given in the B-spline representation

                                    m   m
                                     x   y
                                    --  --
                            s(x,y)= >   >  c  M (x)N (y),
                                    --  --  ij i    j
                                    i=1 j=1

          such that

                                   s(x ,y )=f   ,
                                      q  r   q,r

          where M (x) and N (y) denote normalised cubic B-splines, the
                 i         j
          former defined on the knots (lambda)  to (lambda)    and the
                                              i            i+4
          latter on the knots (mu)  to (mu)   , and the c   are the spline
                                  j        j+4           ij
          coefficients. These knots, as well as the coefficients, are
          determined by the routine, which is derived from the routine
          B2IRE in Anthony et al[1]. The method used is described in
          Section 8.2.

          For further information on splines, see Hayes and Halliday [4]
          for bicubic splines and de Boor [3] for normalised B-splines.

          Values of the computed spline can subsequently be obtained by
          calling E02DEF or E02DFF as described in Section 8.3.

          4. References

          [1]   Anthony G T, Cox M G and Hayes J G (1982) DASL - Data
                Approximation Subroutine Library. National Physical
                Laboratory.

          [2]   Cox M G (1975) An Algorithm for Spline Interpolation. J.
                Inst. Math. Appl. 15 95--108.

          [3]   De Boor C (1972) On Calculating with B-splines. J. Approx.
                Theory. 6 50--62.

          [4]   Hayes J G and Halliday J (1974) The Least-squares Fitting of
                Cubic Spline Surfaces to General Data Sets. J. Inst. Math.
                Appl. 14 89--103.

          5. Parameters

           1:  MX -- INTEGER                                          Input

           2:  MY -- INTEGER                                          Input
               On entry: MX and MY must specify m  and m  respectively,
                                                 x      y
               the number of points along the x and y axis that define the
               rectangular grid. Constraint: MX >= 4 and MY >= 4.

           3:  X(MX) -- DOUBLE PRECISION array                        Input

           4:  Y(MY) -- DOUBLE PRECISION array                        Input
               On entry: X(q) and Y(r) must contain x , for q=1,2,...,m ,
                                                     q                 x
               and y , for r=1,2,...,m , respectively. Constraints:
                    r                 y
                    X(q) < X(q+1), for q=1,2,...,m -1,
                                                  x

                    Y(r) < Y(r+1), for r=1,2,...,m -1.
                                                  y

           5:  F(MX*MY) -- DOUBLE PRECISION array                     Input
               On entry: F(m *(q-1)+r) must contain f   , for q=1,2,...,m ;
                            y                        q,r                 x
               r=1,2,...,m .
                          y

           6:  PX -- INTEGER                                         Output

           7:  PY -- INTEGER                                         Output
               On exit: PX and PY contain m +4 and m +4, the total number
                                           x        y
               of knots of the computed spline with respect to the x and y
               variables, respectively.

           8:  LAMDA(MX+4) -- DOUBLE PRECISION array                 Output

           9:  MU(MY+4) -- DOUBLE PRECISION array                    Output
               On exit: LAMDA contains the complete set of knots (lambda)
                                                                         i
               associated with the x variable, i.e., the interior knots
               LAMDA(5), LAMDA(6), ..., LAMDA(PX-4), as well as the
               additional knots LAMDA(1) = LAMDA(2) = LAMDA(3) = LAMDA(4) =
               X(1) and LAMDA(PX-3) = LAMDA(PX-2) = LAMDA(PX-1) = LAMDA(PX)
               = X(MX) needed for the B-spline representation. MU contains
               the corresponding complete set of knots (mu)  associated
                                                           i
               with the y variable.

          10:  C(MX*MY) -- DOUBLE PRECISION array                    Output
               On exit: the coefficients of the spline interpolant. C(
               m *(i-1)+j) contains the coefficient c   described in
                y                                    ij
               Section 3.

          11:  WRK((MX+6)*(MY+6)) -- DOUBLE PRECISION array       Workspace

          12:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry MX < 4,

               or       MY < 4.

          IFAIL= 2
               On entry either the values in the X array or the values in
               the Y array are not in increasing order.

          IFAIL= 3
               A system of linear equations defining the B-spline
               coefficients was singular; the problem is too ill-
               conditioned to permit solution.

          7. Accuracy

          The main sources of rounding errors are in steps (2), (3), (6)
          and (7) of the algorithm described in Section 8.2. It can be
          shown (Cox [2]) that the matrix A  formed in step (2) has
                                           x
          elements differing relatively from their true values by at most a
          small multiple of 3(epsilon), where (epsilon) is the machine
          precision. A  is 'totally positive', and a linear system with
                      x
          such a coefficient matrix can be solved quite safely by
          elimination without pivoting. Similar comments apply to steps (6)
          and (7). Thus the complete process is numerically stable.

          8. Further Comments

          8.1. Timing

          The time taken by this routine is approximately proportional to
          m m .
           x y

          8.2. Outline of method used

          The process of computing the spline consists of the following
          steps:

          (1)   choice of the interior x-knots (lambda) , (lambda) ,...,
                                                       5          6
                (lambda)   as (lambda) =x   , for i=5,6,...,m ,
                        m             i  i-2                 x
                         x

          (2)   formation of the system
                                          A E=F,
                                           x
                where A  is a band matrix of order m  and bandwidth 4,
                       x                            x
                containing in its qth row the values at x  of the B-splines
                                                         q
                in x, F is the m  by m  rectangular matrix of values f   ,
                                x     y                               q,r
                and E denotes an m  by m  rectangular matrix of
                                  x     y
                intermediate coefficients,

          (3)   use of Gaussian elimination to reduce this system to band
                triangular form,

          (4)   solution of this triangular system for E,

          (5)   choice of the interior y knots (mu) , (mu) ,...,(mu)   as
                                                   5      6         m
                                                                     y
                (mu) =y   , for i=5,6,...,m ,
                    i  i-2                 y

          (6)   formation of the system
                                            T  T
                                         A C =E ,
                                          y
                where A  is the counterpart of A  for the y variable, and C
                       y                        x
                denotes the m  by m  rectangular matrix of values of c  ,
                             x     y                                  ij

          (7)   use of Gaussian elimination to reduce this system to band
                triangular form,

                                                        T
          (8)   solution of this triangular system for C  and hence C.

          For computational convenience, steps (2) and (3), and likewise
          steps (6) and (7), are combined so that the formation of A  and
                                                                    x
          A  and the reductions to triangular form are carried out one row
           y
          at a time.

          8.3. Evaluation of Computed Spline

          The values of the computed spline at the points (TX(r),TY(r)),
          for r = 1,2,...,N, may be obtained in the double precision array
          FF, of length at least N, by the following call:


                IFAIL = 0
                CALL E02DEF(N,PX,PY,TX,TY,LAMDA,MU,C,FF,WRK,IWRK,IFAIL)

          where PX, PY, LAMDA, MU and C are the output parameters of E01DAF
          , WRK is a double precision workspace array of length at least
          PY-4, and IWRK is an integer workspace array of length at least
          PY-4.

          To evaluate the computed spline on an NX by NY rectangular grid
          of points in the x-y plane, which is defined by the x co-
          ordinates stored in TX(q), for q = 1,2,...,NX, and the y co-
          ordinates stored in TY(r), for r = 1,2,...,NY, returning the
          results in the double precision array FG which is of length at
          least NX*NY, the following call may be used:


                 IFAIL = 0
                 CALL E02DFF(NX,NY,PX,PY,TX,TY,LAMDA,MU,C,FG,WRK,LWRK,
                *            IWRK,LIWRK,IFAIL)

          where PX, PY, LAMDA, MU and C are the output parameters of E01DAF
          , WRK is a double precision workspace array of length at least
          LWRK = min(NWRK1,NWRK2), NWRK1 = NX*4+PX, NWRK2 = NY*4+PY, and
          IWRK is an integer workspace array of length at least LIWRK = NY
          + PY - 4 if NWRK1 > NWRK2, or NX + PX - 4 otherwise. The result
          of the spline evaluated at grid point (q,r) is returned in
          element (NY*(q-1)+r) of the array FG.

          9. Example

          This program reads in values of m , x  for q=1,2,...,m , m  and
                                           x   q                x   y
          y  for r=1,2,...,m , followed by values of the ordinates f
           r                y                                       q,r
          defined at the grid points (x ,y ). It then calls E01DAF to
                                       q  r
          compute a bicubic spline interpolant of the data values, and
          prints the values of the knots and B-spline coefficients. Finally
          it evaluates the spline at a small sample of points on a
          rectangular grid.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe01saf}{nage.ht}
{ Two-D surface interpolating a set of scattered data points}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe01saf}{NAG Documentation: e01saf}
\beginscroll
\begin{verbatim}



     E01SAF(3NAG)      Foundation Library (12/10/92)      E01SAF(3NAG)



          E01 -- Interpolation                                       E01SAF
                  E01SAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E01SAF generates a two-dimensional surface interpolating a set of
          scattered data points, using the method of Renka and Cline.

          2. Specification

                 SUBROUTINE E01SAF (M, X, Y, F, TRIANG, GRADS, IFAIL)
                 INTEGER          M, TRIANG(7*M), IFAIL
                 DOUBLE PRECISION X(M), Y(M), F(M), GRADS(2,M)

          3. Description

          This routine constructs an interpolating surface F(x,y) through a
          set of m scattered data points (x ,y ,f ), for r=1,2,...,m, using
                                           r  r  r
          a method due to Renka and Cline. In the (x,y) plane, the data
          points must be distinct. The constructed surface is continuous
          and has continuous first derivatives.

          The method involves firstly creating a triangulation with all the
          (x,y) data points as nodes, the triangulation being as nearly
          equiangular as possible (see Cline and Renka [1]). Then gradients
          in the x- and y-directions are estimated at node r, for
          r=1,2,...,m, as the partial derivatives of a quadratic function
          of x and y which interpolates the data value f , and which fits
                                                        r
          the data values at nearby nodes (those within a certain distance
          chosen by the algorithm) in a weighted least-squares sense. The
          weights are chosen such that closer nodes have more influence
          than more distant nodes on derivative estimates at node r. The
          computed partial derivatives, with the f  values, at the three
                                                  r
          nodes of each triangle define a piecewise polynomial surface of a
          certain form which is the interpolant on that triangle. See Renka
          and Cline [4] for more detailed information on the algorithm, a
          development of that by Lawson [2]. The code is derived from Renka
          [3].

          The interpolant F(x,y) can subsequently be evaluated at any point
          (x,y) inside or outside the domain of the data by a call to
          E01SBF. Points outside the domain are evaluated by extrapolation.

          4. References

          [1]   Cline A K and Renka R L (1984) A Storage-efficient Method
                for Construction of a Thiessen Triangulation. Rocky Mountain
                J. Math. 14 119--139.

                                                1
          [2]   Lawson C L (1977) Software for C  Surface Interpolation.
                Mathematical Software III. (ed J R Rice) Academic Press.
                161--194.

          [3]   Renka R L (1984) Algorithm 624: Triangulation and
                Interpolation of Arbitrarily Distributed Points in the
                Plane. ACM Trans. Math. Softw. 10 440--442.

                                                                 1
          [4]   Renka R L and Cline A K (1984) A Triangle-based C
                Interpolation Method. Rocky Mountain J. Math. 14 223--237.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: m, the number of data points. Constraint: M >= 3.

           2:  X(M) -- DOUBLE PRECISION array                         Input

           3:  Y(M) -- DOUBLE PRECISION array                         Input

           4:  F(M) -- DOUBLE PRECISION array                         Input
               On entry: the co-ordinates of the rth data point, for
               r=1,2,...,m. The data points are accepted in any order, but
               see Section 8. Constraint: The (x,y) nodes must not all be
               collinear, and each node must be unique.

           5:  TRIANG(7*M) -- INTEGER array                          Output
               On exit: a data structure defining the computed
               triangulation, in a form suitable for passing to E01SBF.

           6:  GRADS(2,M) -- DOUBLE PRECISION array                  Output
               On exit: the estimated partial derivatives at the nodes, in
               a form suitable for passing to E01SBF. The derivatives at
               node r with respect to x and y are contained in GRADS(1,r)
               and GRADS(2,r) respectively, for r=1,2,...,m.

           7:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry M < 3.

          IFAIL= 2
               On entry all the (X,Y) pairs are collinear.

          IFAIL= 3
               On entry (X(i),Y(i)) = (X(j),Y(j)) for some i/=j.

          7. Accuracy

          On successful exit, the computational errors should be negligible
          in most situations but the user should always check the computed
          surface for acceptability, by drawing contours for instance. The
          surface always interpolates the input data exactly.

          8. Further Comments

          The time taken for a call of E01SAF is approximately proportional
          to the number of data points, m. The routine is more efficient
          if, before entry, the values in X, Y, F are arranged so that the
          X array is in ascending order.

          9. Example

          This program reads in a set of 30 data points and calls E01SAF to
          construct an interpolating surface. It then calls E01SBF to
          evaluate the interpolant at a sample of points on a rectangular
          grid.

          Note that this example is not typical of a realistic problem: the
          number of data points would normally be larger, and the
          interpolant would need to be evaluated on a finer grid to obtain
          an accurate plot, say.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe01sbf}{nage.ht}
{ Evaluate 2D interpolant function from E01SAF}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe01sbf}{NAG Documentation: e01sbf}
\beginscroll
\begin{verbatim}



     E01SBF(3NAG)      Foundation Library (12/10/92)      E01SBF(3NAG)



          E01 -- Interpolation                                       E01SBF
                  E01SBF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E01SBF evaluates at a given point the two-dimensional interpolant
          function computed by E01SAF.

          2. Specification

                 SUBROUTINE E01SBF (M, X, Y, F, TRIANG, GRADS, PX, PY, PF,
                1                   IFAIL)
                 INTEGER          M, TRIANG(7*M), IFAIL
                 DOUBLE PRECISION X(M), Y(M), F(M), GRADS(2,M), PX, PY, PF

          3. Description

          This routine takes as input the parameters defining the
          interpolant F(x,y) of a set of scattered data points (x ,y ,f ),
                                                                 r  r  r
          for r=1,2,...,m, as computed by E01SAF, and evaluates the
          interpolant at the point (px,py).

          If (px,py) is equal to (x ,y ) for some value of r, the returned
                                   r  r
          value will be equal to f .
                                  r

          If (px,py) is not equal to (x ,y ) for any r, the derivatives in
                                       r  r
          GRADS will be used to compute the interpolant. A triangle is
          sought which contains the point (px,py), and the vertices of the
          triangle along with the partial derivatives and f  values at the
                                                           r
          vertices are used to compute the value F(px,py). If the point
          (px,py) lies outside the triangulation defined by the input
          parameters, the returned value is obtained by extrapolation. In
          this case, the interpolating function F is extended linearly
          beyond the triangulation boundary. The method is described in
          more detail in Renka and Cline [2] and the code is derived from
          Renka [1].

          E01SBF must only be called after a call to E01SAF.

          4. References

          [1]   Renka R L (1984) Algorithm 624: Triangulation and
                Interpolation of Arbitrarily Distributed Points in the
                Plane. ACM Trans. Math. Softw. 10 440--442.

                                                                 1
          [2]   Renka R L and Cline A K (1984) A Triangle-based C
                Interpolation Method. Rocky Mountain J. Math. 14 223--237.

          5. Parameters

           1:  M -- INTEGER                                           Input

           2:  X(M) -- DOUBLE PRECISION array                         Input

           3:  Y(M) -- DOUBLE PRECISION array                         Input

           4:  F(M) -- DOUBLE PRECISION array                         Input

           5:  TRIANG(7*M) -- INTEGER array                           Input

           6:  GRADS(2,M) -- DOUBLE PRECISION array                   Input
               On entry: M, X, Y, F, TRIANG and GRADS must be unchanged
               from the previous call of E01SAF.

           7:  PX -- DOUBLE PRECISION                                 Input

           8:  PY -- DOUBLE PRECISION                                 Input
               On entry: the point (px,py) at which the interpolant is to
               be evaluated.

           9:  PF -- DOUBLE PRECISION                                Output
               On exit: the value of the interpolant evaluated at the
               point (px,py).

          10:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry M < 3.

          IFAIL= 2
               On entry the triangulation information held in the array
               TRIANG does not specify a valid triangulation of the data
               points. TRIANG may have been corrupted since the call to
               E01SAF.

          IFAIL= 3
               The evaluation point (PX,PY) lies outside the nodal
               triangulation, and the value returned in PF is computed by
               extrapolation.

          7. Accuracy

          Computational errors should be negligible in most practical
          situations.

          8. Further Comments

          The time taken for a call of E01SBF is approximately proportional
          to the number of data points, m.

          The results returned by this routine are particularly suitable
          for applications such as graph plotting, producing a smooth
          surface from a number of scattered points.

          9. Example

          See the example for E01SAF.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe01sef}{nage.ht}
{ Generate 2D surface interpolating a scattered data points}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe01sef}{NAG Documentation: e01sef}
\beginscroll
\begin{verbatim}



     E01SEF(3NAG)      Foundation Library (12/10/92)      E01SEF(3NAG)



          E01 -- Interpolation                                       E01SEF
                  E01SEF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E01SEF generates a two-dimensional surface interpolating a set of
          scattered data points, using a modified Shepard method.

          2. Specification

                 SUBROUTINE E01SEF (M, X, Y, F, RNW, RNQ, NW, NQ, FNODES,
                1                   MINNQ, WRK, IFAIL)
                 INTEGER          M, NW, NQ, MINNQ, IFAIL
                 DOUBLE PRECISION X(M), Y(M), F(M), RNW, RNQ, FNODES(5*M),
                1                 WRK(6*M)

          3. Description

          This routine constructs an interpolating surface F(x,y) through a
          set of m scattered data points (x ,y ,f ), for r=1,2,...,m, using
                                           r  r  r
          a modification of Shepard's method. The surface is continuous and
          has continuous first derivatives.

          The basic Shepard method, described in [2], interpolates the
          input data with the weighted mean

                                        m
                                        --
                                        >  w (x,y)f
                                        --  r      r
                                        r=1
                               F(x,y)= -------------,
                                         m
                                         --
                                         >  w (x,y)
                                         --  r
                                         r=1

                                    1         2       2       2
                     where w (x,y)= --  and  d =(x-x ) +(y-y ) .
                            r        2        r     r       r
                                    d
                                     r

          The basic method is global in that the interpolated value at any
          point depends on all the data, but this routine uses a
          modification due to Franke and Nielson described in [1], whereby
          the method becomes local by adjusting each w (x,y) to be zero
                                                      r
          outside a circle with centre (x ,y ) and some radius R . Also, to
                                         r  r                   w
          improve the performance of the basic method, each f  above is
                                                             r
          replaced by a function f (x,y), which is a quadratic fitted by
                                  r
          weighted least-squares to data local to (x ,y ) and forced to
                                                    r  r
          interpolate (x ,y ,f ). In this context, a point (x,y) is defined
                        r  r  r
          to be local to another point if it lies within some distance R
                                                                        q
          of it. Computation of these quadratics constitutes the main work
          done by this routine. If there are less than 5 other points
          within distance R  from (x ,y ), the quadratic is replaced by a
                           q        r  r
          linear function. In cases of rank-deficiency, the minimum norm
          solution is computed.

          The user may specify values for R  and R , but it is usually
                                           w      q
          easier to choose instead two integers N  and N , from which the
                                                 w      q
          routine will compute R  and R . These integers can be thought of
                                w      q
          as the average numbers of data points lying within distances R
                                                                        w
          and R  respectively from each node. Default values are provided,
               q
          and advice on alternatives is given in Section 8.2.

          The interpolant F(x,y) generated by this routine can subsequently
          be evaluated for any point (x,y) in the domain of the data by a
          call to E01SFF.

          4. References

          [1]   Franke R and Nielson G (1980) Smooth Interpolation of Large
                Sets of Scattered Data. Internat. J. Num. Methods Engrg. 15
                1691--1704.

          [2]   Shepard D (1968) A Two-dimensional Interpolation Function
                for Irregularly Spaced Data. Proc. 23rd Nat. Conf. ACM.
                Brandon/Systems Press Inc., Princeton. 517--523.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: m, the number of data points. Constraint: M >= 3.

           2:  X(M) -- DOUBLE PRECISION array                         Input

           3:  Y(M) -- DOUBLE PRECISION array                         Input

           4:  F(M) -- DOUBLE PRECISION array                         Input
               On entry: the co-ordinates of the rth data point, for
               r=1,2,...,m. The order of the data points is immaterial.
               Constraint: each of the (X(r),Y(r)) pairs must be unique.

           5:  RNW -- DOUBLE PRECISION                         Input/Output

           6:  RNQ -- DOUBLE PRECISION                         Input/Output
               On entry: suitable values for the radii R  and R ,
                                                         w      q
               described in Section 3. Constraint: RNQ <= 0 or 0 < RNW <=
               RNQ. On exit: if RNQ is set less than or equal to zero on
               entry, then default values for both of them will be computed
               from the parameters NW and NQ, and RNW and RNQ will contain
               these values on exit.

           7:  NW -- INTEGER                                          Input

           8:  NQ -- INTEGER                                          Input
               On entry: if RNQ > 0.0 and RNW > 0.0 then NW and NQ are not
               referenced by the routine. Otherwise, NW and NQ must specify
               suitable values for the integers N  and N  described in
                                                 w      q
               Section 3.

               If NQ is less than or equal to zero on entry, then default
               values for both of them, namely NW = 9 and NQ = 18, will be
               used. Constraint: NQ <= 0 or 0 < NW <= NQ.

           9:  FNODES(5*M) -- DOUBLE PRECISION array                 Output
               On exit: the coefficients of the constructed quadratic
               nodal functions. These are in a form suitable for passing to
               E01SFF.

          10:  MINNQ -- INTEGER                                      Output
               On exit: the minimum number of data points that lie within
               radius RNQ of any node, and thus define a nodal function. If
               MINNQ is very small (say, less than 5), then the interpolant
               may be unsatisfactory in regions where the data points are
               sparse.

          11:  WRK(6*M) -- DOUBLE PRECISION array                 Workspace

          12:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry M < 3.

          IFAIL= 2
               On entry RNQ > 0 and either RNW > RNQ or RNW <= 0.

          IFAIL= 3
               On entry NQ > 0 and either NW > NQ or NW <= 0.

          IFAIL= 4
               On entry (X(i),Y(i)) is equal to (X(j),Y(j)) for some i/=j.

          7. Accuracy

          On successful exit, the computational errors should be negligible
          in most situations but the user should always check the computed
          surface for acceptability, by drawing contours for instance. The
          surface always interpolates the input data exactly.

          8. Further Comments

          8.1. Timing

          The time taken for a call of E01SEF is approximately proportional
          to the number of data points, m, provided that N  is of the same
                                                          q
          order as its default value (18). However if N  is increased so
                                                       q
          that the method becomes more global, the time taken becomes
                                         2
          approximately proportional to m .
                            m N} {{\rm w}}$ and ${\rm N} {{\rm q}}$
          8.2. Choice of ${\
          Note first that the radii R  and R , described in Section 3, are
                                     w      q
                                            

                            / N            / N
                       D   /   w      D   /   q
          computed as  -  /   -- and  -  /   -- respectively, where D is
                       2\/    m       2/    m
          the maximum distance between any pair of data points.
          Default values N =9 and N =18 work quite well when the data
                          w        q
          points are fairly uniformly distributed. However, for data having
          some regions with relatively few points or for small data sets
          (m<25), a larger value of N  may be needed. This is to ensure a
                                    w
          reasonable number of data points within a distance R  of each
                                                              w
          node, and to avoid some regions in the data area being left
          outside all the discs of radius R  on which the weights w (x,y)
                                           w                       r
          are non-zero. Maintaining N  approximately equal to 2N  is
                                     q                          w
          usually an advantage.

          Note however that increasing N  and N  does not improve the
                                        w      q
          quality of the interpolant in all cases. It does increase the
          computational cost and makes the method less local.

          9. Example

          This program reads in a set of 30 data points and calls E01SEF to
          construct an interpolating surface. It then calls E01SFF to
          evaluate the interpolant at a sample of points on a rectangular
          grid.

          Note that this example is not typical of a realistic problem: the
          number of data points would normally be larger, and the
          interpolant would need to be evaluated on a finer grid to obtain
          an accurate plot, say.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe01sff}{nage.ht}
{ Evaluate 2D interpolating function from E01SEF}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe01sff}{NAG Documentation: e01sff}
\beginscroll
\begin{verbatim}



     E01SFF(3NAG)      Foundation Library (12/10/92)      E01SFF(3NAG)



          E01 -- Interpolation                                       E01SFF
                  E01SFF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E01SFF evaluates at a given point the two-dimensional
          interpolating function computed by E01SEF.

          2. Specification

                 SUBROUTINE E01SFF (M, X, Y, F, RNW, FNODES, PX, PY, PF,
                1                   IFAIL)
                 INTEGER          M, IFAIL
                 DOUBLE PRECISION X(M), Y(M), F(M), RNW, FNODES(5*M), PX,
                1                 PY, PF

          3. Description

          This routine takes as input the interpolant F(x,y) of a set of
          scattered data points (x ,y ,f ), for r=1,2,...,m, as computed by
                                  r  r  r
          E01SEF, and evaluates the interpolant at the point (px,py).

          If (px,py) is equal to (x ,y ) for some value of r, the returned
                                   r  r
          value will be equal to f .
                                  r

          If (px,py) is not equal to (x ,y ) for any r, all points that are
                                       r  r
          within distance RNW of (px,py), along with the corresponding
          nodal functions given by FNODES, will be used to compute a value
          of the interpolant.

          E01SFF must only be called after a call to E01SEF.

          4. References

          [1]   Franke R and Nielson G (1980) Smooth Interpolation of Large
                Sets of Scattered Data. Internat. J. Num. Methods Engrg. 15
                1691--1704.

          [2]   Shepard D (1968) A Two-dimensional Interpolation Function
                for Irregularly Spaced Data. Proc. 23rd Nat. Conf. ACM.
                Brandon/Systems Press Inc., Princeton. 517--523.

          5. Parameters

           1:  M -- INTEGER                                           Input

           2:  X(M) -- DOUBLE PRECISION array                         Input

           3:  Y(M) -- DOUBLE PRECISION array                         Input

           4:  F(M) -- DOUBLE PRECISION array                         Input

           5:  RNW -- DOUBLE PRECISION                                Input

           6:  FNODES(5*M) -- DOUBLE PRECISION array                  Input
               On entry: M, X, Y, F, RNW and FNODES must be unchanged from
               the previous call of E01SEF.

           7:  PX -- DOUBLE PRECISION                                 Input

           8:  PY -- DOUBLE PRECISION                                 Input
               On entry: the point (px,py) at which the interpolant is to
               be evaluated.

           9:  PF -- DOUBLE PRECISION                                Output
               On exit: the value of the interpolant evaluated at the
               point (px,py).

          10:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry M < 3.

          IFAIL= 2
               The interpolant cannot be evaluated because the evaluation
               point (PX,PY) lies outside the support region of the data
               supplied in X, Y and F. This error exit will occur if
               (PX,PY) lies at a distance greater than or equal to RNW from
               every point given by arrays X and Y.

               The value 0.0 is returned in PF. This value will not provide
               continuity with values obtained at other points (PX,PY),
               i.e., values obtained when IFAIL = 0 on exit.

          7. Accuracy

          Computational errors should be negligible in most practical
          situations.

          8. Further Comments

          The time taken for a call of E01SFF is approximately proportional
          to the number of data points, m.

          The results returned by this routine are particularly suitable
          for applications such as graph plotting, producing a smooth
          surface from a number of scattered points.

          9. Example

          See the example for E01SEF.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe02}{nage.ht}{ Curve and Surface Fitting}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe02}{NAG Documentation: e02}
\beginscroll
\begin{verbatim}



     E02(3NAG)         Foundation Library (12/10/92)         E02(3NAG)



          E02 -- Curve and Surface Fitting              Introduction -- E02
                                    Chapter E02
                             Curve and Surface Fitting

          Contents of this Introduction:

          1.     Scope of the Chapter

          2.     Background to the Problems

          2.1.   Preliminary Considerations

          2.1.1. Fitting criteria: norms

          2.1.2. Weighting of data points

          2.2.   Curve Fitting

          2.2.1. Representation of polynomials

          2.2.2. Representation of cubic splines

          2.3.   Surface Fitting

          2.3.1. Bicubic splines: definition and representation

          2.4.   General Linear and Nonlinear Fitting Functions

          2.5.   Constrained Problems

          2.6.   References

          3.     Recommendations on Choice and Use of Routines

          3.1.   General

          3.1.1. Data considerations

          3.1.2. Transformation of variables

          3.2.   Polynomial Curves

          3.2.1. Least-squares polynomials: arbitrary data points

          3.2.2. Least-squares polynomials: selected data points

          3.3.   Cubic Spline Curves

          3.3.1. Least-squares cubic splines

          3.3.2. Automatic fitting with cubic splines

          3.4.   Spline Surfaces

          3.4.1. Least-squares bicubic splines

          3.4.2. Automatic fitting with bicubic splines

          3.5.   General Linear and Nonlinear Fitting Functions

          3.5.1. General linear functions

          3.5.2. Nonlinear functions

          3.6.   Constraints

          3.7.   Evaluation, Differentiation and Integration

          3.8.   Index



          1. Scope of the Chapter

          The main aim of this chapter is to assist the user in finding a
          function which approximates a set of data points. Typically the
          data contain random errors, as of experimental measurement, which
          need to be smoothed out. To seek an approximation to the data, it
          is first necessary to specify for the approximating function a
          mathematical form (a polynomial, for example) which contains a
          number of unspecified coefficients: the appropriate fitting
          routine then derives for the coefficients the values which
          provide the best fit of that particular form. The chapter deals
          mainly with curve and surface fitting (i.e., fitting with
          functions of one and of two variables) when a polynomial or a
          cubic spline is used as the fitting function, since these cover
          the most common needs. However, fitting with other functions
          and/or more variables can be undertaken by means of general
          linear or nonlinear routines (some of which are contained in
          other chapters) depending on whether the coefficients in the
          function occur linearly or nonlinearly. Cases where a graph
          rather than a set of data points is given can be treated simply
          by first reading a suitable set of points from the graph.

          The chapter also contains routines for evaluating,
          differentiating and integrating polynomial and spline curves and
          surfaces, once the numerical values of their coefficients have
          been determined.

          2. Background to the Problems

          2.1. Preliminary Considerations

          In the curve-fitting problems considered in this chapter, we have
          a dependent variable y and an independent variable x, and we are
          given a set of data points (x ,y ), for r=1,2,...,m. The
                                       r  r
          preliminary matters to be considered in this section will, for
          simplicity, be discussed in this context of curve-fitting
          problems. In fact, however, these considerations apply equally
          well to surface and higher-dimensional problems. Indeed, the
          discussion presented carries over essentially as it stands if,
          for these cases, we interpret x as a vector of several
          independent variables and correspondingly each x  as a vector
                                                          r
          containing the rth data value of each independent variable.

          We wish, then, to approximate the set of data points as closely
          as possible with a specified function, f(x) say, which is as
          smooth as possible -- f(x) may, for example, be a polynomial. The
          requirements of smoothness and closeness conflict, however, and a
          balance has to be struck between them. Most often, the smoothness
          requirement is met simply by limiting the number of coefficients
          allowed in the fitting function -- for example, by restricting
          the degree in the case of a polynomial. Given a particular number
          of coefficients in the function in question, the fitting routines
          of this chapter determine the values of the coefficients such
          that the 'distance' of the function from the data points is as
          small as possible. The necessary balance is struck by the user
          comparing a selection of such fits having different numbers of
          coefficients. If the number of coefficients is too low, the
          approximation to the data will be poor. If the number is too
          high, the fit will be too close to the data, essentially
          following the random errors and tending to have unwanted
          fluctuations between the data points. Between these extremes,
          there is often a group of fits all similarly close to the data
          points and then, particularly when least-squares polynomials are
          used, the choice is clear: it is the fit from this group having
          the smallest number of coefficients.

          The above process can be seen as the user minimizing the
          smoothness measure (i.e., the number of coefficients) subject to
          the distance from the data points being acceptably small. Some of
          the routines, however, do this task themselves. They use a
          different measure of smoothness (in each case one that is
          continuous) and minimize it subject to the distance being less
          than a threshold specified by the user. This is a much more
          automatic process, requiring only some experimentation with the
          threshold.

          2.1.1.  Fitting criteria: norms

          A measure of the above 'distance' between the set of data points
          and the function f(x) is needed. The distance from a single data
          point (x ,y ) to the function can simply be taken as
                  r  r

                              (epsilon) =y -f(x ),                      (1)
                                       r  r    r

          and is called the residual of the point. (With this definition,
          the residual is regarded as a function of the coefficients
          contained in f(x); however, the term is also used to mean the
          particular value of (epsilon)  which corresponds to the fitted
                                       r
          values of the coefficients.) However, we need a measure of
          distance for the set of data points as a whole. Three different
          measures are used in the different routines (which measure to
          select, according to circumstances, is discussed later in this
          sub-section). With (epsilon)  defined in (1), these measures, or
                                      r
          norms, are

                                m
                                --
                                >  |(epsilon) |,                        (2)
                                --           r
                                r=1

                                 

                                / m
                               /  --          2
                              /   >  (epsilon) ,  and                   (3)
                             /    --          r
                           \/     r=1

                               max |(epsilon) |,                        (4)
                                  r          r

          respectively the l  norm, the l  norm and the l      norm.
                            1            2               infty

          Minimization of one or other of these norms usually provides the
          fitting criterion, the minimization being carried out with
          respect to the coefficients in the mathematical form used for
          f(x): with respect to the b  for example if the mathematical form
                                     i
          is the power series in (8) below. The fit which results from
          minimizing (2) is known as the l  fit, or the fit in the l  norm:
                                          1                         1
          that which results from minimizing (3) is the l  fit, the well-
                                                         2
          known least-squares fit (minimizing (3) is equivalent to
          minimizing the square of (3), i.e., the sum of squares of
          residuals, and it is the latter which is used in practice), and
          that from minimizing (4) is the l     , or minimax, fit.
                                           infty

          Strictly speaking, implicit in the use of the above norms are the
          statistical assumptions that the random errors in the y  are
                                                                 r
          independent of one another and that any errors in the x  are
                                                                 r
          negligible by comparison. From this point of view, the use of the
          l  norm is appropriate when the random errors in the y  have a
           2                                                    r
          normal distribution, and the l      norm is appropriate when they
                                        infty
          have a rectangular distribution, as when fitting a table of
          values rounded to a fixed number of decimal places. The l  norm
                                                                   1
          is appropriate when the error distribution has its frequency
          function proportional to the negative exponential of the modulus
          of the normalised error -- not a common situation.

          However, the user is often indifferent to these statistical
          considerations, and simply seeks a fit which he can assess by
          inspection, perhaps visually from a graph of the results. In this
          event, the l  norm is particularly appropriate when the data are
                      1
          thought to contain some 'wild' points (since fitting in this norm
          tends to be unaffected by the presence of a small number of such
          points), though of course in simple situations the user may
          prefer to identify and reject these points. The l      norm
                                                           infty
          should be used only when the maximum residual is of particular
          concern, as may be the case for example when the data values have
          been obtained by accurate computation, as of a mathematical
          function. Generally, however, a routine based on least-squares
          should be preferred, as being computationally faster and usually
          providing more information on which to assess the results. In
          many problems the three fits will not differ significantly for
          practical purposes.

          Some of the routines based on the l  norm do not minimize the
                                             2
          norm itself but instead minimize some (intuitively acceptable)
          measure of smoothness subject to the norm being less than a user-
          specified threshold. These routines fit with cubic or bicubic
          splines (see (10) and (14) below) and the smoothing measures
          relate to the size of the discontinuities in their third
          derivatives. A much more automatic fitting procedure follows from
          this approach.

          2.1.2.  Weighting of data points

          The use of the above norms also assumes that the data values y
                                                                        r
          are of equal (absolute) accuracy. Some of the routines enable an
          allowance to be made to take account of differing accuracies. The
          allowance takes the form of 'weights' applied to the y-values so
          that those values known to be more accurate have a greater
          influence on the fit than others. These weights, to be supplied
          by the user, should be calculated from estimates of the absolute
          accuracies of the y-values, these estimates being expressed as
          standard deviations, probable errors or some other measure which
          has the same dimensions as y. Specifically, for each y  the
                                                                r
          corresponding weight w  should be inversely proportional to the
                                r
          accuracy estimate of y . For example, if the percentage accuracy
                                r
          is the same for all y , then the absolute accuracy of y  is
                               r                                 r
          proportional to y  (assuming y  to be positive, as it usually is
                           r            r
          in such cases) and so w =K/y , for r=1,2,...,m, for an arbitrary
                                 r    r
          positive constant K. (This definition of weight is stressed
          because often weight is defined as the square of that used here.)
          The norms (2), (3) and (4) above are then replaced respectively
          by

                               m
                               --
                               >  |w (epsilon) |,                       (5)
                               --   r         r
                               r=1

                                

                               / m
                              /  --  2         2
                             /   >  w (epsilon) ,  and                  (6)
                            /    --  r         r
                          \/     r=1

                              max |w (epsilon) |.                       (7)
                                 r  r         r

          Again it is the square of (6) which is used in practice rather
          than (6) itself.

          2.2. Curve Fitting

          When, as is commonly the case, the mathematical form of the
          fitting function is immaterial to the problem, polynomials and
          cubic splines are to be preferred because their simplicity and
          ease of handling confer substantial benefits. The cubic spline is
          the more versatile of the two. It consists of a number of cubic
          polynomial segments joined end to end with continuity in first
          and second derivatives at the joins. The third derivative at the
          joins is in general discontinuous. The x-values of the joins are
          called knots, or, more precisely, interior knots. Their number
          determines the number of coefficients in the spline, just as the
          degree determines the number of coefficients in a polynomial.

          2.2.1.  Representation of polynomials

          Rather than using the power-series form

                                           2        k
                           f(x)==b +b x+b x +...+b x                    (8)
                                  0  1   2        k

          to represent a polynomial, the routines in this chapter use the
          Chebyshev series form

                         1
                  f(x)== -a T (x)+a T (x)+a T (x)+...+a T (x),          (9)
                         2 0 0     1 1     2 2         k k

          where T (x) is the Chebyshev polynomial of the first kind of
                 i
          degree i (see Cox and Hayes [1], page 9), and where the range of
          x has been normalised to run from -1 to +1. The use of either
          form leads theoretically to the same fitted polynomial, but in
          practice results may differ substantially because of the effects
          of rounding error. The Chebyshev form is to be preferred, since
          it leads to much better accuracy in general, both in the
          computation of the coefficients and in the subsequent evaluation
          of the fitted polynomial at specified points. This form also has
          other advantages: for example, since the later terms in (9)
          generally decrease much more rapidly from left to right than do
          those in (8), the situation is more often encountered where the
          last terms are negligible and it is obvious that the degree of
          the polynomial can be reduced (note that on the interval -1<=x<=1
          for all i, T (x) attains the value unity but never exceeds it, so
                      i
          that the coefficient a  gives directly the maximum value of the
                                i
          term containing it).

          2.2.2.  Representation of cubic splines

          A cubic spline is represented in the form

                      f(x)==c N (x)+c N (x)+...+c N (x),               (10)
                             1 1     2 2         p p

          where N (x), for i=1,2,...,p, is a normalised cubic B-spline (see
                 i
          Hayes [2]). This form, also, has advantages of computational
          speed and accuracy over alternative representations.

          2.3. Surface Fitting

          There are now two independent variables, and we shall denote
          these by x and y. The dependent variable, which was denoted by y
          in the curve-fitting case, will now be denoted by f. (This is a
          rather different notation from that indicated for the general-
          dimensional problem in the first paragraph of Section 2.1 , but
          it has some advantages in presentation.)

          Again, in the absence of contrary indications in the particular
          application being considered, polynomials and splines are the
          approximating functions most commonly used. Only splines are used
          by the surface-fitting routines in this chapter.

          2.3.1.  Bicubic splines: definition and representation

          The bicubic spline is defined over a rectangle R in the (x,y)
          plane, the sides of R being parallel to the x- and y-axes. R is
          divided into rectangular panels, again by lines parallel to the
          axes. Over each panel the bicubic spline is a bicubic polynomial,
          that is it takes the form

                                3   3
                                --  --     i j
                                >   >  a  x y .                        (13)
                                --  --  ij
                                i=0 j=0

          Each of these polynomials joins the polynomials in adjacent
          panels with continuity up to the second derivative. The constant
          x-values of the dividing lines parallel to the y-axis form the
          set of interior knots for the variable x, corresponding precisely
          to the set of interior knots of a cubic spline. Similarly, the
          constant y-values of dividing lines parallel to the x-axis form
          the set of interior knots for the variable y. Instead of
          representing the bicubic spline in terms of the above set of
          bicubic polynomials, however, it is represented, for the sake of
          computational speed and accuracy, in the form

                                 p   q
                                 --  --
                         f(x,y)= >   >  c  M (x)N (y),                 (14)
                                 --  --  ij i    j
                                 i=1 j=1

          where M (x), for i=1,2,...,p, and N (y), for j=1,2,...,q, are
                 i                           j
          normalised B-splines (see Hayes and Halliday [4] for further
          details of bicubic splines and Hayes [2] for normalised B-
          splines).

          2.4. General Linear and Nonlinear Fitting Functions

          We have indicated earlier that, unless the data-fitting
          application under consideration specifically requires some other
          type of fitting function, a polynomial or a spline is usually to
          be preferred. Special routines for these functions, in one and in
          two variables, are provided in this chapter. When the application
          does specify some other fitting function, however, it may be
          treated by a routine which deals with a general linear function,
          or by one for a general nonlinear function, depending on whether
          the coefficients in the given function occur linearly or
          nonlinearly.

          The general linear fitting function can be written in the form

                f(x)==c (phi) (x)+c (phi) (x)+...+c (phi) (x),         (15)
                       1     1     2     2         p     p

          where x is a vector of one or more independent variables, and the
          (phi)  are any given functions of these variables (though they
               i
          must be linearly independent of one another if there is to be the
          possibility of a unique solution to the fitting problem). This is
          not intended to imply that each (phi)  is necessarily a function
                                               i
          of all the variables: we may have, for example, that each (phi)
                                                                         i
          is a function of a different single variable, and even that one
          of the (phi)  is a constant. All that is required is that a value
                      i
          of each (phi) (x) can be computed when a value of each
                       i
          independent variable is given.

          When the fitting function f(x) is not linear in its coefficients,
          no more specific representation is available in general than f(x)
          itself. However, we shall find it helpful later on to indicate
          the fact that f(x) contains a number of coefficients (to be
          determined by the fitting process) by using instead the notation
          f(x;c), where c denotes the vector of coefficients. An example of
          a nonlinear fitting function is


                      f(x;c)==c +c exp(-c x)+c exp(-c x),              (16)
                               1  2      4    3      5

          which is in one variable and contains five coefficients. Note
          that here, as elsewhere in this Chapter Introduction, we use the
          term 'coefficients' to include all the quantities whose values
          are to be determined by the fitting process, not just those which
          occur linearly. We may observe that it is only the presence of
          the coefficients c  and c  which makes the form (16) nonlinear.
                            4      5
          If the values of these two coefficients were known beforehand,
          (16) would instead be a linear function which, in terms of the
          general linear form (15), has p=3 and

           (phi) (x)==1,  (phi) (x)==exp(-c x), and (phi) (x)==exp(-c x).
                1              2           4             3           5

          We may note also that polynomials and splines, such as (9) and
          (14), are themselves linear in their coefficients. Thus if, when
          fitting with these functions, a suitable special routine is not
          available (as when more than two independent variables are
          involved or when fitting in the l  norm), it is appropriate to
                                           1
          use a routine designed for a general linear function.

          2.5. Constrained Problems

          So far, we have considered only fitting processes in which the
          values of the coefficients in the fitting function are determined
          by an unconstrained minimization of a particular norm. Some
          fitting problems, however, require that further restrictions be
          placed on the determination of the coefficient values. Sometimes
          these restrictions are contained explicitly in the formulation of
          the problem in the form of equalities or inequalities which the
          coefficients, or some function of them, must satisfy. For
          example, if the fitting function contains a term Aexp(-kx), it
          may be required that k>=0. Often, however, the equality or
          inequality constraints relate to the value of the fitting
          function or its derivatives at specified values of the
          independent variable(s), but these too can be expressed in terms
          of the coefficients of the fitting function, and it is
          appropriate to do this if a general linear or nonlinear routine
          is being used. For example, if the fitting function is that given
          in (10), the requirement that the first derivative of the
          function at x=x  be non-negative can be expressed as
                         0

                     c N '(x )+c N '(x )+...+c N '(x )>=0,             (17)
                      1 1   0   2 2   0       p p   0

          where the prime denotes differentiation with respect to x and
          each derivative is evaluated at x=x . On the other hand, if the
                                             0
          requirement had been that the derivative at x=x  be exactly zero,
                                                         0
          the inequality sign in (17) would be replaced by an equality.

          Routines which provide a facility for minimizing the appropriate
          norm subject to such constraints are discussed in Section 3.6.

          2.6. References

          [1]   Cox M G and Hayes J G (1973) Curve fitting: a guide and
                suite of algorithms for the non-specialist user. Report
                NAC26. National Physical Laboratory.

          [2]   Hayes J G (1974 ) Numerical Methods for Curve and Surface
                Fitting. Bull Inst Math Appl. 10 144--152.

                (For definition of normalised B-splines and details of
                numerical methods.)

          [3]   Hayes J G (1970) Curve Fitting by Polynomials in One
                Variable. Numerical Approximation to Functions and Data. (ed
                J G Hayes) Athlone Press, London.

          [4]   Hayes J G and Halliday J (1974) The Least-squares Fitting of
                Cubic Spline Surfaces to General Data Sets. J. Inst. Math.
                Appl. 14 89--103.

          3. Recommendations on Choice and Use of Routines

          3.1. General

          The choice of a routine to treat a particular fitting problem
          will depend first of all on the fitting function and the norm to
          be used. Unless there is good reason to the contrary, the fitting
          function should be a polynomial or a cubic spline (in the
          appropriate number of variables) and the norm should be the l
                                                                       2
          norm (leading to the least-squares fit). If some other function
          is to be used, the choice of routine will depend on whether the
          function is nonlinear (in which case see Section 3.5.2) or linear
          in its coefficients (see Section 3.5.1), and, in the latter case,
          on whether the l  or l  norm is to be used. The latter section is
                          1     2
          appropriate for polynomials and splines, too, if the l  norm is
                                                                1
          preferred.

          In the case of a polynomial or cubic spline, if there is only one
          independent variable, the user should choose a spline (Section
          3.3) when the curve represented by the data is of complicated
          form, perhaps with several peaks and troughs. When the curve is
          of simple form, first try a polynomial (see Section 3.2) of low
          degree, say up to degree 5 or 6, and then a spline if the
          polynomial fails to provide a satisfactory fit. (Of course, if
          third-derivative discontinuities are unacceptable to the user, a
          polynomial is the only choice.) If the problem is one of surface
          fitting, one of the spline routines should be used (Section 3.4).
          If the problem has more than two independent variables, it may be
          treated by the general linear routine in Section 3.5.1, again
          using a polynomial in the first instance.

          Another factor which affects the choice of routine is the
          presence of constraints, as previously discussed in Section 2.5.
          Indeed this factor is likely to be overriding at present, because
          of the limited number of routines which have the necessary
          facility. See Section 3.6.

          3.1.1.  Data considerations

          A satisfactory fit cannot be expected by any means if the number
          and arrangement of the data points do not adequately represent
          the character of the underlying relationship: sharp changes in
          behaviour, in particular, such as sharp peaks, should be well
          covered. Data points should extend over the whole range of
          interest of the independent variable(s): extrapolation outside
          the data ranges is most unwise. Then, with polynomials, it is
          advantageous to have additional points near the ends of the
          ranges, to counteract the tendency of polynomials to develop
          fluctuations in these regions. When, with polynomial curves, the
          user can precisely choose the x-values of the data, the special
          points defined in Section 3.2.2 should be selected. With splines
          the choice is less critical as long as the character of the
          relationship is adequately represented. All fits should be tested
          graphically before accepting them as satisfactory.

          For this purpose it should be noted that it is not sufficient to
          plot the values of the fitted function only at the data values of
          the independent variable(s); at the least, its values at a
          similar number of intermediate points should also be plotted, as
          unwanted fluctuations may otherwise go undetected. Such
          fluctuations are the less likely to occur the lower the number of
          coefficients chosen in the fitting function. No firm guide can be
          given, but as a rough rule, at least initially, the number of
          coefficients should not exceed half the number of data points
          (points with equal or nearly equal values of the independent
          variable, or both independent variables in surface fitting,
          counting as a single point for this purpose). However, the
          situation may be such, particularly with a small number of data
          points, that a satisfactorily close fit to the data cannot be
          achieved without unwanted fluctuations occurring. In such cases,
          it is often possible to improve the situation by a transformation
          of one or more of the variables, as discussed in the next
          paragraph: otherwise it will be necessary to provide extra data
          points. Further advice on curve fitting is given in Cox and Hayes
          [1] and, for polynomials only, in Hayes [3] of Section 2.7. Much
          of the advice applies also to surface fitting; see also the
          Routine Documents.

          3.1.2.  Transformation of variables

          Before starting the fitting, consideration should be given to the
          choice of a good form in which to deal with each of the
          variables: often it will be satisfactory to use the variables as
          they stand, but sometimes the use of the logarithm, square root,
          or some other function of a variable will lead to a better-
          behaved relationship. This question is customarily taken into
          account in preparing graphs and tables of a relationship and the
          same considerations apply when curve or surface fitting. The
          practical context will often give a guide. In general, it is best
          to avoid having to deal with a relationship whose behaviour in
          one region is radically different from that in another. A steep
          rise at the left-hand end of a curve, for example, can often best
          be treated by curve fitting in terms of log(x+c) with some
          suitable value of the constant c. A case when such a
          transformation gave substantial benefit is discussed in Hayes [3]
          page 60. According to the features exhibited in any particular
          case, transformation of either dependent variable or independent
          variable(s) or both may be beneficial. When there is a choice it
          is usually better to transform the independent variable(s): if
          the dependent variable is transformed, the weights attached to
          the data points must be adjusted. Thus (denoting the dependent
          variable by y, as in the notation for curves) if the y  to be
                                                                r
          fitted have been obtained by a transformation y=g(Y) from
          original data values Y , with weights W , for r=1,2,...,m, we
                                r                r
          must take

                                w =W /(dy/dY),                         (18)
                                 r  r

          where the derivative is evaluated at Y . Strictly, the
                                                r
          transformation of Y and the adjustment of weights are valid only
          when the data errors in the Y  are small compared with the range
                                       r
          spanned by the Y , but this is usually the case.
                          r

          3.2. Polynomial Curves

          3.2.1.  Least-squares polynomials: arbitrary data points

          E02ADF fits to arbitrary data points, with arbitrary weights,
          polynomials of all degrees up to a maximum degree k, which is at
          choice. If the user is seeking only a low degree polynomial, up
          to degree 5 or 6 say, k=10 is an appropriate value, providing
          there are about 20 data points or more. To assist in deciding the
          degree of polynomial which satisfactorily fits the data, the
          routine provides the root-mean-square-residual s  for all degrees
                                                          i
          i=1,2,...,k. In a satisfactory case, these s  will decrease
                                                      i
          steadily as i increases and then settle down to a fairly constant
          value, as shown in the example

                  i    s
                        i

                  0    3.5215

                  1    0.7708

                  2    0.1861

                  3    0.0820

                  4    0.0554

                  5    0.0251

                  6    0.0264

                  7    0.0280

                  8    0.0277

                  9    0.0297

                  10   0.0271

          If the s  values settle down in this way, it indicates that the
                  i
          closest polynomial approximation justified by the data has been
          achieved. The degree which first gives the approximately constant
          value of s  (degree 5 in the example) is the appropriate degree
                    i
          to select. (Users who are prepared to accept a fit higher than
          sixth degree, should simply find a high enough value of k to
          enable the type of behaviour indicated by the example to be
          detected: thus they should seek values of k for which at least 4
          or 5 consecutive values of s  are approximately the same.) If the
                                      i
          degree were allowed to go high enough, s  would, in most cases,
                                                  i
          eventually start to decrease again, indicating that the data
          points are being fitted too closely and that undesirable
          fluctuations are developing between the points. In some cases,
          particularly with a small number of data points, this final
          decrease is not distinguishable from the initial decrease in s .
                                                                        i
          In such cases, users may seek an acceptable fit by examining the
          graphs of several of the polynomials obtained. Failing this, they
          may (a) seek a transformation of variables which improves the
          behaviour, (b) try fitting a spline, or (c) provide more data
          points. If data can be provided simply by drawing an
          approximating curve by hand and reading points from it, use the
          points discussed in Section 3.2.2.

          3.2.2.  Least-squares polynomials: selected data points

          When users are at liberty to choose the x-values of data points,
          such as when the points are taken from a graph, it is most
          advantageous when fitting with polynomials to use the values
          x =cos((pi)r/n), for r=0,1,...,n for some value of n, a suitable
           r
          value for which is discussed at the end of this section. Note
          that these x  relate to the variable x after it has been
                      r
          normalised so that its range of interest is -1 to +1. E02ADF may
          then be used as in Section 3.2.1 to seek a satisfactory fit.

          3.3. Cubic Spline Curves

          3.3.1.  Least-squares cubic splines

          E02BAF fits to arbitrary data points, with arbitrary weights, a
          cubic spline with interior knots specified by the user. The
          choice of these knots so as to give an acceptable fit must
          largely be a matter of trial and error, though with a little
          experience a satisfactory choice can often be made after one or
          two trials. It is usually best to start with a small number of
          knots (too many will result in unwanted fluctuations in the fit,
          or even in there being no unique solution) and, examining the fit
          graphically at each stage, to add a few knots at a time at places
          where the fit is particularly poor. Moving the existing knots
          towards these places will also often improve the fit. In regions
          where the behaviour of the curve underlying the data is changing
          rapidly, closer knots will be needed than elsewhere. Otherwise,
          positioning is not usually very critical and equally-spaced knots
          are often satisfactory. See also the next section, however.

          A useful feature of the routine is that it can be used in
          applications which require the continuity to be less than the
          normal continuity of the cubic spline. For example, the fit may
          be required to have a discontinuous slope at some point in the
          range. This can be achieved by placing three coincident knots at
          the given point. Similarly a discontinuity in the second
          derivative at a point can be achieved by placing two knots there.
          Analogy with these discontinuous cases can provide guidance in
          more usual cases: for example, just as three coincident knots can
          produce a discontinuity in slope, so three close knots can
          produce a rapid change in slope. The closer the knots are, the
          more rapid can the change be.

                                     Figure 1
                   Please see figure in printed Reference Manual

          An example set of data is given in Figure 1. It is a rather
          tricky set, because of the scarcity of data on the right, but it
          will serve to illustrate some of the above points and to show
          some of the dangers to be avoided. Three interior knots
          (indicated by the vertical lines at the top of the diagram) are
          chosen as a start. We see that the resulting curve is not steep
          enough in the middle and fluctuates at both ends, severely on the
          right. The spline is unable to cope with the shape and more knots
          are needed.

          In Figure 2, three knots have been added in the centre, where the
          data shows a rapid change in behaviour, and one further out at
          each end, where the fit is poor. The fit is still poor, so a
          further knot is added in this region and, in Figure 3, disaster
          ensues in rather spectacular fashion.

                                     Figure 2
                   Please see figure in printed Reference Manual

                                     Figure 3
                   Please see figure in printed Reference Manual

          The reason is that, at the right-hand end, the fits in Figure 1
          and Figure 2 have been interpreted as poor simply because of the
          fluctuations about the curve underlying the data (or what it is
          naturally assumed to be). But the fitting process knows only
          about the data and nothing else about the underlying curve, so it
          is important to consider only closeness to the data when deciding
          goodness of fit.

          Thus, in Figure 1, the curve fits the last two data points quite
          well compared with the fit elsewhere, so no knot should have been
          added in this region. In Figure 2, the curve goes exactly through
          the last two points, so a further knot is certainly not needed
          here.


                                     Figure 4
                   Please see figure in printed Reference Manual

          Figure 4 shows what can be achieved without the extra knot on
          each of the flat regions. Remembering that within each knot
          interval the spline is a cubic polynomial, there is really no
          need to have more than one knot interval covering each flat
          region.

          What we have, in fact, in Figure 2 and Figure 3 is a case of too
          many knots (so too many coefficients in the spline equation) for
          the number of data points. The warning in the second paragraph of
          Section 2.1 was that the fit will then be too close to the data,
          tending to have unwanted fluctuations between the data points.
          The warning applies locally for splines, in the sense that, in
          localities where there are plenty of data points, there can be a
          lot of knots, as long as there are few knots where there are few
          points, especially near the ends of the interval. In the present
          example, with so few data points on the right, just the one extra
          knot in Figure 2 is too many! The signs are clearly present, with
          the last two points fitted exactly (at least to the graphical
          accuracy and actually much closer than that) and fluctuations
          within the last two knot-intervals (cf. Figure 1, where only the
          final point is fitted exactly and one of the wobbles spans
          several data points).

          The situation in Figure 3 is different. The fit, if computed
          exactly, would still pass through the last two data points, with
          even more violent fluctuations. However, the problem has become
          so ill-conditioned that all accuracy has been lost. Indeed, if
          the last interior knot were moved a tiny amount to the right,
          there would be no unique solution and an error message would have
          been caused. Near-singularity is, sadly, not picked up by the
          routine, but can be spotted readily in a graph, as Figure 3. B-
          spline coefficients becoming large, with alternating signs, is
          another indication. However, it is better to avoid such
          situations, firstly by providing, whenever possible, data
          adequately covering the range of interest, and secondly by
          placing knots only where there is a reasonable amount of data.

          The example here could, in fact, have utilised from the start the
          observation made in the second paragraph of this section, that
          three close knots can produce a rapid change in slope. The
          example has two such rapid changes and so requires two sets of
          three close knots (in fact, the two sets can be so close that one
          knot can serve in both sets, so only five knots prove sufficient
          in Figure 4). It should be noted, however, that the rapid turn
          occurs within the range spanned by the three knots. This is the
          reason that the six knots in Figure 2 are not satisfactory as
          they do not quite span the two turns.

          Some more examples to illustrate the choice of knots are given in
          Cox and Hayes [1].

          3.3.2.  Automatic fitting with cubic splines

          E02BEF also fits cubic splines to arbitrary data points with
          arbitrary weights but itself chooses the number and positions of
          the knots. The user has to supply only a threshold for the sum of
          squares of residuals. The routine first builds up a knot set by a
          series of trial fits in the l  norm. Then, with the knot set
                                       2
          decided, the final spline is computed to minimize a certain
          smoothing measure subject to satisfaction of the chosen
          threshold. Thus it is easier to use than E02BAF (see previous
          section), requiring only some experimentation with this
          threshold. It should therefore be first choice unless the user
          has a preference for the ordinary least-squares fit or, for
          example, wishes to experiment with knot positions, trying to keep
          their number down (E02BEF aims only to be reasonably frugal with
          knots).

          3.4. Spline Surfaces

          3.4.1.  Least-squares bicubic splines

          E02DAF fits to arbitrary data points, with arbitrary weights, a
          bicubic spline with its two sets of interior knots specified by
          the user. For choosing these knots, the advice given for cubic
          splines, in Section 3.3.1 above, applies here too. (See also the
          next section, however.) If changes in the behaviour of the
          surface underlying the data are more marked in the direction of
          one variable than of the other, more knots will be needed for the
          former variable than the latter. Note also that, in the surface
          case, the reduction in continuity caused by coincident knots will
          extend across the whole spline surface: for example, if three
          knots associated with the variable x are chosen to coincide at a
          value L, the spline surface will have a discontinuous slope
          across the whole extent of the line x=L.

          With some sets of data and some choices of knots, the least-
          squares bicubic spline will not be unique. This will not occur,
          with a reasonable choice of knots, if the rectangle R is well
          covered with data points: here R is defined as the smallest
          rectangle in the (x,y) plane, with sides parallel to the axes,
          which contains all the data points. Where the least-squares
          solution is not unique, the minimal least-squares solution is
          computed, namely that least-squares solution which has the
          smallest value of the sum of squares of the B-spline coefficients
          c   (see the end of Section 2.3.2 above). This choice of least-
           ij
          squares solution tends to minimize the risk of unwanted
          fluctuations in the fit. The fit will not be reliable, however,
          in regions where there are few or no data points.

          3.4.2.  Automatic fitting with bicubic splines

          E02DDF also fits bicubic splines to arbitrary data points with
          arbitrary weights but chooses the knot sets itself. The user has
          to supply only a threshold for the sum of squares of residuals.
          Just like the automatic curve E02BEF (Section 3.3.2), E02DDF then
          builds up the knot sets and finally fits a spline minimizing a
          smoothing measure subject to satisfaction of the threshold.
          Again, this easier to use routine is normally to be preferred, at
          least in the first instance.

          E02DCF is a very similar routine to E02DDF but deals with data
          points of equal weight which lie on a rectangular mesh in the
          (x,y) plane. This kind of data allows a very much faster
          computation and so is to be preferred when applicable.
          Substantial departures from equal weighting can be ignored if the
          user is not concerned with statistical questions, though the
          quality of the fit will suffer if this is taken too far. In such
          cases, the user should revert to E02DDF.

          3.5. General Linear and Nonlinear Fitting Functions

          3.5.1.  General linear functions

          For the general linear function (15), routines are available for
          fitting in the l  and l  norms. The least-squares routines (which
                          1      2
          are to be preferred unless there is good reason to use another
          norm -- see Section 2.1.1) are in Chapter F04. The l  routine is
                                                              1
          E02GAF.

          All the above routines are essentially linear algebra routines,
          and in considering their use we need to view the fitting process
          in a slightly different way from hitherto. Taking y to be the
          dependent variable and x the vector of independent variables, we
          have, as for equation (1) but with each x  now a vector,
                                                   r

                          (epsilon) =y -f(x )  r=1,2,...,m.
                                   r  r    r

          Substituting for f(x) the general linear form (15), we can write
          this as

          c (phi) (x )+c (phi) (x )+...+c (phi) (x )=y -(epsilon) ,
           1     1  r   2     2  r       p     p  r   r          r
           r=1,2,...,m                                                 (19)


          Thus we have a system of linear equations in the coefficients c .
                                                                         j
          Usually, in writing these equations, the (epsilon)  are omitted
                                                            r
          and simply taken as implied. The system of equations is then
          described as an overdetermined system (since we must have m>=p if
          there is to be the possibility of a unique solution to our
          fitting problem), and the fitting process of computing the c  to
                                                                      j
          minimize one or other of the norms (2), (3) and (4) can be
          described, in relation to the system of equations, as solving the
          overdetermined system in that particular norm. In matrix
          notation, the system can be written as

                                   (Phi)c=y,                           (20)

          where (Phi) is the m by p matrix whose element in row r and
          column j is (phi) (x ), for r=1,2,...,m; j=1,2,...,p. The vectors
                           j  r
          c and y respectively contain the coefficients c  and the data
                                                         j
          values y .
                  r

          The routines, however, use the standard notation of linear
          algebra, the overdetermined system of equations being denoted by

                                     Ax=b                              (21)

          The correspondence between this notation and that which we have
          used for the data-fitting problem (equation (20)) is therefore
          given by

                            A==(Phi),   x==c   b==y                    (22)

          Note that the norms used by these routines are the unweighted
          norms (2) and (3). If the user wishes to apply weights to the
          data points, that is to use the norms (5) or (6), the
          equivalences (22) should be replaced by

                              A==D(Phi),   x==c   b==Dy

          where D is a diagonal matrix with w  as the rth diagonal element.
                                             r
          Here w , for r=1,2,...,m, is the weight of the rth data point as
                r
          defined in Section 2.1.2.

          3.5.2.  Nonlinear functions

          Routines for fitting with a nonlinear function in the l  norm are
                                                                 2
          provided in Chapter E04, and that chapter's Introduction should
          be consulted for the appropriate choice of routine. Again,
          however, the notation adopted is different from that we have used
          for data fitting. In the latter, we denote the fitting function
          by f(x;c), where x is the vector of independent variables and c
          is the vector of coefficients, whose values are to be determined.
          The squared l  norm, to be minimized with respect to the elements
                       2
          of c, is then

                               m
                               --  2            2
                               >  w [y -f(x ;c)]                       (23)
                               --  r  r    r
                               r=1

          where y  is the rth data value of the dependent variable, x  is
                 r                                                   r
          the vector containing the rth values of the independent
          variables, and w  is the corresponding weight as defined in
                          r
          Section 2.1.2.

          On the other hand, in the nonlinear least-squares routines of
          Chapter E04, the function to be minimized is denoted by

                                   m
                                   --  2
                                   >  f (x),                           (24)
                                   --  i
                                   i=1

          the minimization being carried out with respect to the elements
          of the vector x. The correspondence between the two notations is
          given by

          x==c and

          f (x)==w [y -f(x ;c)],  i=r=1,2,...,m.
           i      r  r    r

          Note especially that the vector x of variables of the nonlinear
          least-squares routines is the vector c of coefficients of the
          data-fitting problem, and in particular that, if the selected
          routine requires derivatives of the f (x) to be provided, these
                                               i
          are derivatives of w [y -f(x ;c)] with respect to the
                              r  r    r
          coefficients of the data-fitting problem.

          3.6. Constraints

          At present, there are only a limited number of routines which fit
          subject to constraints. Chapter E04 contains a routine, E04UCF,
          which can be used for fitting with a nonlinear function in the l
                                                                          2
          norm subject to equality or inequality constraints. This routine,
          unlike those in that chapter suited to the unconstrained case, is
          not designed specifically for minimizing functions which are sums
          of squares, and so the function (23) has to be treated as a
          general nonlinear function. The E04 Chapter Introduction should
          be consulted.

          The remaining constraint routine relates to fitting with
          polynomials in the l  norm. E02AGF deals with polynomial curves
                              2
          and allows precise values of the fitting function and (if
          required) all its derivatives up to a given order to be
          prescribed at one or more values of the independent variable.

          3.7. Evaluation, Differentiation and Integration

          Routines are available to evaluate, differentiate and integrate
          polynomials in Chebyshev-series form and cubic or bicubic splines
          in B-spline form. These polynomials and splines may have been
          produced by the various fitting routines or, in the case of
          polynomials, from prior calls of the differentiation and
          integration routines themselves.

          E02AEF and E02AKF evaluate polynomial curves: the latter has a
          longer parameter list but does not require the user to normalise
          the values of the independent variable and can accept
          coefficients which are not stored in contiguous locations. E02BBF
          evaluates cubic spline curves, and E02DEF and E02DFF bicubic
          spline surfaces.

          Differentiation and integration of polynomial curves are carried
          out by E02AHF and E02AJF respectively. The results are provided
          in Chebyshev-series form and so repeated differentiation and
          integration are catered for. Values of the derivative or integral
          can then be computed using the appropriate evaluation routine.

          For splines the differentiation and integration routines provided
          are of a different nature from those for polynomials. E02BCF
          provides values of a cubic spline curve and its first three
          derivatives (the rest, of course, are zero) at a given value of x
          spline over its whole range. These routines can also be applied
          to surfaces of the form (14). For example, if, for each value of
          j in turn, the coefficients c  , for i=1,2,...,p are supplied to
                                       ij
          E02BCF with x=x  and on each occasion we select from the output
                         0
          the value of the second derivative, d  say, and if the whole set
                                               j
          of d  are then supplied to the same routine with x=y , the output
              j                                               0
          will contain all the values at (x ,y ) of
                                           0  0

                             2             r+2
                           dd f          dd   f
                           -----  and   --------,  r=1,2,3.
                             2             2   r
                           dd fx        ddx ddy

          Equally, if after each of the first p calls of E02BCF we had
          selected the function value (E02BBF would also provide this)
          instead of the second derivative and we had supplied these values
          to E02BDF, the result obtained would have been the value of

                                     B
                                     /
                                     |f(x ,y)dy,
                                     /   0
                                     A

          where A and B are the end-points of the y interval over which the
          spline was defined.

          3.8. Index

          Automatic fitting,
               with bicubic splines                                  E02DCF
                                                                     E02DDF
               with cubic splines                                    E02BEF
          Data on rectangular mesh                                   E02DCF
          Differentiation,
               of cubic splines                                      E02BCF
               of polynomials                                        E02AHF
          Evaluation,
               of bicubic splines                                    E02DEF
                                                                     E02DFF
               of cubic splines                                      E02BBF
               of cubic splines and derivatives                      E02BCF
               of definite integral of cubic splines                 E02BDF
               of polynomials                                        E02AEF
                                                                     E02AKF
          Integration,
               of cubic splines (definite integral)                  E02BDF
               of polynomials                                        E02AJF
          Least-squares curve fit,
               with cubic splines                                    E02BAF
               with polynomials,
                    arbitrary data points                            E02ADF
                    with constraints                                 E02AGF
          Least-squares surface fit with bicubic splines             E02DAF
          l  fit with general linear function,                       E02GAF
           1
          Sorting,
               2-D data into panels                                  E02ZAF


          E02 -- Curve and Surface Fitting                  Contents -- E02
          Chapter E02

          Curve and Surface Fitting

          E02ADF  Least-squares curve fit, by polynomials, arbitrary data
                  points

          E02AEF  Evaluation of fitted polynomial in one variable from
                  Chebyshev series form (simplified parameter list)

          E02AGF  Least-squares polynomial fit, values and derivatives may
                  be constrained, arbitrary data points,

          E02AHF  Derivative of fitted polynomial in Chebyshev series form

          E02AJF  Integral of fitted polynomial in Chebyshev series form

          E02AKF  Evaluation of fitted polynomial in one variable, from
                  Chebyshev series form

          E02BAF  Least-squares curve cubic spline fit (including
                  interpolation)

          E02BBF  Evaluation of fitted cubic spline, function only

          E02BCF  Evaluation of fitted cubic spline, function and
                  derivatives

          E02BDF  Evaluation of fitted cubic spline, definite integral

          E02BEF  Least-squares cubic spline curve fit, automatic knot
                  placement

          E02DAF  Least-squares surface fit, bicubic splines

          E02DCF  Least-squares surface fit by bicubic splines with
                  automatic knot placement, data on rectangular grid

          E02DDF  Least-squares surface fit by bicubic splines with
                  automatic knot placement, scattered data

          E02DEF  Evaluation of a fitted bicubic spline at a vector of
                  points

          E02DFF  Evaluation of a fitted bicubic spline at a mesh of points

          E02GAF  L -approximation by general linear function
                   1

          E02ZAF  Sort 2-D data into panels for fitting bicubic splines

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe02adf}{nage.ht}{ Least-squares polynomial approximations}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe02adf}{NAG Documentation: e02adf}
\beginscroll
\begin{verbatim}



     E02ADF(3NAG)      Foundation Library (12/10/92)      E02ADF(3NAG)



          E02 -- Curve and Surface Fitting                           E02ADF
                  E02ADF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E02ADF computes weighted least-squares polynomial approximations
          to an arbitrary set of data points.

          2. Specification

                 SUBROUTINE E02ADF (M, KPLUS1, NROWS, X, Y, W, WORK1,
                1                   WORK2, A, S, IFAIL)
                 INTEGER          M, KPLUS1, NROWS, IFAIL
                 DOUBLE PRECISION X(M), Y(M), W(M), WORK1(3*M), WORK2
                1                 (2*KPLUS1), A(NROWS,KPLUS1), S(KPLUS1)

          3. Description

          This routine determines least-squares polynomial approximations
          of degrees 0,1,...,k to the set of data points (x ,y ) with
                                                           r  r
          weights w , for r=1,2,...,m.
                   r

          The approximation of degree i has the property that it minimizes
          (sigma)  the sum of squares of the weighted residuals (epsilon) ,
                 i                                                       r
          where

                                (epsilon) =w (y -f )
                                         r  r  r  r

          and f  is the value of the polynomial of degree i at the rth data
               r
          point.

          Each polynomial is represented in Chebyshev-series form with
                              

          normalised argument x. This argument lies in the range -1 to +1
          and is related to the original variable x by the linear
          transformation

                                    (2x-x   -x   )
                                         max  min
                                 x= --------------.
                                     (x   -x   )
                                       max  min

          Here x    and x    are respectively the largest and smallest
                max      min
          values of x . The polynomial approximation of degree i is
                     r
          represented as

               1                                                   
               -a     T (x)+a     T (x)+a     T (x)+...+a       T (x),
               2 i+1,1 0     i+1,2 1     i+1,3 2         i+1,i+1 i

                   

          where T (x) is the Chebyshev polynomial of the first kind of
                 j
                                  

          degree j with argument (x).

          For i=0,1,...,k, the routine produces the values of a       , for
                                                               i+1,j+1
          j=0,1,...,i, together with the value of the root mean square
                           

                          / (sigma)
                         /         i
          residual s =  /   --------. In the case m=i+1 the routine sets
                    i \/     m-i-1
          the value of s  to zero.
                        i

          The method employed is due to Forsythe [4] and is based upon the
          generation of a set of polynomials orthogonal with respect to
          summation over the normalised data set. The extensions due to
          Clenshaw [1] to represent these polynomials as well as the
          approximating polynomials in their Chebyshev-series forms are
          incorporated. The modifications suggested by Reinsch and
          Gentleman (see [5]) to the method originally employed by Clenshaw
          for evaluating the orthogonal polynomials from their Chebyshev-
          series representations are used to give greater numerical
          stability.

          For further details of the algorithm and its use see Cox [2] and
          [3].

          Subsequent evaluation of the Chebyshev-series representations of
          the polynomial approximations should be carried out using E02AEF.

          4. References

          [1]   Clenshaw C W (1960) Curve Fitting with a Digital Computer.
                Comput. J. 2 170--173.

          [2]   Cox M G (1974) A Data-fitting Package for the Non-specialist
                User. Software for Numerical Mathematics. (ed D J Evans)
                Academic Press.

          [3]   Cox M G and Hayes J G (1973) Curve fitting: a guide and
                suite of algorithms for the non-specialist user. Report
                NAC26. National Physical Laboratory.

          [4]   Forsythe G E (1957) Generation and use of orthogonal
                polynomials for data fitting with a digital computer. J.
                Soc. Indust. Appl. Math. 5 74--88.

          [5]   Gentlemen W M (1969) An Error Analysis of Goertzel's
                (Watt's) Method for Computing Fourier Coefficients. Comput.
                J. 12 160--165.

          [6]   Hayes J G (1970) Curve Fitting by Polynomials in One
                Variable. Numerical Approximation to Functions and Data. (ed
                J G Hayes) Athlone Press, London.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: the number m of data points. Constraint: M >=
               MDIST >= 2, where MDIST is the number of distinct x values
               in the data.

           2:  KPLUS1 -- INTEGER                                      Input
               On entry: k+1, where k is the maximum degree required.
               Constraint: 0 < KPLUS1 <= MDIST, where MDIST is the number
               of distinct x values in the data.

           3:  NROWS -- INTEGER                                       Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which E02ADF is called.
               Constraint: NROWS >= KPLUS1.

           4:  X(M) -- DOUBLE PRECISION array                         Input
               On entry: the values x  of the independent variable, for
                                     r
               r=1,2,...,m. Constraint: the values must be supplied in non-
               decreasing order with X(M) > X(1).

           5:  Y(M) -- DOUBLE PRECISION array                         Input
               On entry: the values y  of the dependent variable, for
                                     r
               r=1,2,...,m.

           6:  W(M) -- DOUBLE PRECISION array                         Input
               On entry: the set of weights, w , for r=1,2,...,m. For
                                              r
               advice on the choice of weights, see Section 2.1.2 of the
               Chapter Introduction. Constraint: W(r) > 0.0, for r=1,2,...m.

           7:  WORK1(3*M) -- DOUBLE PRECISION array               Workspace

           8:  WORK2(2*KPLUS1) -- DOUBLE PRECISION array          Workspace

           9:  A(NROWS,KPLUS1) -- DOUBLE PRECISION array             Output
                                                

               On exit: the coefficients of T (x) in the approximating
                                             j
               polynomial of degree i. A(i+1,j+1) contains the coefficient
               a       , for i=0,1,...,k; j=0,1,...,i.
                i+1,j+1

          10:  S(KPLUS1) -- DOUBLE PRECISION array                   Output
               On exit: S(i+1) contains the root mean square residual s ,
                                                                       i
               for i=0,1,...,k, as described in Section 3. For the
               interpretation of the values of the s  and their use in
                                                    i
               selecting an appropriate degree, see Section 3.1 of the
               Chapter Introduction.

          11:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               The weights are not all strictly positive.

          IFAIL= 2
               The values of X(r), for r=1,2,...,M are not in non-
               decreasing order.

          IFAIL= 3
               All X(r) have the same value: thus the normalisation of X is
               not possible.

          IFAIL= 4
               On entry KPLUS1 < 1 (so the maximum degree required is
                        negative)

               or       KPLUS1 > MDIST, where MDIST is the number of
                        distinct x values in the data (so there cannot be a
                        unique solution for degree k=KPLUS1-1).

          IFAIL= 5
               NROWS < KPLUS1.

          7. Accuracy

          No error analysis for the method has been published. Practical
          experience with the method, however, is generally extremely
          satisfactory.

          8. Further Comments

          The time taken by the routine is approximately proportional to
          m(k+1)(k+11).

          The approximating polynomials may exhibit undesirable
          oscillations (particularly near the ends of the range) if the
          maximum degree k exceeds a critical value which depends on the
          number of data points m and their relative positions. As a rough
          guide, for equally-spaced data, this critical value is about
              

          2*\/m. For further details see Hayes [6] page 60.

          9. Example

          Determine weighted least-squares polynomial approximations of
          degrees 0, 1, 2 and 3 to a set of 11 prescribed data points. For
          the approximation of degree 3, tabulate the data and the
          corresponding values of the approximating polynomial, together
          with the residual errors, and also the values of the
          approximating polynomial at points half-way between each pair of
          adjacent data points.

          The example program supplied is written in a general form that
          will enable polynomial approximations of degrees 0,1,...,k to be
          obtained to m data points, with arbitrary positive weights, and
          the approximation of degree k to be tabulated. E02AEF is used to
          evaluate the approximating polynomial. The program is self-
          starting in that any number of data sets can be supplied.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe02aef}{nage.ht}
{ Evaluate polynomial from Chebyshev-series representation}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe02aef}{NAG Documentation: e02aef}
\beginscroll
\begin{verbatim}



     E02AEF(3NAG)      Foundation Library (12/10/92)      E02AEF(3NAG)



          E02 -- Curve and Surface Fitting                           E02AEF
                  E02AEF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E02AEF evaluates a polynomial from its Chebyshev-series
          representation.

          2. Specification

                 SUBROUTINE E02AEF (NPLUS1, A, XCAP, P, IFAIL)
                 INTEGER          NPLUS1, IFAIL
                 DOUBLE PRECISION A(NPLUS1), XCAP, P

          3. Description

          This routine evaluates the polynomial

                        1                                   
                        -a T (x)+a T (x)+a T (x)+...+a   T (x)
                        2 1 0     2 1     3 2         n+1 n

                                                          

          for any value of x satisfying -1<=x<=1. Here T (x) denotes the
                                                        j
          Chebyshev polynomial of the first kind of degree j with argument
          

          x. The value of n is prescribed by the user.

                                    

          In practice, the variable x will usually have been obtained from
          an original variable x, where x   <=x<=x    and
                                         min      max

                                  ((x-x   )-(x   -x))
                                       min    max
                               x= -------------------
                                      (x   -x   )
                                        max  min

          Note that this form of the transformation should be used
          computationally rather than the mathematical equivalent

                                     (2x-x   -x   )
                                          min  max
                                  x= --------------
                                      (x   -x   )
                                        max  min

                                                                 

          since the former guarantees that the computed value of x differs
          from its true value by at most 4(epsilon), where (epsilon) is the
          machine precision, whereas the latter has no such guarantee.

          The method employed is based upon the three-term recurrence
          relation due to Clenshaw [1], with modifications to give greater
          numerical stability due to Reinsch and Gentleman (see [4]).

          For further details of the algorithm and its use see Cox [2] and
          [3].

          4. References

          [1]   Clenshaw C W (1955) A Note on the Summation of Chebyshev
                Series. Math. Tables Aids Comput. 9 118--120.

          [2]   Cox M G (1974) A Data-fitting Package for the Non-specialist
                User. Software for Numerical Mathematics. (ed D J Evans)
                Academic Press.

          [3]   Cox M G and Hayes J G (1973) Curve fitting: a guide and
                suite of algorithms for the non-specialist user. Report
                NAC26. National Physical Laboratory.

          [4]   Gentlemen W M (1969) An Error Analysis of Goertzel's
                (Watt's) Method for Computing Fourier Coefficients. Comput.
                J. 12 160--165.

          5. Parameters

           1:  NPLUS1 -- INTEGER                                      Input
               On entry: the number n+1 of terms in the series (i.e., one
               greater than the degree of the polynomial). Constraint:
               NPLUS1 >= 1.

           2:  A(NPLUS1) -- DOUBLE PRECISION array                    Input
               On entry: A(i) must be set to the value of the ith
               coefficient in the series, for i=1,2,...,n+1.

           3:  XCAP -- DOUBLE PRECISION                               Input
                         

               On entry: x, the argument at which the polynomial is to be
               evaluated. It should lie in the range -1 to +1, but a value
               just outside this range is permitted (see Section 6) to
               allow for possible rounding errors committed in the
                                        

               transformation from x to x discussed in Section 3. Provided
               the recommended form of the transformation is used, a
               successful exit is thus assured whenever the value of x lies
               in the range x    to x   .
                             min     max

           4:  P -- DOUBLE PRECISION                                 Output
               On exit: the value of the polynomial.

           5:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               ABS(XCAP) > 1.0 + 4(epsilon), where (epsilon) is the
               machine precision. In this case the value of P is set
               arbitrarily to zero.

          IFAIL= 2
               On entry NPLUS1 < 1.

          7. Accuracy

          The rounding errors committed are such that the computed value of
          the polynomial is exact for a slightly perturbed set of
          coefficients a +(delta)a . The ratio of the sum of the absolute
                        i         i
          values of the (delta)a  to the sum of the absolute values of the
                                i
          a  is less than a small multiple of (n+1) times machine
           i
          precision.

          8. Further Comments

          The time taken by the routine is approximately proportional to
          n+1.

          It is expected that a common use of E02AEF will be the evaluation
          of the polynomial approximations produced by E02ADF and E02AFF(*)

          9. Example

                                                                   

          Evaluate at 11 equally-spaced points in the interval -1<=x<=1 the
          polynomial of degree 4 with Chebyshev coefficients, 2.0, 0.5, 0.
          25, 0.125, 0.0625.

          The example program is written in a general form that will enable
          a polynomial of degree n in its Chebyshev-series form to be
                                                                   

          evaluated at m equally-spaced points in the interval -1<=x<=1.
          The program is self-starting in that any number of data sets can
          be supplied.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe02agf}{nage.ht}
{ Constrained weighted least-squares polynomial}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe02agf}{NAG Documentation: e02agf}
\beginscroll
\begin{verbatim}



     E02AGF(3NAG)      Foundation Library (12/10/92)      E02AGF(3NAG)



          E02 -- Curve and Surface Fitting                           E02AGF
                  E02AGF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E02AGF computes constrained weighted least-squares polynomial
          approximations in Chebyshev-series form to an arbitrary set of
          data points. The values of the approximations and any number of
          their derivatives can be specified at selected points.

          2. Specification

                 SUBROUTINE E02AGF (M, KPLUS1, NROWS, XMIN, XMAX, X, Y, W,
                1                   MF, XF, YF, LYF, IP, A, S, NP1, WRK,
                2                   LWRK, IWRK, LIWRK, IFAIL)
                 INTEGER          M, KPLUS1, NROWS, MF, LYF, IP(MF), NP1,
                1                 LWRK, IWRK(LIWRK), LIWRK, IFAIL
                 DOUBLE PRECISION XMIN, XMAX, X(M), Y(M), W(M), XF(MF), YF
                1                 (LYF), A(NROWS,KPLUS1), S(KPLUS1), WRK
                2                 (LWRK)

          3. Description

          This routine determines least-squares polynomial approximations
          of degrees up to k to the set of data points (x ,y ) with weights
                                                         r  r
          w , for r=1,2,...,m. The value of k, the maximum degree required,
           r
          is prescribed by the user. At each of the values XF , for r =
                                                             r
          1,2,...,MF, of the independent variable x, the approximations and
          their derivatives up to order p  are constrained to have one of
                                         r
                                                                      MF
                                                                      --
          the user-specified values YF , for s=1,2,...,n, where n=MF+ >  p
                                      s                               --  r
                                                                      r=1

          The approximation of degree i has the property that, subject to
          the imposed contraints, it minimizes (Sigma) , the sum of the
                                                      i
          squares of the weighted residuals (epsilon)  for r=1,2,...,m
                                                     r
          where

                              (epsilon) =w (y -f (x ))
                                       r  r  r  i  r

          and f (x ) is the value of the polynomial approximation of degree
               i  r
          i at the rth data point.

          Each polynomial is represented in Chebyshev-series form with
                              

          normalised argument x. This argument lies in the range -1 to +1
          and is related to the original variable x by the linear
          transformation

                                     2x-(x   +x   )
                                          max  min
                                  x= --------------
                                      (x   -x   )
                                        max  min

          where x    and x   , specified by the user, are respectively the
                 min      max
          lower and upper end-points of the interval of x over which the
          polynomials are to be defined.

          The polynomial approximation of degree i can be written as

                      1                                      
                      -a   +a   T (x)+...+a  T (x)+...+a  T (x)
                      2 i,0  i,1 1         ij j         ii i

                   

          where T (x) is the Chebyshev polynomial of the first kind of
                 j
                                 

          degree j with argument x. For i=n,n+1,...,k, the routine produces
          the values of the coefficients a  , for j=0,1,...,i, together
                                          ij
          with the value of the root mean square residual, S , defined as
                                                            i
                 

                /     --
               /      >
              /       --
             /        i
            /     ----------, where m' is the number of data points with
          \/      (m'+n-i-1)
          non-zero weight.

          Values of the approximations may subsequently be computed using
          E02AEF or E02AKF.

                                                    

          First E02AGF determines a polynomial (mu)(x), of degree n-1,
          which satisfies the given constraints, and a polynomial (nu)(x),
          of degree n, which has value (or derivative) zero wherever a
          constrained value (or derivative) is specified. It then fits
          y -(mu)(x ), for r=1,2,...,m with polynomials of the required
           r       r
                                            

          degree in x each with factor (nu)(x). Finally the coefficients of
               

          (mu)(x) are added to the coefficients of these fits to give the
          coefficients of the constrained polynomial approximations to the
          data points (x ,y ), for r=1,2,...,m. The method employed is
                        r  r
          given in Hayes [3]: it is an extension of Forsythe's orthogonal
          polynomials method [2] as modified by Clenshaw [1].

          4. References

          [1]   Clenshaw C W (1960) Curve Fitting with a Digital Computer.
                Comput. J. 2 170--173.

          [2]   Forsythe G E (1957) Generation and use of orthogonal
                polynomials for data fitting with a digital computer. J.
                Soc. Indust. Appl. Math. 5 74--88.

          [3]   Hayes J G (1970) Curve Fitting by Polynomials in One
                Variable. Numerical Approximation to Functions and Data. (ed
                J G Hayes) Athlone Press, London.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: the number m of data points to be fitted.
               Constraint: M >= 1.

           2:  KPLUS1 -- INTEGER                                      Input
               On entry: k+1, where k is the maximum degree required.
               Constraint: n+1<=KPLUS1<=m''+n, where n is the total number
               of constraints and m'' is the number of data points with
               non-zero weights and distinct abscissae which do not
               coincide with any of the XF(r).

           3:  NROWS -- INTEGER                                       Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which E02AGF is called.
               Constraint: NROWS >= KPLUS1.

           4:  XMIN -- DOUBLE PRECISION                               Input

           5:  XMAX -- DOUBLE PRECISION                               Input
               On entry: the lower and upper end-points, respectively, of
               the interval [x   ,x   ]. Unless there are specific reasons
                              min  max
               to the contrary, it is recommended that XMIN and XMAX be set
               respectively to the lowest and highest value among the x
                                                                       r
               and XF(r). This avoids the danger of extrapolation provided
               there is a constraint point or data point with non-zero
               weight at each end-point. Constraint: XMAX > XMIN.

           6:  X(M) -- DOUBLE PRECISION array                         Input
               On entry: the value x  of the independent variable at the r
                                    r
               th data point, for r=1,2,...,m. Constraint: the X(r) must be
               in non-decreasing order and satisfy XMIN <= X(r) <= XMAX.

           7:  Y(M) -- DOUBLE PRECISION array                         Input
               On entry: Y(r) must contain y , the value of the dependent
                                            r
               variable at the rth data point, for r=1,2,...,m.

           8:  W(M) -- DOUBLE PRECISION array                         Input
               On entry: the weights w  to be applied to the data points
                                      r
               x , for r=1,2...,m. For advice on the choice of weights see
                r
               the Chapter Introduction. Negative weights are treated as
               positive. A zero weight causes the corresponding data point
               to be ignored. Zero weight should be given to any data point
               whose x and y values both coincide with those of a
               constraint (otherwise the denominators involved in the root-
               mean-square residuals s  will be slightly in error).
                                      i

           9:  MF -- INTEGER                                          Input
               On entry: the number of values of the independent variable
               at which a constraint is specified. Constraint: MF >= 1.

          10:  XF(MF) -- DOUBLE PRECISION array                       Input
               On entry: the rth value of the independent variable at
               which a constraint is specified, for r = 1,2,...,MF.
               Constraint: these values need not be ordered but must be
               distinct and satisfy XMIN <= XF(r) <= XMAX.

          11:  YF(LYF) -- DOUBLE PRECISION array                      Input
               On entry: the values which the approximating polynomials
               and their derivatives are required to take at the points
               specified in XF. For each value of XF(r), YF contains in
               successive elements the required value of the approximation,
               its first derivative, second derivative,..., p th
                                                             r
               derivative, for r = 1,2,...,MF. Thus the value which the kth
               derivative of each approximation (k=0 referring to the
               approximation itself) is required to take at the point XF(r)
               must be contained in YF(s), where
                                  s=r+k+p +p +...+p   ,
                                         1  2      r-1
               for k=0,1,...,p  and r = 1,2,...,MF. The derivatives are
                              r
               with respect to the user's variable x.

          12:  LYF -- INTEGER                                         Input
               On entry:
               the dimension of the array YF as declared in the
               (sub)program from which E02AGF is called.
               Constraint: LYF>=n, where n=MF+p +p +...+p  .
                                               1  2      MF

          13:  IP(MF) -- INTEGER array                                Input
               On entry: IP(r) must contain p , the order of the highest-
                                             r
               order derivative specified at XF(r), for r = 1,2,...,MF.
               p =0 implies that the value of the approximation at XF(r) is
                r
               specified, but not that of any derivative. Constraint: IP(r)
               >= 0, for r=1,2,...,MF.

          14:  A(NROWS,KPLUS1) -- DOUBLE PRECISION array             Output
               On exit: A(i+1,j+1) contains the coefficient a   in the
                                                             ij
               approximating polynomial of degree i, for i=n,n+1,...,k;
               j=0,1,...,i.

          15:  S(KPLUS1) -- DOUBLE PRECISION array                   Output
               On exit: S(i+1) contains s , for i=n,n+1,...,k, the root-
                                          i
               mean-square residual corresponding to the approximating
               polynomial of degree i. In the case where the number of data
               points with non-zero weight is equal to k+1-n, s  is
                                                               i
               indeterminate: the routine sets it to zero. For the
               interpretation of the values of s  and their use in
                                                i
               selecting an appropriate degree, see Section 3.1 of the
               Chapter Introduction.

          16:  NP1 -- INTEGER                                        Output
               On exit: n+1, where n is the total number of constraint
               conditions imposed: n=MF+p +p +...+p  .
                                         1  2      MF

          17:  WRK(LWRK) -- DOUBLE PRECISION array                   Output
               On exit: WRK contains weighted residuals of the highest
               degree of fit determined (k). The residual at x  is in
               element 2(n+1)+3(m+k+1)+r, for r=1,2,...,m. The rest of the
               array is used as workspace.

          18:  LWRK -- INTEGER                                        Input
               On entry:
               the dimension of the array WRK as declared in the
               (sub)program from which E02AGF is called.
               Constraint: LWRK>=max(4*M+3*KPLUS1, 8*n+5*IPMAX+MF+10)+2*n+2
               , where IPMAX = max(IP(R)).

          19:  IWRK(LIWRK) -- INTEGER array                       Workspace

          20:  LIWRK -- INTEGER                                       Input
               On entry:
               the dimension of the array IWRK as declared in the
               (sub)program from which E02AGF is called.
               Constraint: LIWRK>=2*MF+2.

          21:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               On entry M < 1,

               or       KPLUS1 < n + 1,

               or       NROWS < KPLUS1,

               or       MF < 1,

               or       LYF < n,

               or       LWRK is too small (see Section 5),

               or       LIWRK<2*MF+2.
               (Here n is the total number of constraint conditions.)

          IFAIL= 2
               IP(r) < 0 for some r = 1,2,...,MF.

          IFAIL= 3
               XMIN >= XMAX, or XF(r) is not in the interval XMIN to XMAX
               for some r = 1,2,...,MF, or the XF(r) are not distinct.

          IFAIL= 4
               X(r) is not in the interval XMIN to XMAX for some
               r=1,2,...,M.

          IFAIL= 5
               X(r) < X(r-1) for some r=2,3,...,M.

          IFAIL= 6
               KPLUS1>m''+n, where m'' is the number of data points with
               non-zero weight and distinct abscissae which do not coincide
               with any XF(r). Thus there is no unique solution.

          IFAIL= 7
               The polynomials (mu)(x) and/or (nu)(x) cannot be determined.
               The problem supplied is too ill-conditioned. This may occur
               when the constraint points are very close together, or large
               in number, or when an attempt is made to constrain high-
               order derivatives.

          7. Accuracy

          No complete error analysis exists for either the interpolating
          algorithm or the approximating algorithm. However, considerable
          experience with the approximating algorithm shows that it is
          generally extremely satisfactory. Also the moderate number of
          constraints, of low order, which are typical of data fitting
          applications, are unlikely to cause difficulty with the
          interpolating routine.

          8. Further Comments

          The time taken by the routine to form the interpolating
                                                       3
          polynomial is approximately proportional to n , and that to form
          the approximating polynomials is very approximately proportional
          to m(k+1)(k+1-n).

          To carry out a least-squares polynomial fit without constraints,
          use E02ADF. To carry out polynomial interpolation only, use
          E01AEF(*).

          9. Example

          The example program reads data in the following order, using the
          notation of the parameter list above:

               MF

               IP(i), XF(i), Y-value and derivative values (if any) at
               XF(i), for i= 1,2,...,MF

               M

               X(i), Y(i), W(i), for i=1,2,...,M

               k, XMIN, XMAX

          The output is:

               the root-mean-square residual for each degree from n to k;

               the Chebyshev coefficients for the fit of degree k;

               the data points, and the fitted values and residuals for
               the fit of degree k.

          The program is written in a generalized form which will read any
          number of data sets.

          The data set supplied specifies 5 data points in the interval [0.
          0,4.0] with unit weights, to which are to be fitted polynomials,
          p, of degrees up to 4, subject to the 3 constraints:

               p(0.0)=1.0,  p'(0.0)=-2.0,  p(4.0)=9.0.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe02ahf}{nage.ht}{ Coefficients of polynomial derivative}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe02ahf}{NAG Documentation: e02ahf}
\beginscroll
\begin{verbatim}



     E02AHF(3NAG)      Foundation Library (12/10/92)      E02AHF(3NAG)



          E02 -- Curve and Surface Fitting                           E02AHF
                  E02AHF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E02AHF determines the coefficients in the Chebyshev-series
          representation of the derivative of a polynomial given in
          Chebyshev-series form.

          2. Specification

                 SUBROUTINE E02AHF (NP1, XMIN, XMAX, A, IA1, LA, PATM1,
                1                   ADIF, IADIF1, LADIF, IFAIL)
                 INTEGER          NP1, IA1, LA, IADIF1, LADIF, IFAIL
                 DOUBLE PRECISION XMIN, XMAX, A(LA), PATM1, ADIF(LADIF)

          3. Description

          This routine forms the polynomial which is the derivative of a
          given polynomial. Both the original polynomial and its derivative
          are represented in Chebyshev-series form. Given the coefficients
          a , for i=0,1,...,n, of a polynomial p(x) of degree n, where
           i

                                  1                    
                            p(x)= -a +a T (x)+...+a T (x)
                                  2 0  1 1         n n

                                               

          the routine returns the coefficients a , for i=0,1,...,n-1, of
                                                i
          the polynomial q(x) of degree n-1, where

                            dp(x)  1                        
                      q(x)= -----= -a +a T (x)+...+a   T   (x).
                             dx    2 0  1 1         n-1 n-1

                  

          Here T (x) denotes the Chebyshev polynomial of the first kind of
                j
                                 

          degree j with argument x. It is assumed that the normalised
                   

          variable x in the interval [-1,+1] was obtained from the user's
          original variable x in the interval [x   ,x   ] by the linear
                                                min  max
          transformation

                                     2x-(x   +x   )
                                          max  min
                                  x= --------------
                                       x   -x
                                        max  min

          and that the user requires the derivative to be with respect to
                                                            

          the variable x. If the derivative with respect to x is required,
          set x   =1 and x   =-1.
               max        min

          Values of the derivative can subsequently be computed, from the
          coefficients obtained, by using E02AKF.

          The method employed is that of [1] modified to obtain the
                                                               

          derivative with respect to x. Initially setting a   =a =0, the
                                                           n+1  n
          routine forms successively

                                    2
                     a   =a   + ---------2ia ,   i=n,n-1,...,1.
                      i-1  i+1  x   -x      i
                                 max  min

          4. References

          [1]   Unknown (1961) Chebyshev-series. Modern Computing Methods,
                Chapter 8. NPL Notes on Applied Science (2nd Edition). 16
                HMSO.

          5. Parameters

           1:  NP1 -- INTEGER                                         Input
               On entry: n+1, where n is the degree of the given
               polynomial p(x). Thus NP1 is the number of coefficients in
               this polynomial. Constraint: NP1 >= 1.

           2:  XMIN -- DOUBLE PRECISION                               Input

           3:  XMAX -- DOUBLE PRECISION                               Input
               On entry: the lower and upper end-points respectively of
               the interval [x   ,x   ]. The Chebyshev-series
                              min  max
                                                                     

               representation is in terms of the normalised variable x,
               where
                                       2x-(x   +x   )
                                            max  min
                                    x= --------------.
                                         x   -x
                                          max  min
               Constraint: XMAX > XMIN.

           4:  A(LA) -- DOUBLE PRECISION array                        Input
               On entry: the Chebyshev coefficients of the polynomial p(x).
               Specifically, element 1 + i*IA1 of A must contain the
               coefficient a , for i=0,1,...,n. Only these n+1 elements
                            i
               will be accessed.

               Unchanged on exit, but see ADIF, below.

           5:  IA1 -- INTEGER                                         Input
               On entry: the index increment of A. Most frequently the
               Chebyshev coefficients are stored in adjacent elements of A,
               and IA1 must be set to 1. However, if, for example, they are
               stored in A(1),A(4),A(7),..., then the value of IA1 must be
               3. See also Section 8. Constraint: IA1 >= 1.

           6:  LA -- INTEGER                                          Input
               On entry:
               the dimension of the array A as declared in the (sub)program
               from which E02AHF is called.
               Constraint: LA>=1+(NP1-1)*IA1.

           7:  PATM1 -- DOUBLE PRECISION                             Output
               On exit: the value of p(x   ). If this value is passed to
                                         min
               the integration routine E02AJF with the coefficients of q(x)
               , then the original polynomial p(x) is recovered, including
               its constant coefficient.

           8:  ADIF(LADIF) -- DOUBLE PRECISION array                 Output
               On exit: the Chebyshev coefficients of the derived
               polynomial q(x). (The differentiation is with respect to the
               variable x). Specifically, element 1+i*IADIF1 of ADIF
                                        

               contains the coefficient a , i=0,1,...n-1. Additionally
                                         i
               element 1+n*IADIF1 is set to zero. A call of the routine may
               have the array name ADIF the same as A, provided that note
               is taken of the order in which elements are overwritten,
               when choosing the starting elements and increments IA1 and
               IADIF1: i.e., the coefficients a ,a ,...,a    must be intact
                                               0  1      i-1
                                 

               after coefficient a  is stored. In particular, it is
                                  i
               possible to overwrite the a  completely by having IA1 =
                                          i
               IADIF1, and the actual arrays for A and ADIF identical.

           9:  IADIF1 -- INTEGER                                      Input
               On entry: the index increment of ADIF. Most frequently the
               Chebyshev coefficients are required in adjacent elements of
               ADIF, and IADIF1 must be set to 1. However, if, for example,
               they are to be stored in ADIF(1),ADIF(4),ADIF(7),..., then
               the value of IADIF1 must be 3. See Section 8. Constraint:
               IADIF1 >= 1.

          10:  LADIF -- INTEGER                                       Input
               On entry:
               the dimension of the array ADIF as declared in the
               (sub)program from which E02AHF is called.
               Constraint: LADIF>=1+(NP1-1)*IADIF1.

          11:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               On entry NP1 < 1,

               or       XMAX <= XMIN,

               or       IA1 < 1,

               or       LA<=(NP1-1)*IA1,

               or       IADIF1 < 1,

               or       LADIF<=(NP1-1)*IADIF1.

          7. Accuracy

          There is always a loss of precision in numerical differentiation,
          in this case associated with the multiplication by 2i in the
          formula quoted in Section 3.

          8. Further Comments

          The time taken by the routine is approximately proportional to
          n+1.

          The increments IA1, IADIF1 are included as parameters to give a
          degree of flexibility which, for example, allows a polynomial in
          two variables to be differentiated with respect to either
          variable without rearranging the coefficients.

          9. Example

          Suppose a polynomial has been computed in Chebyshev-series form
          to fit data over the interval [-0.5,2.5]. The example program
          evaluates the 1st and 2nd derivatives of this polynomial at 4
          equally spaced points over the interval. (For the purposes of
          this example, XMIN, XMAX and the Chebyshev coefficients are
          simply supplied in DATA statements. Normally a program would
          first read in or generate data and compute the fitted
          polynomial.)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe02ajf}{nage.ht}
{ Find coefficients of indefinite integral of polynomial}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe02ajf}{NAG Documentation: e02ajf}
\beginscroll
\begin{verbatim}



     E02AJF(3NAG)      Foundation Library (12/10/92)      E02AJF(3NAG)



          E02 -- Curve and Surface Fitting                           E02AJF
                  E02AJF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E02AJF determines the coefficients in the Chebyshev-series
          representation of the indefinite integral of a polynomial given
          in Chebyshev-series form.

          2. Specification

                 SUBROUTINE E02AJF (NP1, XMIN, XMAX, A, IA1, LA, QATM1,
                1                   AINT, IAINT1, LAINT, IFAIL)
                 INTEGER          NP1, IA1, LA, IAINT1, LAINT, IFAIL
                 DOUBLE PRECISION XMIN, XMAX, A(LA), QATM1, AINT(LAINT)

          3. Description

          This routine forms the polynomial which is the indefinite
          integral of a given polynomial. Both the original polynomial and
          its integral are represented in Chebyshev-series form. If
          supplied with the coefficients a , for i=0,1,...,n, of a
                                          i
          polynomial p(x) of degree n, where

                                 1                    
                           p(x)= -a +a T (x)+...+a T (x),
                                 2 0  1 1         n n

          the routine returns the coefficients a' , for i=0,1,...,n+1, of
                                                 i
          the polynomial q(x) of degree n+1, where

                              1                           
                        q(x)= -a' +a' T (x)+...+a'   T   (x),
                              2  0   1 1          n+1 n+1

          and

                                         /
                                   q(x)= |p(x)dx.
                                         /

                  

          Here T (x) denotes the Chebyshev polynomial of the first kind of
                j
          degree j with argument x. It is assumed that the normalised
                   

          variable x in the interval [-1,+1] was obtained from the user's
          original variable x in the interval [x   ,x   ] by the linear
                                                min  max
          transformation

                                     2x-(x   +x   )
                                          max  min
                                  x= --------------
                                       x   -x
                                        max  min

          and that the user requires the integral to be with respect to the
                                                      

          variable x. If the integral with respect to x is required, set
          x   =1 and x   =-1.
           max        min

          Values of the integral can subsequently be computed, from the
          coefficients obtained, by using E02AKF.

          The method employed is that of Chebyshev-series [1] modified for
          integrating with respect to x. Initially taking a   =a   =0, the
                                                           n+1  n+2
          routine forms successively

                          a   -a     x   -x
                           i-1  i+1   max  min
                     a' = ---------* ---------,   i=n+1,n,...,1.
                       i     2i          2

          The constant coefficient a'  is chosen so that q(x) is equal to a
                                     0
          specified value, QATM1, at the lower end-point of the interval on
                                     

          which it is defined, i.e., x=-1, which corresponds to x=x   .
                                                                   min

          4. References

          [1]   Unknown (1961) Chebyshev-series. Modern Computing Methods,
                Chapter 8. NPL Notes on Applied Science (2nd Edition). 16
                HMSO.

          5. Parameters

           1:  NP1 -- INTEGER                                         Input
               On entry: n+1, where n is the degree of the given
               polynomial p(x). Thus NP1 is the number of coefficients in
               this polynomial. Constraint: NP1 >= 1.

           2:  XMIN -- DOUBLE PRECISION                               Input

           3:  XMAX -- DOUBLE PRECISION                               Input
               On entry: the lower and upper end-points respectively of
               the interval [x   ,x   ]. The Chebyshev-series
                              min  max
                                                                     

               representation is in terms of the normalised variable x,
               where
                                       2x-(x   +x   )
                                            max  min
                                    x= --------------.
                                         x   -x
                                          max  min
               Constraint: XMAX > XMIN.

           4:  A(LA) -- DOUBLE PRECISION array                        Input
               On entry: the Chebyshev coefficients of the polynomial p(x)
               . Specifically, element 1+i*IA1 of A must contain the
               coefficient a , for i=0,1,...,n. Only these n+1 elements
                            i
               will be accessed.

               Unchanged on exit, but see AINT, below.

           5:  IA1 -- INTEGER                                         Input
               On entry: the index increment of A. Most frequently the
               Chebyshev coefficients are stored in adjacent elements of A,
               and IA1 must be set to 1. However, if for example, they are
               stored in A(1),A(4),A(7),..., then the value of IA1 must be
               3. See also Section 8. Constraint: IA1 >= 1.

           6:  LA -- INTEGER                                          Input
               On entry:
               the dimension of the array A as declared in the (sub)program
               from which E02AJF is called.
               Constraint: LA>=1+(NP1-1)*IA1.

           7:  QATM1 -- DOUBLE PRECISION                              Input
               On entry: the value that the integrated polynomial is
               required to have at the lower end-point of its interval of
                                    

               definition, i.e., at x=-1 which corresponds to x=x   . Thus,
                                                                 min
               QATM1 is a constant of integration and will normally be set
               to zero by the user.

           8:  AINT(LAINT) -- DOUBLE PRECISION array                 Output
               On exit: the Chebyshev coefficients of the integral q(x).
               (The integration is with respect to the variable x, and the
               constant coefficient is chosen so that q(x   ) equals QATM1)
                                                         min
               Specifically, element 1+i*IAINT1 of AINT contains the
               coefficient a' , for i=0,1,...,n+1. A call of the routine
                             i
               may have the array name AINT the same as A, provided that
               note is taken of the order in which elements are overwritten
               when choosing starting elements and increments IA1 and
               IAINT1: i.e., the coefficients, a ,a ,...,a    must be
                                                0  1      i-2
               intact after coefficient a'  is stored. In particular it is
                                          i
               possible to overwrite the a  entirely by having IA1 =
                                          i
               IAINT1, and the actual array for A and AINT identical.

           9:  IAINT1 -- INTEGER                                      Input
               On entry: the index increment of AINT. Most frequently the
               Chebyshev coefficients are required in adjacent elements of
               AINT, and IAINT1 must be set to 1. However, if, for example,
               they are to be stored in AINT(1),AINT(4),AINT(7),..., then
               the value of IAINT1 must be 3. See also Section 8.
               Constraint: IAINT1 >= 1.

          10:  LAINT -- INTEGER                                       Input
               On entry:
               the dimension of the array AINT as declared in the
               (sub)program from which E02AJF is called.
               Constraint: LAINT>=1+NP1*IAINT1.

          11:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               On entry NP1 < 1,

               or       XMAX <= XMIN,

               or       IA1 < 1,

               or       LA<=(NP1-1)*IA1,

               or       IAINT1 < 1,

               or       LAINT<=NP1*IAINT1.

          7. Accuracy

          In general there is a gain in precision in numerical integration,
          in this case associated with the division by 2i in the formula
          quoted in Section 3.

          8. Further Comments

          The time taken by the routine is approximately proportional to
          n+1.

          The increments IA1, IAINT1 are included as parameters to give a
          degree of flexibility which, for example, allows a polynomial in
          two variables to be integrated with respect to either variable
          without rearranging the coefficients.

          9. Example

          Suppose a polynomial has been computed in Chebyshev-series form
          to fit data over the interval [-0.5,2.5]. The example program
          evaluates the integral of the polynomial from 0.0 to 2.0. (For
          the purpose of this example, XMIN, XMAX and the Chebyshev
          coefficients are simply supplied in DATA statements. Normally a
          program would read in or generate data and compute the fitted
          polynomial).

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe02akf}{nage.ht}
{ Evaluate polynomial in Chebyshev-series representation}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe02akf}{NAG Documentation: e02akf}
\beginscroll
\begin{verbatim}



     E02AKF(3NAG)      Foundation Library (12/10/92)      E02AKF(3NAG)



          E02 -- Curve and Surface Fitting                           E02AKF
                  E02AKF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E02AKF evaluates a polynomial from its Chebyshev-series
          representation, allowing an arbitrary index increment for
          accessing the array of coefficients.

          2. Specification

                 SUBROUTINE E02AKF (NP1, XMIN, XMAX, A, IA1, LA, X, RESULT,
                1                   IFAIL)
                 INTEGER          NP1, IA1, LA, IFAIL
                 DOUBLE PRECISION XMIN, XMAX, A(LA), X, RESULT

          3. Description

          If supplied with the coefficients a , for i=0,1,...,n, of a
                                             i
                       

          polynomial p(x) of degree n, where

                                 1                    
                           p(x)= -a +a T (x)+...+a T (x),
                                 2 0  1 1         n n

                                              

          this routine returns the value of p(x) at a user-specified value
                                     

          of the variable x. Here T (x) denotes the Chebyshev polynomial of
                                   j
                                                   

          the first kind of degree j with argument x. It is assumed that
                                   

          the independent variable x in the interval [-1,+1] was obtained
          from the user's original variable x in the interval [x   ,x   ]
                                                                min  max
          by the linear transformation

                                    2x-(x   +x   )
                                         max  min
                                 x= --------------.
                                      x   -x
                                       max  min

          The coefficients a  may be supplied in the array A, with any
                            i
          increment between the indices of array elements which contain
          successive coefficients. This enables the routine to be used in
          surface fitting and other applications, in which the array might
          have two or more dimensions.

          The method employed is based upon the three-term recurrence
          relation due to Clenshaw [1], with modifications due to Reinsch
          and Gentleman (see [4]). For further details of the algorithm and
          its use see Cox [2] and Cox and Hayes [3].

          4. References

          [1]   Clenshaw C W (1955) A Note on the Summation of Chebyshev-
                series. Math. Tables Aids Comput. 9 118--120.

          [2]   Cox M G (1973) A data-fitting package for the non-specialist
                user. Report NAC40. National Physical Laboratory.

          [3]   Cox M G and Hayes J G (1973) Curve fitting: a guide and
                suite of algorithms for the non-specialist user. Report
                NAC26. National Physical Laboratory.

          [4]   Gentlemen W M (1969) An Error Analysis of Goertzel's
                (Watt's) Method for Computing Fourier Coefficients. Comput.
                J. 12 160--165.

          5. Parameters

           1:  NP1 -- INTEGER                                         Input
               On entry: n+1, where n is the degree of the given
                            

               polynomial p(x). Constraint: NP1 >= 1.

           2:  XMIN -- DOUBLE PRECISION                               Input

           3:  XMAX -- DOUBLE PRECISION                               Input
               On entry: the lower and upper end-points respectively of
               the interval [x   ,x   ]. The Chebyshev-series
                              min  max
                                                                     

               representation is in terms of the normalised variable x,
               where
                                       2x-(x   +x   )
                                            max  min
                                    x= --------------.
                                         x   -x
                                          max  min
               Constraint: XMIN < XMAX.

           4:  A(LA) -- DOUBLE PRECISION array                        Input
               On entry: the Chebyshev coefficients of the polynomial p(x).
               Specifically, element 1+i*IA1 must contain the coefficient
               a , for i=0,1,...,n. Only these n+1 elements will be
                i
               accessed.

           5:  IA1 -- INTEGER                                         Input
               On entry: the index increment of A. Most frequently, the
               Chebyshev coefficients are stored in adjacent elements of A,
               and IA1 must be set to 1. However, if, for example, they are
               stored in A(1),A(4),A(7),..., then the value of IA1 must be
               3. Constraint: IA1 >= 1.

           6:  LA -- INTEGER                                          Input
               On entry:
               the dimension of the array A as declared in the (sub)program
               from which E02AKF is called.
               Constraint: LA>=(NP1-1)*IA1+1.

           7:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x at which the polynomial is to be
               evaluated. Constraint: XMIN <= X <= XMAX.

           8:  RESULT -- DOUBLE PRECISION                            Output
                                                      

               On exit: the value of the polynomial p(x).

           9:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               On entry NP1 < 1,

               or       IA1 < 1,

               or       LA<=(NP1-1)*IA1,

               or       XMIN >= XMAX.

          IFAIL= 2
               X does not satisfy the restriction XMIN <= X <= XMAX.

          7. Accuracy

          The rounding errors are such that the computed value of the
          polynomial is exact for a slightly perturbed set of coefficients
          a +(delta)a . The ratio of the sum of the absolute values of the
           i         i
          (delta)a  to the sum of the absolute values of the a  is less
                  i                                           i
          than a small multiple of (n+1)*machine precision.

          8. Further Comments

          The time taken by the routine is approximately proportional to
          n+1.

          9. Example

          Suppose a polynomial has been computed in Chebyshev-series form
          to fit data over the interval [-0.5,2.5]. The example program
          evaluates the polynomial at 4 equally spaced points over the
          interval. (For the purposes of this example, XMIN, XMAX and the
          Chebyshev coefficients are supplied in DATA statements. Normally
          a program would first read in or generate data and compute the
          fitted polynomial.)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe02baf}{nage.ht}
{ Weighted least-squares aprrox to data points}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe02baf}{NAG Documentation: e02baf}
\beginscroll
\begin{verbatim}



     E02BAF(3NAG)      Foundation Library (12/10/92)      E02BAF(3NAG)



          E02 -- Curve and Surface Fitting                           E02BAF
                  E02BAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E02BAF computes a weighted least-squares approximation to an
          arbitrary set of data points by a cubic spline with knots
          prescribed by the user. Cubic spline interpolation can also be
          carried out.

          2. Specification

                 SUBROUTINE E02BAF (M, NCAP7, X, Y, W, LAMDA, WORK1, WORK2,
                1                   C, SS, IFAIL)
                 INTEGER          M, NCAP7, IFAIL
                 DOUBLE PRECISION X(M), Y(M), W(M), LAMDA(NCAP7), WORK1(M),
                1                 WORK2(4*NCAP7), C(NCAP7), SS

          3. Description

          This routine determines a least-squares cubic spline
          approximation s(x) to the set of data points (x ,y ) with weights
                                                         r  r
                                                               

          w , for r=1,2,...,m. The value of NCAP7 = n+7, where n is the
           r
          number of intervals of the spline (one greater than the number of
          interior knots), and the values of the knots
          (lambda) ,(lambda) ,...,(lambda)   , interior to the data
                  5         6             n+3
          interval, are prescribed by the user.

          s(x) has the property that it minimizes (theta), the sum of
          squares of the weighted residuals (epsilon) , for r=1,2,...,m,
                                                     r
          where

                              (epsilon) =w (y -s(x )).
                                       r  r  r    r

          The routine produces this minimizing value of (theta) and the
                                             

          coefficients c ,c ,...,c , where q=n+3, in the B-spline
                        1  2      q
          representation

                                        q
                                        --
                                  s(x)= >  c N (x).
                                        --  i i
                                        i=1

          Here N (x) denotes the normalised B-spline of degree 3 defined
                i
          upon the knots (lambda) ,(lambda)   ,...,(lambda)   .
                                 i         i+1             i+4

          In order to define the full set of B-splines required, eight
          additional knots (lambda) ,(lambda) ,(lambda) ,(lambda)  and
                                   1         2         3         4
          (lambda)   ,(lambda)-  ,(lambda)   ,(lambda)    are inserted
                  n+4         n+5         n+6         n+7
          automatically by the routine. The first four of these are set
          equal to the smallest x  and the last four to the largest x .
                                 r                                   r

          The representation of s(x) in terms of B-splines is the most

          compact form possible in that only n+3 coefficients, in addition
                 

          to the n+7 knots, fully define s(x).

          The method employed involves forming and then computing the
          least-squares solution of a set of m linear equations in the
                                     

          coefficients c  (i=1,2,...,n+3). The equations are formed using a
                        i
          recurrence relation for B-splines that is unconditionally stable
          (Cox [1], de Boor [5]), even for multiple (coincident) knots. The
          least-squares solution is also obtained in a stable manner by
          using orthogonal transformations, viz. a variant of Givens
          rotations (Gentleman [6] and [7]). This requires only one
          equation to be stored at a time. Full advantage is taken of the
          structure of the equations, there being at most four non-zero
          values of N (x) for any value of x and hence at most four
                     i
          coefficients in each equation.

          For further details of the algorithm and its use see Cox [2], [3]
          and [4].

          Subsequent evaluation of s(x) from its B-spline representation
          may be carried out using E02BBF. If derivatives of s(x) are also
          required, E02BCF may be used. E02BDF can be used to compute the
          definite integral of s(x).

          4. References

          [1]   Cox M G (1972) The Numerical Evaluation of B-splines. J.
                Inst. Math. Appl. 10 134--149.

          [2]   Cox M G (1974) A Data-fitting Package for the Non-specialist
                User. Software for Numerical Mathematics. (ed D J Evans)
                Academic Press.

          [3]   Cox M G (1975) Numerical methods for the interpolation and
                approximation of data by spline functions. PhD Thesis. City
                University, London.

          [4]   Cox M G and Hayes J G (1973) Curve fitting: a guide and
                suite of algorithms for the non-specialist user. Report
                NAC26. National Physical Laboratory.

          [5]   De Boor C (1972) On Calculating with B-splines. J. Approx.
                Theory. 6 50--62.

          [6]   Gentleman W M (1974) Algorithm AS 75. Basic Procedures for
                Large Sparse or Weighted Linear Least-squares Problems.
                Appl. Statist. 23 448--454.

          [7]   Gentleman W M (1973) Least-squares Computations by Givens
                Transformations without Square Roots. J. Inst. Math. Applic.
                12 329--336.

          [8]   Schoenberg I J and Whitney A (1953) On Polya Frequency
                Functions III. Trans. Amer. Math. Soc. 74  246--259.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: the number m of data points. Constraint: M >=
               MDIST >= 4, where MDIST is the number of distinct x values
               in the data.

           2:  NCAP7 -- INTEGER                                       Input
                                    

               On entry: n+7, where n is the number of intervals of the
               spline (which is one greater than the number of interior
               knots, i.e., the knots strictly within the range x  to x )
                                                                 1     m
               over which the spline is defined. Constraint: 8 <= NCAP7 <=
               MDIST + 4, where MDIST is the number of distinct x values in
               the data.

           3:  X(M) -- DOUBLE PRECISION array                         Input
               On entry: the values x  of the independent variable
                                     r
               (abscissa), for r=1,2,...,m. Constraint: x <=x <=...<=x .
                                                         1   2        m

           4:  Y(M) -- DOUBLE PRECISION array                         Input
               On entry: the values y  of the dependent variable
                                     r
               (ordinate), for r=1,2,...,m.

           5:  W(M) -- DOUBLE PRECISION array                         Input
               On entry: the values w  of the weights, for r=1,2,...,m.
                                     r
               For advice on the choice of weights, see the Chapter
               Introduction. Constraint: W(r) > 0, for r=1,2,...,m.

           6:  LAMDA(NCAP7) -- DOUBLE PRECISION array          Input/Output
               On entry: LAMDA(i) must be set to the (i-4)th (interior)

               knot, (lambda) , for i=5,6,...,n+3. Constraint: X(1) < LAMDA
                             i
               (5) <= LAMDA(6) <=... <= LAMDA(NCAP7-4) < X(M). On exit: the
               input values are unchanged, and LAMDA(i), for i = 1, 2, 3,
               4, NCAP7-3, NCAP7-2, NCAP7-1, NCAP7 contains the additional
               (exterior) knots introduced by the routine. For advice on
               the choice of knots, see Section 3.3 of the Chapter
               Introduction.

           7:  WORK1(M) -- DOUBLE PRECISION array                 Workspace

           8:  WORK2(4*NCAP7) -- DOUBLE PRECISION array           Workspace

           9:  C(NCAP7) -- DOUBLE PRECISION array                    Output
               On exit: the coefficient c  of the B-spline N (x), for
                                         i                  i
                         

               i=1,2,...,n+3. The remaining elements of the array are not
               used.

          10:  SS -- DOUBLE PRECISION                                Output
               On exit: the residual sum of squares, (theta).

          11:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               The knots fail to satisfy the condition

               X(1) < LAMDA(5) <= LAMDA(6) <=... <= LAMDA(NCAP7-4) < X(M).
               Thus the knots are not in correct order or are not interior
               to the data interval.

          IFAIL= 2
               The weights are not all strictly positive.

          IFAIL= 3
               The values of X(r), for r = 1,2,...,M are not in non-
               decreasing order.

          IFAIL= 4
               NCAP7 < 8 (so the number of interior knots is negative) or
               NCAP7 > MDIST + 4, where MDIST is the number of distinct x
               values in the data (so there cannot be a unique solution).

          IFAIL= 5
               The conditions specified by Schoenberg and Whitney [8] fail
               to hold for at least one subset of the distinct data
               abscissae. That is, there is no subset of NCAP7-4 strictly
               increasing values, X(R(1)),X(R(2)),...,X(R(NCAP7-4)), among
               the abscissae such that
                    X(R(1)) < LAMDA(1) < X(R(5)),

                    X(R(2)) < LAMDA(2) < X(R(6)),

                    ...

                    X(R(NCAP7-8)) < LAMDA(NCAP7-8) < X(R(NCAP7-4)).
               This means that there is no unique solution: there are
               regions containing too many knots compared with the number
               of data points.

          7. Accuracy

          The rounding errors committed are such that the computed
          coefficients are exact for a slightly perturbed set of ordinates
          y +(delta)y . The ratio of the root-mean-square value for the
           r         r
          (delta)y  to the root-mean-square value of the y  can be expected
                  r                                       r
          to be less than a small multiple of (kappa)*m*machine precision,
          where (kappa) is a condition number for the problem. Values of
          (kappa) for 20-30 practical data sets all proved to lie between
          4.5 and 7.8 (see Cox [3]). (Note that for these data sets,
          replacing the coincident end knots at the end-points x  and x
                                                                1      m
          used in the routine by various choices of non-coincident exterior
          knots gave values of (kappa) between 16 and 180. Again see Cox
          [3] for further details.) In general we would not expect (kappa)
          to be large unless the choice of knots results in near-violation
          of the Schoenberg-Whitney conditions.

          A cubic spline which adequately fits the data and is free from
          spurious oscillations is more likely to be obtained if the knots
          are chosen to be grouped more closely in regions where the
          function (underlying the data) or its derivatives change more
          rapidly than elsewhere.

          8. Further Comments

                                                               

          The time taken by the routine is approximately C*(2m+n+7)
          seconds, where C is a machine-dependent constant.

          Multiple knots are permitted as long as their multiplicity does
          not exceed 4, i.e., the complete set of knots must satisfy
                                               

          (lambda) <(lambda)   , for i=1,2,...,n+3, (cf. Section 6). At a
                  i         i+4
          knot of multiplicity one (the usual case), s(x) and its first two
          derivatives are continuous. At a knot of multiplicity two, s(x)
          and its first derivative are continuous. At a knot of
          multiplicity three, s(x) is continuous, and at a knot of
          multiplicity four, s(x) is generally discontinous.

          The routine can be used efficiently for cubic spline
                                   

          interpolation, i.e.,if m=n+3. The abscissae must then of course
          satisfy x <x <...<x . Recommended values for the knots in this
                   1  2      m
                                                 

          case are (lambda) =x   , for i=5,6,...,n+3.
                           i  i-2

          9. Example

          Determine a weighted least-squares cubic spline approximation
          with five intervals (four interior knots) to a set of 14 given
          data points. Tabulate the data and the corresponding values of
          the approximating spline, together with the residual errors, and
          also the values of the approximating spline at points half-way
          between each pair of adjacent data points.

          The example program is written in a general form that will enable
                                                         

          a cubic spline approximation with n intervals (n-1 interior
          knots) to be obtained to m data points, with arbitrary positive
          weights, and the approximation to be tabulated. Note that E02BBF
          is used to evaluate the approximating spline. The program is
          self-starting in that any number of data sets can be supplied.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe02bbf}{nage.ht}
{ Evaluates a cubic spline from its B-spline representation}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe02bbf}{NAG Documentation: e02bbf}
\beginscroll
\begin{verbatim}



     E02BBF(3NAG)      Foundation Library (12/10/92)      E02BBF(3NAG)



          E02 -- Curve and Surface Fitting                           E02BBF
                  E02BBF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E02BBF evaluates a cubic spline from its B-spline representation.

          2. Specification

                 SUBROUTINE E02BBF (NCAP7, LAMDA, C, X, S, IFAIL)
                 INTEGER          NCAP7, IFAIL
                 DOUBLE PRECISION LAMDA(NCAP7), C(NCAP7), X, S

          3. Description

          This routine evaluates the cubic spline s(x) at a prescribed
          argument x from its augmented knot set (lambda) , for
                                                         i
                    

          i=1,2,...,n+7, (see E02BAF) and from the coefficients c , for
                                                                 i
          i=1,2,...,q in its B-spline representation

                                        q
                                        --
                                  s(x)= >  c N (x)
                                        --  i i
                                        i=1

                            

          Here q=n+3, where n is the number of intervals of the spline, and
          N (x) denotes the normalised B-spline of degree 3 defined upon
           i
          the knots (lambda) ,(lambda)   ,...,(lambda)   . The prescribed
                            i         i+1             i+4
          argument x must satisfy (lambda) <=x<=(lambda)   .
                                          4             n+4

                                                                   

          It is assumed that (lambda) >=(lambda)   , for j=2,3,...,n+7, and
                                     j          j-1
          (lambda)   >(lambda) .
                              4
                  n+4

          The method employed is that of evaluation by taking convex
          combinations due to de Boor [4]. For further details of the
          algorithm and its use see Cox [1] and [3].

          It is expected that a common use of E02BBF will be the evaluation
          of the cubic spline approximations produced by E02BAF. A
          generalization of E02BBF which also forms the derivative of s(x)
          is E02BCF. E02BCF takes about 50% longer than E02BBF.

          4. References

          [1]   Cox M G (1972) The Numerical Evaluation of B-splines. J.
                Inst. Math. Appl. 10 134--149.

          [2]   Cox M G (1978) The Numerical Evaluation of a Spline from its
                B-spline Representation. J. Inst. Math. Appl. 21 135--143.

          [3]   Cox M G and Hayes J G (1973) Curve fitting: a guide and
                suite of algorithms for the non-specialist user. Report
                NAC26. National Physical Laboratory.

          [4]   De Boor C (1972) On Calculating with B-splines. J. Approx.
                Theory. 6 50--62.

          5. Parameters

           1:  NCAP7 -- INTEGER                                       Input
                                    

               On entry: n+7, where n is the number of intervals (one
               greater than the number of interior knots, i.e., the knots
               strictly within the range (lambda)  to (lambda)   ) over
                                                 4            
                                                              n+4
               which the spline is defined. Constraint: NCAP7 >= 8.

           2:  LAMDA(NCAP7) -- DOUBLE PRECISION array                 Input
               On entry: LAMDA(j) must be set to the value of the jth
               member of the complete set of knots, (lambda)  for
                                                            j
                         

               j=1,2,...,n+7. Constraint: the LAMDA(j) must be in non-
               decreasing order with LAMDA(NCAP7-3) > LAMDA(4).

           3:  C(NCAP7) -- DOUBLE PRECISION array                     Input
               On entry: the coefficient c  of the B-spline N (x), for
                                          i                  i
                         

               i=1,2,...,n+3. The remaining elements of the array are not
               used.

           4:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x at which the cubic spline is to be
               evaluated. Constraint: LAMDA(4) <= X <= LAMDA(NCAP7-3).

           5:  S -- DOUBLE PRECISION                                 Output
               On exit: the value of the spline, s(x).

           6:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               The argument X does not satisfy LAMDA(4) <= X <= LAMDA(
               NCAP7-3).

               In this case the value of S is set arbitrarily to zero.

          IFAIL= 2
               NCAP7 < 8, i.e., the number of interior knots is negative.

          7. Accuracy

          The computed value of s(x) has negligible error in most practical
          situations. Specifically, this value has an absolute error
          bounded in modulus by 18*c   * machine precision, where c    is
                                    max                            max
          the largest in modulus of c ,c   ,c    and c   , and j is an
                                     j  j+1  j+2      j+3
          integer such that (lambda)   <=x<=(lambda)   . If c ,c   ,c
                                    j+3             j+4      j  j+1  j+2
          and c    are all of the same sign, then the computed value of
               j+3
          s(x) has a relative error not exceeding 20*machine precision in
          modulus. For further details see Cox [2].

          8. Further Comments

                                                                      

          The time taken by the routine is approximately C*(1+0.1*log(n+7))
          seconds, where C is a machine-dependent constant.

          Note: the routine does not test all the conditions on the knots
          given in the description of LAMDA in Section 5, since to do this
          would result in a computation time approximately linear in n+7
          instead of log(n+7). All the conditions are tested in E02BAF,
          however.

          9. Example

          Evaluate at 9 equally-spaced points in the interval 1.0<=x<=9.0
          the cubic spline with (augmented) knots 1.0, 1.0, 1.0, 1.0, 3.0,
          6.0, 8.0, 9.0, 9.0, 9.0, 9.0 and normalised cubic B-spline
          coefficients 1.0, 2.0, 4.0, 7.0, 6.0, 4.0, 3.0.

          The example program is written in a general form that will enable
                              

          a cubic spline with n intervals, in its normalised cubic B-spline
          form, to be evaluated at m equally-spaced points in the interval
                                 

          LAMDA(4) <= x <= LAMDA(n+4). The program is self-starting in that
          any number of data sets may be supplied.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe02bcf}{nage.ht}
{ Evaluate cubic spline and 3 derivatives from B-spline}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe02bcf}{NAG Documentation: e02bcf}
\beginscroll
\begin{verbatim}



     E02BCF(3NAG)      Foundation Library (12/10/92)      E02BCF(3NAG)



          E02 -- Curve and Surface Fitting                           E02BCF
                  E02BCF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E02BCF evaluates a cubic spline and its first three derivatives
          from its B-spline representation.

          2. Specification

                 SUBROUTINE E02BCF (NCAP7, LAMDA, C, X, LEFT, S, IFAIL)
                 INTEGER          NCAP7, LEFT, IFAIL
                 DOUBLE PRECISION LAMDA(NCAP7), C(NCAP7), X, S(4)

          3. Description

          This routine evaluates the cubic spline s(x) and its first three
          derivatives at a prescribed argument x. It is assumed that s(x)
          is represented in terms of its B-spline coefficients c , for
                                                                i
                    

          i=1,2,...,n+3 and (augmented) ordered knot set (lambda) , for
                                                                 i
                    

          i=1,2,...,n+7, (see E02BAF), i.e.,

                                        q
                                        --
                                  s(x)= >  c N (x)
                                        --  i i
                                        i=1

                      

          Here q=n+3, n is the number of intervals of the spline and N (x)
                                                                      i
          denotes the normalised B-spline of degree 3 (order 4) defined
          upon the knots (lambda) ,(lambda)   ,...,(lambda)   . The
                                 i         i+1             i+4
          prescribed argument x must satisfy

                              (lambda) <=x<=(lambda)
                                      4             n+4

          At a simple knot (lambda)  (i.e., one satisfying
                                   i
          (lambda)   <(lambda) <(lambda)   ), the third derivative of the
                  i-1         i         i+1
          spline is in general discontinuous. At a multiple knot (i.e., two
          or more knots with the same value), lower derivatives, and even
          the spline itself, may be discontinuous. Specifically, at a point
          x=u where (exactly) r knots coincide (such a point is termed a
          knot of multiplicity r), the values of the derivatives of order
          4-j, for j=1,2,...,r, are in general discontinuous. (Here
          1<=r<=4;r>4 is not meaningful.) The user must specify whether the
          value at such a point is required to be the left- or right-hand
          derivative.

          The method employed is based upon:

               (i) carrying out a binary search for the knot interval
               containing the argument x (see Cox [3]),

               (ii) evaluating the non-zero B-splines of orders 1,2,3 and
               4 by recurrence (see Cox [2] and [3]),

               (iii) computing all derivatives of the B-splines of order 4
               by applying a second recurrence to these computed B-spline
               values (see de Boor [1]),

               (iv) multiplying the 4th-order B-spline values and their
               derivative by the appropriate B-spline coefficients, and
               summing, to yield the values of s(x) and its derivatives.

          E02BCF can be used to compute the values and derivatives of cubic
          spline fits and interpolants produced by E02BAF.

          If only values and not derivatives are required, E02BBF may be
          used instead of E02BCF, which takes about 50% longer than E02BBF.

          4. References

          [1]   De Boor C (1972) On Calculating with B-splines. J. Approx.
                Theory. 6 50--62.

          [2]   Cox M G (1972) The Numerical Evaluation of B-splines. J.
                Inst. Math. Appl. 10 134--149.

          [3]   Cox M G (1978) The Numerical Evaluation of a Spline from its
                B-spline Representation. J. Inst. Math. Appl. 21 135--143.

          5. Parameters

           1:  NCAP7 -- INTEGER                                       Input
                                    

               On entry: n+7, where n is the number of intervals of the
               spline (which is one greater than the number of interior
               knots, i.e., the knots strictly within the range (lambda)
                                                                        4
               to (lambda)    over which the spline is defined).
                          n+4
               Constraint: NCAP7 >= 8.

           2:  LAMDA(NCAP7) -- DOUBLE PRECISION array                 Input
               On entry: LAMDA(j) must be set to the value of the jth
               member of the complete set of knots, (lambda) , for
                                                            j
                         

               j=1,2,...,n+7. Constraint: the LAMDA(j) must be in non-
               decreasing order with

               LAMDA(NCAP7-3) > LAMDA(4).

           3:  C(NCAP7) -- DOUBLE PRECISION array                     Input
               On entry: the coefficient c  of the B-spline N (x), for
                                          i                  i

               i=1,2,...,n+3. The remaining elements of the array are not
               used.

           4:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x at which the cubic spline and its
               derivatives are to be evaluated. Constraint: LAMDA(4) <= X
               <= LAMDA(NCAP7-3).

           5:  LEFT -- INTEGER                                        Input
               On entry: specifies whether left- or right-hand values of
               the spline and its derivatives are to be computed (see
               Section 3). Left- or right-hand values are formed according
               to whether LEFT is equal or not equal to 1. If x does not
               coincide with a knot, the value of LEFT is immaterial. If x
               = LAMDA(4), right-hand values are computed, and if x = LAMDA
               (NCAP7-3), left-hand values are formed, regardless of the
               value of LEFT.

           6:  S(4) -- DOUBLE PRECISION array                        Output
               On exit: S(j) contains the value of the (j-1)th derivative
               of the spline at the argument x, for j = 1,2,3,4. Note that
               S(1) contains the value of the spline.

           7:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               NCAP7 < 8, i.e., the number of intervals is not positive.

          IFAIL= 2
               Either LAMDA(4) >= LAMDA(NCAP7-3), i.e., the range over
               which s(x) is defined is null or negative in length, or X is
               an invalid argument, i.e., X < LAMDA(4) or X >
               LAMDA(NCAP7-3).

          7. Accuracy

          The computed value of s(x) has negligible error in most practical
          situations. Specifically, this value has an absolute error
          bounded in modulus by 18*c   * machine precision, where c    is
                                    max                            max
          the largest in modulus of c ,c   ,c    and c   , and j is an
                                     j  j+1  j+2      j+3
          integer such that (lambda)   <=x<=(lambda)   . If c ,c   ,c
                                    j+3             j+4      j  j+1  j+2
          and c    are all of the same sign, then the computed value of
               j+3
          s(x) has relative error bounded by 18*machine precision. For full
          details see Cox [3].

          No complete error analysis is available for the computation of
          the derivatives of s(x). However, for most practical purposes the
          absolute errors in the computed derivatives should be small.

          8. Further Comments

          The time taken by this routine is approximately linear in
              

          log(n+7).

          Note: the routine does not test all the conditions on the knots
          given in the description of LAMDA in Section 5, since to do this
                                                                     

          would result in a computation time approximately linear in n+7
                         

          instead of log(n+7). All the conditions are tested in E02BAF,
          however.

          9. Example

          Compute, at the 7 arguments x = 0, 1, 2, 3, 4, 5, 6, the left-
          and right-hand values and first 3 derivatives of the cubic spline
          defined over the interval 0<=x<=6 having the 6 interior knots x =
          1, 3, 3, 3, 4, 4, the 8 additional knots 0, 0, 0, 0, 6, 6, 6, 6,
          and the 10 B-spline coefficients 10, 12, 13, 15, 22, 26, 24, 18,
          14, 12.

          The input data items (using the notation of Section 5) comprise
          the following values in the order indicated:

              

              n           m

              LAMDA(j),   for j= 1,2,...,NCAP7

              C(j),       for j= 1,2,...,NCAP7-4

              x(i),       for i=1,2,...,m

          The example program is written in a general form that will enable
          the values and derivatives of a cubic spline having an arbitrary
          number of knots to be evaluated at a set of arbitrary points. Any
          number of data sets may be supplied. The only changes required to
          the program relate to the dimensions of the arrays LAMDA and C.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe02bdf}{nage.ht}
{ Definite integral of cubic spline from B-spline}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe02bdf}{NAG Documentation: e02bdf}
\beginscroll
\begin{verbatim}



     E02BDF(3NAG)      Foundation Library (12/10/92)      E02BDF(3NAG)



          E02 -- Curve and Surface Fitting                           E02BDF
                  E02BDF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E02BDF computes the definite integral of a cubic spline from its
          B-spline representation.

          2. Specification

                 SUBROUTINE E02BDF (NCAP7, LAMDA, C, DEFINT, IFAIL)
                 INTEGER          NCAP7, IFAIL
                 DOUBLE PRECISION LAMDA(NCAP7), C(NCAP7), DEFINT

          3. Description

          This routine computes the definite integral of the cubic spline
          s(x) between the limits x=a and x=b, where a and b are
          respectively the lower and upper limits of the range over which
          s(x) is defined. It is assumed that s(x) is represented in terms
                                                         

          of its B-spline coefficients c , for i=1,2,...,n+3 and
                                        i
                                                                

          (augmented) ordered knot set (lambda) , for i=1,2,...,n+7, with
                                               i
          (lambda) =a, for i = 1,2,3,4 and (lambda) =b, for
                  i                                i
                        

          i=n+4,n+5,n+6,n+7, (see E02BAF), i.e.,

                                        q
                                        --
                                  s(x)= >  c N (x).
                                        --  i i
                                        i=1

                      

          Here q=n+3, n is the number of intervals of the spline and N (x)
                                                                      i
          denotes the normalised B-spline of degree 3 (order 4) defined
          upon the knots (lambda) ,(lambda)   ,...,(lambda)   .
                                 i         i+1             i+4

          The method employed uses the formula given in Section 3 of Cox
          [1].

          E02BDF can be used to determine the definite integrals of cubic
          spline fits and interpolants produced by E02BAF.

          4. References

          [1]   Cox M G (1975) An Algorithm for Spline Interpolation. J.
                Inst. Math. Appl. 15 95--108.

          5. Parameters

           1:  NCAP7 -- INTEGER                                       Input
                                    

               On entry: n+7, where n is the number of intervals of the
               spline (which is one greater than the number of interior
               knots, i.e., the knots strictly within the range a to b)
               over which the spline is defined. Constraint: NCAP7 >= 8.

           2:  LAMDA(NCAP7) -- DOUBLE PRECISION array                 Input
               On entry: LAMDA(j) must be set to the value of the jth
               member of the complete set of knots, (lambda)  for
                                                            j
                         

               j=1,2,...,n+7. Constraint: the LAMDA(j) must be in non-
               decreasing order with LAMDA(NCAP7-3) > LAMDA(4) and satisfy
                           LAMDA(1)=LAMDA(2)=LAMDA(3)=LAMDA(4)
               and

               LAMDA(NCAP7-3)=LAMDA(NCAP7-2)=LAMDA(NCAP7-1)=LAMDA(NCAP7).

           3:  C(NCAP7) -- DOUBLE PRECISION array                     Input
               On entry: the coefficient c  of the B-spline N (x), for
                                          i                  i
                         

               i=1,2,...,n+3. The remaining elements of the array are not
               used.

           4:  DEFINT -- DOUBLE PRECISION                            Output
               On exit: the value of the definite integral of s(x) between
               the limits x=a and x=b, where a=(lambda)  and b=(lambda)   .
                                                       4               n+4

           5:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               NCAP7 < 8, i.e., the number of intervals is not positive.

          IFAIL= 2
               At least one of the following restrictions on the knots is
               violated:
                    LAMDA(NCAP7-3) > LAMDA(4),

                    LAMDA(j) >= LAMDA(j-1),
               for j = 2,3,...,NCAP7, with equality in the cases
               j=2,3,4,NCAP7-2,NCAP7-1, and NCAP7.

          7. Accuracy

          The rounding errors are such that the computed value of the
          integral is exact for a slightly perturbed set of B-spline
          coefficients c  differing in a relative sense from those supplied
                        i      
          by no more than 2.2*(n+3)*machine precision.

          8. Further Comments

          The time taken by the routine is approximately proportional to
          

          n+7.

          9. Example

          Determine the definite integral over the interval 0<=x<=6 of a
          cubic spline having 6 interior knots at the positions (lambda)=1,
          3, 3, 3, 4, 4, the 8 additional knots 0, 0, 0, 0, 6, 6, 6, 6, and
          the 10 B-spline coefficients 10, 12, 13, 15, 22, 26, 24, 18, 14,
          12.

          The input data items (using the notation of Section 5) comprise
          the following values in the order indicated:

              

              n

              LAMDA(j) for j = 1,2,...,NCAP7
              ,

              C(j),    for j = 1,2,...,NCAP7-3

          The example program is written in a general form that will enable
          the definite integral of a cubic spline having an arbitrary
          number of knots to be computed. Any number of data sets may be
          supplied. The only changes required to the program relate to the
          dimensions of the arrays LAMDA and C.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe02bef}{nage.ht}
{ Cubic spline approximation to an arbitrary set points}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe02bef}{NAG Documentation: e02bef}
\beginscroll
\begin{verbatim}



     E02BEF(3NAG)      Foundation Library (12/10/92)      E02BEF(3NAG)



          E02 -- Curve and Surface Fitting                           E02BEF
                  E02BEF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E02BEF computes a cubic spline approximation to an arbitrary set
          of data points. The knots of the spline are located
          automatically, but a single parameter must be specified to
          control the trade-off between closeness of fit and smoothness of
          fit.

          2. Specification

                 SUBROUTINE E02BEF (START, M, X, Y, W, S, NEST, N, LAMDA,
                1                   C, FP, WRK, LWRK, IWRK, IFAIL)
                 INTEGER          M, NEST, N, LWRK, IWRK(NEST), IFAIL
                 DOUBLE PRECISION X(M), Y(M), W(M), S, LAMDA(NEST), C(NEST),
                1                 FP, WRK(LWRK)
                 CHARACTER*1      START

          3. Description

          This routine determines a smooth cubic spline approximation s(x)
          to the set of data points (x ,y ), with weights w , for
                                      r  r                 r
          r=1,2,...,m.

          The spline is given in the B-spline representation

                                      n-4
                                      --
                                s(x)= >  c N (x)                        (1)
                                      --  i i
                                      i=1

          where N (x) denotes the normalised cubic B-spline defined upon
                 i
          the knots (lambda) ,(lambda)   ,...,(lambda)   .
                            i         i+1             i+4

          The total number n of these knots and their values
          (lambda) ,...,(lambda)  are chosen automatically by the routine.
                  1             n
          The knots (lambda) ,...,(lambda)    are the interior knots; they
                            5             n-4
          divide the approximation interval [x ,x ] into n-7 sub-intervals.
                                              1  m
          The coefficients c ,c ,...,c    are then determined as the
                            1  2      n-4
          solution of the following constrained minimization problem:

          minimize

                                      n-4
                                      --        2
                               (eta)= >  (delta)                        (2)
                                      --        i
                                      i=5

          subject to the constraint

                                    m
                                    --          2
                           (theta)= >  (epsilon) <=S                    (3)
                                    --          r
                                    r=1

          where: (delta)    stands for the discontinuity jump in the third
                        i   order derivative of s(x) at the interior knot
                      (lambda) ,
                                    i

                 (epsilon)  denotes the weighted residual w (y -s(x )),
                          r                                r  r    r

          and    S          is a non-negative number to be specified by
                            the user.

          The quantity (eta) can be seen as a measure of the (lack of)
          smoothness of s(x), while closeness of fit is measured through
          (theta). By means of the parameter S, 'the smoothing factor', the
          user will then control the balance between these two (usually
          conflicting) properties. If S is too large, the spline will be
          too smooth and signal will be lost (underfit); if S is too small,
          the spline will pick up too much noise (overfit). In the extreme
          cases the routine will return an interpolating spline ((theta)=0)
          if S is set to zero, and the weighted least-squares cubic
          polynomial ((eta)=0) if S is set very large. Experimenting with S
          values between these two extremes should result in a good
          compromise. (See Section 8.2 for advice on choice of S.)

          The method employed is outlined in Section 8.3 and fully
          described in Dierckx [1], [2] and [3]. It involves an adaptive
          strategy for locating the knots of the cubic spline (depending on
          the function underlying the data and on the value of S), and an
          iterative method for solving the constrained minimization problem
          once the knots have been determined.

          Values of the computed spline, or of its derivatives or definite
          integral, can subsequently be computed by calling E02BBF, E02BCF
          or E02BDF, as described in Section 8.4.

          4. References

          [1]   Dierckx P (1975) An Algorithm for Smoothing, Differentiating
                and Integration of Experimental Data Using Spline Functions.
                J. Comput. Appl. Math. 1 165--184.

          [2]   Dierckx P (1982) A Fast Algorithm for Smoothing Data on a
                Rectangular Grid while using Spline Functions. SIAM J.
                Numer. Anal. 19 1286--1304.

          [3]   Dierckx P (1981) An Improved Algorithm for Curve Fitting
                with Spline Functions. Report TW54. Department of Computer
                Science, Katholieke Universiteit Leuven.

          [4]   Reinsch C H (1967) Smoothing by Spline Functions. Num. Math.
                10 177--183.

          5. Parameters

           1:  START -- CHARACTER*1                                   Input
               On entry: START must be set to 'C' or 'W'.

               If START = 'C' (Cold start), the routine will build up the
               knot set starting with no interior knots. No values need be
               assigned to the parameters N, LAMDA, WRK or IWRK.

               If START = 'W' (Warm start), the routine will restart the
               knot-placing strategy using the knots found in a previous
               call of the routine. In this case, the parameters N, LAMDA,
               WRK, and IWRK must be unchanged from that previous call.
               This warm start can save much time in searching for a
               satisfactory value of S. Constraint: START = 'C' or 'W'.

           2:  M -- INTEGER                                           Input
               On entry: m, the number of data points. Constraint: M >= 4.

           3:  X(M) -- DOUBLE PRECISION array                         Input
               On entry: the values x  of the independent variable
                                     r
               (abscissa) x, for r=1,2,...,m. Constraint: x <x <...<x
                                                           1  2      m

           4:  Y(M) -- DOUBLE PRECISION array                         Input
               On entry: the values y  of the dependent variable
                                     r
               (ordinate) y, for r=1,2,...,m.

           5:  W(M) -- DOUBLE PRECISION array                         Input
               On entry: the values w  of the weights, for r=1,2,...,m.
                                     r
               For advice on the choice of weights, see the Chapter
               Introduction, Section 2.1.2. Constraint: W(r) > 0, for
               r=1,2,...,m.

           6:  S -- DOUBLE PRECISION                                  Input
               On entry: the smoothing factor, S.

               If S=0.0, the routine returns an interpolating spline.

               If S is smaller than machine precision, it is assumed equal
               to zero.

               For advice on the choice of S, see Section 3 and Section 8.2
               Constraint: S >= 0.0.

           7:  NEST -- INTEGER                                        Input
               On entry: an over-estimate for the number, n, of knots
               required. Constraint: NEST >= 8. In most practical
               situations, NEST = M/2 is sufficient. NEST never needs to be
               larger than M + 4, the number of knots needed for
               interpolation (S = 0.0).

           8:  N -- INTEGER                                    Input/Output
               On entry: if the warm start option is used, the value of N
               must be left unchanged from the previous call. On exit: the
               total number, n, of knots of the computed spline.

           9:  LAMDA(NEST) -- DOUBLE PRECISION array           Input/Output
               On entry: if the warm start option is used, the values
               LAMDA(1), LAMDA(2),...,LAMDA(N) must be left unchanged from
               the previous call. On exit: the knots of the spline i.e.,
               the positions of the interior knots LAMDA(5), LAMDA(6),...
               ,LAMDA(N-4) as well as the positions of the additional knots
               LAMDA(1) = LAMDA(2) = LAMDA(3) = LAMDA(4) = x  and
                                                            1

               LAMDA(N-3) = LAMDA(N-2) = LAMDA(N-1) = LAMDA(N) = x  needed
                                                                  m
               for the B-spline representation.

          10:  C(NEST) -- DOUBLE PRECISION array                     Output
               On exit: the coefficient c  of the B-spline N (x) in the
                                          i                  i
               spline approximation s(x), for i=1,2,...,n-4.

          11:  FP -- DOUBLE PRECISION                                Output
               On exit: the sum of the squared weighted residuals, (theta),
               of the computed spline approximation. If FP = 0.0, this is
               an interpolating spline. FP should equal S within a relative
               tolerance of 0.001 unless n=8 when the spline has no
               interior knots and so is simply a cubic polynomial. For
               knots to be inserted, S must be set to a value below the
               value of FP produced in this case.

          12:  WRK(LWRK) -- DOUBLE PRECISION array                Workspace
               On entry: if the warm start option is used, the values WRK
               (1),...,WRK(n) must be left unchanged from the previous
               call.

          13:  LWRK -- INTEGER                                        Input
               On entry:
               the dimension of the array WRK as declared in the
               (sub)program from which E02BEF is called.
               Constraint: LWRK>=4*M+16*NEST+41.

          14:  IWRK(NEST) -- INTEGER array                        Workspace
               On entry: if the warm start option is used, the values IWRK
               (1), ..., IWRK(n) must be left unchanged from the previous
               call.

               This array is used as workspace.

          15:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry START /= 'C' or 'W',

               or       M < 4,

               or       S < 0.0,

               or       S = 0.0 and NEST < M + 4,

               or       NEST < 8,

               or       LWRK<4*M+16*NEST+41.

          IFAIL= 2
               The weights are not all strictly positive.

          IFAIL= 3
               The values of X(r), for r=1,2,...,M, are not in strictly
               increasing order.

          IFAIL= 4
               The number of knots required is greater than NEST. Try
               increasing NEST and, if necessary, supplying larger arrays
               for the parameters LAMDA, C, WRK and IWRK. However, if NEST
               is already large, say NEST > M/2, then this error exit may
               indicate that S is too small.

          IFAIL= 5
               The iterative process used to compute the coefficients of
               the approximating spline has failed to converge. This error
               exit may occur if S has been set very small. If the error
               persists with increased S, consult NAG.

          If IFAIL = 4 or 5, a spline approximation is returned, but it
          fails to satisfy the fitting criterion (see (2) and (3) in
          Section 3) - perhaps by only a small amount, however.

          7. Accuracy

          On successful exit, the approximation returned is such that its
          weighted sum of squared residuals FP is equal to the smoothing
          factor S, up to a specified relative tolerance of 0.001 - except
          that if n=8, FP may be significantly less than S: in this case
          the computed spline is simply a weighted least-squares polynomial
          approximation of degree 3, i.e., a spline with no interior knots.

          8. Further Comments

          8.1. Timing

          The time taken for a call of E02BEF depends on the complexity of
          the shape of the data, the value of the smoothing factor S, and
          the number of data points. If E02BEF is to be called for
          different values of S, much time can be saved by setting START =

          8.2. Choice of S

          If the weights have been correctly chosen (see Section 2.1.2 of
          the Chapter Introduction), the standard deviation of w y  would
                                                                r r
          be the same for all r, equal to (sigma), say. In this case,
                                                              2      
          choosing the smoothing factor S in the range (sigma) (m+-\/2m),
          as suggested by Reinsch [4], is likely to give a good start in
          the search for a satisfactory value. Otherwise, experimenting
          with different values of S will be required from the start,
          taking account of the remarks in Section 3.

          In that case, in view of computation time and memory
          requirements, it is recommended to start with a very large value
          for S and so determine the least-squares cubic polynomial; the
          value returned for FP, call it FP , gives an upper bound for S.
                                           0
          Then progressively decrease the value of S to obtain closer fits
          - say by a factor of 10 in the beginning, i.e., S=FP /10, S=FP
                                                              0         0
          /100, and so on, and more carefully as the approximation shows
          more details.

          The number of knots of the spline returned, and their location,
          generally depend on the value of S and on the behaviour of the
          function underlying the data. However, if E02BEF is called with
          START = 'W', the knots returned may also depend on the smoothing
          factors of the previous calls. Therefore if, after a number of
          trials with different values of S and START = 'W', a fit can
          finally be accepted as satisfactory, it may be worthwhile to call
          E02BEF once more with the selected value for S but now using
          START = 'C'. Often, E02BEF then returns an approximation with the
          same quality of fit but with fewer knots, which is therefore
          better if data reduction is also important.

          8.3. Outline of Method Used

          If S=0, the requisite number of knots is known in advance, i.e.,
          n=m+4; the interior knots are located immediately as (lambda)  =
                                                                       i
          x   , for i=5,6,...,n-4. The corresponding least-squares spline
           i-2
          (see E02BAF) is then an interpolating spline and therefore a
          solution of the problem.

          If S>0, a suitable knot set is built up in stages (starting with
          no interior knots in the case of a cold start but with the knot
          set found in a previous call if a warm start is chosen). At each
          stage, a spline is fitted to the data by least-squares (see
          E02BAF) and (theta), the weighted sum of squares of residuals, is
          computed. If (theta)>S, new knots are added to the knot set to
          reduce (theta) at the next stage. The new knots are located in
          intervals where the fit is particularly poor, their number
          depending on the value of S and on the progress made so far in
          reducing (theta). Sooner or later, we find that (theta)<=S and at
          that point the knot set is accepted. The routine then goes on to
          compute the (unique) spline which has this knot set and which
          satisfies the full fitting criterion specified by (2) and (3).
          The theoretical solution has (theta)=S. The routine computes the
          spline by an iterative scheme which is ended when (theta)=S
          within a relative tolerance of 0.001. The main part of each
          iteration consists of a linear least-squares computation of
          special form, done in a similarly stable and efficient manner as
          in E02BAF.

          An exception occurs when the routine finds at the start that,
          even with no interior knots (n=8), the least-squares spline
          already has its weighted sum of squares of residuals <=S. In this
          case, since this spline (which is simply a cubic polynomial) also
          has an optimal value for the smoothness measure (eta), namely
          zero, it is returned at once as the (trivial) solution. It will
          usually mean that S has been chosen too large.

          For further details of the algorithm and its use, see Dierckx [3]

          8.4. Evaluation of Computed Spline

          The value of the computed spline at a given value X may be
          obtained in the double precision variable S by the call:


                 CALL E02BBF(N,LAMDA,C,X,S,IFAIL)

          where N, LAMDA and C are the output parameters of E02BEF.

          The values of the spline and its first three derivatives at a
          given value X may be obtained in the double precision array SDIF
          of dimension at least 4 by the call:

                 CALL E02BCF(N,LAMDA,C,X,LEFT,SDIF,IFAIL)

          where if LEFT = 1, left-hand derivatives are computed and if LEFT
          /= 1, right-hand derivatives are calculated. The value of LEFT is
          only relevant if X is an interior knot.

          The value of the definite integral of the spline over the
          interval X(1) to X(M) can be obtained in the double precision
          variable SINT by the call:

                 CALL E02BDF(N,LAMDA,C,SINT,IFAIL)

          9. Example

          This example program reads in a set of data values, followed by a
          set of values of S. For each value of S it calls E02BEF to
          compute a spline approximation, and prints the values of the
          knots and the B-spline coefficients c .
                                               i

          The program includes code to evaluate the computed splines, by
          calls to E02BBF, at the points x  and at points mid-way between
                                          r
          them. These values are not printed out, however; instead the
          results are illustrated by plots of the computed splines,
          together with the data points (indicated by *) and the positions
          of the knots (indicated by vertical lines): the effect of
          decreasing S can be clearly seen. (The plots were obtained by
          calling NAG Graphical Supplement routine J06FAF(*).)


                   Please see figures in printed Reference Manual

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe02daf}{nage.ht}
{ Minimal, weighted least-squares bicubic spline fit}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe02daf}{NAG Documentation: e02daf}
\beginscroll
\begin{verbatim}



     E02DAF(3NAG)      Foundation Library (12/10/92)      E02DAF(3NAG)



          E02 -- Curve and Surface Fitting                           E02DAF
                  E02DAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E02DAF forms a minimal, weighted least-squares bicubic spline
          surface fit with prescribed knots to a given set of data points.

          2. Specification

                 SUBROUTINE E02DAF (M, PX, PY, X, Y, F, W, LAMDA, MU,
                1                   POINT, NPOINT, DL, C, NC, WS, NWS, EPS,
                2                   SIGMA, RANK, IFAIL)
                 INTEGER          M, PX, PY, POINT(NPOINT), NPOINT, NC, NWS,
                1                 RANK, IFAIL
                 DOUBLE PRECISION X(M), Y(M), F(M), W(M), LAMDA(PX), MU(PY),
                1                 DL(NC), C(NC), WS(NWS), EPS, SIGMA

          3. Description

          This routine determines a bicubic spline fit s(x,y) to the set of
          data points (x ,y ,f ) with weights w , for r=1,2,...,m. The two
                        r  r  r                r
          sets of internal knots of the spline, {(lambda)} and {(mu)},
          associated with the variables x and y respectively, are
          prescribed by the user. These knots can be thought of as dividing
          the data region of the (x,y) plane into panels (see diagram in
          Section 5). A bicubic spline consists of a separate bicubic
          polynomial in each panel, the polynomials joining together with
          continuity up to the second derivative across the panel
          boundaries.

          s(x,y) has the property that (Sigma), the sum of squares of its
          weighted residuals (rho) , for r=1,2,...,m, where
                                  r

                            (rho) =w (s(x ,y )-f ),                     (1)
                                 r  r    r  r   r

          is as small as possible for a bicubic spline with the given knot
          sets. The routine produces this minimized value of (Sigma) and
          the coefficients c   in the B-spline representation of s(x,y) -
                            ij
          see Section 8. E02DEF and E02DFF are available to compute values
          of the fitted spline from the coefficients c  .
                                                      ij

          The least-squares criterion is not always sufficient to determine
          the bicubic spline uniquely: there may be a whole family of
          splines which have the same minimum sum of squares. In these
          cases, the routine selects from this family the spline for which
          the sum of squares of the coefficients c   is smallest: in other
                                                  ij
          words, the minimal least-squares solution. This choice, although
          arbitrary, reduces the risk of unwanted fluctuations in the
          spline fit. The method employed involves forming a system of m
          linear equations in the coefficients c   and then computing its
                                                ij
          least-squares solution, which will be the minimal least-squares
          solution when appropriate. The basis of the method is described
          in Hayes and Halliday [4]. The matrix of the equation is formed
          using a recurrence relation for B-splines which is numerically
          stable (see Cox [1] and de Boor [2] - the former contains the
          more elementary derivation but, unlike [2], does not cover the
          case of coincident knots). The least-squares solution is also
          obtained in a stable manner by using orthogonal transformations,
          viz. a variant of Givens rotation (see Gentleman [3]). This
          requires only one row of the matrix to be stored at a time.
          Advantage is taken of the stepped-band structure which the matrix
          possesses when the data points are suitably ordered, there being
          at most sixteen non-zero elements in any row because of the
          definition of B-splines. First the matrix is reduced to upper
          triangular form and then the diagonal elements of this triangle
          are examined in turn. When an element is encountered whose
          square, divided by the mean squared weight, is less than a
          threshold (epsilon), it is replaced by zero and the rest of the
          elements in its row are reduced to zero by rotations with the
          remaining rows. The rank of the system is taken to be the number
          of non-zero diagonal elements in the final triangle, and the non-
          zero rows of this triangle are used to compute the minimal least-
          squares solution. If all the diagonal elements are non-zero, the
          rank is equal to the number of coefficients c   and the solution
                                                       ij
          obtained is the ordinary least-squares solution, which is unique
          in this case.

          4. References

          [1]   Cox M G (1972) The Numerical Evaluation of B-splines. J.
                Inst. Math. Appl. 10 134--149.

          [2]   De Boor C (1972) On Calculating with B-splines. J. Approx.
                Theory. 6 50--62.

          [3]   Gentleman W M (1973) Least-squares Computations by Givens
                Transformations without Square Roots. J. Inst. Math. Applic.
                12 329--336.

          [4]   Hayes J G and Halliday J (1974) The Least-squares Fitting of
                Cubic Spline Surfaces to General Data Sets. J. Inst. Math.
                Appl. 14 89--103.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: the number of data points, m. Constraint: M > 1.

           2:  PX -- INTEGER                                          Input

           3:  PY -- INTEGER                                          Input
               On entry: the total number of knots (lambda) and (mu)
               associated with the variables x and y, respectively.
               Constraint: PX >= 8 and PY >= 8.

               (They are such that PX-8 and PY-8 are the corresponding
               numbers of interior knots.) The running time and storage
               required by the routine are both minimized if the axes are
               labelled so that PY is the smaller of PX and PY.

           4:  X(M) -- DOUBLE PRECISION array                         Input

           5:  Y(M) -- DOUBLE PRECISION array                         Input

           6:  F(M) -- DOUBLE PRECISION array                         Input
               On entry: the co-ordinates of the data point (x ,y ,f ), for
                                                              r  r  r
               r=1,2,...,m. The order of the data points is immaterial, but
               see the array POINT, below.

           7:  W(M) -- DOUBLE PRECISION array                         Input
               On entry: the weight w  of the rth data point. It is
                                     r
               important to note the definition of weight implied by the
               equation (1) in Section 3, since it is also common usage to
               define weight as the square of this weight. In this routine,
               each w  should be chosen inversely proportional to the
                     r
               (absolute) accuracy of the corresponding f , as expressed,
                                                         r
               for example, by the standard deviation or probable error of
               the f . When the f  are all of the same accuracy, all the w
                    r            r                                        r
               may be set equal to 1.0.

           8:  LAMDA(PX) -- DOUBLE PRECISION array             Input/Output
               On entry: LAMDA(i+4) must contain the ith interior knot
               (lambda)     associated with the variable x, for
                       i+4
               i=1,2,...,PX-8. The knots must be in non-decreasing order
               and lie strictly within the range covered by the data values
               of x. A knot is a value of x at which the spline is allowed
               to be discontinuous in the third derivative with respect to
               x, though continuous up to the second derivative. This
               degree of continuity can be reduced, if the user requires,
               by the use of coincident knots, provided that no more than
               four knots are chosen to coincide at any point. Two, or
               three, coincident knots allow loss of continuity in,
               respectively, the second and first derivative with respect
               to x at the value of x at which they coincide. Four
               coincident knots split the spline surface into two
               independent parts. For choice of knots see Section 8. On
               exit: the interior knots LAMDA(5) to LAMDA(PX-4) are
               unchanged, and the segments LAMDA(1:4) and LAMDA(PX-3:PX)
               contain additional (exterior) knots introduced by the
               routine in order to define the full set of B-splines
               required. The four knots in the first segment are all set
               equal to the lowest data value of x and the other four
               additional knots are all set equal to the highest value:
               there is experimental evidence that coincident end-knots are
               best for numerical accuracy. The complete array must be left
               undisturbed if E02DEF or E02DFF is to be used subsequently.

           9:  MU(PY) -- DOUBLE PRECISION array                       Input
               On entry: MU(i+4) must contain the ith interior knot (mu)
                                                                        i+4
               associated with the variable y, i=1,2,...,PY-8. The same
               remarks apply to MU as to LAMDA above, with Y replacing X,
               and y replacing x.

          10:  POINT(NPOINT) -- INTEGER array                         Input
               On entry: indexing information usually provided by E02ZAF
               which enables the data points to be accessed in the order
               which produces the advantageous matrix structure mentioned
               in Section 3. This order is such that, if the (x,y) plane is
               thought of as being divided into rectangular panels by the
               two sets of knots, all data in a panel occur before data in
               succeeding panels, where the panels are numbered from bottom
               to top and then left to right with the usual arrangement of
               axes, as indicated in the diagram.

                      Please see figure in printed Reference Manual

               A data point lying exactly on one or more panel sides is
               considered to be in the highest numbered panel adjacent to
               the point. E02ZAF should be called to obtain the array
               POINT, unless it is provided by other means.

          11:  NPOINT -- INTEGER                                      Input
               On entry:
               the dimension of the array POINT as declared in the
               (sub)program from which E02DAF is called.
               Constraint: NPOINT >= M + (PX-7)*(PY-7).

          12:  DL(NC) -- DOUBLE PRECISION array                      Output
               On exit: DL gives the squares of the diagonal elements of
               the reduced triangular matrix, divided by the mean squared
               weight. It includes those elements, less than (epsilon),
               which are treated as zero (see Section 3).

          13:  C(NC) -- DOUBLE PRECISION array                       Output
               On exit: C gives the coefficients of the fit. C((PY-4)*(i-
               1)+j) is the coefficient c   of Section 3 and Section 8 for
                                         ij
               i=1,2,...,PX-4 and j=1,2,...,PY-4. These coefficients are
               used by E02DEF or E02DFF to calculate values of the fitted
               function.

          14:  NC -- INTEGER                                          Input
               On entry: the value (PX-4)*(PY-4).

          15:  WS(NWS) -- DOUBLE PRECISION array                  Workspace

          16:  NWS -- INTEGER                                         Input
               On entry:
               the dimension of the array WS as declared in the
               (sub)program from which E02DAF is called.
               Constraint: NWS>=(2*NC+1)*(3*PY-6)-2.

          17:  EPS -- DOUBLE PRECISION                                Input
               On entry: a threshold (epsilon) for determining the
               effective rank of the system of linear equations. The rank
               is determined as the number of elements of the array DL (see
               below) which are non-zero. An element of DL is regarded as
               zero if it is less than (epsilon). Machine precision is a
               suitable value for (epsilon) in most practical applications
               which have only 2 or 3 decimals accurate in data. If some
               coefficients of the fit prove to be very large compared with
               the data ordinates, this suggests that (epsilon) should be
               increased so as to decrease the rank. The array DL will give
               a guide to appropriate values of (epsilon) to achieve this,
               as well as to the choice of (epsilon) in other cases where
               some experimentation may be needed to determine a value
               which leads to a satisfactory fit.

          18:  SIGMA -- DOUBLE PRECISION                             Output
               On exit: (Sigma), the weighted sum of squares of residuals.
               This is not computed from the individual residuals but from
               the right-hand sides of the orthogonally-transformed linear
               equations. For further details see Hayes and Halliday [4]
               page 97. The two methods of computation are theoretically
               equivalent, but the results may differ because of rounding
               error.

          19:  RANK -- INTEGER                                       Output
               On exit: the rank of the system as determined by the value
               of the threshold (epsilon). When RANK = NC, the least-
               squares solution is unique: in other cases the minimal
               least-squares solution is computed.

          20:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               At least one set of knots is not in non-decreasing order, or
               an interior knot is outside the range of the data values.

          IFAIL= 2
               More than four knots coincide at a single point, possibly
               because all data points have the same value of x (or y) or
               because an interior knot coincides with an extreme data
               value.

          IFAIL= 3
               Array POINT does not indicate the data points in panel
               order. Call E02ZAF to obtain a correct array.

          IFAIL= 4
               On entry M <= 1,

               or       PX < 8,

               or       PY < 8,

               or       NC /= (PX-4)*(PY-4),

               or       NWS is too small,

               or       NPOINT is too small.

          IFAIL= 5
               All the weights w  are zero or rank determined as zero.
                                r

          7. Accuracy

          The computation of the B-splines and reduction of the observation
          matrix to triangular form are both numerically stable.

          8. Further Comments

          The time taken by this routine is approximately proportional to
                                                           2
          the number of data points, m, and to (3*(PY-4)+4) .

          The B-spline representation of the bicubic spline is

                                       --
                               s(x,y)= > c  M (x)N (y)
                                       -- ij i    j
                                       ij

          summed over i=1,2,...,PX-4 and over j=1,2,...,PY-4. Here M (x)
                                                                    i
          and N (y) denote normalised cubic B-splines,the former defined on
               j
          the knots (lambda) ,(lambda)   ,...,(lambda)    and the latter on
                            i         i+1             i+4
          the knots (mu) ,(mu)   ,...,(mu)   . For further details, see
                        j     j+1         j+4
          Hayes and Halliday [4] for bicubic splines and de Boor [2] for
          normalised B-splines.

          The choice of the interior knots, which help to determine the
          spline's shape, must largely be a matter of trial and error. It
          is usually best to start with a small number of knots and,
          examining the fit at each stage, add a few knots at a time at
          places where the fit is particularly poor. In intervals of x or y
          where the surface represented by the data changes rapidly, in
          function value or derivatives, more knots will be needed than
          elsewhere. In some cases guidance can be obtained by analogy with
          the case of coincident knots: for example, just as three
          coincident knots can produce a discontinuity in slope, three
          close knots can produce rapid change in slope. Of course, such
          rapid changes in behaviour must be adequately represented by the
          data points, as indeed must the behaviour of the surface
          generally, if a satisfactory fit is to be achieved. When there is
          no rapid change in behaviour, equally-spaced knots will often
          suffice.

          In all cases the fit should be examined graphically before it is
          accepted as satisfactory.

          The fit obtained is not defined outside the rectangle

                  (lambda) <=x<=(lambda)    ,   (mu) <=y<=(mu)
                          4             PX-3        4         PY-3

          The reason for taking the extreme data values of x and y for
          these four knots is that, as is usual in data fitting, the fit
          cannot be expected to give satisfactory values outside the data
          region. If, nevertheless, the user requires values over a larger
          rectangle, this can be achieved by augmenting the data with two
          artificial data points (a,c,0) and (b,d,0) with zero weight,
          where a<=x<=b, c<=y<=d defines the enlarged rectangle. In the
          case when the data are adequate to make the least-squares
          solution unique (RANK = NC), this enlargement will not affect the
          fit over the original rectangle, except for possibly enlarged
          rounding errors, and will simply continue the bicubic polynomials
          in the panels bordering the rectangle out to the new boundaries:
          in other cases the fit will be affected. Even using the original
          rectangle there may be regions within it, particularly at its
          corners, which lie outside the data region and where, therefore,
          the fit will be unreliable. For example, if there is no data
          point in panel 1 of the diagram in Section 5, the least-squares
          criterion leaves the spline indeterminate in this panel: the
          minimal spline determined by the subroutine in this case passes
          through the value zero at the point ((lambda) ,(mu) ).
                                                       4     4

          9. Example

          This example program reads a value for (epsilon), and a set of
          data points, weights and knot positions. If there are more y
          knots than x knots, it interchanges the x and y axes. It calls
          E02ZAF to sort the data points into panel order, E02DAF to fit a
          bicubic spline to them, and E02DEF to evaluate the spline at the
          data points.

          Finally it prints:

               the weighted sum of squares of residuals computed from the
               linear equations;

               the rank determined by E02DAF;

               data points, fitted values and residuals in panel order;

               the weighted sum of squares of the residuals;

               the coefficients of the spline fit.

          The program is written to handle any number of data sets.

          Note: the data supplied in this example is not typical of a
          realistic problem: the number of data points would normally be
          much larger (in which case the array dimensions and the value of
          NWS in the program would have to be increased); and the value of
          (epsilon) would normally be much smaller on most machines (see
                                                     -6
          Section 5; the relatively large value of 10   has been chosen in
          order to illustrate a minimal least-squares solution when RANK <
          NC; in this example NC = 24).

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe02dcf}{nage.ht}
{ Bicubic spline approximation to a set of data values}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe02dcf}{NAG Documentation: e02dcf}
\beginscroll
\begin{verbatim}



     E02DCF(3NAG)      Foundation Library (12/10/92)      E02DCF(3NAG)



          E02 -- Curve and Surface Fitting                           E02DCF
                  E02DCF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E02DCF computes a bicubic spline approximation to a set of data
          values, given on a rectangular grid in the x-y plane. The knots
          of the spline are located automatically, but a single parameter
          must be specified to control the trade-off between closeness of
          fit and smoothness of fit.

          2. Specification

                 SUBROUTINE E02DCF (START, MX, X, MY, Y, F, S, NXEST,
                1                   NYEST, NX, LAMDA, NY, MU, C, FP, WRK,
                2                   LWRK, IWRK, LIWRK, IFAIL)
                 INTEGER          MX, MY, NXEST, NYEST, NX, NY, LWRK, IWRK
                1                 (LIWRK), LIWRK, IFAIL
                 DOUBLE PRECISION X(MX), Y(MY), F(MX*MY), S, LAMDA(NXEST),
                1                 MU(NYEST), C((NXEST-4)*(NYEST-4)), FP, WRK
                2                 (LWRK)
                 CHARACTER*1      START

          3. Description

          This routine determines a smooth bicubic spline approximation
          s(x,y) to the set of data points (x ,y ,f   ), for q=1,2,...,m
                                             q  r  q,r                  x
          and r=1,2,...,m .
                         y

          The spline is given in the B-spline representation

                                n -4 n -4
                                 x    y
                                --   --
                        s(x,y)= >    >   c  M (x)N (y),                 (1)
                                --   --   ij i    j
                                i=1  j=1

          where M (x) and N (y) denote normalised cubic B-splines, the
                 i         j
          former defined on the knots (lambda)  to (lambda)    and the
                                              i            i+4
          latter on the knots (mu)  to (mu)   . For further details, see
                                  j        j+4
          Hayes and Halliday [4] for bicubic splines and de Boor [1] for
          normalised B-splines.

          The total numbers n  and n  of these knots and their values
                             x      y
          (lambda) ,...,(lambda)   and (mu) ,...,(mu)   are chosen
                  1             n          1         n
                                 x                    y
          automatically by the routine. The knots (lambda) ,...,
                                                          5
          (lambda)     and (mu) ,...,(mu)     are the interior knots; they
                  n -4         5         n -4
                   x                      y
          divide the approximation domain [x ,x  ]*[y ,y  ] into (
                                            1  m     1  m
                                               m        m
          n -7)*(n -7) subpanels [(lambda) ,(lambda)   ]*[(mu) ,(mu)   ],
           x      y                       i         i+1       j     j+1
          for i=4,5,...,n -4, j=4,5,...,n -4. Then, much as in the curve
                         x               y
          case (see E02BEF), the coefficients c   are determined as the
                                               ij
          solution of the following constrained minimization problem:

          minimize

                                     (eta),                             (2)

          subject to the constraint

                                 m   m
                                  x   y
                                 --  --          2
                        (theta)= >   >  (epsilon)   <=S,                (3)
                                 --  --          q,r
                                 q=1 r=1

          where  (eta) is a measure of the (lack of) smoothness of s(x,y).
                       Its value depends on the discontinuity jumps in
                       s(x,y) across the boundaries of the subpanels. It is
                       zero only when there are no discontinuities and is
                       positive otherwise, increasing with the size of the
                       jumps (see Dierckx [2] for details).

                 (epsilon)    denotes the residual f   -s(x ,y ),
                          q,r                       q,r    q  r

          and    S    is a non-negative number to be specified by the user.

          By means of the parameter S, 'the smoothing factor', the user
          will then control the balance between smoothness and closeness of
          fit, as measured by the sum of squares of residuals in (3). If S
          is too large, the spline will be too smooth and signal will be
          lost (underfit); if S is too small, the spline will pick up too
          much noise (overfit). In the extreme cases the routine will
          return an interpolating spline ((theta)=0) if S is set to zero,
          and the least-squares bicubic polynomial ((eta)=0) if S is set
          very large. Experimenting with S-values between these two
          extremes should result in a good compromise. (See Section 8.3 for
          advice on choice of S.)

          The method employed is outlined in Section 8.5 and fully
          described in Dierckx [2] and [3]. It involves an adaptive
          strategy for locating the knots of the bicubic spline (depending
          on the function underlying the data and on the value of S), and
          an iterative method for solving the constrained minimization
          problem once the knots have been determined.

          Values of the computed spline can subsequently be computed by
          calling E02DEF or E02DFF as described in Section 8.6.

          4. References

          [1]   De Boor C (1972) On Calculating with B-splines. J. Approx.
                Theory. 6 50--62.

          [2]   Dierckx P (1982) A Fast Algorithm for Smoothing Data on a
                Rectangular Grid while using Spline Functions. SIAM J.
                Numer. Anal. 19 1286--1304.

          [3]   Dierckx P (1981) An Improved Algorithm for Curve Fitting
                with Spline Functions. Report TW54. Department of Computer
                Science, Katholieke Universiteit Leuven.

          [4]   Hayes J G and Halliday J (1974) The Least-squares Fitting of
                Cubic Spline Surfaces to General Data Sets. J. Inst. Math.
                Appl. 14 89--103.

          [5]   Reinsch C H (1967) Smoothing by Spline Functions. Num. Math.
                10 177--183.

          5. Parameters

           1:  START -- CHARACTER*1                                   Input
               On entry: START must be set to 'C' or 'W'.

               If START = 'C' (Cold start), the routine will build up the
               knot set starting with no interior knots. No values need be
               assigned to the parameters NX, NY, LAMDA, MU, WRK or IWRK.

               If START = 'W' (Warm start), the routine will restart the
               knot-placing strategy using the knots found in a previous
               call of the routine. In this case, the parameters NX, NY,
               LAMDA, MU, WRK and IWRK must be unchanged from that previous
               call. This warm start can save much time in searching for a
               satisfactory value of S. Constraint: START = 'C' or 'W'.

           2:  MX -- INTEGER                                          Input
               On entry: m , the number of grid points along the x axis.
                          x
               Constraint: MX >= 4.

           3:  X(MX) -- DOUBLE PRECISION array                        Input
               On entry: X(q) must be set to x , the x co-ordinate of the
                                              q
               qth grid point along the x axis, for q=1,2,...,m .
                                                               x
               Constraint: x <x <...<x  .
                            1  2      m
                                       x

           4:  MY -- INTEGER                                          Input
               On entry: m , the number of grid points along the y axis.
                          y
               Constraint: MY >= 4.

           5:  Y(MY) -- DOUBLE PRECISION array                        Input
               On entry: Y(r) must be set to y , the y co-ordinate of the
                                              r
               rth grid point along the y axis, for r=1,2,...,m .
                                                               y
               Constraint: y <y <...<y  .
                            1  2      m
                                       y

           6:  F(MX*MY) -- DOUBLE PRECISION array                     Input
               On entry: F(m *(q-1)+r) must contain the data value f   ,
                            y                                       q,r
               for q=1,2,...,m  and r=1,2,...,m .
                              x                y

           7:  S -- DOUBLE PRECISION                                  Input
               On entry: the smoothing factor, S.

               If S=0.0, the routine returns an interpolating spline.

               If S is smaller than machine precision, it is assumed equal
               to zero.

               For advice on the choice of S, see Section 3 and Section 8.3
               Constraint: S >= 0.0.

           8:  NXEST -- INTEGER                                       Input

           9:  NYEST -- INTEGER                                       Input
               On entry: an upper bound for the number of knots n  and n
                                                                  x      y
               required in the x- and y-directions respectively.

               In most practical situations, NXEST =m /2 and NYEST m /2 is
                                                     x              y
               sufficient. NXEST and NYEST never need to be larger than
               m +4 and m +4 respectively, the numbers of knots needed for
                x        y
               interpolation (S=0.0). See also Section 8.4. Constraint:
               NXEST >= 8 and NYEST >= 8.

          10:  NX -- INTEGER                                   Input/Output
               On entry: if the warm start option is used, the value of NX
               must be left unchanged from the previous call. On exit: the
               total number of knots, n , of the computed spline with
                                       x
               respect to the x variable.

          11:  LAMDA(NXEST) -- DOUBLE PRECISION array          Input/Output
               On entry: if the warm start option is used, the values
               LAMDA(1), LAMDA(2),...,LAMDA(NX) must be left unchanged from
               the previous call. On exit: LAMDA contains the complete set
               of knots (lambda)  associated with the x variable, i.e., the
                                i
               interior knots LAMDA(5), LAMDA(6), ..., LAMDA(NX-4) as well
               as the additional knots LAMDA(1) = LAMDA(2) = LAMDA(3) =
               LAMDA(4) = X(1) and LAMDA(NX-3) = LAMDA(NX-2) = LAMDA(NX-1)
               = LAMDA(NX) = X(MX) needed for the B-spline representation.

          12:  NY -- INTEGER                                   Input/Output
               On entry: if the warm start option is used, the value of NY
               must be left unchanged from the previous call. On exit: the
               total number of knots, n , of the computed spline with
                                       y
               respect to the y variable.

          13:  MU(NYEST) -- DOUBLE PRECISION array             Input/Output
               On entry: if the warm start option is used, the values MU
               (1), MU(2),...,MU(NY) must be left unchanged from the
               previous call. On exit: MU contains the complete set of
               knots (mu)  associated with the y variable, i.e., the
                         i
               interior knots MU(5), MU(6),...,MU(NY-4) as well as the
               additional knots MU(1) = MU(2) = MU(3) = MU(4) = Y(1) and MU
               (NY-3) = MU(NY-2) = MU(NY-1) = MU(NY) = Y(MY) needed for the
               B-spline representation.

          14:  C((NXEST-4)*(NYEST-4)) -- DOUBLE PRECISION array      Output
               On exit: the coefficients of the spline approximation. C(
               (n -4)*(i-1)+j) is the coefficient c   defined in Section 3.
                 y                                 ij

          15:  FP -- DOUBLE PRECISION                                Output
               On exit: the sum of squared residuals, (theta), of the
               computed spline approximation. If FP = 0.0, this is an
               interpolating spline. FP should equal S within a relative
               tolerance of 0.001 unless NX = NY = 8, when the spline has
               no interior knots and so is simply a bicubic polynomial. For
               knots to be inserted, S must be set to a value below the
               value of FP produced in this case.

          16:  WRK(LWRK) -- DOUBLE PRECISION array                Workspace
               On entry: if the warm start option is used, the values WRK
               (1),...,WRK(4) must be left unchanged from the previous
               call.

               This array is used as workspace.

          17:  LWRK -- INTEGER                                        Input
               On entry:
               the dimension of the array WRK as declared in the
               (sub)program from which E02DCF is called.
               Constraint:
                    LWRK>=4*(MX+MY)+11*(NXEST+NYEST)+NXEST*MY

                          +max(MY,NXEST)+54.

          18:  IWRK(LIWRK) -- INTEGER array                       Workspace
               On entry: if the warm start option is used, the values IWRK
               (1), ..., IWRK(3) must be left unchanged from the previous
               call.

               This array is used as workspace.

          19:  LIWRK -- INTEGER                                       Input
               On entry:
               the dimension of the array IWRK as declared in the
               (sub)program from which E02DCF is called.
               Constraint: LIWRK >= 3 + MX + MY + NXEST + NYEST.

          20:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry START /= 'C' or 'W',

               or       MX < 4,

               or       MY < 4,

               or       S < 0.0,

               or       S = 0.0 and NXEST < MX + 4,

               or       S = 0.0 and NYEST < MY + 4,

               or       NXEST < 8,

               or       NYEST < 8,

               or       LWRK < 4*(MX+MY)+11*(NXEST+NYEST)+NXEST*MY+
                               +max(MY,NXEST)+54

               or       LIWRK < 3 + MX + MY + NXEST + NYEST.

          IFAIL= 2
               The values of X(q), for q = 1,2,...,MX, are not in strictly
               increasing order.

          IFAIL= 3
               The values of Y(r), for r = 1,2,...,MY, are not in strictly
               increasing order.

          IFAIL= 4
               The number of knots required is greater than allowed by
               NXEST and NYEST. Try increasing NXEST and/or NYEST and, if
               necessary, supplying larger arrays for the parameters LAMDA,
               MU, C, WRK and IWRK. However, if NXEST and NYEST are already
               large, say NXEST > MX/2 and NYEST > MY/2, then this error
               exit may indicate that S is too small.

          IFAIL= 5
               The iterative process used to compute the coefficients of
               the approximating spline has failed to converge. This error
               exit may occur if S has been set very small. If the error
               persists with increased S, consult NAG.

          If IFAIL = 4 or 5, a spline approximation is returned, but it
          fails to satisfy the fitting criterion (see (2) and (3) in
          Section 3) -- perhaps by only a small amount, however.

          7. Accuracy

          On successful exit, the approximation returned is such that its
          sum of squared residuals FP is equal to the smoothing factor S,
          up to a specified relative tolerance of 0.001 - except that if
          n =8 and n =8, FP may be significantly less than S: in this case
           x        y
          the computed spline is simply the least-squares bicubic
          polynomial approximation of degree 3, i.e., a spline with no
          interior knots.

          8. Further Comments

          8.1. Timing

          The time taken for a call of E02DCF depends on the complexity of
          the shape of the data, the value of the smoothing factor S, and
          the number of data points. If E02DCF is to be called for
          different values of S, much time can be saved by setting START =

          8.2. Weighting of Data Points

          E02DCF does not allow individual weighting of the data values. If
          these were determined to widely differing accuracies, it may be
          better to use E02DDF. The computation time would be very much
          longer, however.

          8.3. Choice of S

          If the standard deviation of f    is the same for all q and r
                                        q,r
          (the case for which this routine is designed - see Section 8.2.)
          and known to be equal, at least approximately, to (sigma), say,
          then following Reinsch [5] and choosing the smoothing factor S in
                           2      
          the range (sigma) (m+-\/2m), where m=m m , is likely to give a
                                                x y
          good start in the search for a satisfactory value. If the
          standard deviations vary, the sum of their squares over all the
          data points could be used. Otherwise experimenting with different
          values of S will be required from the start, taking account of
          the remarks in Section 3.

          In that case, in view of computation time and memory
          requirements, it is recommended to start with a very large value
          for S and so determine the least-squares bicubic polynomial; the
          value returned for FP, call it FP , gives an upper bound for S.
                                           0
          Then progressively decrease the value of S to obtain closer fits
          - say by a factor of 10 in the beginning, i.e., S=FP /10,
                                                              0
          S=FP /100, and so on, and more carefully as the approximation
              0
          shows more details.

          The number of knots of the spline returned, and their location,
          generally depend on the value of S and on the behaviour of the
          function underlying the data. However, if E02DCF is called with
          START = 'W', the knots returned may also depend on the smoothing
          factors of the previous calls. Therefore if, after a number of
          trials with different values of S and START = 'W', a fit can
          finally be accepted as satisfactory, it may be worthwhile to call
          E02DCF once more with the selected value for S but now using
          START = 'C'. Often, E02DCF then returns an approximation with the
          same quality of fit but with fewer knots, which is therefore
          better if data reduction is also important.

          8.4. Choice of NXEST and NYEST

          The number of knots may also depend on the upper bounds NXEST and
          NYEST. Indeed, if at a certain stage in E02DCF the number of
          knots in one direction (say n ) has reached the value of its
                                       x
          upper bound (NXEST), then from that moment on all subsequent
          knots are added in the other (y) direction. Therefore the user
          has the option of limiting the number of knots the routine
          locates in any direction. For example, by setting NXEST = 8 (the
          lowest allowable value for NXEST), the user can indicate that he
          wants an approximation which is a simple cubic polynomial in the
          variable x.

          8.5. Outline of Method Used

          If S=0, the requisite number of knots is known in advance, i.e.,
          n =m +4 and n =m +4; the interior knots are located immediately
           x  x        y  y
          as (lambda)  = x    and (mu)  = y   , for i=5,6,...,n -4 and
                     i    i-2         j    j-2                 x
          j=5,6,...,n -4. The corresponding least-squares spline is then an
                     y
          interpolating spline and therefore a solution of the problem.

          If S>0, suitable knot sets are built up in stages (starting with
          no interior knots in the case of a cold start but with the knot
          set found in a previous call if a warm start is chosen). At each
          stage, a bicubic spline is fitted to the data by least-squares,
          and (theta), the sum of squares of residuals, is computed. If
          (theta)>S, new knots are added to one knot set or the other so as
          to reduce (theta) at the next stage. The new knots are located in
          intervals where the fit is particularly poor, their number
          depending on the value of S and on the progress made so far in
          reducing (theta). Sooner or later, we find that (theta)<=S and at
          that point the knot sets are accepted. The routine then goes on
          to compute the (unique) spline which has these knot sets and
          which satisfies the full fitting criterion specified by (2) and
          (3). The theoretical solution has (theta)=S. The routine computes
          the spline by an iterative scheme which is ended when (theta)=S
          within a relative tolerance of 0.001. The main part of each
          iteration consists of a linear least-squares computation of
          special form, done in a similarly stable and efficient manner as
          in E02BAF for least-squares curve fitting.

          An exception occurs when the routine finds at the start that,
          even with no interior knots (n =n =8), the least-squares spline
                                        x  y
          already has its sum of residuals <=S. In this case, since this
          spline (which is simply a bicubic polynomial) also has an optimal
          value for the smoothness measure (eta), namely zero, it is
          returned at once as the (trivial) solution. It will usually mean
          that S has been chosen too large.

          For further details of the algorithm and its use see Dierckx [2].

          8.6. Evaluation of Computed Spline

          The values of the computed spline at the points (TX(r),TY(r)),
          for r = 1,2,...,N, may be obtained in the double precision array
          FF, of length at least N, by the following code:

                 IFAIL = 0
                 CALL E02DEF(N,NX,NY,TX,TY,LAMDA,MU,C,FF,WRK,IWRK,IFAIL)

          where NX, NY, LAMDA, MU and C are the output parameters of E02DCF
          , WRK is a double precision workspace array of length at least
          NY-4, and IWRK is an integer workspace array of length at least
          NY-4.

          To evaluate the computed spline on a KX by KY rectangular grid of
          points in the x-y plane, which is defined by the x co-ordinates
          stored in TX(q), for q=1,2,...,KX, and the y co-ordinates stored
          in TY(r), for r=1,2,...,KY, returning the results in the double
          precision array FG which is of length at least KX*KY, the
          following call may be used:

                IFAIL = 0
                CALL E02DFF(KX,KY,NX,NY,TX,TY,LAMDA,MU,C,FG,WRK,LWRK,
               *            IWRK,LIWRK,IFAIL)

          where NX, NY, LAMDA, MU and C are the output parameters of E02DCF
          , WRK is a double precision workspace array of length at least
          LWRK = min(NWRK1,NWRK2), NWRK1 = KX*4+NX, NWRK2 = KY*4+NY, and
          IWRK is an integer workspace array of length at least LIWRK = KY
          + NY - 4 if NWRK1 >= NWRK2, or KX + NX - 4 otherwise. The result
          of the spline evaluated at grid point (q,r) is returned in
          element (KY*(q-1)+r) of the array FG.

          9. Example

          This example program reads in values of MX, MY, x , for q = 1,2,.
                                                           q
                      r
          ordinates f    defined at the grid points (x ,y ). It then calls
                     q,r                              q  r
          E02DCF to compute a bicubic spline approximation for one
          specified value of S, and prints the values of the computed knots
          and B-spline coefficients. Finally it evaluates the spline at a
          small sample of points on a rectangular grid.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe02ddf}{nage.ht}
{ Bicubic spline approximation to a set of scattered data}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe02ddf}{NAG Documentation: e02ddf}
\beginscroll
\begin{verbatim}



     E02DDF(3NAG)      Foundation Library (12/10/92)      E02DDF(3NAG)



          E02 -- Curve and Surface Fitting                           E02DDF
                  E02DDF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E02DDF computes a bicubic spline approximation to a set of
          scattered data. The knots of the spline are located
          automatically, but a single parameter must be specified to
          control the trade-off between closeness of fit and smoothness of
          fit.

          2. Specification

                 SUBROUTINE E02DDF (START, M, X, Y, F, W, S, NXEST, NYEST,
                1                   NX, LAMDA, NY, MU, C, FP, RANK, WRK,
                2                   LWRK, IWRK, LIWRK, IFAIL)
                 INTEGER          M, NXEST, NYEST, NX, NY, RANK, LWRK, IWRK
                1                 (LIWRK), LIWRK, IFAIL
                 DOUBLE PRECISION X(M), Y(M), F(M), W(M), S, LAMDA(NXEST),
                1                 MU(NYEST), C((NXEST-4)*(NYEST-4)), FP, WRK
                2                 (LWRK)
                 CHARACTER*1      START

          3. Description

          This routine determines a smooth bicubic spline approximation
          s(x,y) to the set of data points (x ,y ,f ) with weights w , for
                                             r  r  r                r
          r=1,2,...,m.

          The approximation domain is considered to be the rectangle
          [x   ,x   ]*[y   ,y   ], where x    (y   ) and x    (y   ) denote
            min  max    min  max          min   min       max   max
          the lowest and highest data values of x (y).

          The spline is given in the B-spline representation

                                n -4 n -4
                                 x    y
                                --   --
                        s(x,y)= >    >   c  M (x)N (y),                 (1)
                                --   --   ij i    j
                                i=1  j=1

          where M (x) and N (y) denote normalised cubic B-splines, the
                 i         j
          former defined on the knots (lambda)  to (lambda)    and the
                                              i            i+4
          latter on the knots (mu)  to (mu)   . For further details, see
                                  j        j+4
          Hayes and Halliday [4] for bicubic splines and de Boor [1] for
          normalised B-splines.

          The total numbers n  and n  of these knots and their values
                             x      y
          (lambda) ,...,(lambda)   and (mu) ,...,(mu)   are chosen
                  1             n          1         n
                                 x                    y
          automatically by the routine. The knots (lambda) ,...,
                                                          5
          (lambda)     and (mu) ,..., (mu)     are the interior knots; they
                  n -4         5          n -4
                   x                       y
          divide the approximation domain [x   ,x   ]*[y   ,y   ] into (
                                            min  max    min  max
          n -7)*(n -7) subpanels [(lambda) ,(lambda)   ]*[(mu) ,(mu)   ],
           x      y                       i         i+1       j     j+1
          for i=4,5,...,n -4; j=4,5,...,n -4. Then, much as in the curve
                         x               y
          case (see E02BEF), the coefficients c   are determined as the
                                               ij
          solution of the following constrained minimization problem:

          minimize

                                     (eta),                             (2)

          subject to the constraint

                                    m
                                    --          2
                           (theta)= >  (epsilon) <=S                    (3)
                                    --          r
                                    r=1

          where: (eta) is a measure of the (lack of) smoothness of s(x,y).
                       Its value depends on the discontinuity jumps in
                       s(x,y) across the boundaries of the subpanels. It is
                       zero only when there are no discontinuities and is
                       positive otherwise, increasing with the size of the
                       jumps (see Dierckx [2] for details).

                 (epsilon)  denotes the weighted residual w (f -s(x ,y )),
                          r                                r  r    r  r

          and    S     is a non-negative number to be specified by the user.

          By means of the parameter S, 'the smoothing factor', the user
          will then control the balance between smoothness and closeness of
          fit, as measured by the sum of squares of residuals in (3). If S
          is too large, the spline will be too smooth and signal will be
          lost (underfit); if S is too small, the spline will pick up too
          much noise (overfit). In the extreme cases the method would
          return an interpolating spline ((theta)=0) if S were set to zero,
          and returns the least-squares bicubic polynomial ((eta)=0) if S
          is set very large. Experimenting with S-values between these two
          extremes should result in a good compromise. (See Section 8.2 for
          advice on choice of S.) Note however, that this routine, unlike
          E02BEF and E02DCF, does not allow S to be set exactly to zero: to
          compute an interpolant to scattered data, E01SAF or E01SEF should
          be used.

          The method employed is outlined in Section 8.5 and fully
          described in Dierckx [2] and [3]. It involves an adaptive
          strategy for locating the knots of the bicubic spline (depending
          on the function underlying the data and on the value of S), and
          an iterative method for solving the constrained minimization
          problem once the knots have been determined.

          Values of the computed spline can subsequently be computed by
          calling E02DEF or E02DFF as described in Section 8.6.

          4. References

          [1]   De Boor C (1972) On Calculating with B-splines. J. Approx.
                Theory. 6 50--62.

          [2]   Dierckx P (1981) An Algorithm for Surface Fitting with
                Spline Functions. IMA J. Num. Anal. 1 267--283.

          [3]   Dierckx P (1981) An Improved Algorithm for Curve Fitting
                with Spline Functions. Report TW54. Department of Computer
                Science, Katholieke Universiteit Leuven.

          [4]   Hayes J G and Halliday J (1974) The Least-squares Fitting of
                Cubic Spline Surfaces to General Data Sets. J. Inst. Math.
                Appl. 14 89--103.

          [5]   Peters G and Wilkinson J H (1970) The Least-squares Problem
                and Pseudo-inverses. Comput. J. 13 309--316.

          [6]   Reinsch C H (1967) Smoothing by Spline Functions. Num. Math.
                10 177--183.

          5. Parameters

           1:  START -- CHARACTER*1                                   Input
               On entry: START must be set to 'C' or 'W'.

               If START = 'C' (Cold start), the routine will build up the
               knot set starting with no interior knots. No values need be
               assigned to the parameters NX, NY, LAMDA, MU or WRK.

               If START = 'W' (Warm start), the routine will restart the
               knot-placing strategy using the knots found in a previous
               call of the routine. In this case, the parameters NX, NY,
               LAMDA, MU and WRK must be unchanged from that previous call.
               This warm start can save much time in searching for a
               satisfactory value of S. Constraint: START = 'C' or 'W'.

           2:  M -- INTEGER                                           Input
               On entry: m, the number of data points.

               The number of data points with non-zero weight (see W below)
               must be at least 16.

           3:  X(M) -- DOUBLE PRECISION array                         Input

           4:  Y(M) -- DOUBLE PRECISION array                         Input

           5:  F(M) -- DOUBLE PRECISION array                         Input
               On entry: X(r), Y(r), F(r) must be set to the co-ordinates
               of (x ,y ,f ), the rth data point, for r=1,2,...,m. The
                    r  r  r
               order of the data points is immaterial.

           6:  W(M) -- DOUBLE PRECISION array                         Input
               On entry: W(r) must be set to w , the rth value in the set
                                              r
               of weights, for r=1,2,...,m. Zero weights are permitted and
               the corresponding points are ignored, except when
               determining x   , x   , y    and y    (see Section 8.4). For
                            min   max   min      max
               advice on the choice of weights, see Section 2.1.2 of the
               Chapter Introduction. Constraint: the number of data points
               with non-zero weight must be at least 16.

           7:  S -- DOUBLE PRECISION                                  Input
               On entry: the smoothing factor, S.

               For advice on the choice of S, see Section 3 and Section 8.2
               . Constraint: S > 0.0.

           8:  NXEST -- INTEGER                                       Input


           9:  NYEST -- INTEGER                                       Input
               On entry: an upper bound for the number of knots n  and n
                                                                 x      y
               required in the x- and y-directions respectively.
                                                                 ___
               In most practical situations, NXEST = NYEST = 4+\/m/2 is
               sufficient. See also Section 8.3. Constraint: NXEST >= 8 and
               NYEST >= 8.

          10:  NX -- INTEGER                                   Input/Output
               On entry: if the warm start option is used, the value of NX
               must be left unchanged from the previous call. On exit: the
               total number of knots, n , of the computed spline with
                                       x
               respect to the x variable.

          11:  LAMDA(NXEST) -- DOUBLE PRECISION array          Input/Output
               On entry: if the warm start option is used, the values LAMDA
               (1), LAMDA(2),...,LAMDA(NX) must be left unchanged from the
               previous call. On exit: LAMDA contains the complete set of
               knots (lambda)  associated with the x variable, i.e., the
                             i
               interior knots LAMDA(5), LAMDA(6),...,LAMDA(NX-4) as well as
               the additional knots LAMDA(1) = LAMDA(2) = LAMDA(3) = LAMDA
               (4) = x    and LAMDA(NX-3) = LAMDA(NX-2) = LAMDA(NX-1) =
                      min
               LAMDA(NX) = x    needed for the B-spline representation
                            max
               (where x    and x    are as described in Section 3).
                       min      max

          12:  NY -- INTEGER                                   Input/Output
               On entry: if the warm start option is used, the value of NY
               must be left unchanged from the previous call. On exit: the
               total number of knots, n , of the computed spline with
                                       y
               respect to the y variable.

          13:  MU(NYEST) -- DOUBLE PRECISION array             Input/Output
               On entry: if the warm start option is used, the values MU(1)
               MU(2),...,MU(NY) must be left unchanged from the previous
               call. On exit: MU contains the complete set of knots (mu)
                                                                        i
               associated with the y variable, i.e., the interior knots MU
               (5), MU(6),...,MU(NY-4) as well as the additional knots MU
               (1) = MU(2) = MU(3) = MU(4) = y    and MU(NY-3) = MU(NY-2) =
                                              min
               MU(NY-1) = MU(NY) = y    needed for the B-spline
                                    max
               representation (where y    and y    are as described in
                                      min      max
               Section 3).

          14:  C((NXEST-4)*(NYEST-4)) -- DOUBLE PRECISION array      Output
               On exit: the coefficients of the spline approximation. C(
               (n -4)*(i-1)+j) is the coefficient c   defined in Section 3.
                 y                                 ij

          15:  FP -- DOUBLE PRECISION                                Output
               On exit: the weighted sum of squared residuals, (theta), of
               the computed spline approximation. FP should equal S within
               a relative tolerance of 0.001 unless NX = NY = 8, when the
               spline has no interior knots and so is simply a bicubic
               polynomial. For knots to be inserted, S must be set to a
               value below the value of FP produced in this case.

          16:  RANK -- INTEGER                                       Output
               On exit: RANK gives the rank of the system of equations used
               to compute the final spline (as determined by a suitable
               machine-dependent threshold). When RANK = (NX-4)*(NY-4), the
               solution is unique; otherwise the system is rank-deficient
               and the minimum-norm solution is computed. The latter case
               may be caused by too small a value of S.

          17:  WRK(LWRK) -- DOUBLE PRECISION array                Workspace
               On entry: if the warm start option is used, the value of WRK
               (1) must be left unchanged from the previous call.

               This array is used as workspace.

          18:  LWRK -- INTEGER                                        Input
               On entry:
               the dimension of the array WRK as declared in the
               (sub)program from which E02DDF is called.
               Constraint: LWRK >= (7*u*v+25*w)*(w+1)+2*(u+v+4*M)+23*w+56,

               where

               u=NXEST-4, v=NYEST-4, and w=max(u,v).

               For some problems, the routine may need to compute the
               minimal least-squares solution of a rank-deficient system of
               linear equations (see Section 3). The amount of workspace
               required to solve such problems will be larger than
               specified by the value given above, which must be increased
               by an amount, LWRK2 say. An upper bound for LWRK2 is given
               by 4*u*v*w+2*u*v+4*w, where u, v and w are as above.
               However, if there are enough data points, scattered
               uniformly over the approximation domain, and if the
               smoothing factor S is not too small, there is a good chance
               that this extra workspace is not needed. A lot of memory
               might therefore be saved by assuming LWRK2 = 0.

          19:  IWRK(LIWRK) -- INTEGER array                       Workspace


          20:  LIWRK -- INTEGER                                       Input
               On entry:
               the dimension of the array IWRK as declared in the
               (sub)program from which E02DDF is called.
               Constraint: LIWRK>=M+2*(NXEST-7)*(NYEST-7).

          21:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry START /= 'C' or 'W',

               or       the number of data points with non-zero weight <
                        16,

               or       S <= 0.0,

               or       NXEST < 8,

               or       NYEST < 8,

               or       LWRK < (7*u*v+25*w)*(w+1)+2*(u+v+4*M)+23*w+56,
                        where u = NXEST - 4, v = NYEST - 4 and w=max(u,v),

               or       LIWRK <M+2*(NXEST-7)*(NYEST-7).

          IFAIL= 2
               On entry either all the X(r), for r = 1,2,...,M, are equal,
               or all the Y(r), for r = 1,2,...,M, are equal.

          IFAIL= 3
               The number of knots required is greater than allowed by
               NXEST and NYEST. Try increasing NXEST and/or NYEST and, if
               necessary, supplying larger arrays for the parameters LAMDA,
               MU, C, WRK and IWRK. However, if NXEST and NYEST are already
                                               

               large, say NXEST, NYEST > 4 + \/M/2, then this error exit
               may indicate that S is too small.

          IFAIL= 4
               No more knots can be added because the number of B-spline
               coefficients (NX-4)*(NY-4) already exceeds the number of
               data points M. This error exit may occur if either of S or M
               is too small.

          IFAIL= 5
               No more knots can be added because the additional knot would
               (quasi) coincide with an old one. This error exit may occur
               if too large a weight has been given to an inaccurate data
               point, or if S is too small.

          IFAIL= 6
               The iterative process used to compute the coefficients of
               the approximating spline has failed to converge. This error
               exit may occur if S has been set very small. If the error
               persists with increased S, consult NAG.

          IFAIL= 7
               LWRK is too small; the routine needs to compute the minimal
               least-squares solution of a rank-deficient system of linear
               equations, but there is not enough workspace. There is no
               approximation returned but, having saved the information
               contained in NX, LAMDA, NY, MU and WRK, and having adjusted
               the value of LWRK and the dimension of array WRK
               accordingly, the user can continue at the point the program
               was left by calling E02DDF with START = 'W'. Note that the
               requested value for LWRK is only large enough for the
               current phase of the algorithm. If the routine is restarted
               with LWRK set to the minimum value requested, a larger
               request may be made at a later stage of the computation. See
               Section 5 for the upper bound on LWRK. On soft failure, the
               minimum requested value for LWRK is returned in IWRK(1) and
               the safe value for LWRK is returned in IWRK(2).

          If IFAIL = 3,4,5 or 6, a spline approximation is returned, but it
          fails to satisfy the fitting criterion (see (2) and (3) in
          Section 3 -- perhaps only by a small amount, however.

          7. Accuracy

          On successful exit, the approximation returned is such that its
          weighted sum of squared residuals FP is equal to the smoothing
          factor S, up to a specified relative tolerance of 0.001 - except
          that if n =8 and n =8, FP may be significantly less than S: in
                   x        y
          this case the computed spline is simply the least-squares bicubic
          polynomial approximation of degree 3, i.e., a spline with no
          interior knots.

          8. Further Comments

          8.1. Timing

          The time taken for a call of E02DDF depends on the complexity of
          the shape of the data, the value of the smoothing factor S, and
          the number of data points. If E02DDF is to be called for
          different values of S, much time can be saved by setting START =
          It should be noted that choosing S very small considerably
          increases computation time.

          8.2. Choice of S

          If the weights have been correctly chosen (see Section 2.1.2 of
          the Chapter Introduction), the standard deviation of w f  would
                                                                r r
          be the same for all r, equal to (sigma), say. In this case,
                                                              2      
          choosing the smoothing factor S in the range (sigma) (m+-\/2m),
          as suggested by Reinsch [6], is likely to give a good start in
          the search for a satisfactory value. Otherwise, experimenting
          with different values of S will be required from the start.

          In that case, in view of computation time and memory
          requirements, it is recommended to start with a very large value
          for S and so determine the least-squares bicubic polynomial; the
          value returned for FP, call it FP , gives an upper bound for S.
                                           0
          Then progressively decrease the value of S to obtain closer fits
          - say by a factor of 10 in the beginning, i.e., S=FP /10,
                                                              0
          S=FP /100, and so on, and more carefully as the approximation
              0
          shows more details.

          To choose S very small is strongly discouraged. This considerably
          increases computation time and memory requirements. It may also
          cause rank-deficiency (as indicated by the parameter RANK) and
          endanger numerical stability.

          The number of knots of the spline returned, and their location,
          generally depend on the value of S and on the behaviour of the
          function underlying the data. However, if E02DDF is called with
          START = 'W', the knots returned may also depend on the smoothing
          factors of the previous calls. Therefore if, after a number of
          trials with different values of S and START = 'W', a fit can
          finally be accepted as satisfactory, it may be worthwhile to call
          E02DDF once more with the selected value for S but now using
          START = 'C'. Often, E02DDF then returns an approximation with the
          same quality of fit but with fewer knots, which is therefore
          better if data reduction is also important.

          8.3. Choice of NXEST and NYEST

          The number of knots may also depend on the upper bounds NXEST and
          NYEST. Indeed, if at a certain stage in E02DDF the number of
          knots in one direction (say n ) has reached the value of its
                                       x
          upper bound (NXEST), then from that moment on all subsequent
          knots are added in the other (y) direction. This may indicate
          that the value of NXEST is too small. On the other hand, it gives
          the user the option of limiting the number of knots the routine
          locates in any direction. For example, by setting NXEST = 8 (the
          lowest allowable value for NXEST), the user can indicate that he
          wants an approximation which is a simple cubic polynomial in the
          variable x.

          8.4. Restriction of the approximation domain

          The fit obtained is not defined outside the rectangle
          [(lambda) ,(lambda)    ]*[(mu) ,(mu)    ]. The reason for taking
                   4         n -3       4     n -3
                              x                y
          the extreme data values of x and y for these four knots is that,
          as is usual in data fitting, the fit cannot be expected to give
          satisfactory values outside the data region. If, nevertheless,
          the user requires values over a larger rectangle, this can be
          achieved by augmenting the data with two artificial data points
          (a,c,0) and (b,d,0) with zero weight, where [a,b]*[c,d] denotes
          the enlarged rectangle.

          8.5. Outline of method used

          First suitable knot sets are built up in stages (starting with no
          interior knots in the case of a cold start but with the knot set
          found in a previous call if a warm start is chosen). At each
          stage, a bicubic spline is fitted to the data by least-squares
          and (theta), the sum of squares of residuals, is computed. If
          (theta)>S, a new knot is added to one knot set or the other so as
          to reduce (theta) at the next stage. The new knot is located in
          an interval where the fit is particularly poor. Sooner or later,
          we find that (theta)<=S and at that point the knot sets are
          accepted. The routine then goes on to compute a spline which has
          these knot sets and which satisfies the full fitting criterion
          specified by (2) and (3). The theoretical solution has (theta)=S.
          The routine computes the spline by an iterative scheme which is
          ended when (theta)=S within a relative tolerance of 0.001. The
          main part of each iteration consists of a linear least-squares
          computation of special form, done in a similarly stable and
          efficient manner as in E02DAF. As there also, the minimal least-
          squares solution is computed wherever the linear system is found
          to be rank-deficient.

          An exception occurs when the routine finds at the start that,
          even with no interior knots (N = 8), the least-squares spline
          already has its sum of squares of residuals <=S. In this case,
          since this spline (which is simply a bicubic polynomial) also has
          an optimal value for the smoothness measure (eta), namely zero,
          it is returned at once as the (trivial) solution. It will usually
          mean that S has been chosen too large.

          For further details of the algorithm and its use see Dierckx [2].

          8.6. Evaluation of computed spline

          The values of the computed spline at the points (TX(r),TY(r)),
          for r = 1,2,...,N, may be obtained in the double precision array
          FF, of length at least N, by the following code:


                IFAIL = 0
                CALL E02DEF(N,NX,NY,TX,TY,LAMDA,MU,C,FF,WRK,IWRK,IFAIL)


          where NX, NY, LAMDA, MU and C are the output parameters of E02DDF
          , WRK is a double precision workspace array of length at least
          NY-4, and IWRK is an integer workspace array of length at least
          NY-4.

          To evaluate the computed spline on a KX by KY rectangular grid of
          points in the x-y plane, which is defined by the x co-ordinates
          stored in TX(q), for q=1,2,...,KX, and the y co-ordinates stored
          in TY(r), for r=1,2,...,KY, returning the results in the double
          precision array FG which is of length at least KX*KY, the
          following call may be used:


                IFAIL = 0
                CALL E02DFF(KX,KY,NX,NY,TX,TY,LAMDA,MU,C,FG,WRK,LWRK,
               *            IWRK,LIWRK,IFAIL)


          where NX, NY, LAMDA, MU and C are the output parameters of E02DDF
          , WRK is a double precision workspace array of length at least
          LWRK = min(NWRK1,NWRK2), NWRK1 = KX*4+NX, NWRK2 = KY*4+NY, and
          IWRK is an integer workspace array of length at least LIWRK = KY
          + NY - 4 if NWRK1 >= NWRK2, or KX + NX - 4 otherwise. The result
          of the spline evaluated at grid point (q,r) is returned in
          element (KY*(q-1)+r) of the array FG.

          9. Example

          This example program reads in a value of M, followed by a set of
          M data points (x ,y ,f ) and their weights w . It then calls
                          r  r  r                     r
          E02DDF to compute a bicubic spline approximation for one
          specified value of S, and prints the values of the computed knots
          and B-spline coefficients. Finally it evaluates the spline at a
          small sample of points on a rectangular grid.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe02def}{nage.ht}
{ Calculates values of a bicubic spline from B-spline}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe02def}{NAG Documentation: e02def}
\beginscroll
\begin{verbatim}



     E02DEF(3NAG)      Foundation Library (12/10/92)      E02DEF(3NAG)



          E02 -- Curve and Surface Fitting                           E02DEF
                  E02DEF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E02DEF calculates values of a bicubic spline from its B-spline
          representation.

          2. Specification

                 SUBROUTINE E02DEF (M, PX, PY, X, Y, LAMDA, MU, C, FF, WRK,
                1                   IWRK, IFAIL)
                 INTEGER          M, PX, PY, IWRK(PY-4), IFAIL
                 DOUBLE PRECISION X(M), Y(M), LAMDA(PX), MU(PY), C((PX-4)*
                1                 (PY-4)), FF(M), WRK(PY-4)

          3. Description

          This routine calculates values of the bicubic spline s(x,y) at
          prescribed points (x ,y ), for r=1,2,...,m, from its augmented
                              r  r
          knot sets {(lambda)} and {(mu)} and from the coefficients c  ,
                                                                     ij
          for i=1,2,...,PX-4; j=1,2,...,PY-4, in its B-spline
          representation

                                      --
                              s(x,y)= > c  M (x)N (y).
                                      -- ij i    j
                                      ij

          Here M (x) and N (y) denote normalised cubic B-splines, the
                i         j
          former defined on the knots (lambda)  to (lambda)    and the
                                              i            i+4
          latter on the knots (mu)  to (mu)   .
                                  j        j+4

          This routine may be used to calculate values of a bicubic spline
          given in the form produced by E01DAF, E02DAF, E02DCF and E02DDF.
          It is derived from the routine B2VRE in Anthony et al [1].

          4. References

          [1]   Anthony G T, Cox M G and Hayes J G (1982) DASL - Data
                Approximation Subroutine Library. National Physical
                Laboratory.

          [2]   Cox M G (1978) The Numerical Evaluation of a Spline from its
                B-spline Representation. J. Inst. Math. Appl. 21 135--143.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: m, the number of points at which values of the
               spline are required. Constraint: M >= 1.

           2:  PX -- INTEGER                                          Input

           3:  PY -- INTEGER                                          Input
               On entry: PX and PY must specify the total number of knots
               associated with the variables x and y respectively. They are
               such that PX-8 and PY-8 are the corresponding numbers of
               interior knots. Constraint: PX >= 8 and PY >= 8.

           4:  X(M) -- DOUBLE PRECISION array                         Input

           5:  Y(M) -- DOUBLE PRECISION array                         Input
               On entry: X and Y must contain x  and y , for r=1,2,...,m,
                                               r      r
               respectively. These are the co-ordinates of the points at
               which values of the spline are required. The order of the
               points is immaterial. Constraint: X and Y must satisfy

               LAMDA(4) <= X(r) <= LAMDA(PX-3)

               and

               MU(4) <= Y(r) <= MU(PY-3), for r=1,2,...,m.

               The spline representation is not valid outside these
               intervals.

           6:  LAMDA(PX) -- DOUBLE PRECISION array                    Input

           7:  MU(PY) -- DOUBLE PRECISION array                       Input
               On entry: LAMDA and MU must contain the complete sets of
               knots {(lambda)} and {(mu)} associated with the x and y
               variables respectively. Constraint: the knots in each set
               must be in non-decreasing order, with LAMDA(PX-3) > LAMDA(4)
               and MU(PY-3) > MU(4).

           8:  C((PX-4)*(PY-4)) -- DOUBLE PRECISION array             Input
               On entry: C((PY-4)*(i-1)+j) must contain the coefficient
               c   described in Section 3, for i=1,2,...,PX-4;
                ij
               j=1,2,...,PY-4.

           9:  FF(M) -- DOUBLE PRECISION array                       Output
               On exit: FF(r) contains the value of the spline at the
               point (x ,y ), for r=1,2,...,m.
                       r  r

          10:  WRK(PY-4) -- DOUBLE PRECISION array                Workspace

          11:  IWRK(PY-4) -- INTEGER array                        Workspace

          12:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry M < 1,

               or       PY < 8,

               or       PX < 8.

          IFAIL= 2
               On entry the knots in array LAMDA, or those in array MU, are
               not in non-decreasing order, or LAMDA(PX-3) <= LAMDA(4), or
               MU(PY-3) <= MU(4).

          IFAIL= 3
               On entry at least one of the prescribed points (x ,y ) lies
                                                                r  r
               outside the rectangle defined by LAMDA(4), LAMDA(PX-3) and
               MU(4), MU(PY-3).

          7. Accuracy

          The method used to evaluate the B-splines is numerically stable,
          in the sense that each computed value of s(x ,y ) can be regarded
                                                      r  r
          as the value that would have been obtained in exact arithmetic
          from slightly perturbed B-spline coefficients. See Cox [2] for
          details.

          8. Further Comments

          Computation time is approximately proportional to the number of
          points, m, at which the evaluation is required.

          9. Example

          This program reads in knot sets LAMDA(1),..., LAMDA(PX) and MU(1)
          ,..., MU(PY), and a set of bicubic spline coefficients c  .
                                                                  ij
          Following these are a value for m and the co-ordinates (x ,y ),
                                                                   r  r
          for r=1,2,...,m, at which the spline is to be evaluated.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe02dff}{nage.ht}
{ Calculates values of a bicubic spline from B-spline}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe02dff}{NAG Documentation: e02dff}
\beginscroll
\begin{verbatim}



     E02DFF(3NAG)      Foundation Library (12/10/92)      E02DFF(3NAG)



          E02 -- Curve and Surface Fitting                           E02DFF
                  E02DFF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E02DFF calculates values of a bicubic spline from its B-spline
          representation. The spline is evaluated at all points on a
          rectangular grid.

          2. Specification

                 SUBROUTINE E02DFF (MX, MY, PX, PY, X, Y, LAMDA, MU, C, FF,
                1                   WRK, LWRK, IWRK, LIWRK, IFAIL)
                 INTEGER          MX, MY, PX, PY, LWRK, IWRK(LIWRK), LIWRK,
                1                 IFAIL
                 DOUBLE PRECISION X(MX), Y(MY), LAMDA(PX), MU(PY), C((PX-4)*
                1                 (PY-4)), FF(MX*MY), WRK(LWRK)

          3. Description

          This routine calculates values of the bicubic spline s(x,y) on a
          rectangular grid of points in the x-y plane, from its augmented
          knot sets {(lambda)} and {(mu)} and from the coefficients c  ,
                                                                     ij
          for i=1,2,...,PX-4; j=1,2,...,PY-4, in its B-spline
          representation

                                      --
                              s(x,y)= > c  M (x)N (y).
                                      -- ij i    j
                                      ij

          Here M (x) and N (y) denote normalised cubic B-splines, the
                i         j
          former defined on the knots (lambda)  to (lambda)    and the
                                              i            i+4
          latter on the knots (mu)  to (mu)   .
                                  j        j+4

          The points in the grid are defined by co-ordinates x , for
                                                              q
          q=1,2,...,m , along the x axis, and co-ordinates y , for
                     x                                      r
          r=1,2,...,m  along the y axis.
                     y

          This routine may be used to calculate values of a bicubic spline
          given in the form produced by E01DAF, E02DAF, E02DCF and E02DDF.
          It is derived from the routine B2VRE in Anthony et al [1].

          4. References

          [1]   Anthony G T, Cox M G and Hayes J G (1982) DASL - Data
                Approximation Subroutine Library. National Physical
                Laboratory.

          [2]   Cox M G (1978) The Numerical Evaluation of a Spline from its
                B-spline Representation. J. Inst. Math. Appl. 21 135--143.

          5. Parameters

           1:  MX -- INTEGER                                          Input

           2:  MY -- INTEGER                                          Input
               On entry: MX and MY must specify m  and m  respectively,
                                                 x      y
               the number of points along the x and y axis that define the
               rectangular grid. Constraint: MX >= 1 and MY >= 1.

           3:  PX -- INTEGER                                          Input

           4:  PY -- INTEGER                                          Input
               On entry: PX and PY must specify the total number of knots
               associated with the variables x and y respectively. They are
               such that PX-8 and PY-8 are the corresponding numbers of
               interior knots. Constraint: PX >= 8 and PY >= 8.

           5:  X(MX) -- DOUBLE PRECISION array                        Input

           6:  Y(MY) -- DOUBLE PRECISION array                        Input
               On entry: X and Y must contain x , for q=1,2,...,m , and y ,
                                               q                 x       r
               for r=1,2,...,m , respectively. These are the x and y co-
                              y
               ordinates that define the rectangular grid of points at
               which values of the spline are required. Constraint: X and Y
               must satisfy

               LAMDA(4) <= X(q) < X(q+1) <= LAMDA(PX-3), for q=1,2,...,m -1
                                                                        x
               and

               MU(4) <= Y(r) < Y(r+1) <= MU(PY-3), for r=1,2,...,m -1.
                                                                  y

               The spline representation is not valid outside these
               intervals.

           7:  LAMDA(PX) -- DOUBLE PRECISION array                    Input

           8:  MU(PY) -- DOUBLE PRECISION array                       Input
               On entry: LAMDA and MU must contain the complete sets of
               knots {(lambda)} and {(mu)} associated with the x and y
               variables respectively. Constraint: the knots in each set
               must be in non-decreasing order, with LAMDA(PX-3) > LAMDA(4)
               and MU(PY-3) > MU(4).

           9:  C((PX-4)*(PY-4)) -- DOUBLE PRECISION array             Input
               On entry: C((PY-4)*(i-1)+j) must contain the coefficient
               c   described in Section 3, for i=1,2,...,PX-4;
                ij
               j=1,2,...,PY-4.

          10:  FF(MX*MY) -- DOUBLE PRECISION array                   Output
               On exit: FF(MY*(q-1)+r) contains the value of the spline at
               the point (x ,y ), for q=1,2,...,m ; r=1,2,...,m .
                           q  r                  x             y

          11:  WRK(LWRK) -- DOUBLE PRECISION array                Workspace

          12:  LWRK -- INTEGER                                        Input
               On entry:
               the dimension of the array WRK as declared in the
               (sub)program from which E02DFF is called.
               Constraint: LWRK >= min(NWRK1,NWRK2), where NWRK1=4*MX+PX,
               NWRK2=4*MY+PY.

          13:  IWRK(LIWRK) -- INTEGER array                       Workspace

          14:  LIWRK -- INTEGER                                       Input
               On entry:
               the dimension of the array IWRK as declared in the
               (sub)program from which E02DFF is called.
               Constraint: LIWRK >= MY + PY - 4 if NWRK1 > NWRK2, or MX +
               PX - 4 otherwise, where NWRK1 and NWRK2 are as defined in
               the description of argument LWRK.

          15:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry MX < 1,

               or       MY < 1,

               or       PY < 8,

               or       PX < 8.

          IFAIL= 2
               On entry LWRK is too small,

               or       LIWRK is too small.

          IFAIL= 3
               On entry the knots in array LAMDA, or those in array MU, are
               not in non-decreasing order, or LAMDA(PX-3) <= LAMDA(4), or
               MU(PY-3) <= MU(4).

          IFAIL= 4
               On entry the restriction LAMDA(4) <= X(1) <... < X(MX) <=
               LAMDA(PX-3), or the restriction MU(4) <= Y(1) <... < Y(MY)
               <= MU(PY-3), is violated.

          7. Accuracy

          The method used to evaluate the B-splines is numerically stable,
          in the sense that each computed value of s(x ,y ) can be regarded
                                                      r  r
          as the value that would have been obtained in exact arithmetic
          from slightly perturbed B-spline coefficients. See Cox [2] for
          details.

          8. Further Comments

          Computation time is approximately proportional to m m +4(m +m ).
                                                             x y    x  y

          9. Example

          This program reads in knot sets LAMDA(1),..., LAMDA(PX) and MU(1)
          ,..., MU(PY), and a set of bicubic spline coefficients c  .
                                                                  ij
          Following these are values for m  and the x co-ordinates x , for
                                          x                         q
          q=1,2,...,m , and values for m  and the y co-ordinates y , for
                     x                  y                         r
          r=1,2,...,m , defining the grid of points on which the spline is
                     y
          to be evaluated.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe02gaf}{nage.ht}
{ Calculates $l_1$ solution to over-determined system equations}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe02gaf}{NAG Documentation: e02gaf}
\beginscroll
\begin{verbatim}



     E02GAF(3NAG)      Foundation Library (12/10/92)      E02GAF(3NAG)



          E02 -- Curve and Surface Fitting                           E02GAF
                  E02GAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E02GAF calculates an l  solution to an over-determined system of
                                1
          linear equations.

          2. Specification

                 SUBROUTINE E02GAF (M, A, LA, B, NPLUS2, TOLER, X, RESID,
                1                   IRANK, ITER, IWORK, IFAIL)
                 INTEGER          M, LA, NPLUS2, IRANK, ITER, IWORK(M),
                1                 IFAIL
                 DOUBLE PRECISION A(LA,NPLUS2), B(M), TOLER, X(NPLUS2),
                1                 RESID

          3. Description

          Given a matrix A with m rows and n columns (m>=n) and a vector b
          with m elements, the routine calculates an l  solution to the
                                                      1
          over-determined system of equations

                                        Ax=b.

          That is to say, it calculates a vector x, with n elements, which
          minimizes the l -norm (the sum of the absolute values) of the
                         1
          residuals

                                         m
                                         --
                                   r(x)= >  |r |,
                                         --   i
                                         i=1

          where the residuals r  are given by
                               i

                                  n
                                  --
                           r =b - >  a  x ,   i=1,2,...,m.
                            i  i  --  ij j
                                  j=1

          Here a   is the element in row i and column j of A, b  is the ith
                ij                                             i
          element of b and x  the jth element of x. The matrix A need not
                            j
          be of full rank.

          Typically in applications to data fitting, data consisting of m
          points with co-ordinates (t ,y ) are to be approximated in the l
                                     i  i                                 1
          -norm by a linear combination of known functions (phi) (t),
                                                                j

             (alpha) (phi) (t)+(alpha) (phi) (t)+...+(alpha) (phi) (t).
                    1     1           2     2               n     n

          This is equivalent to fitting an l  solution to the over-
                                            1
          determined system of equations

                       n
                       --
                       >  (phi) (t )(alpha) =y ,   i=1,2,...,m.
                       --      j  i        j  i
                       j=1

          Thus if, for each value of i and j, the element a   of the matrix
                                                           ij
          A in the previous paragraph is set equal to the value of
          (phi) (t ) and b  is set equal to y , the solution vector x will
               j  i       i                  i
          contain the required values of the (alpha) . Note that the
                                                    j
          independent variable t above can, instead, be a vector of several
          independent variables (this includes the case where each (phi)
                                                                        i
          is a function of a different variable, or set of variables).

          The algorithm is a modification of the simplex method of linear
          programming applied to the primal formulation of the l  problem
                                                                1
          (see Barrodale and Roberts [1] and [2]). The modification allows
          several neighbouring simplex vertices to be passed through in a
          single iteration, providing a substantial improvement in
          efficiency.

          4. References

          [1]   Barrodale I and Roberts F D K (1973) An Improved Algorithm
                for Discrete \\ll  Linear Approximation. SIAM J. Numer.
                                 1
                Anal. 10 839--848.

          [2]   Barrodale I and Roberts F D K (1974) Solution of an
                Overdetermined System of Equations in the \\ll -norm. Comm.
                                                              1
                ACM. 17, 6 319--320.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: the number of equations, m (the number of rows of
               the matrix A). Constraint: M >= n >= 1.

           2:  A(LA,NPLUS2) -- DOUBLE PRECISION array          Input/Output
               On entry: A(i,j) must contain a  , the element in the ith
                                              ij
               row and jth column of the matrix A, for i=1,2,...,m and
               j=1,2,...,n. The remaining elements need not be set. On
               exit: A contains the last simplex tableau generated by the
               simplex method.

           3:  LA -- INTEGER                                          Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which E02GAF is called.
               Constraint: LA >= M + 2.

           4:  B(M) -- DOUBLE PRECISION array                  Input/Output
               On entry: b , the ith element of the vector b, for
                          i
               i=1,2,...,m. On exit: the ith residual r  corresponding to
                                                       i
               the solution vector x, for i=1,2,...,m.

           5:  NPLUS2 -- INTEGER                                      Input
               On entry: n+2, where n is the number of unknowns (the
               number of columns of the matrix A). Constraint: 3 <= NPLUS2
               <= M + 2.

           6:  TOLER -- DOUBLE PRECISION                              Input
               On entry: a non-negative value. In general TOLER specifies
               a threshold below which numbers are regarded as zero. The
                                                       2/3
               recommended threshold value is (epsilon)    where (epsilon)
               is the machine precision. The recommended value can be
               computed within the routine by setting TOLER to zero. If
               premature termination occurs a larger value for TOLER may
               result in a valid solution. Suggested value: 0.0.

           7:  X(NPLUS2) -- DOUBLE PRECISION array                   Output
               On exit: X(j) contains the jth element of the solution
               vector x, for j=1,2,...,n. The elements X(n+1) and X(n+2)
               are unused.

           8:  RESID -- DOUBLE PRECISION                             Output
               On exit: the sum of the absolute values of the residuals
               for the solution vector x.

           9:  IRANK -- INTEGER                                      Output
               On exit: the computed rank of the matrix A.

          10:  ITER -- INTEGER                                       Output
               On exit: the number of iterations taken by the simplex
               method.

          11:  IWORK(M) -- INTEGER array                          Workspace

          12:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               An optimal solution has been obtained but this may not be
               unique.

          IFAIL= 2
               The calculations have terminated prematurely due to rounding
               errors. Experiment with larger values of TOLER or try
               scaling the columns of the matrix (see Section 8).

          IFAIL= 3
               On entry NPLUS2 < 3,

               or       NPLUS2 > M + 2,

               or       LA < M + 2.

          7. Accuracy

          Experience suggests that the computational accuracy of the
          solution x is comparable with the accuracy that could be obtained
          by applying Gaussian elimination with partial pivoting to the n
          equations satisfied by this algorithm (i.e., those equations with
          zero residuals). The accuracy therefore varies with the
          conditioning of the problem, but has been found generally very
          satisfactory in practice.

          8. Further Comments

          The effects of m and n on the time and on the number of
          iterations in the Simplex Method vary from problem to problem,
          but typically the number of iterations is a small multiple of n
          and the total time taken by the routine is approximately
                            2
          proportional to mn .

          It is recommended that, before the routine is entered, the
          columns of the matrix A are scaled so that the largest element in
          each column is of the order of unity. This should improve the
          conditioning of the matrix, and also enable the parameter TOLER
          to perform its correct function. The solution x obtained will
          then, of course, relate to the scaled form of the matrix. Thus if
          the scaling is such that, for each j=1,2,...,n, the elements of
          the jth column are multiplied by the constant k , the element x
                                                         j               j
          of the solution vector x must be multiplied by k  if it is
                                                          j
          desired to recover the solution corresponding to the original
          matrix A.

          9. Example

          Suppose we wish to approximate a set of data by a curve of the
          form

                   t   -t
               y=Ke +Le  +M

          where K, L and M are unknown. Given values y  at 5 points t  we
                                                      i              i
          may form the over-determined set of equations for K, L and M

                            x    -x
                             i     i
                           e  K+e   L+M=y ,  i=1,2,...,5.
                                         i

          E02GAF is used to solve these in the l  sense.
                                                1

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe02zaf}{nage.ht}
{ Sorts two-dimensional data into rectangular panels}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe02zaf}{NAG Documentation: e02zaf}
\beginscroll
\begin{verbatim}



     E02ZAF(3NAG)      Foundation Library (12/10/92)      E02ZAF(3NAG)



          E02 -- Curve and Surface Fitting                           E02ZAF
                  E02ZAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E02ZAF sorts two-dimensional data into rectangular panels.

          2. Specification

                 SUBROUTINE E02ZAF (PX, PY, LAMDA, MU, M, X, Y, POINT,
                1                   NPOINT, ADRES, NADRES, IFAIL)
                 INTEGER          PX, PY, M, POINT(NPOINT), NPOINT, ADRES
                1                 (NADRES), NADRES, IFAIL
                 DOUBLE PRECISION LAMDA(PX), MU(PY), X(M), Y(M)

          3. Description

          A set of m data points with rectangular Cartesian co-ordinates
          x ,y  are sorted into panels defined by lines parallel to the y
           r  r
          and x axes. The intercepts of these lines on the x and y axes are
          given in LAMDA(i), for i=5,6,...,PX-4 and MU(j), for
          j=5,6,...,PY-4, respectively. The subroutine orders the data so
          that all points in a panel occur before data in succeeding
          panels, where the panels are numbered from bottom to top and then
          left to right, with the usual arrangement of axes, as shown in
          the diagram. Within a panel the points maintain their original
          order.

                   Please see figure in printed Reference Manual

          A data point lying exactly on one or more panel sides is taken to
          be in the highest-numbered panel adjacent to the point. The
          subroutine does not physically rearrange the data, but provides
          the array POINT which contains a linked list for each panel,
          pointing to the data in that panel. The total number of panels is
          (PX-7)*(PY-7).

          4. References

          None.

          5. Parameters

           1:  PX -- INTEGER                                          Input

           2:  PY -- INTEGER                                          Input

               On entry: PX and PY must specify eight more than the number
               of intercepts on the x axis and y axis, respectively.
               Constraint: PX >= 8 and PY >= 8.

           3:  LAMDA(PX) -- DOUBLE PRECISION array                    Input
               On entry: LAMDA(5) to LAMDA(PX-4) must contain, in non-
               decreasing order, the intercepts on the x axis of the sides
               of the panels parallel to the y axis.

           4:  MU(PY) -- DOUBLE PRECISION array                       Input
               On entry: MU(5) to MU(PY-4) must contain, in non-decreasing
               order, the intercepts on the y axis of the sides of the
               panels parallel to the x axis.

           5:  M -- INTEGER                                           Input
               On entry: the number m of data points.

           6:  X(M) -- DOUBLE PRECISION array                         Input

           7:  Y(M) -- DOUBLE PRECISION array                         Input
               On entry: the co-ordinates of the rth data point (x ,y ),
                                                                  r  r
               for r=1,2,...,m.

           8:  POINT(NPOINT) -- INTEGER array                        Output
               On exit: for i = 1,2,...,NADRES, POINT(m+i) = I1 is the
               index of the first point in panel i, POINT(I1) = I2 is the
               index of the second point in panel i and so on.

               POINT(IN) = 0 indicates that X(IN),Y(IN) was the last point
               in the panel.

               The co-ordinates of points in panel i can be accessed in
               turn by means of the following instructions:
                  IN = M + I
               10 IN = POINT(IN)
                  IF (IN.EQ. 0) GOTO 20
                  XI = X(IN)
                  YI = Y(IN)
                  .
                  .
                  .
                  GOTO 10
               20...

           9:  NPOINT -- INTEGER                                      Input
               On entry:
               the dimension of the array POINT as declared in the
               (sub)program from which E02ZAF is called.
               Constraint: NPOINT >= M + (PX-7)*(PY-7).

          10:  ADRES(NADRES) -- INTEGER array                     Workspace

          11:  NADRES -- INTEGER                                      Input
               On entry: the value (PX-7)*(PY-7), the number of panels
               into which the (x,y) plane is divided.

          12:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               The intercepts in the array LAMDA, or in the array MU, are
               not in non-decreasing order.

          IFAIL= 2
               On entry PX < 8,

               or       PY < 8,

               or       M <= 0,

               or       NADRES /= (PX-7)*(PY-7),

               or       NPOINT < M + (PX-7)*(PY-7).

          7. Accuracy

          Not applicable.

          8. Further Comments

          The time taken by this routine is approximately proportional to
          m*log(NADRES).

          This subroutine was written to sort two dimensional data in the
          manner required by routines E02DAF and E02DBF(*). The first 9
          parameters of E02ZAF are the same as the parameters in E02DAF and
          E02DBF(*) which have the same name.

          9. Example

          This example program reads in data points and the intercepts of
          the panel sides on the x and y axes; it calls E02ZAF to set up
          the index array POINT; and finally it prints the data points in
          panel order.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe04}{nage.ht}
{ Minimizing or Maximizing a Function}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe04}{NAG Documentation: e04}
\beginscroll
\begin{verbatim}



     E04(3NAG)         Foundation Library (12/10/92)         E04(3NAG)



          E04 -- Minimizing or Maximizing a Function    Introduction -- E04
                                    Chapter E04
                        Minimizing or Maximizing a Function

          Contents of this Introduction:

          1.     Scope of the Chapter

          2.     Background to the Problems

          2.1.   Types of Optimization Problems

          2.1.1. Unconstrained minimization

          2.1.2. Nonlinear least-squares problems

          2.1.3. Minimization subject to bounds on the variables

          2.1.4. Minimization subject to linear constraints

          2.1.5. Minimization subject to nonlinear constraints
          
          2.2.   Geometric Representation and Terminology

          2.2.1. Gradient vector

          2.2.2. Hessian matrix

          2.2.3. Jacobian matrix; matrix of constraint normals

          2.3.   Sufficient Conditions for a Solution

          2.3.1. Unconstrained minimization

          2.3.2. Minimization subject to bounds on the variables

          2.3.3. Linearly-constrained minimization

          2.3.4. Nonlinearly-constrained minimization

          2.4.   Background to Optimization Methods

          2.4.1. Methods for unconstrained optimization

          2.4.2. Methods for nonlinear least-squares problems

          2.4.3. Methods for handling constraints

          2.5.   Scaling

          2.5.1. Transformation of variables

          2.5.2. Scaling the objective function

          2.5.3. Scaling the constraints

          2.6.   Analysis of Computed Results

          2.6.1. Convergence criteria

          2.6.2. Checking results

          2.6.3. Monitoring progress

          2.6.4. Confidence intervals for least-squares solutions

          2.7.   References

          3.     Recommendations on Choice and Use of Routines

          3.1.   Choice of Routine

          3.2.   Service Routines

          3.3.   Function Evaluations at Infeasible Points

          3.4.   Related Problems



          1. Scope of the Chapter

          An optimization problem involves minimizing a function (called
          the objective function) of several variables, possibly subject to
          restrictions on the values of the variables defined by a set of
          constraint functions. The routines in the NAG Foundation Library
          are concerned with function minimization only, since the problem
          of maximizing a given function can be transformed into a
          minimization problem simply by multiplying the function by -1.

          This introduction is only a brief guide to the subject of
          optimization designed for the casual user. Anyone with a
          difficult or protracted problem to solve will find it beneficial
          to consult a more detailed text, such as Gill et al [5] or
          Fletcher [3].

          Readers who are unfamiliar with the mathematics of the subject
          may find some sections difficult at first reading; if so, they
          should concentrate on Sections 2.1, 2.2, 2.5, 2.6 and 3.

          2. Background to the Problems

          2.1. Types of Optimization Problems

          Solution of optimization problems by a single, all-purpose,
          method is cumbersome and inefficient. Optimization problems are
          therefore classified into particular categories, where each
          category is defined by the properties of the objective and
          constraint functions, as illustrated by some examples below.

          Properties of Objective   Properties of Constraints
          Function

          Nonlinear                 Nonlinear

          Sums of squares of        Sparse linear
          nonlinear functions

          Quadratic                 Linear

          Sums of squares of linear Bounds
          functions

          Linear                    None

          For instance, a specific problem category involves the
          minimization of a nonlinear objective function subject to bounds
          on the variables. In the following sections we define the
          particular categories of problems that can be solved by routines
          contained in this Chapter.

          2.1.1.  Unconstrained minimization

          In unconstrained minimization problems there are no constraints
          on the variables. The problem can be stated mathematically as
          follows:

                                    minimize F(x)
                                     x

                         n                           T
          where x is in R , that is, x=(x ,x ,...,x ) .
                                        1  2      n

          2.1.2.  Nonlinear least-squares problems

          Special consideration is given to the problem for which the
          function to be minimized can be expressed as a sum of squared
          functions. The least-squares problem can be stated mathematically
          as follows:

                                 {     m       }
                                 { T   --  2   }            n
                        minimize {f f= >  f (x)},  x is in R
                         x       {     --  i   }
                                 {     i=1     }

          where the ith element of the m-vector f is the function f (x).
                                                                   i

          2.1.3.  Minimization subject to bounds on the variables

          These problems differ from the unconstrained problem in that at
          least one of the variables is subject to a simple restriction on
          its value, e.g.x <=10, but no constraints of a more general form
                          5
          are present.

          The problem can be stated mathematically as follows:

                                                       n
                              minimize F(x),  x is in R
                               x

          subject to l <=x <=u , i=1,2,...,n.
                      i   i   i

          This format assumes that upper and lower bounds exist on all the
          variables. By conceptually allowing u =infty and l =-infty all
                                               i            i
          the variables need not be restricted.

          2.1.4.  Minimization subject to linear constraints

          A general linear constraint is defined as a constraint function
          that is linear in more than one of the variables, e.g. 3x +2x >=4
                                                                   1   2
          The various types of linear constraint are reflected in the
          following mathematical statement of the problem:


                                                       n
                              minimize F(x),  x is in R
                               x

          subject to the

                             T
             equality       a x=b        i=1,2,...,m ;
             constraints:    i   i                1

                             T
             inequality     a x>=b       i=m +1,m +2,...,m ;
             constraints:    i    i         1    1        2

                             T
                            a x<=b       i=m +1,m +2,...,m ;
                             i    i         2    2        3

                                 T
             range          s <=a x<=t   i=m +1,m +2,...,m ;
             constraints:    j   i    j     3    3        4
                                         j=1,2,...,m -m ;
                                                    4  3

             bounds         l <=x <=u    i=1,2,...,n
             constraints:    i   i   i

          where each a  is a vector of length n; b , s  and t  are constant
                      i                           i   j      j
          scalars; and any of the categories may be empty.

          Although the bounds on x  could be included in the definition of
                                  i
          general linear constraints, we prefer to distinguish between them
          for reasons of computational efficiency.

          If F(x) is a linear function, the linearly-constrained problem is
          termed a linear programming problem (LP problem); if F(x) is a
          quadratic function, the problem is termed a quadratic programming
          problem (QP problem). For further discussion of LP and QP
          problems, including the dual formulation of such problems, see
          Dantzig [2].

          2.1.5.  Minimization subject to nonlinear constraints

          A problem is included in this category if at least one constraint
                                       2
          function is nonlinear, e.g. x +x +x -2>=0. The mathematical
                                       1  3  4
          statement of the problem is identical to that for the linearly-
          constrained case, except for the addition of the following
          constraints:

             equality       c (x)=0        i=1,2,...,m ;
             constraints:    i                        5

             inequality     c (x)>=0       i=m +1,m +2,...,m ;
             constraints:    i                5    5        6

             range          v <=c (x)<=w   i=m +1,m +2,...,m ,
             constraints:    j   i      j     6    6        7
                                           j=1,2,...,m -m
                                                      7  6

          where each c  is a nonlinear function; v  and w  are constant
                      i                           j      j
          scalars; and any category may be empty. Note that we do not
          include a separate category for constraints of the form c (x)<=0,
                                                                   i
          since this is equivalent to -c (x)>=0.
                                        i

          2.2. Geometric Representation and Terminology

          To illustrate the nature of optimization problems it is useful to
          consider the following example in two dimensions

                                 x
                                  1   2   2
                           F(x)=e  (4x +2x +4x x +2x +1).
                                      1   2   1 2   2

          (This function is used as the example function in the
          documentation for the unconstrained routines.)


                                     Figure 1
                   Please see figure in printed Reference Manual

          Figure 1 is a contour diagram of F(x). The contours labelled
          F ,F ,...,F  are isovalue contours, or lines along which the
           0  1      4
                                                                   *
          function F(x) takes specific constant values. The point x  is a
                                                                *
          local unconstrained minimum, that is, the value of F(x ) is less
          than at all the neighbouring points. A function may have several
          such minima. The lowest of the local minima is termed a global
                                                            *
          minimum. In the problem illustrated in Figure 1, x  is the only
                                   

          local minimum. The point x is said to be a saddle point because
          it is a minimum along the line AB, but a maximum along CD.

          If we add the constraint x >=0 to the problem of minimizing F(x),
                                    1
          the solution remains unaltered. In Figure 1 this constraint is
          represented by the straight line passing through x =0, and the
                                                            1
          shading on the line indicates the unacceptable region. The region
              n
          in R  satisfying the constraints of an optimization problem is
          termed the feasible region. A point satisfying the constraints is
          defined as a feasible point.

          If we add the nonlinear constraint x +x -x x -1.5>=0, represented
                                              1  2  1 2
                                                       *
          by the curved shaded line in Figure 1, then x  is not a feasible
                                                                ^
          point. The solution of the new constrained problem is x, the
          feasible point with the smallest function value.

          2.2.1.  Gradient vector

          The vector of first partial derivatives of F(x) is called the
          gradient vector, and is denoted by g(x), i.e.,

                             [ ddF(x)  ddF(x)      ddF(x)]T
                        g(x)=[ ------, ------,..., ------] .
                             [  ddx     ddx         ddx  ]
                             [     1       2           n ]

          For the function illustrated in Figure 1,

                                   [      x          ]
                                   [       1         ]
                                   [F(x)+e  (8x +4x )]
                                   [           1   2 ]
                                   [ x               ]
                                   [  1              ]
                              g(x)=[e  (4x +4x +2)   ].
                                   [      2   1      ]

          The gradient vector is of importance in optimization because it
          must be zero at an unconstrained minimum of any function with
          continuous first derivatives.

          2.2.2.  Hessian matrix

          The matrix of second partial derivatives of a function is termed
          its Hessian matrix. The Hessian matrix of F(x) is denoted by G(x)
                                                  2
          and its (i,j)th element is given by dd F(x)/ddx ddx . If F(x)
                                                           i   j
          has continuous second derivatives, then G(x) must be positive
          semi-definite at any unconstrained minimum of F.

          2.2.3.  Jacobian matrix; matrix of constraint normals

          In nonlinear least-squares problems, the matrix of first partial
          derivatives of the vector-valued function f(x) is termed the
          Jacobian matrix of f(x) and its (i,j)th component is ddf /ddx .
                                                                  i    j

          The vector of first partial derivatives of the constraint c (x)
                                                                     i
          is denoted by

                                 [ ddc (x)      ddc (x)]T
                                 [    i            i   ]
                           a (x)=[ -------,..., -------] .
                            i    [  ddx          ddx   ]
                                 [     1            n  ]

                      ^                ^
          At a point, x, the vector a (x) is orthogonal (normal) to the
                                     i
                                                    ^
          isovalue contour of c (x) passing through x; this relationship is
                               i
          illustrated for a two-dimensional function in Figure 2.


                                     Figure 2
                   Please see figure in printed Reference Manual

          The matrix whose columns are the vectors {a } is termed the
                                                     i
          matrix of constraint normals. Note that if c (x) is a linear
                                                      i
                                T
          constraint involving a x, then its vector of first partial
                                i
          derivatives is simply the vector a .
                                            i

          2.3. Sufficient Conditions for a Solution

          All nonlinear functions will be assumed to have continuous second
          derivatives in the neighbourhood of the solution.

          2.3.1.  Unconstrained minimization

                                                                 *
          The following conditions are sufficient for the point x  to be an
          unconstrained local minimum of F(x):

                      *
          (i)   |||g(x )|||=0; and

                   *
          (ii)  G(x ) is positive-definite,

          where |||g||| denotes the Euclidean length of g.

          2.3.2.  Minimization subject to bounds on the variables

          At the solution of a bounds-constrained problem, variables which
          are not on their bounds are termed free variables. If it is known
          in advance which variables are on their bounds at the solution,
          the problem can be solved as an unconstrained problem in just the
          free variables; thus, the sufficient conditions for a solution
          are similar to those for the unconstrained case, applied only to
          the free variables.

                                                      *
          Sufficient conditions for a feasible point x  to be the solution
          of a bound-constrained problem are as follows:

                      *
          (i)   |||g(x )|||=0; and

                   *
          (ii)  G(x ) is positive-definite; and

                    *               *
          (iii) g (x )<0,x =u ; g (x )>0,x =l ,
                 j        j  j   j        j  j

                

          where g(x) is the gradient of F(x) with respect to the free
                         

          variables, and G(x) is the Hessian matrix of F(x) with respect to
          the free variables. The extra condition (iii) ensures that F(x)
          cannot be reduced by moving off one or more of the bounds.

          2.3.3.  Linearly-constrained minimization

          For the sake of simplicity, the following description does not
          include a specific treatment of bounds or range constraints,
          since the results for general linear inequality constraints can
          be applied directly to these cases.

                         *
          At a solution x , of a linearly-constrained problem, the
          constraints which hold as equalities are called the active or
          binding constraints. Assume that there are t active constraints
                           *          ^
          at the solution x , and let A denote the matrix whose columns are
                                                                         ^
          the columns of A corresponding to the active constraints, with b
          the vector similarly obtained from b; then

                                       ^T * ^
                                       A x =b.

          The matrix Z is defined as an n by (n-t) matrix satisfying:

                                   ^T        T
                                   A Z=0;   Z Z=I.

          The columns of Z form an orthogonal basis for the set of vectors
                                       ^
          orthogonal to the columns of A.

          Define

                      T
               g (x)=Z g(x), the projected gradient vector of F(x);
                z

                      T
               G (x)=Z G(x)Z, the projected Hessian matrix of F(x).
                z

          At the solution of a linearly-constrained problem, the projected
          gradient vector must be zero, which implies that the gradient
                    *
          vector g(x ) can be written as a linear combination of the
                                     t
                     ^           *   --          ^  ^
          columns of A, i.e., g(x )= >  (lambda) a =A(lambda). The scalar
                                     --         i i
                                     i=1
          (lambda)  is defined as the Lagrange multiplier corresponding to
                  i
          the ith active constraint. A simple interpretation of the ith
          Lagrange multiplier is that it gives the gradient of F(x) along
          the ith active constraint normal; a convenient definition of the
          Lagrange multiplier vector (although not a recommended method for
          computation) is:


                                        ^T^ -1^T   *
                              (lambda)=(A A)  A g(x ).

                                     *
          Sufficient conditions for x  to be the solution of a linearly-
          constrained problem are:

                 *                  ^T * ^
          (i)   x  is feasible, and A x =b; and

                       *                            *  ^
          (ii)  |||g (x )|||=0, or equivalently, g(x )=A(lambda); and
                    z

                    *
          (iii) G (x ) is positive-definite; and
                 z

          (iv)  (lambda) >0 if (lambda)  corresponds to a constraint
                        i              i
                ^T *  ^
                a x >=b ;
                 i     i

               (lambda) <0 if (lambda)  corresponds to a constraint
                       i              i
               ^T *  ^
               a x <=b .
                i     i

               The sign of (lambda)  is immaterial for equality
                                   i
               constraints, which by definition are always active.

          2.3.4.  Nonlinearly-constrained minimization

          For nonlinearly-constrained problems, much of the terminology is
          defined exactly as in the linearly-constrained case. The set of
          active constraints at x again means the set of constraints that
                                                                     ^
          hold as equalities at x, with corresponding definitions of c and
          ^             ^
          A: the vector c(x) contains the active constraint functions, and
                         ^
          the columns of A(x) are the gradient vectors of the active
                                                           ^
          constraints. As before, Z is defined in terms of A(x) as a matrix
          such that:


                                   ^T        T
                                   A Z=0;   Z Z=I

          where the dependence on x has been suppressed for compactness.

                                                             T
          The projected gradient vector g (x) is the vector Z g(x). At the
                                         z
                    *
          solution x  of a nonlinearly-constrained problem, the projected
          gradient must be zero, which implies the existence of Lagrange
          multipliers corresponding to the active constraints, i.e.,
             *  ^  *
          g(x )=A(x )(lambda).

          The Lagrangian function is given by:


                                                     T^
                          L(x,(lambda))=F(x)-(lambda) c(x).

          We define g (x) as the gradient of the Lagrangian function; G (x)
                     L                                                 L
                                     ^
          as its Hessian matrix, and G (x) as its projected Hessian matrix,
                                      L
                ^   T
          i.e., G =Z G Z.
                 L    L
                                     *
          Sufficient conditions for x  to be a solution of nonlinearly-
          constrained problem are:

                 *                  ^  *
          (i)   x  is feasible, and c(x )=0; and

                       *                             *  ^  *
          (ii)  |||g (x )|||=0, or, equivalently, g(x )=A(x )(lambda); and
                    z

                ^   *
          (iii) G (x ) is positive-definite; and
                 L

          (iv)  (lambda) >0 if (lambda)  corresponds to a constraint of the
                        i              i
                     ^
                form c >=0; the sign of (lambda)  is immaterial for an
                      i                         i
                equality constraint.

          Note that condition (ii) implies that the projected gradient of
                                                        *
          the Lagrangian function must also be zero at x , since the
                          T                        ^  *
          application of Z  annihilates the matrix A(x ).

          2.4. Background to Optimization Methods

          All the algorithms contained in this Chapter generate an
                               (k)                                  *
          iterative sequence {x   } that converges to the solution x  in
          the limit, except for some special problem categories (i.e.,
          linear and quadratic programming). To terminate computation of
          the sequence, a convergence test is performed to determine
          whether the current estimate of the solution is an adequate
          approximation. The convergence tests are discussed in Section 2.6

                                                     (k)
          Most of the methods construct a sequence {x   } satisfying:

                              (k+1)  (k)        (k) (k)
                             x     =x   +(alpha)   p   ,

                            (k)
          where the vector p    is termed the direction of search, and
                 (k)                                          (k)
          (alpha)    is the steplength. The steplength (alpha)    is chosen
                     (k+1)     (k)
          so that F(x     )<F(x   ).


          2.4.1.  Methods for unconstrained optimization

          The distinctions among methods arise primarily from the need to
          use varying levels of information about derivatives of F(x) in
          defining the search direction. We describe three basic approaches
          to unconstrained problems, which may be extended to other problem
          categories. Since a full description of the methods would fill
          several volumes, the discussion here can do little more than
          allude to the processes involved, and direct the reader to other
          sources for a full explanation.

          (a)   Newton-type Methods (Modified Newton Methods)

                                                              (k)
                Newton-type methods use the Hessian matrix G(x   ), or a
                                                      (k)
                finite difference approximation to G(x   ), to define the
                search direction. The routines in the Library either
                                                                      (k)
                require a subroutine that computes the elements of G(x   ),
                                       (k)
                or they approximate G(x   ) by finite differences.

                Newton-type methods are the most powerful methods available
                for general problems and will find the minimum of a
                quadratic function in one iteration. See Sections 4.4. and
                4.5.1. of Gill et al [5].

          (b)   Quasi-Newton Methods

                                                                (k)
                Quasi-Newton methods approximate the Hessian G(x   ) by a
                        (k)
                matrix B    which is modified at each iteration to include
                information obtained about the curvature of F along the
                latest search direction. Although not as robust as Newton-
                type methods, quasi-Newton methods can be more efficient
                           (k)
                because G(x   ) is not computed, or approximated by finite-
                differences. Quasi-Newton methods minimize a quadratic
                function in n iterations. See Section 4.5.2 of Gill et al
                [5].

          (c)   Conjugate-Gradient Methods

                Unlike Newton-type and quasi-Newton methods, conjugate
                gradient methods do not require the storage of an n by n
                matrix and so are ideally suited to solve large problems.
                Conjugate-gradient type methods are not usually as reliable
                or efficient as Newton-type, or quasi-Newton methods. See
                Section 4.8.3 of Gill et al [5].


          2.4.2.  Methods for nonlinear least-squares problems

          These methods are similar to those for unconstrained
          optimization, but exploit the special structure of the Hessian
          matrix to give improved computational efficiency.

          Since

                                         m
                                         --  2
                                   F(x)= >  f (x)
                                         --  i
                                         i=1

          the Hessian matrix G(x) is of the form

                                            m
                                     T      --
                          G(x)=2[J(x) J(x)+ >  f (x)G (x)],
                                            --  i    i
                                            i=1

          where J(x) is the Jacobian matrix of f(x), and G (x) is the
                                                          i
          Hessian matrix of f (x).
                             i

          In the neighbourhood of the solution, |||f(x)||| is often small
                             T
          compared to |||J(x) J(x)||| (for example, when f(x) represents
          the goodness of fit of a nonlinear model to observed data). In
                           T
          such cases, 2J(x) J(x) may be an adequate approximation to G(x),
          thereby avoiding the need to compute or approximate second
          derivatives of {f (x)}. See Section 4.7 of Gill et al [5].
                           i

          2.4.3.  Methods for handling constraints

          Bounds on the variables are dealt with by fixing some of the
          variables on their bounds and adjusting the remaining free
          variables to minimize the function. By examining estimates of the
          Lagrange multipliers it is possible to adjust the set of
          variables fixed on their bounds so that eventually the bounds
          active at the solution should be correctly identified. This type
          of method is called an active set method. One feature of such
          methods is that, given an initial feasible point, all
                          (k)
          approximations x    are feasible. This approach can be extended
          to general linear constraints. At a point, x, the set of
          constraints which hold as equalities being used to predict, or
          approximate, the set of active constraints is called the working
          set.

          Nonlinear constraints are more difficult to handle. If at all
          possible, it is usually beneficial to avoid including nonlinear
          constraints during the formulation of the problem. The methods
          currently implemented in the Library handle nonlinearly
          constrained problems either by transforming them into a sequence
          of bound constraint problems, or by transforming them into a
          sequence of quadratic programming problems. A feature of almost
                                                         (k)
          all methods for nonlinear constraints is that x    is not
          guaranteed to be feasible except in the limit, and this is
          certainly true of the routines currently in the Library. See
          Chapter 6, particularly Section 6.4 and Section 6.5 of Gill et al
          [5].

          Anyone interested in a detailed description of methods for
          optimization should consult the references.

          2.5. Scaling

          Scaling (in a broadly defined sense) often has a significant
          influence on the performance of optimization methods. Since
          convergence tolerances and other criteria are necessarily based
          on an implicit definition of 'small' and 'large', problems with
          unusual or unbalanced scaling may cause difficulties for some
          algorithms. Nonetheless, there are currently no scaling routines
          in the Library, although the position is under constant review.
          In light of the present state of the art, it is considered that
          sensible scaling by the user is likely to be more effective than
          any automatic routine. The following sections present some
          general comments on problem scaling.

          2.5.1.  Transformation of variables

          One method of scaling is to transform the variables from their
          original representation, which may reflect the physical nature of
          the problem, to variables that have certain desirable properties
          in terms of optimization. It is generally helpful for the
          following conditions to be satisfied:

          (i)   the variables are all of similar magnitude in the region of
                interest;

          (ii)  a fixed change in any of the variables results in similar
                changes in F(x). Ideally, a unit change in any variable
                produces a unit change in F(x);

          (iii) the variables are transformed so as to avoid cancellation
                error in the evaluation of F(x).

          Normally, users should restrict themselves to linear
          transformations of variables, although occasionally nonlinear
          transformations are possible. The most common such transformation
          (and often the most appropriate) is of the form

                                     x   =Dx   ,
                                      new   old

          where D is a diagonal matrix with constant coefficients. Our
          experience suggests that more use should be made of the
          transformation

                                    x   =Dx   +v,
                                     new   old

          where v is a constant vector.

          Consider, for example, a problem in which the variable x
                                                                  3
          represents the position of the peak of a Gaussian curve to be
          fitted to data for which the extreme values are 150 and 170;
          therefore x  is known to lie in the range 150--170. One possible
                     3
                                                    

          scaling would be to define a new variable x , given by
                                                     3


                                          x
                                           3
                                      x = ---.
                                       3  170

                                                                 

          A better transformation, however, is given by defining x  as
                                                                  3

                                         x -160
                                          3
                                     x = ------.
                                      3    10

          Frequently, an improvement in the accuracy of evaluation of F(x)
          can result if the variables are scaled before the routines to
          evaluate F(x) are coded. For instance, in the above problem just
          mentioned of Gaussian curve fitting, x  may always occur in terms
                                                3
          of the form (x -x ), where x  is a constant representing the mean
                        3  m          m
          peak position.

          2.5.2.  Scaling the objective function

          The objective function has already been mentioned in the
          discussion of scaling the variables. The solution of a given
          problem is unaltered if F(x) is multiplied by a positive
          constant, or if a constant value is added to F(x). It is
          generally preferable for the objective function to be of the
          order of unity in the region of interest; thus, if in the
                                                                +5
          original formulation F(x) is always of the order of 10   (say),
                                                           -5
          then the value of F(x) should be multiplied by 10   when
          evaluating the function within the optimization routines. If a
          constant is added or subtracted in the computation of F(x),
          usually it should be omitted - i.e., it is better to formulate
                   2  2                 2  2               2  2
          F(x) as x +x  rather than as x +x +1000 or even x +x +1. The
                   1  2                 1  2               1  2
          inclusion of such a constant in the calculation of F(x) can
          result in a loss of significant figures.

          2.5.3.  Scaling the constraints

          The solution of a nonlinearly-constrained problem is unaltered if
          the ith constraint is multiplied by a positive weight w . At the
                                                                 i
          approximation of the solution determined by a Library routine,
          the active constraints will not be satisfied exactly, but will
                                                 -8       -6
          have 'small' values (for example, c =10  , c =10  , etc.). In
                                             1        2
          general, this discrepancy will be minimized if the constraints
          are weighted so that a unit change in x produces a similar change
          in each constraint.

          A second reason for introducing weights is related to the effect
          of the size of the constraints on the Lagrange multiplier
          estimates and, consequently, on the active set strategy.
          Additional discussion is given in Gill et al [5].

          2.6. Analysis of Computed Results

          2.6.1.  Convergence criteria

          The convergence criteria inevitably vary from routine to routine,
          since in some cases more information is available to be checked
          (for example, is the Hessian matrix positive-definite?), and
          different checks need to be made for different problem categories
          (for example, in constrained minimization it is necessary to
          verify whether a trial solution is feasible). Nonetheless, the
          underlying principles of the various criteria are the same; in
          non-mathematical terms, they are:

                                  (k)
          (i)   is the sequence {x   } converging?

                                  (k)
          (ii)  is the sequence {F   } converging?

          (iii) are the necessary and sufficient conditions for the
                solution satisfied?

          The decision as to whether a sequence is converging is
          necessarily speculative. The criterion used in the present
          routines is to assume convergence if the relative change
          occurring between two successive iterations is less than some
          prescribed quantity. Criterion (iii) is the most reliable but
          often the conditions cannot be checked fully because not all the
          required information may be available.

          2.6.2.  Checking results

          Little a priori guidance can be given as to the quality of the
          solution found by a nonlinear optimization algorithm, since no
          guarantees can be given that the methods will always work.
          Therefore, it is necessary for the user to check the computed
          solution even if the routine reports success. Frequently a '
          solution' may have been found even when the routine does not
          report a success. The reason for this apparent contradiction is
          that the routine needs to assess the accuracy of the solution.
          This assessment is not an exact process and consequently may be
          unduly pessimistic. Any 'solution' is in general only an
          approximation to the exact solution, and it is possible that the
          accuracy specified by the user is too stringent.

          Further confirmation can be sought by trying to check whether or
          not convergence tests are almost satisfied, or whether or not
          some of the sufficient conditions are nearly satisfied. When it
          is thought that a routine has returned a non-zero value of IFAIL
          only because the requirements for 'success' were too stringent it
          may be worth restarting with increased convergence tolerances.

          For nonlinearly-constrained problems, check whether the solution
          returned is feasible, or nearly feasible; if not, the solution
          returned is not an adequate solution.

          Confidence in a solution may be increased by resolving the
          problem with a different initial approximation to the solution.
          See Section 8.3 of Gill et al [5] for further information.

          2.6.3.  Monitoring progress

          Many of the routines in the Chapter have facilities to allow the
          user to monitor the progress of the minimization process, and
          users are encouraged to make use of these facilities. Monitoring
          information can be a great aid in assessing whether or not a
          satisfactory solution has been obtained, and in indicating
          difficulties in the minimization problem or in the routine's
          ability to cope with the problem.

          The behaviour of the function, the estimated solution and first
          derivatives can help in deciding whether a solution is acceptable
          and what to do in the event of a return with a non-zero value of
          IFAIL.

          2.6.4.  Confidence intervals for least-squares solutions

          When estimates of the parameters in a nonlinear least-squares
          problem have been found, it may be necessary to estimate the
          variances of the parameters and the fitted function. These can be
          calculated from the Hessian of F(x) at the solution.

          In many least-squares problems, the Hessian is adequately
                                              T
          approximated at the solution by G=2J J (see Section 2.4.3). The
          Jacobian, J, or a factorization of J is returned by all the
          comprehensive least-squares routines and, in addition, a routine
          is supplied in the Library to estimate variances of the
          parameters following the use of most of the nonlinear least-
                                                 T
          squares routines, in the case that G=2J J is an adequate
          approximation.

          Let H be the inverse of G, and S be the sum of squares, both
                                     

          calculated at the solution x; an unbiased estimate of the
          variance of the ith parameter x  is
                                         i


                                           2S
                                   var x = ---H
                                        i  m-n ii

                                                               

          and an unbiased estimate of the covariance of x  and x  is
                                                         i      j

                                              2S
                                covar(x ,x )= ---H  .
                                       i  j   m-n ij

              *
          If x  is the true solution, then the 100(1-(beta)) confidence
                      

          interval on x is

                 

                /                          * 
          x -  / var x .t                <x <x
           i \/       i  (1-(beta)/2,m-n)  i  i
               

              /    
          +  / var x .t                ,   i=1,2,...,n
           \/       i  (1-(beta)/2,m-n)

          where t                 is the 100(1-(beta))/2 percentage point
                 (1-(beta)/2,m-n)
          of the t-distribution with m-n degrees of freedom.

          In the majority of problems, the residuals f , for i=1,2,...,m,
                                                      i
          contain the difference between the values of a model function
          (phi)(z,x) calculated for m different values of the independent
          variable z, and the corresponding observed values at these
          points. The minimization process determines the parameters, or
                                                                         

          constants x, of the fitted function (phi)(z,x). For any value, z,
          of the independent variable z, an unbiased estimate of the
          variance of (phi) is


                                 n   n
                             2S  --  -- [ dd(phi)] [ dd(phi)]
                  var (phi)= --- >   >  [ -------] [ -------] H  .
                             m-n --  -- [  ddx   ] [  ddx   ]  ij
                                 i=1 j=1[     i  ]z[     j  ]z

                                                                  

          The 100(1-(beta)) confidence interval on F at the point z is


                                                          *
          (phi)(z,x)-\/var (phi).t               < (phi)(z,x )
                                  ((beta)/2,m-n)
                                             

                             < (phi)(z,x) +\/var (phi).t              .
                                                       ((beta)/2,m-n)

          For further details on the analysis of least-squares solutions
          see Bard [1] and Wolberg [7].

          2.7. References

          [1]   Bard Y (1974) Nonlinear Parameter Estimation. Academic
                Press.

          [2]   Dantzig G B (1963) Linear Programming and Extensions.
                Princeton University Press.

          [3]   Fletcher R (1987) Practical Methods of Optimization. Wiley
                (2nd Edition).

          [4]   Gill P E and Murray W (eds) (1974) Numerical Methods for
                Constrained Optimization. Academic Press.

          [5]   Gill P E, Murray W and Wright M H (1981) Practical
                Optimization. Academic Press.

          [6]   Murray W (ed) (1972) Numerical Methods for Unconstrained
                Optimization. Academic Press.

          [7]   Wolberg J R (1967) Prediction Analysis. Van Nostrand.

          3. Recommendations on Choice and Use of Routines

          The choice of routine depends on several factors: the type of
          problem (unconstrained, etc.); the level of derivative
          information available (function values only, etc.); the
          experience of the user (there are easy-to-use versions of some
          routines); whether or not storage is a problem; and whether
          computational time has a high priority.

          3.1. Choice of Routine

          Routines are provided to solve the following types of problem:


          Nonlinear Programming                                      E04UCF
          Quadratic Programming                                      E04NAF
          Linear Programming                                         E04MBF
          Nonlinear Function                                         E04DGF
          (using 1st derivatives)
          Nonlinear Function, unconstrained or simple bounds         E04JAF
          (using function values only)
          Nonlinear least-squares                                    E04FDF
          (using function values only)
          Nonlinear least-squares                                    E04GCF
          (using function values and 1st derivatives)

          E04UCF can be used to solve unconstrained, bound-constrained and
          linearly-constrained problems.

          E04NAF can be used as a comprehensive linear programming solver;
          however, in most cases the easy-to-use routine E04MBFwill be
          adequate.

          E04MBF can be used to obtain a feasible point for a set of linear
          constraints.

          E04DGF can be used to solve large scale unconstrained problems.

          The routines can be used to solve problems in a single variable.

          3.2. Service Routines

          One of the most common errors in use of optimization routines is
          that the user's subroutines incorrectly evaluate the relevant
          partial derivatives. Because exact gradient information normally
          enhances efficiency in all areas of optimization, the user should
          be encouraged to provide analytical derivatives whenever
          possible. However, mistakes in the computation of derivatives can
          result in serious and obscure run-time errors, as well as
          complaints that the Library routines are incorrect.

          E04UCF incorporates a check on the gradients being supplied and
          users are encouraged to utilize this option; E04GCF also
          incorporates a call to a derivative checker.

          E04YCF estimates selected elements of the variance-covariance
          matrix for the computed regression parameters following the use
          of a nonlinear least-squares routine.

          3.3. Function Evaluations at Infeasible Points

          Users must not assume that the routines for constrained problems
          will require the objective function to be evaluated only at
          points which satisfy the constraints, i.e., feasible points. In
          the first place some of the easy-to-use routines call a service
          routine which will evaluate the objective function at the user-
          supplied initial point, and at neighbouring points (to check
          user-supplied derivatives or to estimate intervals for finite
          differencing). Apart from this, all routines will ensure that any
          evaluations of the objective function occur at points which
          approximately satisfy any simple bounds or linear constraints.
          Satisfaction of such constraints is only approximate because:

          (a)   routines which have a parameter FEATOL may allow such
                constraints to be violated by a margin specified by FEATOL;

          (b)   routines which estimate derivatives by finite differences
                may require function evaluations at points which just
                violate such constraints even though the current iteration
                just satisfies them.

          There is no attempt to ensure that the current iteration
          satisfies any nonlinear constraints. Users who wish to prevent
          their objective function being evaluated outside some known
          region (where it may be undefined or not practically computable),
          may try to confine the iteration within this region by imposing
          suitable simple bounds or linear constraints (but beware as this
          may create new local minima where these constraints are active).

          Note also that some routines allow the user-supplied routine to
          return a parameter (MODE) with a negative value to force an
          immediate clean exit from the minimization when the objective
          function cannot be evaluated.

          3.4. Related Problems

          Apart from the standard types of optimization problem, there are
          other related problems which can be solved by routines in this or
          other chapters of the Library.

          E04MBF can be used to find a feasible point for a set of linear
          constraints and simple bounds.

          Two routines in Chapter F04 solve linear least-squares problems,
                          m                         n
                          --      2                 --
          i.e., minimize  >  r (x)  where r (x)=b - >  a  x .
                          --  i            i     i  --  ij j
                          i=1                       j=1

          E02GAF solves an overdetermined system of linear equations in the
                                    m
                                    --
          l  norm, i.e., minimizes  >  |r (x)|, with r  as above.
           1                        --   i            i
                                    i=1


          E04 -- Minimizing or Maximizing a Function        Contents -- E04
          Chapter E04

          Minimizing or Maximizing a Function

          E04DGF  Unconstrained minimum, pre-conditioned conjugate gradient
                  algorithm, function of several variables using 1st
                  derivatives

          E04DJF  Read optional parameter values for E04DGF from external
                  file

          E04DKF  Supply optional parameter values to E04DGF

          E04FDF  Unconstrained minimum of a sum of squares, combined
                  Gauss-Newton and modified Newton algorithm using function
                  values only

          E04GCF  Unconstrained minimum of a sum of squares, combined
                  Gauss-Newton and quasi-Newton algorithm, using 1st
                  derivatives

          E04JAF  Minimum, function of several variables, quasi-Newton
                  algorithm, simple bounds, using function values only

          E04MBF  Linear programming problem

          E04NAF  Quadratic programming problem

          E04UCF  Minimum, function of several variables, sequential QP
                  method, nonlinear constraints, using function values and
                  optionally 1st derivatives

          E04UDF  Read optional parameter values for E04UCF from external
                  file

          E04UEF  Supply optional parameter values to E04UCF

          E04YCF  Covariance matrix for nonlinear least-squares problem

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe04dgf}{nage.ht}
{ Minimizes a nonlinear function of several variable}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe04dgf}{NAG Documentation: e04dgf}
\beginscroll
\begin{verbatim}

   
   
   
   E04DGF(3NAG)                 E04DGF                  E04DGF(3NAG)
   
   
   
        E04 -- Minimizing or Maximizing a Function                 E04DGF
                E04DGF -- NAG Foundation Library Routine Document
   
        Note: Before using this routine, please read the Users' Note for
        your implementation to check implementation-dependent details.
        The symbol (*) after a NAG routine name denotes a routine that is
        not included in the Foundation Library.
   
        Note for users via the Axiom system: the interface to this routine
        has been enhanced for use with Axiom and is slightly different to
        that offered in the standard version of the Foundation Library.  In
        particular, the optional parameters of the NAG routine are now
        included in the parameter list.  These are described in section
        5.1.2, below.
   
        1. Purpose
   
        E04DGF minimizes an unconstrained nonlinear function of several
        variables using a pre-conditioned, limited memory quasi-Newton
        conjugate gradient method. First derivatives are required. The
        routine is intended for use on large scale problems.
   
        2. Specification
   
               SUBROUTINE E04DGF(N,OBJFUN,ITER,OBJF,OBJGRD,X,IWORK,WORK,IUSER,
              1                  USER,ES,FU,IT,LIN,LIST,MA,OP,PR,STA,STO,
              2                  VE,IFAIL)
               INTEGER           N, ITER, IWORK(N+1), IUSER(*),
              1                  IT, PR, STA, STO, VE, IFAIL
               DOUBLE PRECISION OBJF, OBJGRD(N), X(N), WORK(13*N), USER(*)
              1                  ES, FU, LIN, OP, MA
               LOGICAL           LIST
               EXTERNAL          OBJFUN
   
        3. Description
   
        E04DGF uses a pre-conditioned conjugate gradient method and is
        based upon algorithm PLMA as described in Gill and Murray [1] and
        Gill et al [2] Section 4.8.3.
   
        The algorithm proceeds as follows:
   
        Let x  be a given starting point and let k denote the current
             0
        iteration, starting with k=0. The iteration requires g , the
                                                              k
        gradient vector evaluated at x , the kth estimate of the minimum.
                                      k
        At each iteration a vector p  (known as the direction of search)
                                    k
        is computed and the new estimate x    is given by x +(alpha) p
                                          k+1              k        k k
        where (alpha)  (the step length) minimizes the function
                     k
        F(x +(alpha) p ) with respect to the scalar (alpha) . A choice of
           k        k k                                    k
        initial step (alpha)  is taken as
                            0
   
                                                    T
                         (alpha) =min{1,2|F -F   |/g g }
                                0          k  est   k k
   
        where F    is a user-supplied estimate of the function value at
               est
        the solution. If F    is not specified, the software always
                          est
        chooses the unit step length for (alpha) . Subsequent step length
                                                0
        estimates are computed using cubic interpolation with safeguards.
   
        A quasi-Newton method can be used to compute the search direction
        p  by updating the inverse of the approximate Hessian (H ) and
         k                                                      k
        computing
   
                               p   =-H   g                            (1)
                                k+1   k+1 k+1
   
        The updating formula for the approximate inverse is given by
   
                                               (    T    )
                                               (   y H y )
                       1  (     T    T  )   1  (    k k k)   T
             H   =H - ----(H y s +s y H )+ ----(1+ ------)s s         (2)
              k+1  k   T  ( k k k  k k k)   T  (     T   ) k k
                      y s                  y s (    y s  )
                       k k                  k k(     k k )
   
        where y =g   -g  and s =x   -x =(alpha) p .
               k  k-1  k      k  k+1  k        k k
   
        The method used by E04DGF to obtain the search direction is based
        upon computing p    as -H   g    where H    is a matrix obtained
                        k+1      k+1 k+1        k+1
        by updating the identity matrix with a limited number of quasi-
        Newton corrections. The storage of an n by n matrix is avoided by
        storing only the vectors that define the rank two corrections -
        hence the term limited-memory quasi-Newton method. The precise
        method depends upon the number of updating vectors stored. For
        example, the direction obtained with the 'one-step' limited
        memory update is given by (1) using (2) with H  equal to the
                                                      k
        identity matrix, viz.
                                                   T    (    T  )
                                                  s g   (   y y )
                          1  ( T        T      )   k k+1(    k k)
             p   =-g   + ----(s g   y +y g   s )- ------(1+ ----)s
              k+1   k+1   T  ( k k+1 k  k k+1 k)    T   (    T  ) k
                         y s                       y s  (   y s )
                          k k                       k k (    k k)
   
        E04DGF uses a two-step method described in detail in Gill and
        Murray [1] in which restarts and pre-conditioning are
        incorporated. Using a limited-memory quasi-Newton formula, such
        as the one above, guarantees p    to be a descent direction if
                                      k+1
                                T
        all the inner products y  are positive for all vectors y  and s
                                k                               k      k
        used in the updating formula.
   
        The termination criterion of E04DGF is as follows:
   
        Let (tau)  specify a parameter that indicates the number of
                 F
        correct figures desired in F  ((tau)  is equivalent to Optimality
                                    k       F
        Tolerance in the optional parameter list, see Section 5.1). If
        the following three conditions are satisfied
   
             (i) F   -F <(tau) (1+|F |)
                  k-1  k      F     k
   
                                 ______
             (ii) ||x   -x ||<  /(tau)  (1+||x ||)
                     k-1  k   \/      F       k
   
                               ______
             (iii) ||g ||<= 3 /(tau)  (1+|F |) or ||g ||<(epsilon) ,
                      k     \/      F      k         k            A
             where (epsilon)  is the absolute error associated with
                            A
             computing the objective function
   
        then the algorithm is considered to have converged. For a full
        discussion on termination criteria see Gill et al [2] Chapter 8.
   
        4. References
   
        [1]   Gill P E and Murray W (1979) Conjugate-gradient Methods for
              Large-scale Nonlinear Optimization. Technical Report SOL 79-
              15. Department of Operations Research, Stanford University.
   
        [2]   Gill P E, Murray W and Wright M H (1981) Practical
              Optimization. Academic Press.
   
        5. Parameters
   
         1:  N -- INTEGER                                           Input
             On entry: the number n of variables. Constraint: N >= 1.
   
         2:  OBJFUN -- SUBROUTINE, supplied by the user.
                                                       External Procedure
             OBJFUN must calculate the objective function F(x) and its
             gradient for a specified n element vector x.
   
             Its specification is:
   
                    SUBROUTINE OBJFUN (MODE, N, X, OBJF, OBJGRD,
                   1                   NSTATE, IUSER, USER)
                    INTEGER          MODE, N, NSTATE, IUSER(*)
                    DOUBLE PRECISION X(N), OBJF, OBJGRD(N), USER(*)
   
              1:  MODE -- INTEGER                            Input/Output
                  MODE is a flag that the user may set within OBJFUN to
                  indicate a failure in the evaluation of the objective
                  function. On entry: MODE is always non-negative. On
                  exit: if MODE is negative the execution of E04DGF is
                  terminated with IFAIL set to MODE.
   
              2:  N -- INTEGER                                      Input
                  On entry: the number n of variables.
   
              3:  X(N) -- DOUBLE PRECISION array                    Input
                  On entry: the point x at which the objective function
                  is required.
   
              4:  OBJF -- DOUBLE PRECISION                         Output
                  On exit: the value of the objective function F at the
                  current point x.
   
              5:  OBJGRD(N) -- DOUBLE PRECISION array              Output
                                                                ddF
                  On exit: OBJGRD(i) must contain the value of  ---- at
                                                                ddx
                                                                   i
                  the point x, for i=1,2,...,n.
   
              6:  NSTATE -- INTEGER                                 Input
                  On entry: NSTATE will be 1 on the first call of OBJFUN
                  by E04DGF, and is 0 for all subsequent calls. Thus, if
                  the user wishes, NSTATE may be tested within OBJFUN in
                  order to perform certain calculations once only. For
                  example the user may read data or initialise COMMON
                  blocks when NSTATE = 1.
   
              7:  IUSER(*) -- INTEGER array                User Workspace
   
              8:  USER(*) -- DOUBLE PRECISION array        User Workspace
                  OBJFUN is called from E04DGF with the parameters IUSER
                  and USER as supplied to E04DGF. The user is free to use
                  arrays IUSER and USER to supply information to OBJFUN
                  as an alternative to using COMMON.
             OBJFUN must be declared as EXTERNAL in the (sub)program
             from which E04DGF is called. Parameters denoted as
             Input must not be changed by this procedure.
   
         3:  ITER -- INTEGER                                       Output
             On exit: the number of iterations performed.
   
         4:  OBJF -- DOUBLE PRECISION                              Output
             On exit: the value of the objective function F(x) at the
             final iterate.
   
         5:  OBJGRD(N) -- DOUBLE PRECISION array                   Output
             On exit: the objective gradient at the final iterate.
   
         6:  X(N) -- DOUBLE PRECISION array                  Input/Output
             On entry: an initial estimate of the solution. On exit: the
             final estimate of the solution.
   
         7:  IWORK(N+1) -- INTEGER array                        Workspace
   
         8:  WORK(13*N) -- DOUBLE PRECISION array               Workspace
   
         9:  IUSER(*) -- INTEGER array                     User Workspace
             Note: the dimension of the array IUSER must be at least 1.
             This array is not used by E04DGF, but is passed directly to
             routine OBJFUN and may be used to supply information to
             OBJFUN.
   
        10:  USER(*) -- DOUBLE PRECISION array             User Workspace
             Note: the dimension of the array USER must be at least 1.
             This array is not used by E04DGF, but is passed directly to
             routine OBJFUN and may be used to supply information to
             OBJFUN.
   
        11:  IFAIL -- INTEGER                                Input/Output
             On entry: IFAIL must be set to 0, -1 or 1. Users who are
             unfamiliar with this parameter should refer to the Essential
             Introduction for details.
   
             On exit: IFAIL = 0 unless the routine detects an error or
             gives a warning (see Section 6).
   
             For this routine, because the values of output parameters
             may be useful even if IFAIL /=0 on exit, users are
             recommended to set IFAIL to -1 before entry. It is then
             essential to test the value of IFAIL on exit.
   
   
        5.1. Optional Input Parameters
   
        Several optional parameters in E04DGF define choices in the
        behaviour of the routine. In order to reduce the number of formal
        parameters of E04DGF these optional parameters have associated
        default values (see Section 5.1.3) that are appropriate for most
        problems. Therefore the user need only specify those optional
        parameters whose values are to be different from their default
        values.
   
        The remainder of this section can be skipped by users who wish to
        use the default values for all optional parameters. A complete
        list of optional parameters and their default values is given in
        Section 5.1.3.
   
        5.1.1. Specification of the Optional Parameters
   
        Optional parameters may be specified by calling one, or both, of
        E04DJF and E04DKF prior to a call to E04DGF.
   
        E04DJF reads options from an external options file, with Begin
        and End as the first and last lines respectively and each
        intermediate line defining a single optional parameter. For
        example,
   
              Begin
                Print Level = 1
              End
   
        The call
   
              CALL E04DJF(IOPTNS, INFORM)
   
        can then be used to read the file on unit IOPTNS. INFORM will be
        zero on successful exit. E04DJF should be consulted for a full
        description of this method of supplying optional parameters.
   
        E04DKF can be called to supply options directly, one call being
        necessary for each optional parameter.
   
        For example,
   
   
              CALL E04DKF(`Print level = 1')
   
   
        E04DKF should be consulted for a full description of this method
        of supplying optional parameters.
   
        All optional parameters not specified by the user are set to
        their default values. Optional parameters specified by the user
        are unaltered by E04DGF (unless they define invalid values) and
        so remain in effect for subsequent calls to E04DGF, unless
        altered by the user.
   
        5.1.2. Description of the Optional Parameters
   
        The following list (in alphabetical order) gives the valid
        options. For each option, we give the keyword, any essential
        optional qualifiers, the default value, and the definition. The
        minimum valid abbreviation of each keyword is underlined. If no
        characters of an optional qualifier are underlined, the qualifier
        may be omitted. The letter a denotes a phrase (character string)
        that qualifies an option. The letters i and r denote INTEGER and
        real values required with certain options. The number (epsilon)
        is a generic notation for machine precision, and (epsilon)
                                                                  R
        denotes the relative precision of the objective function (the
        optional parameter Function Precision; see below).
   
        Defaults
   
        This special keyword may be used to reset the default values
        following a call to E04DGF.
   
        Estimated Optimal Function Value r
   
           (Axiom parameter ES)
   
        This value of r specifies the user-supplied guess of the optimum
        objective function value. This value is used by E04DGF to
        calculate an initial step length (see Section 3). If the value of
        r is not specified by the user (the default), then this has the
        effect of setting the initial step length to unity. It should be
        noted that for badly scaled functions a unit step along the
        steepest descent direction will often compute the function at
        very large values of x.
   
                                                 0.9
        Function Precision  r Default = (epsilon)
   
           (Axiom parameter FU)
   
        The parameter defines (epsilon) , which is intended to be a
                                       R
        measure of the accuracy with which the problem function F can be
        computed. The value of (epsilon)  should reflect the relative
                                        R
        precision of 1+|F(x)|; i.e. (epsilon)  acts as a relative
                                             R
        precision when |F| is large, and as an absolute precision when
        |F| is small. For example, if F(x) is typically of order 1000 and
        the first six significant digits are known to be correct, an
        appropriate value for (epsilon)  would be 1.0E-6. In contrast, if
                                       R
                                     -4
        F(x) is typically of order 10   and the first six significant
        digits are known to be correct, an appropriate value for
        (epsilon)  would be 1.0E-10. The choice of (epsilon)  can be
                 R                                          R
        quite complicated for badly scaled problems; see Chapter 8 of
        Gill and Murray [2], for a discussion of scaling techniques. The
        default value is appropriate for most simple functions that are
        computed with full accuracy. However when the accuracy of the
        computed function values is known to be significantly worse than
        full precision, the value of (epsilon)  should be large enough so
                                              R
        that E04DGF will not attempt to distinguish between function
        values that differ by less than the error inherent in the
        calculation. If 0<=r<(epsilon), where (epsilon) is the machine
        precision then the default value is used.
   
        Iteration Limit  i Default = max(50,5n)
   
        Iters
   
        Itns
   
           (Axiom parameter IT)
   
        The value i (i>=0) specifies the maximum number of iterations
        allowed before termination. If i<0 the default value is used. See
        Section 8 for further information.
   
        Linesearch Tolerance  r Default = 0.9
   
           (Axiom parameter LIN)
   
        The value r (0<=r<1) controls the accuracy with which the step
        (alpha) taken during each iteration approximates a minimum of the
        function along the search direction (the smaller the value of r,
        the more accurate the linesearch). The default value r=0.9
        requests an inaccurate search, and is appropriate for most
        problems. A more accurate search may be appropriate when it is
        desirable to reduce the number of iterations - for example, if
        the objective function is cheap to evaluate.
   
        List     Default =  List
        Nolist
   
           (Axiom parameter LIST)
   
        Normally each optional parameter specification is printed as it
        is supplied. Nolist may be used to suppress the printing and List
        may be used to restore printing.
                                           10
        Maximum Step Length  r Default = 10
   
           (Axiom parameter MA)
   
        The value r (r>0) defines the maximum allowable step length for
        the line search. If r<=0 the default value is used.
   
                                                   0.8
        Optimality Tolerance  r Default = (epsilon)
   
           (Axiom parameter OP)
                                                   R
   
        The parameter r ((epsilon) <=r<1) specifies the accuracy to which
                                  R
        the user wishes the final iterate to approximate a solution of
        the problem. Broadly speaking, r indicates the number of correct
        figures desired in the objective function at the solution. For
                           - 6
        example, if r is 10    and E04DGF terminates successfully, the
        final value of F should have approximately six correct figures.
        E04DGF will terminate successfully if the iterative sequence of x
        -values is judged to have converged and the final point satisfies
        the termination criteria (see Section 3, where (tau)  represents
                                                            F
        Optimality Tolerance).
   
        Print Level  i Default = 10
   
           (Axiom parameter PR)
   
        The value i controls the amount of printout produced by E04DGF.
        The following levels of printing are available.
   
        i     Output.
   
        0     No output.
   
        1     The final solution.
   
        5     One line of output for each iteration.
   
        10    The final solution and one line of output for each
              iteration.
   
        Start Objective Check at Variable  i Default = 1
   
           (Axiom parameter STA)
   
        Stop Objective Check at Variable  i Default = n
   
           (Axiom parameter STO)
   
        These keywords take effect only if Verify Level > 0 (see below).
        They may be used to control the verification of gradient elements
        computed by subroutine OBJFUN. For example if the first 30
        variables appear linearly in the objective, so that the
        corresponding gradient elements are constant, then it is
        reasonable to specify Start Objective Check at Variable  31.
   
        Verify Level  i Default = 0
   
        Verify                           No
   
        Verify Level                     -1
   
        Verify Level                     0
   
        Verify
   
        Verify                           Yes
   
        Verify Objective Gradients
   
        Verify Gradients
   
        Verify Level                     1
   
           (Axiom parameter VE)
   
        These keywords refer to finite-difference checks on the gradient
        elements computed by the user-provided subroutine OBJFUN. It is
        possible to set Verify Level in several ways, as indicated above.
        For example, the gradients will be verified if Verify, Verify
        Yes, Verify Gradients, Verify Objective Gradients or Verify Level
        = 1 is specified.
   
        If i<0 then no checking will be performed. If i>0 then the
        gradients will be verified at the user-supplied point. If i=0
        only a 'cheap' test will be performed, requiring one call to
        OBJFUN. If i=1, a more reliable (but more expensive) check will
        be made on individual gradient components, within the ranges
        specified by the Start and Stop keywords as described above. A
        result of the form OK or BAD? is printed by E04DGF to indicate
        whether or not each component appears to be correct.
   
        5.1.3. Optional parameter checklist and default values
   
        For easy reference, the following sample list shows all valid
        keywords and their default values. The default options Function
        Precision and Optimality Tolerance depend upon (epsilon), the
        machine precision.
   
        Optional Parameters          Default Values
   
        Estimated Optimal Function
        Value
   
                                              0.9
        Function precision           (epsilon)
   
        Iterations                   max(50,5n)
   
        Linesearch Tolerance         0.9
   
                                       10
        Maximum Step Length          10
   
        List/Nolist                  List
   
                                              0.8
        Optimality Tolerance         (epsilon)
   
        Print Level                  10
   
        Start Objective Check at     1
        Variable
   
        Stop Objective Check at      n
        Variable
   
        Verify Level                 0
   
        5.2. Description of Printed Output
   
        The level of printed output from E04DGF is controlled by the user
        (see the description of Print Level in Section 5.1).
   
        When Print Level >= 5, the following line of output is produced
        at each iteration.
   
        Itn            is the iteration count.
   
        Step           is the step (alpha) taken along the computed
                       search direction. On reasonably well-behaved
                       problems, the unit step will be taken as the
                       solution is approached.
   
        Nfun           is the cumulated number of evaluations of the
                       objective function needed for the linesearch.
                       Evaluations needed for the estimation of the
                       gradients by finite differences are not included.
                       Nfun is printed as a guide to the amount of work
                       required for the linesearch. E04DGF will perform
                       at most 16 function evaluations per iteration.
   
        Objective      is the value of the objective function.
   
        Norm G         is the Euclidean norm of the gradient of the
                       objective function.
   
        Norm X         is the Euclidean norm of x.
   
        Norm (X(k-1)-X(k)) is the Euclidean norm of x   -x .
                                                     k-1  k
   
        When Print Level = 1 or Print Level >= 10 then the solution at
        the end of execution of E04DGF is printed out.
   
        The following describes the printout for each variable:
   
        Variable       gives the name (VARBL) and index j (j = 1 to n) of
                       the variable
   
        Value          is the value of the variable at the final iterate
   
        Gradient Value is the value of the gradient of the objective
                       function with respect to the jth variable at the
                       final iterate
   
        6. Error Indicators and Warnings
   
        Errors or warnings specified by the routine:
   
        If on entry IFAIL = 0 or -1, explanatory error messages are
        output on the current error message unit (as defined by X04AAF).
   
        On exit from E04DGF, IFAIL should be tested. If Print Level > 0
        then a short description of IFAIL is printed.
   
        Errors and diagnostics indicated by IFAIL from E04DGF are as
        follows:
   
        IFAIL< 0
             A negative value of IFAIL indicates an exit from E04DGF
             because the user set MODE negative in routine OBJFUN. The
             value of IFAIL will be the same as the user's setting of
             MODE.
   
        IFAIL= 1
             Not used by this routine.
   
        IFAIL= 2
             Not used by this routine.
   
        IFAIL= 3
             The maximum number of iterations has been performed. If the
             algorithm appears to be making progress the iterations value
             may be too small (see Section 5.1.2) so the user should
             increase iterations and rerun E04DGF. If the algorithm seems
             to be 'bogged down',the user should check for incorrect
             gradients or ill-conditioning as described below under IFAIL
             = 6.
   
        IFAIL= 4
             The computed upper bound on the step length taken during the
             linesearch was too small. A rerun with an increased value of
             the Maximum Step Length ((rho) say) may be successful unless
                      10
             (rho)>=10   (the default value), in which case the current
             point cannot be improved upon.
   
        IFAIL= 5
             Not used by this routine.
   
        IFAIL= 6
             A sufficient decrease in the function value could not be
             attained during the final linesearch. If the subroutine
             OBJFUN computes the function and gradients correctly, then
             this may occur because an overly stringent accuracy has been
             requested, i.e., Optimality Tolerance is too small or if the
             minimum lies close to a step length of zero. In this case
             the user should apply the four tests described in Section 3
             to determine whether or not the final solution is acceptable
             (the user will need to set Print Level >= 5). For a
             discussion of attainable accuracy see Gill and Murray [2].
   
             If many iterations have occurred in which essentially no
             progress has been made or E04DGF has failed to move from the
             initial point, subroutine OBJFUN may be incorrect. The user
             should refer to the comments below under IFAIL = 7 and check
             the gradients using the Verify parameter. Unfortunately,
             there may be small errors in the objective gradients that
             cannot be detected by the verification process. Finite-
             difference approximations to first derivatives are
             catastrophically affected by even small inaccuracies.
   
        IFAIL= 7
             Large errors were found in the derivatives of the objective
             function. This value of IFAIL will occur if the verification
             process indicated that at least one gradient component had
             no correct figures. The user should refer to the printed
             output to determine which elements are suspected to be in
             error.
   
             As a first step, the user should check that the code for the
             objective values is correct - for example, by computing the
             function at a point where the correct value is known.
             However, care should be taken that the chosen point fully
             tests the evaluation of the function. It is remarkable how
             often the values x=0 or x=1 are used to test function
             evaluation procedures, and how often the special properties
             of these numbers make the test meaningless.
   
             Special care should be used in this test if computation of
             the objective function involves subsidiary data communicated
             in COMMON storage. Although the first evaluation of the
             function may be correct, subsequent calculations may be in
             error because some of the subsidiary data has accidentally
             been overwritten.
   
             Errors in programming the function may be quite subtle in
             that the function value is 'almost' correct. For example,
             the function may not be accurate to full precision because
             of the inaccurate calculation of a subsidiary quantity, or
             the limited accuracy of data upon which the function
             depends. A common error on machines where numerical
             calculations are usually performed in double precision is to
             include even one single-precision constant in the
             calculation of the function; since some compilers do not
             convert such constants to double precision, half the correct
             figures may be lost by such a seemingly trivial error.
   
        IFAIL= 8
             The gradient (g) at the starting point is too small. The
                    T
             value g g is less than (epsilon) |F(x )|, where (epsilon)
                                             m    o                   m
             is the machine precision.
   
             The problem should be rerun at a different starting point.
   
        IFAIL= 9
             On entry N < 1.
   
        7. Accuracy
   
        On successful exit the accuracy of the solution will be as
        defined by the optional parameter Optimality Tolerance.
   
        8. Further Comments
   
        Problems whose Hessian matrices at the solution contain sets of
        clustered eigenvalues are likely to be minimized in significantly
        fewer than n iterations. Problems without this property may
        require anything between n and 5n iterations, with approximately
        2n iterations being a common figure for moderately difficult
        problems.
   
        9. Example
   
        To find a minimum of the function
   
                              x
                               1   2   2
                           F=e  (4x +2x +4x x +2x +1).
                                   1   2   1 2   2
   
        The example program is not reproduced here. The source code for
        all example programs is distributed with the NAG Foundation
        Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe04djf}{nage.ht}
{ Supply optional parameters to E04DGF from file}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe04djf}{NAG Documentation: e04djf}
\beginscroll
\begin{verbatim}



     E04DJF(3NAG)      Foundation Library (12/10/92)      E04DJF(3NAG)



          E04 -- Minimizing or Maximizing a Function                 E04DJF
                  E04DJF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          To supply optional parameters to E04DGF from an external file.

          2. Specification

                 SUBROUTINE E04DJF (IOPTNS, INFORM)
                 INTEGER          IOPTNS, INFORM

          3. Description

          E04DJF may be used to supply values for optional parameters to
          E04DGF. E04DJF reads an external file and each line of the file
          defines a single optional parameter. It is only necessary to
          supply values for those parameters whose values are to be
          different from their default values.

          Each optional parameter is defined by a single character string
          of up to 72 characters, consisting of one or more items. The
          items associated with a given option must be separated by spaces,
          or equal signs (=). Alphabetic characters may be upper or lower
          case. The string

                Print level = 1

          is an example of a string used to set an optional parameter. For
          each option the string contains one or more of the following
          items:

          (a)   A mandatory keyword.

          (b)   A phrase that qualifies the keyword.

          (c)   A number that specifies an INTEGER or real value. Such
                numbers may be up to 16 contiguous characters in Fortran
                77's I, F, E or D formats, terminated by a space if this is
                not the last item on the line.

          Blank strings and comments are ignored. A comment begins with an
          asterisk (*) and all subsequent characters in the string are
          regarded as part of the comment.

          The file containing the options must start with begin and must
          finish with end An example of a valid options file is:

                Begin * Example options file
                  Print level = 10
                End


          Normally each line of the file is printed as it is read, on the
          current advisory message unit (see X04ABF), but printing may be
          suppressed using the keyword nolist. To suppress printing of
          begin, nolist must be the first option supplied as in the file:

                Begin
                  Nolist
                  Print level = 10
                End

          Printing will automatically be turned on again after a call to
          E04DGF and may be turned on again at any time by the user by
          using the keyword list.

          Optional parameter settings are preserved following a call to
          E04DGF, and so the keyword defaults is provided to allow the user
          to reset all the optional parameters to their default values
          prior to a subsequent call to E04DGF.

          A complete list of optional parameters, their abbreviations,
          synonyms and default values is given in Section 5.1 of the
          routine document for E04DGF.

          4. References

          None.

          5. Parameters

           1:  IOPTNS -- INTEGER                                      Input
               On entry: IOPTNS must be the unit number of the options
               file. Constraint: 0 <= IOPTNS <= 99.

           2:  INFORM -- INTEGER                                     Output
               On exit: INFORM will be zero if an options file with the
               correct structure has been read. Otherwise INFORM will be
               positive. Positive values of INFORM indicate that an options
               file may not have been successfully read as follows:
               INFORM = 1
                     IOPTNS is not in the range [0,99].

               INFORM = 2
                     begin was found, but end-of-file was found before end
                     was found.

               INFORM = 3
                     end-of-file was found before begin was found.

          6. Error Indicators and Warnings

          If a line is not recognised as a valid option, then a warning
          message is output on the current advisory message unit (see
          X04ABF).

          7. Accuracy

          Not applicable.

          8. Further Comments

          E04DKF may also be used to supply optional parameters to E04DGF.

          9. Example

          See the example for E04DGF.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe04dkf}{nage.ht}
{ Supply individual optional params to E04DGF}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe04dkf}{NAG Documentation: e04dkf}
\beginscroll
\begin{verbatim}



     E04DKF(3NAG)      Foundation Library (12/10/92)      E04DKF(3NAG)



          E04 -- Minimizing or Maximizing a Function                 E04DKF
                  E04DKF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          To supply individual optional parameters to E04DGF.

          2. Specification

                 SUBROUTINE E04DKF (STRING)
                 CHARACTER*(*)    STRING

          3. Description

          E04DKF may be used to supply values for optional parameters to
          E04DGF. It is only necessary to call E04DKF for those parameters
          whose values are to be different from their default values. One
          call to E04DKF sets one parameter value.

          Each optional parameter is defined by a single character string
          of up to 72 characters, consisting of one or more items. The
          items associated with a given option must be separated by spaces,
          or equal signs (=). Alphabetic characters may be upper or lower
          case. The string

                Print Level = 1

          is an example of a string used to set an optional parameter. For
          each option the string contains one or more of the following
          items:

          (a)   A mandatory keyword.

          (b)   A phrase that qualifies the keyword.

          (c)   A number that specifies an INTEGER or real value. Such
                numbers may be up to 16 contiguous characters in Fortran
                77's I, F, E or D formats, terminated by a space if this is
                not the last item on the line.

          Blank strings and comments are ignored. A comment begins with an
          asterisk (*) and all subsequent characters in the string are
          regarded as part of the comment.

          Normally, each user-specified option is printed as it is defined,
          on the current advisory message unit (see X04ABF), but this
          printing may be suppressed using the keyword nolist Thus the
          statement

               CALL E04DKF (`Nolist')

          suppresses printing of this and subsequent options. Printing will
          automatically be turned on again after a call to E04DGF, and may
          be turned on again at any time by the user, by using the keyword
          list.

          Optional parameter settings are preserved following a call to
          E04DGF, and so the keyword defaults is provided to allow the user
          to reset all the optional parameters to their default values by
          the statement,

               CALL E04DKF (`Defaults')

          prior to a subsequent call to E04DGF.

          A complete list of optional parameters, their abbreviations,
          synonyms and default values is given in Section 5.1 of the
          routine document for E04DGF.

          4. References

          None.

          5. Parameters

           1:  STRING -- CHARACTER*(*)                                Input
               On entry: STRING must be a single valid option string. See
               Section 3 above, and Section 5.1 of the routine document for
               E04DGF.

          6. Error Indicators and Warnings

          If the parameter STRING is not recognised as a valid option
          string, then a warning message is output on the current advisory
          message unit (see X04ABF).

          7. Accuracy

          Not applicable.

          8. Further Comments

          E04DJF may also be used to supply optional parameters to E04DGF.

          9. Example

          See the example for E04DGF.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe04fdf}{nage.ht}
{ Finding an unconstrained minimum of a sum of squares}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe04fdf}{NAG Documentation: e04fdf}
\beginscroll
\begin{verbatim}



     E04FDF(3NAG)      Foundation Library (12/10/92)      E04FDF(3NAG)



          E04 -- Minimizing or Maximizing a Function                 E04FDF
                  E04FDF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E04FDF is an easy-to-use algorithm for finding an unconstrained
          minimum of a sum of squares of m nonlinear functions in n
          variables (m>=n). No derivatives are required.

          It is intended for functions which are continuous and which have
          continuous first and second derivatives (although it will usually
          work even if the derivatives have occasional discontinuities).

          2. Specification

                 SUBROUTINE E04FDF (M, N, X, FSUMSQ, IW, LIW, W, LW, IFAIL)
                 INTEGER          M, N, IW(LIW), LIW, LW, IFAIL
                 DOUBLE PRECISION X(N), FSUMSQ, W(LW)

          3. Description

          This routine is essentially identical to the subroutine LSNDN1 in
          the National Physical Laboratory Algorithms Library. It is
          applicable to problems of the form

                                            m
                                            --        2
                             Minimize F(x)= >  [f (x)]
                                            --   i
                                            i=1

                                T
          where x=(x ,x ,...,x )  and m>=n. (The functions f (x) are often
                    1  2      n                             i
          referred to as 'residuals'.) The user must supply a subroutine
          LSFUN1 to evaluate functions f (x) at any point x.
                                        i

          From a starting point supplied by the user, a sequence of points
          is generated which is intended to converge to a local minimum of
          the sum of squares. These points are generated using estimates of
          the curvature of F(x).

          4. References

          [1]   Gill P E and Murray W (1978) Algorithms for the Solution of
                the Nonlinear Least-squares Problem. SIAM J. Numer. Anal. 15
                977--992.

          5. Parameters

           1:  M -- INTEGER                                           Input

           2:  N -- INTEGER                                           Input
               On entry: the number m of residuals f (x), and the number n
                                                    i
               of variables, x . Constraint: 1 <= N <= M.
                              j

           3:  X(N) -- DOUBLE PRECISION array                  Input/Output
               On entry: X(j) must be set to a guess at the jth component
               of the position of the minimum, for j=1,2,...,n. On exit:
               the lowest point found during the calculations. Thus, if
               IFAIL = 0 on exit, X(j) is the jth component of the position
               of the minimum.

           4:  FSUMSQ -- DOUBLE PRECISION                            Output
               On exit: the value of the sum of squares, F(x),
               corresponding to the final point stored in X.

           5:  IW(LIW) -- INTEGER array                           Workspace

           6:  LIW -- INTEGER                                         Input
               On entry: the length of IW as declared in the (sub)program
               from which E04FDF has been called. Constraint: LIW >= 1.

           7:  W(LW) -- DOUBLE PRECISION array                    Workspace

           8:  LW -- INTEGER                                          Input
               On entry: the length of W as declared in the (sub)program
               from which E04FDF is called. Constraints:
                    LW >= N*(7 + N + 2*M + (N-1)/2) + 3*M, if N > 1,

                    LW >= 9 + 5*>M, if N = 1.

           9:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. Users who are
               unfamiliar with this parameter should refer to the Essential
               Introduction for details.

               On exit: IFAIL = 0 unless the routine detects an error or
               gives a warning (see Section 6).

               For this routine, because the values of output parameters
               may be useful even if IFAIL /=0 on exit, users are
               recommended to set IFAIL to -1 before entry. It is then
               essential to test the value of IFAIL on exit.

          5.1. Optional Parameters

               LSFUN1 -- SUBROUTINE, supplied by the user.
                                                         External Procedure
               This routine must be supplied by the user to calculate the
               vector of values f (x) at any point x. Since the routine is
                                 i
               not a parameter to E04FDF, it must be called LSFUN1. It
               should be tested separately before being used in conjunction
               with E04FDF (see the Chapter Introduction).

               Its specification is:

                      SUBROUTINE LSFUN1 (M, N, XC, FVECC)
                      INTEGER          M, N
                      DOUBLE PRECISION XC(N), FVECC(M)

                1:  M -- INTEGER                                      Input

                2:  N -- INTEGER                                      Input
                    On entry: the numbers m and n of residuals and
                    variables, respectively.

                3:  XC(N) -- DOUBLE PRECISION array                   Input
                    On entry: the point x at which the values of the f
                                                                       i
                    are required.

                4:  FVECC(M) -- DOUBLE PRECISION array               Output
                    On exit: FVECC(i) must contain the value of f  at the
                                                                 i
                    point x, for i=1,2,...,m.
               LSFUN1 must be declared as EXTERNAL in the (sub)program
               from which E04FDF is called. Parameters denoted as
               Input must not be changed by this procedure.

          6. Error Indicators and Warnings

          Errors or warnings specified by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry N < 1,

               or       M < N,

               or       LIW < 1,

               or       LW < N*(7 + N + 2*M + (N-1)/2) + 3*M, when N > 1,

               or       LW < 9 + 5*>M, when N = 1.

          IFAIL= 2
               There have been 400*n calls of LSFUN1, yet the algorithm
               does not seem to have converged. This may be due to an
               awkward function or to a poor starting point, so it is worth
               restarting E04FDF from the final point held in X.

          IFAIL= 3
               The final point does not satisfy the conditions for
               acceptance as a minimum, but no lower point could be found.

          IFAIL= 4
               An auxiliary routine has been unable to complete a singular
               value decomposition in a reasonable number of sub-
               iterations.

          IFAIL= 5

          IFAIL= 6

          IFAIL= 7

          IFAIL= 8
               There is some doubt about whether the point x found by
               E04FDF is a minimum of F(x). The degree of confidence in the
               result decreases as IFAIL increases. Thus when IFAIL = 5, it
               is probable that the final x gives a good estimate of the
               position of a minimum, but when IFAIL = 8 it is very
               unlikely that the routine has found a minimum.

          If the user is not satisfied with the result (e.g. because IFAIL
          lies between 3 and 8), it is worth restarting the calculations
          from a different starting point (not the point at which the
          failure occurred) in order to avoid the region which caused the
          failure. Repeated failure may indicate some defect in the
          formulation of the problem.

          7. Accuracy

          If the problem is reasonably well scaled and a successful exit is
          made, then, for a computer with a mantissa of t decimals, one
          would expect to get about t/2-1 decimals accuracy in the
          components of x and between t-1 (if F(x) is of order 1 at the
          minimum) and 2t-2 (if F(x) is close to zero at the minimum)
          decimals accuracy in F(x).

          8. Further Comments

          The number of iterations required depends on the number of
          variables, the number of residuals and their behaviour, and the
          distance of the starting point from the solution. The number of
          multiplications performed per iteration of E04FDF varies, but for
                                   2    3
          m>>n is approximately n*m +O(n ). In addition, each iteration
          makes at least n+1 calls of LSFUN1. So, unless the residuals can
          be evaluated very quickly, the run time will be dominated by the
          time spent in LSFUN1.

          Ideally, the problem should be scaled so that the minimum value
          of the sum of squares is in the range (0,1), and so that at
          points a unit distance away from the solution the sum of squares
          is approximately a unit value greater than at the minimum. It is
          unlikely that the user will be able to follow these
          recommendations very closely, but it is worth trying (by
          guesswork), as sensible scaling will reduce the difficulty of the
          minimization problem, so that E04FDF will take less computer
          time.

          When the sum of squares represents the goodness of fit of a
          nonlinear model to observed data, elements of the variance-
          covariance matrix of the estimated regression coefficients can be
          computed by a subsequent call to E04YCF, using information
          returned in segments of the workspace array W. See E04YCF for
          further details.

          9. Example

          To find least-squares estimates of x , x  and x  in the model
                                              1   2      3

                                            t
                                             1
                                   y=x + ---------
                                      1  x t +x t
                                          2 2  3 3

          using the 15 sets of data given in the following table.

                                  y    t   t    t
                                        1   2    3
                                 0.14  1.0 15.0 1.0
                                 0.18  2.0 14.0 2.0
                                 0.22  3.0 13.0 3.0
                                 0.25  4.0 12.0 4.0
                                 0.29  5.0 11.0 5.0
                                 0.32  6.0 10.0 6.0
                                 0.35  7.0  9.0 7.0
                                 0.39  8.0  8.0 8.0
                                 0.37  9.0  7.0 7.0
                                 0.58 10.0  6.0 6.0
                                 0.73 11.0  5.0 5.0
                                 0.96 12.0  4.0 4.0
                                 1.34 13.0  3.0 3.0
                                 2.10 14.0  2.0 2.0
                                 4.39 15.0  1.0 1.0

          The program uses (0.5, 1.0, 1.5) as the initial guess at the
          position of the minimum.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe04gcf}{nage.ht}
{ Finding an unconstrained minimum of a sum of squares}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe04gcf}{NAG Documentation: e04gcf}
\beginscroll
\begin{verbatim}



     E04GCF(3NAG)      Foundation Library (12/10/92)      E04GCF(3NAG)



          E04 -- Minimizing or Maximizing a Function                 E04GCF
                  E04GCF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E04GCF is an easy-to-use quasi-Newton algorithm for finding an
          unconstrained minimum of a sum of squares of m nonlinear
          functions in n variables (m>=n). First derivatives are required.

          It is intended for functions which are continuous and which have
          continuous first and second derivatives (although it will usually
          work even if the derivatives have occasional discontinuities).

          2. Specification

                 SUBROUTINE E04GCF (M, N, X, FSUMSQ, IW, LIW, W, LW, IFAIL)
                 INTEGER          M, N, IW(LIW), LIW, LW, IFAIL
                 DOUBLE PRECISION X(N), FSUMSQ, W(LW)

          3. Description

          This routine is essentially identical to the subroutine LSFDQ2 in
          the National Physical Laboratory Algorithms Library. It is
          applicable to problems of the form

                                             m
                                             --        2
                             Minimize  F(x)= >  [f (x)]
                                             --   i
                                             i=1

                                T
          where x=(x ,x ,...,x )  and m>=n. (The functions f (x) are often
                    1  2      n                             i
          referred to as 'residuals'.) The user must supply a subroutine
          LSFUN2 to evaluate the residuals and their first derivatives at
          any point x.

          Before attempting to minimize the sum of squares, the algorithm
          checks LSFUN2 for consistency. Then, from a starting point
          supplied by the user, a sequence of points is generated which is
          intended to converge to a local minimum of the sum of squares.
          These points are generated using estimates of the curvature of
          F(x).

          4. References

          [1]   Gill P E and Murray W (1978) Algorithms for the Solution of
                the Nonlinear Least-squares Problem. SIAM J. Numer. Anal. 15
                977--992.

          5. Parameters

           1:  M -- INTEGER                                           Input

           2:  N -- INTEGER                                           Input
               On entry: the number m of residuals f (x), and the number n
                                                    i
               of variables, x . Constraint: 1 <= N <= M.
                              j

           3:  X(N) -- DOUBLE PRECISION array                  Input/Output
               On entry: X(j) must be set to a guess at the jth component
               of the position of the minimum, for j=1,2,...,n. The routine
               checks the first derivatives calculated by LSFUN2 at the
               starting point, and so is more likely to detect an error in
               the user's routine if the initial X(j) are non-zero and
               mutually distinct. On exit: the lowest point found during
               the calculations. Thus, if IFAIL = 0 on exit, X(j) is the j
               th component of the position of the minimum.

           4:  FSUMSQ -- DOUBLE PRECISION                            Output
               On exit: the value of the sum of squares, F(x),
               corresponding to the final point stored in X.

           5:  IW(LIW) -- INTEGER array                           Workspace

           6:  LIW -- INTEGER                                         Input
               On entry: the length of IW as declared in the (sub)program
               from which E04GCF is called. Constraint: LIW >= 1.

           7:  W(LW) -- DOUBLE PRECISION array                    Workspace

           8:  LW -- INTEGER                                          Input
               On entry: the length of W as declared in the (sub)program
               from which E04GCF is called. Constraints:
                    LW >= 2*N*(4 + N + M) + 3*M, if N > 1,

                    LW >= 11 + 5*M, if N = 1.

           9:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. Users who are
               unfamiliar with this parameter should refer to the Essential
               Introduction for details.

               On exit: IFAIL = 0 unless the routine detects an error or
               gives a warning (see Section 6).

               For this routine, because the values of output parameters
               may be useful even if IFAIL /=0 on exit, users are
               recommended to set IFAIL to -1 before entry. It is then
               essential to test the value of IFAIL on exit.

          5.1. Optional Parameters

               LSFUN2 -- SUBROUTINE, supplied by the user.
                                                         External Procedure
               This routine must be supplied by the user to calculate the
               vector of values f (x) and the Jacobian matrix of first
                                 i
                            ddf
                               i
               derivatives  ---- at any point x. Since the routine is not a
                            ddx
                               j
               parameter to E04GCF, it must be called LSFUN2. It should be
               tested separately before being used in conjunction with
               E04GCF (see the Chapter Introduction).

               Its specification is:

                      SUBROUTINE LSFUN2 (M, N, XC, FVECC, FJACC, LJC)
                      INTEGER          M, N, LJC
                      DOUBLE PRECISION XC(N), FVECC(M), FJACC(LJC,N)
               Important: The dimension declaration for FJACC must
               contain the variable LJC, not an integer constant.

                1:  M -- INTEGER                                      Input

                2:  N -- INTEGER                                      Input
                    On entry: the numbers m and n of residuals and
                    variables, respectively.

                3:  XC(N) -- DOUBLE PRECISION array                   Input
                    On entry: the point x at which the values of the f
                                                                       i
                             ddf
                                i
                    and the  ---- are required.
                             ddx
                                j

                4:  FVECC(M) -- DOUBLE PRECISION array               Output
                    On exit: FVECC(i) must contain the value of f  at the
                                                                  i
                    point x, for i=1,2,...,m.

                5:  FJACC(LJC,N) -- DOUBLE PRECISION array           Output
                                                                    ddf
                                                                       i
                    On exit: FJACC(i,j) must contain the value of  ---- at
                                                                    ddx
                                                                       j
                    the point x, for i=1,2,...,m; j=1,2,...,n.

                6:  LJC -- INTEGER                                    Input
                    On entry: the first dimension of the array FJACC.
               LSFUN2 must be declared as EXTERNAL in the (sub)program
               from which E04GCF is called. Parameters denoted as
               Input must not be changed by this procedure.

          6. Error Indicators and Warnings

          Errors or warnings specified by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry N < 1,

               or       M < N,

               or       LIW < 1,

               or       LW < 2*N*(4 + N + M) + 3*M, when N > 1,

               or       LW < 9 + 5*>M, when N = 1.

          IFAIL= 2
               There have been 50*n calls of LSFUN2, yet the algorithm does
               not seem to have converged. This may be due to an awkward
               function or to a poor starting point, so it is worth
               restarting E04GCF from the final point held in X.

          IFAIL= 3
               The final point does not satisfy the conditions for
               acceptance as a minimum, but no lower point could be found.

          IFAIL= 4
               An auxiliary routine has been unable to complete a singular
               value decomposition in a reasonable number of sub-
               iterations.

          IFAIL= 5

          IFAIL= 6

          IFAIL= 7

          IFAIL= 8
               There is some doubt about whether the point X found by
               E04GCF is a minimum of F(x). The degree of confidence in the
               result decreases as IFAIL increases. Thus, when IFAIL = 5,
               it is probable that the final x gives a good estimate of the
               position of a minimum, but when IFAIL = 8 it is very
               unlikely that the routine has found a minimum.

          IFAIL= 9
               It is very likely that the user has made an error in forming
                                ddf
                                   i
               the derivatives  ---- in LSFUN2.
                                ddx
                                   j

          If the user is not satisfied with the result (e.g. because IFAIL
          lies between 3 and 8), it is worth restarting the calculations
          from a different starting point (not the point at which the
          failure occurred) in order to avoid the region which caused the
          failure. Repeated failure may indicate some defect in the
          formulation of the problem.

          7. Accuracy

          If the problem is reasonably well scaled and a successful exit is
          made then, for a computer with a mantissa of t decimals, one
          would expect to get t/2-1 decimals accuracy in the components of
          x and between t-1 (if F(x) is of order 1 at the minimum) and 2t-2
          (if F(x) is close to zero at the minimum) decimals accuracy in
          F(x).

          8. Further Comments

          The number of iterations required depends on the number of
          variables, the number of residuals and their behaviour, and the
          distance of the starting point from the solution. The number of
          multiplications performed per iteration of E04GCF varies, but for
                                   2    3
          m>>n is approximately n*m +O(n ). In addition, each iteration
          makes at least one call of LSFUN2. So, unless the residuals and
          their derivatives can be evaluated very quickly, the run time
          will be dominated by the time spent in LSFUN2.

          Ideally the problem should be scaled so that the minimum value of
          the sum of squares is in the range (0,1) and so that at points a
          unit distance away from the solution the sum of squares is
          approximately a unit value greater than at the minimum. It is
          unlikely that the user will be able to follow these
          recommendations very closely, but it is worth trying (by
          guesswork), as sensible scaling will reduce the difficulty of the
          minimization problem, so that E04GCF will take less computer
          time.

          When the sum of squares represents the goodness of fit of a
          nonlinear model to observed data, elements of the variance-
          covariance matrix of the estimated regression coefficients can be
          computed by a subsequent call to E04YCF, using information
          returned in segments of the workspace array W. See E04YCF for
          further details.

          9. Example

          To find the least-squares estimates of x , x  and x  in the model
                                                  1   2      3

                                            t
                                             1
                                   y=x + ---------
                                      1  x t +x t
                                          2 2  3 3

          using the 15 sets of data given in the following table.

                                  y    t   t    t
                                        1   2    3
                                 0.14  1.0 15.0 1.0
                                 0.18  2.0 14.0 2.0
                                 0.22  3.0 13.0 3.0
                                 0.25  4.0 12.0 4.0
                                 0.29  5.0 11.0 5.0
                                 0.32  6.0 10.0 6.0
                                 0.35  7.0  9.0 7.0
                                 0.39  8.0  8.0 8.0
                                 0.37  9.0  7.0 7.0
                                 0.58 10.0  6.0 6.0
                                 0.73 11.0  5.0 5.0
                                 0.96 12.0  4.0 4.0
                                 1.34 13.0  3.0 3.0
                                 2.10 14.0  2.0 2.0
                                 4.39 15.0  1.0 1.0

          The program uses (0.5, 1.0, 1.5) as the initial guess at the
          position of the minimum.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe04jaf}{nage.ht}{ Finding a minimum of a function}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe04jaf}{NAG Documentation: e04jaf}
\beginscroll
\begin{verbatim}



     E04JAF(3NAG)      Foundation Library (12/10/92)      E04JAF(3NAG)



          E04 -- Minimizing or Maximizing a Function                 E04JAF
                  E04JAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E04JAF is an easy-to-use quasi-Newton algorithm for finding a
          minimum of a function F(x ,x ,...,x ), subject to fixed upper and
                                   1  2      n
          lower bounds of the independent variables x ,x ,...,x , using
                                                     1  2      n
          function values only.

          It is intended for functions which are continuous and which have
          continuous first and second derivatives (although it will usually
          work even if the derivatives have occasional discontinuities).

          2. Specification

                 SUBROUTINE E04JAF (N, IBOUND, BL, BU, X, F, IW, LIW, W,
                1                   LW, IFAIL)
                 INTEGER          N, IBOUND, IW(LIW), LIW, LW, IFAIL
                 DOUBLE PRECISION BL(N), BU(N), X(N), F, W(LW)

          3. Description

          This routine is applicable to problems of the form:

            Minimize  F(x ,x ,...,x ) subject to l <=x <=u  , j=1,2,...,n
                         1  2      n              j   j   j

          when derivatives of F(x) are unavailable.

          Special provision is made for problems which actually have no
          bounds on the x , problems which have only non-negativity bounds
                         j
          and problems in which l =l =...=l  and u =u =...=u . The user
                                 1  2      n      1  2      n
          must supply a subroutine FUNCT1 to calculate the value of F(x) at
          any point x.

          From a starting point supplied by the user there is generated, on
          the basis of estimates of the gradient and the curvature of F(x),
          a sequence of feasible points which is intended to converge to a
          local minimum of the constrained function. An attempt is made to
          verify that the final point is a minimum.

          4. References

          [1]   Gill P E and Murray W (1976) Minimization subject to bounds
                on the variables. Report NAC 72. National Physical
                Laboratory.

          5. Parameters

           1:  N -- INTEGER                                           Input
               On entry: the number n of independent variables.
               Constraint: N >= 1.

           2:  IBOUND -- INTEGER                                      Input
               On entry: indicates whether the facility for dealing with
               bounds of special forms is to be used.

               It must be set to one of the following values:
               IBOUND = 0
                     if the user will be supplying all the l  and u
                                                            j      j
                     individually.

               IBOUND = 1
                     if there are no bounds on any x .
                                                    j

               IBOUND = 2
                     if all the bounds are of the form 0<=x .
                                                           j

               IBOUND = 3
                     if l =l =...=l  and u =u =...=u .
                         1  2      n      1  2      n

           3:  BL(N) -- DOUBLE PRECISION array                 Input/Output
               On entry: the lower bounds l .
                                           j

               If IBOUND is set to 0, the user must set BL(j) to l , for
                                                                  j
               j=1,2,...,n. (If a lower bound is not specified for a
                                                                          6
               particular x , the corresponding BL(j) should be set to -10.)
                           j

               If IBOUND is set to 3, the user must set BL(1) to l ; E04JAF
                                                                  1
               will then set the remaining elements of BL equal to BL(1).
               On exit: the lower bounds actually used by E04JAF.

           4:  BU(N) -- DOUBLE PRECISION array                 Input/Output
               On entry: the upper bounds u .
                                           j

               If IBOUND is set to 0, the user must set BU(j) to u , for
                                                                  j
               j=1,2,...,n. (If an upper bound is not specified for a
                                                                         6
               particular x , the corresponding BU(j) should be set to 10.)
                           j

               If IBOUND is set to 3, the user must set BU(1) to u ; E04JAF
                                                                  1
               will then set the remaining elements of BU equal to BU(1).
               On exit: the upper bounds actually used by E04JAF.

           5:  X(N) -- DOUBLE PRECISION array                  Input/Output
               On entry: X(j) must be set to an estimate of the jth
               component of the position of the minimum, for j=1,2,...,n.
               On exit: the lowest point found during the calculations.
               Thus, if IFAIL = 0 on exit, X(j) is the jth component of the
               position of the minimum.

           6:  F -- DOUBLE PRECISION                                 Output
               On exit: the value of F(x) corresponding to the final point
               stored in X.

           7:  IW(LIW) -- INTEGER array                           Workspace

           8:  LIW -- INTEGER                                         Input
               On entry: the length of IW as declared in the (sub)program
               from which E04JAF is called. Constraint: LIW >= N + 2.

           9:  W(LW) -- DOUBLE PRECISION array                    Workspace

          10:  LW -- INTEGER                                          Input
               On entry: the length of W as declared in the (sub)program
               from which E04JAF is called. Constraint: LW>=max(N*(N-
               1)/2+12*N,13).

          11:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. Users who are
               unfamiliar with this parameter should refer to the Essential
               Introduction for details.

               On exit: IFAIL = 0 unless the routine detects an error or
               gives a warning (see Section 6).

               For this routine, because the values of output parameters
               may be useful even if IFAIL /=0 on exit, users are
               recommended to set IFAIL to -1 before entry. It is then
               essential to test the value of IFAIL on exit. To suppress
               the output of an error message when soft failure occurs, set
               IFAIL to 1.

          5.1. Optional Parameters

               FUNCT1 -- SUBROUTINE, supplied by the user.
                                                    External Procedure
               This routine must be supplied by the user to calculate the
               value of the function F(x) at any point x. Since this
               routine is not a parameter to E04JAF, it must be called
               FUNCT1. It should be tested separately before being used in
               conjunction with E04JAF (see the Chapter Introduction).

               Its specification is:

                      SUBROUTINE FUNCT1 (N, XC, FC)
                      INTEGER          N
                      DOUBLE PRECISION XC(N), FC

                1:  N -- INTEGER                                      Input
                    On entry: the number n of variables.

                2:  XC(N) -- DOUBLE PRECISION array                   Input
                    On entry: the point x at which the function value is
                    required.

                3:  FC -- DOUBLE PRECISION                           Output
                    On exit: the value of the function F at the current
                    point x.
               FUNCT1 must be declared as EXTERNAL in the (sub)program
               from which E04JAF is called. Parameters denoted as
               Input must not be changed by this procedure.

          6. Error Indicators and Warnings

          Errors or warnings specified by the routine:

          IFAIL= 1
               On entry N < 1,

               or       IBOUND < 0,

               or       IBOUND > 3,

               or       IBOUND = 0 and BL(j) > BU(j) for some j,

               or       IBOUND = 3 and BL(1) > BU(1),

               or       LIW < N + 2,

               or       LW<max(13,12*N+N*(N-1)/2).

          IFAIL= 2
               There have been 400*n function evaluations, yet the
               algorithm does not seem to be converging. The calculations
               can be restarted from the final point held in X. The error
               may also indicate that F(x) has no minimum.

          IFAIL= 3
               The conditions for a minimum have not all been met but a
               lower point could not be found and the algorithm has failed.

          IFAIL= 4
               An overflow has occurred during the computation. This is an
               unlikely failure, but if it occurs the user should restart
               at the latest point given in X.

          IFAIL= 5

          IFAIL= 6

          IFAIL= 7

          IFAIL= 8
               There is some doubt about whether the point x found by
               E04JAF is a minimum. The degree of confidence in the result
               decreases as IFAIL increases. Thus, when IFAIL = 5 it is
               probable that the final x gives a good estimate of the
               position of a minimum, but when IFAIL = 8 it is very
               unlikely that the routine has found a minimum.

          IFAIL= 9
               In the search for a minimum, the modulus of one of the
                                                    6
               variables has become very large  (~10 ).  This indicates
               that there is a mistake in FUNCT1, that the user's problem
               has no finite solution, or that the problem needs rescaling
               (see Section 8).

          If the user is dissatisfied with the result (e.g. because IFAIL =
          5, 6, 7 or 8), it is worth restarting the calculations from a
          different starting point (not the point at which the failure
          occurred) in order to avoid the region which caused the failure.
          If persistent trouble occurs and the gradient can be calculated,
          it may be advisable to change to a routine which uses gradients
          (see the Chapter Introduction).

          7. Accuracy

          When a successful exit is made then, for a computer with a
          mantissa of t decimals, one would expect to get about t/2-1
          decimals accuracy in x and about t-1 decimals accuracy in F,
          provided the problem is reasonably well scaled.

          8. Further Comments

          The number of iterations required depends on the number of
          variables, the behaviour of F(x) and the distance of the starting
          point from the solution. The number of operations performed in an
                                                          2
          iteration of E04JAF is roughly proportional to n . In addition,
          each iteration makes at least m+1 calls of FUNCT1, where m is the
          number of variables not fixed on bounds. So, unless F(x) can be
          evaluated very quickly, the run time will be dominated by the
          time spent in FUNCT1.

          Ideally the problem should be scaled so that at the solution the
          value of F(x) and the corresponding values of x ,x ,...,x  are
                                                         1  2      n
          each in the range (-1,+1), and so that at points a unit distance
          away from the solution, F is approximately a unit value greater
          than at the minimum. It is unlikely that the user will be able to
          follow these recommendations very closely, but it is worth trying
          (by guesswork), as sensible scaling will reduce the difficulty of
          the minimization problem, so that E04JAF will take less computer
          time.

          9. Example

          To minimize

                                2         2         4          4
                     F=(x +10x ) +5(x -x ) +(x -2x ) +10(x -x )
                         1    2      3  4     2   3       1  4

          subject to

                                      1<=x <=3
                                          1

                                      -2<=x <=0
                                           2

                                      1<=x <=3,
                                          4

          starting from the initial guess (3, - 1, 0, 1).

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe04mbf}{nage.ht}{ Solving linear programming problems}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe04mbf}{NAG Documentation: e04mbf}
\beginscroll
\begin{verbatim}



     E04MBF(3NAG)      Foundation Library (12/10/92)      E04MBF(3NAG)



          E04 -- Minimizing or Maximizing a Function                 E04MBF
                  E04MBF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E04MBF is an easy-to-use routine for solving linear programming
          problems, or for finding a feasible point for such problems. It
          is not intended for large sparse problems.

          2. Specification

                 SUBROUTINE E04MBF (ITMAX, MSGLVL, N, NCLIN, NCTOTL, NROWA,
                1                   A, BL, BU, CVEC, LINOBJ, X, ISTATE,
                2                   OBJLP, CLAMDA, IWORK, LIWORK, WORK,
                3                   LWORK, IFAIL)
                 INTEGER          ITMAX, MSGLVL, N, NCLIN, NCTOTL, NROWA,
                1                 ISTATE(NCTOTL), IWORK(LIWORK), LIWORK,
                2                 LWORK, IFAIL
                 DOUBLE PRECISION A(NROWA,N), BL(NCTOTL), BU(NCTOTL), CVEC
                1                 (N), X(N), OBJLP, CLAMDA(NCTOTL), WORK
                2                 (LWORK)
                 LOGICAL          LINOBJ

          3. Description

          E04MBF solves linear programming (LP) problems of the form

                                T                   (x )
                    Minimize   c x   subject to  l<=(Ax)<=u            (LP)
                             n
                    x is in R

          where c is an n element vector and A is an m by n matrix i.e.,
          there are n variables and m general linear constraints. m may be
          zero in which case the LP problem is subject only to bounds on
          the variables. Notice that upper and lower bounds are specified
          for all the variables and constraints. This form allows full
          generality in specifying other types of constraints. For example
          the ith constraint may be specified as equality by setting l =u .
                                                                      i  i
          If certain bounds are not present the associated elements of l or
          u can be set to special values that will be treated as -infty or
          +infty.

          The routine allows the linear objective function to be omitted in
          which case a feasible point for the set of constraints is sought.

          The user must supply an initial estimate of the solution.

          Users who wish to exercise additional control and users with
          problems whose solution would benefit from additional flexibility
          should consider using the comprehensive routine E04NAF.

          4. References

          [1]   Gill P E, Murray W and Wright M H (1981) Practical
                Optimization. Academic Press.

          [2]   Gill P E, Murray W, Saunders M A and Wright M H (1983)
                User's Guide for SOL/QPSOL. Report SOL 83-7. Department of
                Operations Research, Stanford University.

          5. Parameters

           1:  ITMAX -- INTEGER                                       Input
               On entry: an upper bound on the number of iterations to be
               taken. If ITMAX is not positive, then the value 50 is used
               in place of ITMAX.

           2:  MSGLVL -- INTEGER                                      Input
               On entry: indicates whether or not printout is required at
               the final solution. When printing occurs the output is on
               the advisory message channel (see X04ABF). A description of
               the printed output is given in Section 5.1. The level of
               printing is determined as follows:
               MSGLVL < 0
                     No printing.

               MSGLVL = 0
                     Printing only if an input parameter is incorrect, or
                     if the problem is so ill-conditioned that subsequent
                     overflow is likely. This setting is strongly
                     recommended in preference to MSGLVL < 0.

               MSGLVL = 1
                     Printing at the solution.

               MSGLVL > 1
                     Values greater than 1 should normally be used only at
                     the direction of NAG; such values may generate large
                     amounts of printed output.

           3:  N -- INTEGER                                           Input
               On entry: the number n of variables. Constraint: N >= 1.

           4:  NCLIN -- INTEGER                                       Input
               On entry: the number of general linear constraints in the
               problem. Constraint: NCLIN >= 0.

           5:  NCTOTL -- INTEGER                                      Input
               On entry: the value (N+NCLIN).

           6:  NROWA -- INTEGER                                       Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which E04MBF is called.
               Constraint: NROWA >= max(1,NCLIN).

           7:  A(NROWA,N) -- DOUBLE PRECISION array                   Input
               On entry: the leading NCLIN by n part of A must contain the
               NCLIN general constraints, with the coefficients of the ith
               constraint in the ith row of A. If NCLIN = 0, then A is not
               referenced.

           8:  BL(NCTOTL) -- DOUBLE PRECISION array                   Input
               On entry: the first n elements of BL must contain the lower
               bounds on the n variables, and when NCLIN > 0, the next
               NCLIN elements of BL must contain the lower bounds on the
               NCLIN general linear constraints. To specify a non-existent
               lower bound (l =-infty), set BL(j)<=-1.0E+20.
                             j

           9:  BU(NCTOTL) -- DOUBLE PRECISION array                   Input
               On entry: the first n elements of BU must contain the upper
               bounds on the n variables, and when NCLIN > 0, the next
               NCLIN elements of BU must contain the upper bounds on the
               NCLIN general linear constraints. To specify a non-existent
               upper bound (u =+infty), set BU(j)>=1.0E+20. Constraint:
                             j
               BL(j)<=BU(j), for j=1,2,...,NCTOTL.

          10:  CVEC(N) -- DOUBLE PRECISION array                      Input
               On entry: with LINOBJ = .TRUE., CVEC must contain the
               coefficients of the objective function. If LINOBJ = .FALSE.,
               then CVEC is not referenced.

          11:  LINOBJ -- LOGICAL                                      Input
               On entry: indicates whether or not a linear objective
               function is present. If LINOBJ = .TRUE., then the full LP
               problem is solved, but if LINOBJ = .FALSE., only a feasible
               point is found and the array CVEC is not referenced.

          12:  X(N) -- DOUBLE PRECISION array                  Input/Output
               On entry: an estimate of the solution, or of a feasible
               point. Even when LINOBJ = .TRUE. it is not necessary for the
               point supplied in X to be feasible. In the absence of better
               information all elements of X may be set to zero. On exit:
               the solution to the LP problem when LINOBJ = .TRUE., or a
               feasible point when LINOBJ = .FALSE..

               When no feasible point exists (see IFAIL = 1 in Section 6)
               then X contains the point for which the sum of the
               infeasibilities is a minimum. On return with IFAIL = 2, 3 or
               4, X contains the point at which E04MBF terminated.

          13:  ISTATE(NCTOTL) -- INTEGER array                       Output
               On exit: with IFAIL < 5, ISTATE indicates the status of
               every constraint at the final point. The first n elements of
               ISTATE refer to the upper and lower bounds on the variables
               and when NCLIN > 0 the next NCLIN elements refer to the
               general constraints.

               Their meaning is:
               ISTATE(j) Meaning

               -2        The constraint violates its lower bound. This
                         value cannot occur for any element of ISTATE when
                         a feasible point has been found.

               -1        The constraint violates its upper bound. This
                         value cannot occur for any element of ISTATE when
                         a feasible point has been found.

               0         The constraint is not in the working set (is not
                         active) at the final point. Usually this means
                         that the constraint lies strictly between its
                         bounds.

               1         This inequality constraint is in the working set
                         (is active) at its lower bound.

               2         This inequality constraint is in the working set
                         (is active) at its upper bound.

               3         This constraint is included in the working set (is
                         active) as an equality. This value can only occur
                         when BL(j) = BU(j).

          14:  OBJLP -- DOUBLE PRECISION                             Output
               On exit: when LINOBJ = .TRUE., then on successful exit,
               OBJLP contains the value of the objective function at the
               solution, and on exit with IFAIL = 2, 3 or 4, OBJLP contains
               the value of the objective function at the point returned in
               X.

               When LINOBJ = .FALSE., then on successful exit OBJLP will be
               zero and on return with IFAIL = 1, OBJLP contains the
               minimum sum of the infeasibilities corresponding to the
               point returned in X.

          15:  CLAMDA(NCTOTL) -- DOUBLE PRECISION array              Output
               On exit: when LINOBJ = .TRUE., then on successful exit, or
               on exit with IFAIL = 2, 3, or 4, CLAMDA contains the
               Lagrange multipliers (reduced costs) for each constraint
               with respect to the working set. The first n components of
               CLAMDA contain the multipliers for the bound constraints on
               the variables and the remaining NCLIN components contain the
               multipliers for the general linear constraints.

               If ISTATE(j) = 0 so that the jth constraint is not in the
               working set then CLAMDA(j) is zero. If X is optimal and
               ISTATE(j) = 1, then CLAMDA(j) should be non-negative, and if
               ISTATE(j) = 2, then CLAMDA(j) should be non-positive.

               When LINOBJ = .FALSE., all NCTOTL elements of CLAMDA are
               returned as zero.

          16:  IWORK(LIWORK) -- INTEGER array                     Workspace

          17:  LIWORK -- INTEGER                                      Input
               On entry: the length of the array IWORK as declared in the
               (sub)program from which E04MBF is called. Constraint:
               LIWORK>=2*N.

          18:  WORK(LWORK) -- DOUBLE PRECISION array              Workspace

          19:  LWORK -- INTEGER                                       Input
               On entry: the length of the array WORK as declared in the
               (sub)program from which E04MBF is called. Constraints:
               when N <= NCLIN then
                               2
                     LWORK>=2*N +6*N+4*NCLIN+NROWA;

               when 0 <= NCLIN < N then
                                       2
                     LWORK>=2*(NCLIN+1) +4*NCLIN+6*N+NROWA.

          20:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. Users who are
               unfamiliar with this parameter should refer to the Essential
               Introduction for details.

               On exit: IFAIL = 0 unless the routine detects an error or
               gives a warning (see Section 6).

               For this routine, because the values of output parameters
               may be useful even if IFAIL /=0 on exit, users are
               recommended to set IFAIL to -1 before entry. It is then
               essential to test the value of IFAIL on exit. To suppress
               the output of an error message when soft failure occurs, set
               IFAIL to 1.

          5.1. Description of the Printed Output

          When MSGLVL = 1, then E04MBF will produce output on the advisory
          message channel (see X04ABF ), giving information on the final
          point. The following describes the printout associated with each
          variable.

          Output         Meaning

          VARBL          The name (V) and index j, for j=1,2,...,n, of the
                         variable.

          STATE          The state of the variable. (FR if neither bound is
                         in the working set, EQ for a fixed variable, LL if
                         on its lower bound, UL if on its upper bound and
                         TB if held on a temporary bound.) If the value of
                         the variable lies outside the upper or lower bound
                         then STATE will be ++ or -- respectively.

          VALUE          The value of the variable at the final iteration.

          LOWER BOUND    The lower bound specified for the variable.

          UPPER BOUND    The upper bound specified for the variable.

          LAGR MULT      The value of the Lagrange multiplier for the
                         associated bound.

          RESIDUAL       The difference between the value of the variable
                         and the nearer of its bounds.

          For each of the general constraints the printout is as above with
          refers to the jth element of Ax, except that VARBL is replaced
          by:

          LNCON          The name (L) and index j, for j = 1,2,...,NCLIN of
                         the constraint.

          6. Error Indicators and Warnings

          Errors or warnings specified by the routine:

          Note: when MSGLVL=1 a short description of the error is printed.

          IFAIL= 1
               No feasible point could be found. Moving violated
               constraints so that they are satisfied at the point returned
               in X gives the minimum moves necessary to make the LP
               problem feasible.

          IFAIL= 2
               The solution to the LP problem is unbounded.

          IFAIL= 3
               A total of 50 changes were made to the working set without
               altering x. Cycling is probably occurring. The user should
               consider using E04NAF with MSGLVL >= 5 to monitor constraint
               additions and deletions in order to determine whether or not
               cycling is taking place.

          IFAIL= 4
               The limit on the number of iterations has been reached.
               Increase ITMAX or consider using E04NAF to monitor progress.

          IFAIL= 5
               An input parameter is invalid. Unless MSGLVL < 0 a message
               will be printed.

          IFAILOverflow
               If the printed output before the overflow occurred contains
               a warning about serious ill-conditioning in the working set
               when adding the jth constraint, then either the user should
               try using E04NAF and experiment with the magnitude of FEATOL
               (j) in that routine, or the offending linearly dependent
               constraint (with index j) should be removed from the
               problem.

          7. Accuracy

          The routine implements a numerically stable active set strategy
          and returns solutions that are as accurate as the condition of
          the LP problem warrants on the machine.

          8. Further Comments

          The time taken by each iteration is approximately proportional to
               2      2
          min(n ,NCLIN ).

          Sensible scaling of the problem is likely to reduce the number of
          iterations required and make the problem less sensitive to
          perturbations in the data, thus improving the condition of the LP
          problem. In the absence of better information it is usually
          sensible to make the Euclidean lengths of each constraint of
          comparable magnitude. See Gill et al [1] for further information
          and advice.

          Note that the routine allows constraints to be violated by an
          absolute tolerance equal to the machine precision (see X02AJF(*))

          9. Example

          To minimize the function

                    -0.02x -0.2x -0.2x -0.2x -0.2x +0.04x +0.04x
                          1     2     3     4     5      6      7

          subject to the bounds

                                -0.01 <= x  <= 0.01
                                          1
                                -0.1 <= x  <= 0.15,
                                         2
                                -0.01 <= x  <= 0.03,
                                          3
                                -0.04 <= x  <= 0.02,
                                          4
                                -0.1 <= x  <= 0.05,
                                         5
                                -0.01 <= x
                                          6
                                -0.01 <= x
                                          7

          and the general constraints

                             x +x +x +x +x +x +x =-0.13
                              1  2  3  4  5  6  7

              0.15x +0.04x +0.02x +0.04x +0.02x +0.01x +0.03x <=-0.0049
                   1      2      3      4      5      6      7

                 0.03x +0.05x +0.08x +0.02x +0.06x +0.01x <=-0.0064
                      1      2      3      4      5      6

                     0.02x +0.04x +0.01x +0.02x +0.02x <=-0.0037
                          1      2      3      4      5

                            0.02x +0.03x +0.01x <=-0.0012
                                 1      2      5

                 -0.0992<=0.70x +0.75x +0.80x +0.75x +0.80x +0.97x
                               1      2      3      4      5      6

           -0.003<=0.02x +0.06x +0.08x +0.12x +0.02x +0.01x +0.97x <=0.002
                        1      2      3      4      5      6      7

          The initial point, which is infeasible, is

                                                                 T
                  x =(-0.01, -0.03, 0.0, -0.01, -0.1, 0.02, 0.01) .
                   0

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe04naf}{nage.ht}{ Solving linear or quadratic problems}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe04naf}{NAG Documentation: e04naf}
\beginscroll
\begin{verbatim}



     E04NAF(3NAG)      Foundation Library (12/10/92)      E04NAF(3NAG)



          E04 -- Minimizing or Maximizing a Function                 E04NAF
                  E04NAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E04NAF is a comprehensive routine for solving quadratic
          programming (QP) or linear programming (LP) problems. It is not
          intended for large sparse problems.

          2. Specification

                 SUBROUTINE E04NAF (ITMAX, MSGLVL, N, NCLIN, NCTOTL, NROWA,
                1                   NROWH, NCOLH, BIGBND, A, BL, BU, CVEC,
                2                   FEATOL, HESS, QPHESS, COLD, LP, ORTHOG,
                3                   X, ISTATE, ITER, OBJ, CLAMDA, IWORK,
                4                   LIWORK, WORK, LWORK, IFAIL)
                 INTEGER          ITMAX, MSGLVL, N, NCLIN, NCTOTL, NROWA,
                1                 NROWH, NCOLH, ISTATE(NCTOTL), ITER, IWORK
                2                 (LIWORK), LIWORK, LWORK, IFAIL
                 DOUBLE PRECISION BIGBND, A(NROWA,N), BL(NCTOTL),
                1                 BU(NCTOTL), CVEC(N), FEATOL(NCTOTL), HESS
                2                 (NROWH,NCOLH), X(N), OBJ, CLAMDA(NCTOTL),
                3                 WORK(LWORK)
                 LOGICAL          COLD, LP, ORTHOG
                 EXTERNAL         QPHESS

          3. Description

          E04NAF is essentially identical to the subroutine SOL/QPSOL
          described in Gill et al [1].

          E04NAF is designed to solve the quadratic programming (QP)
          problem - the minimization of a quadratic function subject to a
          set of linear constraints on the variables. The problem is
          assumed to be stated in the following form:

                           T   1 T                    (x )
                Minimize  c x+ -x Hx   subject to  l<=(Ax)<=u ,         (1)
                               2

          where c is a constant n-vector and H is a constant n by n
          symmetric matrix; note that H is the Hessian matrix (matrix of
          second partial derivatives) of the quadratic objective function.
          The matrix A is m by n, where m may be zero; A is treated as a
          dense matrix.

          The constraints involving A will be called the general
          constraints. Note that upper and lower bounds are specified for
          all the variables and for all the general constraints. The form
          of (1) allows full generality in specifying other types of
          constraints. In particular, an equality constraint is specified
          by setting l =u . If certain bounds are not present, the
                      i  i
          associated elements of l or u can be set to special values that
          will be treated as -infty or +infty.

          The user must supply an initial estimate of the solution to (1),
          and a subroutine that computes the product Hx for any given
          vector x. If H is positive-definite or positive semi-definite,
          E04NAF will obtain a global minimum; otherwise, the solution
          obtained will be a local minimum (which may or may not be a
          global minimum). If H is defined as the zero matrix, E04NAF will
          solve the resulting linear programming (LP) problem; however,
          this can be accomplished more efficiently by setting a logical
          variable in the call of the routine (see the parameter LP in
          Section 5).

          E04NAF allows the user to provide the indices of the constraints
          that are believed to be exactly satisfied at the solution. This
          facility, known as a warm start, can lead to significant savings
          in computational effort when solving a sequence of related
          problems.

          The method has two distinct phases. In the first (the LP phase),
          an iterative procedure is carried out to determine a feasible
          point. In this context, feasibility is defined by a user-provided
          array FEATOL; the jth constraint is considered satisfied if its
          violation does not exceed FEATOL(j). The second phase (the QP
          phase) generates a sequence of feasible iterates in order to
          minimize the quadratic objective function. In both phases, a
          subset of the constraints - called the working set - is used to
          define the search direction at each iteration; typically, the
          working set includes constraints that are satisfied to within the
          corresponding tolerances in the FEATOL array.

          We now briefly describe a typical iteration in the QP phase. Let
          x  denote the estimate of the solution at the kth iteration; the
           k
          next iterate is defined by

                                 x   =x +(alpha) p
                                  k+1  k        k k

          where p  is an n-dimensional search direction and (alpha)  is a
                 k                                                 k
          scalar step length. Assume that the working (active) set contains
          t  linearly independent constraints, and let C  denote the matrix
           k                                            k
          of coefficients of the bounds and general constraints in the
          current working set.

          Let Z  denote a matrix whose columns form a basis for the null
               k
          space of C , so that C Z =0. (Note that Z  has n  columns, where
                    k           k k                k      z
                                T
          n =n-t .) The vector Z (c+Hx ) is called the projected gradient
           z    k               k     k
          at x . If the projected gradient is zero at x  (i.e., x  is a
              k                                        k         k
          constrained stationary point in the subspace defined by Z ),
                                                                   k
          Lagrange multipliers (lambda)  are defined as the solution of the
                                       k
          compatible overdetermined system

                                T
                               C (lambda) =c+Hx                         (2)
                                k        k     k

          The Lagrange multiplier (lambda) corresponding to an inequality
          constraint in the working set is said to be optimal if
          (lambda)<=0 when the associated constraint is at its upper bound,
          or if (lambda)>=0 when the associated constraint is at its lower
          bound. If a multiplier is non-optimal, the objective function can
          be reduced by deleting the corresponding constraint (with index
          JDEL, see Section 5.1) from the working set.

          If the projected gradient at x  is non-zero, the search direction
                                        k
          p  is defined as
           k

                                    p =Z p                              (3)
                                     k  k z

          where p  is an n -vector. In effect, the constraints in the
                 z        z
          working set are treated as equalities, by constraining p  to lie
                                                                  k
          within the subspace of vectors orthogonal to the rows of C . This
                                                                    k
          definition ensures that C p =0, and hence the values of the
                                   k k
          constraints in the working set are not altered by any move along
          p .
           k

          The vector p  is obtained by solving the equations
                      z

                                T        T
                               Z HZ p =-Z (c+Hx )                       (4)
                                k  k z   k     k

                       T
          (The matrix Z HZ  is called the projected Hessian matrix.) If the
                       k  k
          projected Hessian is positive-definite, the vector defined by (3)
          and (4) is the step to the minimum of the quadratic function in
          the subspace defined by Z .
                                   k

          If the projected Hessian is positive-definite and x +p  is
                                                             k  k
          feasible, (alpha)  will be taken as unity. In this case, the
                           k
          projected gradient at x    will be zero (see NORM ZTG in Section
                                 k+1
          5.1), and Lagrange multipliers can be computed (see Gill et al
          [2]). Otherwise, (alpha)  is set to the step to the 'nearest'
                                  k
          constraint (with index JADD, see Section 5.1), which is added to
          the working set at the next iteration.

          The matrix Z  is obtained from the TQ factorization of C , in
                      k                                           k
          which C  is represented as
                 k

                                   C Q=(0 T )                           (5)
                                    k      k

          where T  is reverse-triangular. It follows from (5) that Z  may
                 k                                                  k
          be taken as the first n  columns of Q. If the projected Hessian
                                 z
          is positive-definite, (3) is solved using the Cholesky
          factorization

                                      T     T
                                     Z HZ =R R
                                      k  k  k k

          where R  is upper triangular. These factorizations are updated as
                 k
          constraints enter or leave the working set (see Gill et al [2]
          for further details).

          An important feature of E04NAF is the treatment of indefiniteness
          in the projected Hessian. If the projected Hessian is positive-
          definite, it may become indefinite only when a constraint is
          deleted from the working set. In this case, a temporary
          modification (of magnitude HESS MOD, see Section 5.1) is added to
          the last diagonal element of the Cholesky factor. Once a
          modification has occurred, no further constraints are deleted
          from the working set until enough constraints have been added so
          that the projected Hessian is again positive-definite. If
          equation (1) has a finite solution, a move along the direction
          obtained by solving (4) with the modified Cholesky factor must
          encounter a constraint that is not already in the working set.

          In order to resolve indefiniteness in this way, we must ensure
          that the projected Hessian is positive-definite at the first
          iterate in the QP phase. Given the n  by n  projected Hessian, a
                                              z     z
          step-wise Cholesky factorization is performed with symmetric
          interchanges (and corresponding rearrangement of the columns of Z
          ), terminating if the next step would cause the matrix to become
          indefinite. This determines the largest possible positive-
          definite principal sub-matrix of the (permuted) projected
          Hessian. If n  steps of the Cholesky factorization have been
                       R
          successfully completed, the relevant projected Hessian is an n
                                                                        R
                                          T
          by n  positive-definite matrix Z HZ , where Z  comprises the
              R                           R  R         R
          first n  columns of Z. The quadratic function will subsequently
                 R
          be minimized within subspaces of reduced dimension until the full
          projected Hessian is positive-definite.

          If a linear program is being solved and there are fewer general
          constraints than variables, the method moves from one vertex to
          another while minimizing the objective function. When necessary,
          an initial vertex is defined by temporarily fixing some of the
          variables at their initial values.

          Several strategies are used to control ill-conditioning in the
          working set. One such strategy is associated with the FEATOL
          array. Allowing the jth constraint to be violated by as much as
          FEATOL(j) often provides a choice of constraints that could be
          added to the working set. When a choice exists, the decision is
          based on the conditioning of the working set. Negative steps are
          occasionally permitted, since x  may violate the constraint to be
                                         k
          added.

          4. References

          [1]   Gill P E, Murray W, Saunders M A and Wright M H (1983)
                User's Guide for SOL/QPSOL. Report SOL 83-7. Department of
                Operations Research, Stanford University.

          [2]   Gill P E, Murray W, Saunders M A and Wright M H (1982) The
                design and implementation of a quadratic programming
                algorithm. Report SOL 82-7. Department of Operations
                Research, Stanford University.

          [3]   Gill P E, Murray W and Wright M H (1981) Practical
                Optimization. Academic Press.

          5. Parameters

           1:  ITMAX -- INTEGER                                       Input
               On entry: an upper bound on the number of iterations to be
               taken during the LP phase or the QP phase. If ITMAX is not
               positive, then the value 50 is used in place of ITMAX.

           2:  MSGLVL -- INTEGER                                      Input
               On entry: MSGLVL must indicate the amount of intermediate
               output desired (see Section 5.1 for a description of the
               printed output). All output is written to the current
               advisory message unit (see X04ABF). For MSGLVL >= 10, each
               level includes the printout for all lower levels.
               Value   Definition

               <0      No printing.

               0       Printing only if an input parameter is incorrect, or
                       if the working set is so ill-conditioned that
                       subsequent overflow is likely. This setting is
                       strongly recommended in preference to MSGLVL < 0.

               1       The final solution only.

               5       One brief line of output for each constraint
                       addition or deletion (no printout of the final
                       solution).

               >=10    The final solution and one brief line of output for
                       each constraint addition or deletion.

               >=15    At each iteration, X, ISTATE, and the indices of the
                       free variables (i.e.,the variables not currently
                       held on a bound).

               >=20    At each iteration, the Lagrange multiplier estimates
                       and the general constraint values.

               >=30    At each iteration, the diagonal elements of the
                       matrix T associated with the TQ factorization of the
                       working set, and the diagonal elements of the
                       Cholesky factor R of the projected Hessian.

               >=80    Debug printout.

               99      The arrays CVEC and HESS.

           3:  N -- INTEGER                                           Input
               On entry: the number, n, of variables. Constraint: N >= 1.

           4:  NCLIN -- INTEGER                                       Input
               On entry: the number of general linear constraints in the
               problem. Constraint: NCLIN >= 0.

           5:  NCTOTL -- INTEGER                                      Input
               On entry: the value (N+NCLIN).

           6:  NROWA -- INTEGER                                       Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which E04NAF is called.
               Constraint: NROWA >= max(1,NCLIN).

           7:  NROWH -- INTEGER                                       Input
               On entry: the first dimension of the array HESS as declared
               in the (sub)program from which E04NAF is called.
               Constraint: NROWH >= 1.

           8:  NCOLH -- INTEGER                                       Input
               On entry: the column dimension of the array HESS as declared
               in the (sub)program from which E04NAF is called.
               Constraint: NCOLH >= 1.

           9:  BIGBND -- DOUBLE PRECISION                             Input
               On entry: BIGBND must denote an 'infinite' component of l
               and u. Any upper bound greater than or equal to BIGBND will
               be regarded as plus infinity, and a lower bound less than or
               equal to -BIGBND will be regarded as minus infinity.
               Constraint: BIGBND > 0.0.

          10:  A(NROWA,N) -- DOUBLE PRECISION array                   Input
               On entry: the leading NCLIN by n part of A must contain the
               NCLIN general constraints, with the ith constraint in the i
               th row of A. If NCLIN = 0, then A is not referenced.

          11:  BL(NCTOTL) -- DOUBLE PRECISION array                   Input
               On entry: the lower bounds for all the constraints, in the
               following order. The first n elements of BL must contain the
               lower bounds on the variables. If NCLIN > 0, the next NCLIN
               elements of BL must contain the lower bounds for the general
               linear constraints. To specify a non-existent lower bound
               (i.e., l =-infty), the value used must satisfy BL(j)<=-
                       j
               BIGBND To specify the jth constraint as an equality, the
               user must set BL(j) = BU(j). Constraint: BL(j) <= BU(j),
               j=1,2,...,NCTOTL.

          12:  BU(NCTOTL) -- DOUBLE PRECISION array                   Input
               On entry: the upper bounds for all the constraints, in the
               following order. The first n elements of BU must contain the
               upper bounds on the variables. If NCLIN > 0, the next NCLIN
               elements of BU must contain the upper bounds for the general
               linear constraints. To specify a non-existent upper bound
               (i.e., u =+infty), the value used must satisfy BU(j) >=
                       j
               BIGBND. To specify the jth constraint as an equality, the
               user must set BU(j) = BL(j). Constraint: BU(j) >= BL(j),
               j=1,2,...,NCTOTL.

          13:  CVEC(N) -- DOUBLE PRECISION array                      Input
               On entry: the coefficients of the linear term of the
               objective function (the vector c in equation  (1)).

          14:  FEATOL(NCTOTL) -- DOUBLE PRECISION array               Input
               On entry: a set of positive tolerances that define the
               maximum permissible absolute violation in each constraint in
               order for a point to be considered feasible, i.e., if the
               violation in constraint j is less than FEATOL(j), the point
               is considered to be feasible with respect to the jth
               constraint. The ordering of the elements of FEATOL is the
               same as that described above for BL.

               The elements of FEATOL should not be too small and a warning
               message will be printed on the current advisory message
               channel if any element of FEATOL is less than the machine
               precision (see X02AJF(*)). As the elements of FEATOL
               increase, the algorithm is less likely to encounter
               difficulties with ill-conditioning and degeneracy. However,
               larger values of FEATOL(j) mean that constraint j could be
               violated by a significant amount. It is recommended that
               FEATOL(j) be set to a value equal to the largest acceptable
               violation for constraint j. For example, if the data
               defining the constraints are of order unity and are correct
               to about 6 decimal digits, it would be appropriate to choose
                              -6
               FEATOL(j) as 10   for all relevant j. Often the square root
               of the machine precision is a reasonable choice if the
               constraint is well scaled.

          15:  HESS(NROWH,NCOLH) -- DOUBLE PRECISION array            Input
               On entry: HESS may be used to store the Hessian matrix H of
               equation (1) if desired. HESS is accessed only by the
               subroutine QPHESS and is not accessed if LP = .TRUE.. Refer
               to the specification of QPHESS (below) for further details
               of how HESS may be used to pass data to QPHESS.

          16:  QPHESS -- SUBROUTINE, supplied by the user.
                                                         External Procedure
               QPHESS must define the product of the Hessian matrix H and a
               vector x. The elements of H need not be defined explicitly.
               QPHESS is not accessed if LP is set to .TRUE. and in this
               case QPHESS may be the dummy routine E04NAN. (E04NAN is
               included in the NAG Foundation Library and so need not be
               supplied by the user. Its name may be implementation-
               dependent: see the Users' Note for your implementation for
               details.)

               Its specification is:

                      SUBROUTINE QPHESS (N, NROWH, NCOLH, JTHCOL,
                     1                   HESS, X, HX)
                      INTEGER          N, NROWH, NCOLH, JTHCOL
                      DOUBLE PRECISION HESS(NROWH,NCOLH), X(N), HX(N)

                1:  N -- INTEGER                                      Input
                    On entry: the number n of variables.

                2:  NROWH -- INTEGER                                  Input
                    On entry: the row dimension of the array HESS.

                3:  NCOLH -- INTEGER                                  Input
                    On entry: the column dimension of the array HESS.

                4:  JTHCOL -- INTEGER                                 Input
                    The input parameter JTHCOL is included to allow
                    flexibility for the user in the special situation when
                    x is the jth co-ordinate vector (i.e.,the jth column of
                    the identity matrix). This may be of interest because
                    the product Hx is then the jth column of H, which can
                    sometimes be computed very efficiently. The user may
                    code QPHESS to take advantage of this case. On entry:
                    if JTHCOL = j, where j>0, HX must contain column JTHCOL
                    of H, and hence special code may be included in QPHESS
                    to test JTHCOL if desired. However, special code is not
                    necessary, since the vector x always contains column
                    JTHCOL of the identity matrix whenever QPHESS is called
                    with JTHCOL > 0.

                5:  HESS(NROWH,NCOLH) -- DOUBLE PRECISION array       Input
                    On entry: the Hessian matrix H.

                    In some cases, it may be desirable to use a one-
                    dimensional array to transmit data or workspace to
                    QPHESS; HESS should then be declared with dimension
                    (NROWH) in the (sub)program from which E04NAF is called
                    and the parameter NCOLH must be 1.

                    In other situations, it may be desirable to compute Hx
                    without accessing HESS - for example, if H is sparse or
                    has special structure. (This is illustrated in the
                    subroutine QPHES1 in the example program in Section 9.)
                    The parameters HESS, NROWH and NCOLH may then refer to
                    any convenient array.

                    When MSGLVL = 99, the (possibly undefined) contents of
                    HESS will be printed, except if NROWH and NCOLH are
                    both 1. Also printed are the results of calling QPHESS
                    with JTHCOL = 1,2,...,n.

                6:  X(N) -- DOUBLE PRECISION array                    Input
                    On entry: the vector x.

                7:  HX(N) -- DOUBLE PRECISION array                  Output
                    On exit: HX must contain the product Hx.
               QPHESS must be declared as EXTERNAL in the (sub)program
               from which E04NAF is called. Parameters denoted as
               Input must not be changed by this procedure.

          17:  COLD -- LOGICAL                                        Input
               On entry: COLD must indicate whether the user has specified
               an initial estimate of the active set of constraints. If
               COLD is set to .TRUE., the initial working set is determined
               by E04NAF. If COLD is set to .FALSE. (a 'warm start'), the
               user must define the ISTATE array which gives the status of
               each constraint with respect to the working set. E04NAF will
               override the user's specification of ISTATE if necessary, so
               that a poor choice of working set will not cause a fatal
               error.

               The warm start option is particularly useful when E04NAF is
               called repeatedly to solve related problems.

          18:  LP -- LOGICAL                                          Input
               On entry: if LP = .FALSE., E04NAF will solve the specified
               quadratic programming problem. If LP = .TRUE., E04NAF will
               treat H as zero and solve the resulting linear programming
               problem; in this case, the parameters HESS and QPHESS will
               not be referenced.

          19:  ORTHOG -- LOGICAL                                      Input
               On entry: ORTHOG must indicate whether orthogonal
               transformations are to be used in computing and updating the
               TQ factorization of the working set
                                        A Q=(0 T),
                                         s
               where A  is a sub-matrix of A and T is reverse-triangular.
                      s
               If ORTHOG = .TRUE., the TQ factorization is computed using
               Householder reflections and plane rotations, and the matrix
               Q is orthogonal. If ORTHOG = .FALSE., stabilized elementary
               transformations are used to maintain the factorization, and
               Q is not orthogonal. A rule of thumb in making the choice is
               that orthogonal transformations require more work, but
               provide greater numerical stability. Thus, we recommend
               setting ORTHOG to .TRUE. if the problem is reasonably small
               or the active set is ill-conditioned. Otherwise, setting
               ORTHOG to .FALSE. will often lead to a reduction in solution
               time with negligible loss of reliability.

          20:  X(N) -- DOUBLE PRECISION array                  Input/Output
               On entry: an estimate of the solution. In the absence of
               better information all elements of X may be set to zero. On
               exit: from E04NAF, X contains the best estimate of the
               solution.

          21:  ISTATE(NCTOTL) -- INTEGER array                 Input/Output
               On entry: with COLD as .FALSE., ISTATE must indicate the
               status of every constraint with respect to the working set.
               The ordering of ISTATE is as follows; the first n elements
               of ISTATE refer to the upper and lower bounds on the
               variables and elements n+1 through n + NCLIN refer to the
               upper and lower bounds on Ax. The significance of each
               possible value of ISTATE(j) is as follows:
               ISTATE(j) Meaning

               -2        The constraint violates its lower bound by more
                         than FEATOL(j). This value of ISTATE cannot occur
                         after a feasible point has been found.

               -1        The constraint violates its upper bound by more
                         than FEATOL(j). This value of ISTATE cannot occur
                         after a feasible point has been found.

               0         The constraint is not in the working set. Usually,
                         this means that the constraint lies strictly
                         between its bounds.

               1         This inequality constraint is included in the
                         working set at its lower bound. The value of the
                         constraint is within FEATOL(j) of its lower bound.

               2         This inequality constraint is included in the
                         working set at its upper bound. The value of the
                         constraint is within FEATOL(j) of its upper bound.

               3         The constraint is included in the working set as
                         an equality. This value of ISTATE can occur only
                         when BL(j) = BU(j). The corresponding constraint
                         is within FEATOL(j) of its required value.
               If COLD = .TRUE., ISTATE need not be set by the user.
               However, when COLD = .FALSE., every element of ISTATE must
               be set to one of the values given above to define a
               suggested initial working set (which will be changed by
               E04NAF if necessary). The most likely values are:
               ISTATE(j) Meaning

               0         The corresponding constraint should not be in the
                         initial working set.

               1         The constraint should be in the initial working
                         set at its lower bound.

               2         The constraint should be in the initial working
                         set at its upper bound.

               3         The constraint should be in the initial working
                         set as an equality. This value must not be
                         specified unless BL(j) = BU(j). The values 1, 2 or
                         3 all have the same effect when BL(j) = BU(j).
               Note that if E04NAF has been called previously with the same
               values of N and NCLIN, ISTATE already contains satisfactory
               values. On exit: when E04NAF exits with IFAIL set to 0, 1 or
               3, the values in the array ISTATE indicate the status of the
               constraints in the active set at the solution. Otherwise,
               ISTATE indicates the composition of the working set at the
               final iterate.

          22:  ITER -- INTEGER                                       Output
               On exit: the number of iterations performed in either the LP
               phase or the QP phase, whichever was last entered.

               Note that ITER is reset to zero after the LP phase.

          23:  OBJ -- DOUBLE PRECISION                               Output
               On exit: the value of the quadratic objective function at x
               if x is feasible (IFAIL <= 5), or the sum of infeasibilities
               at x otherwise (6 <= IFAIL <= 8).

          24:  CLAMDA(NCTOTL) -- DOUBLE PRECISION array              Output
               On exit: the values of the Lagrange multiplier for each
               constraint with respect to the current working set. The
               ordering of CLAMDA is as follows; the first n components
               contain the multipliers for the bound constraints on the
               variables, and the remaining components contain the
               multipliers for the general linear constraints. If ISTATE(j)
               = 0 (i.e.,constraint j is not in the working set), CLAMDA(j)
               is zero. If x is optimal and ISTATE(j) = 1, CLAMDA(j) should
               be non-negative; if ISTATE(j) = 2, CLAMDA(j) should be non-
               positive.

          25:  IWORK(LIWORK) -- INTEGER array                     Workspace

          26:  LIWORK -- INTEGER                                      Input
               On entry:
               the dimension of the array IWORK as declared in the
               (sub)program from which E04NAF is called.
               Constraint: LIWORK>=2*N.

          27:  WORK(LWORK) -- DOUBLE PRECISION array              Workspace

          28:  LWORK -- INTEGER                                       Input
               On entry:
               the dimension of the array WORK as declared in the
               (sub)program from which E04NAF is called.
               Constrai if LP = .FALSE. or NCLIN >= N then
               nts:               2
                        LWORK>=2*N +4*N*NCLIN+NROWA.

                        if LP = .TRUE. and NCLIN < N then
                                          2
                        LWORK>=2*(NCLIN+1) +4*N+2*NCLIN+NROWA.
               If MSGLVL > 0, the amount of workspace provided and the
               amount of workspace required are output on the current
               advisory message unit (as defined by X04ABF). As an
               alternative to computing LWORK from the formula given above,
               the user may prefer to obtain an appropriate value from the
               output of a preliminary run with a positive value of MSGLVL
               and LWORK set to 1 (E04NAF will then terminate with IFAIL =
               9).

          29:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. Users who are
               unfamiliar with this parameter should refer to the Essential
               Introduction for details.

               On exit: IFAIL = 0 unless the routine detects an error or
               gives a warning (see Section 6).

               For this routine, because the values of output parameters
               may be useful even if IFAIL /=0 on exit, users are
               recommended to set IFAIL to -1 before entry. It is then
               essential to test the value of IFAIL on exit. To suppress
               the output of an error message when soft failure occurs, set
               IFAIL to 1.

               IFAIL contains zero on exit if x is a strong local minimum.
               i.e., the projected gradient is neglible, the Lagrange
               multipliers are optimal, and the projected Hessian is
               positive-definite. In some cases, a zero value of IFAIL
               means that x is a global minimum (e.g. when the Hessian
               matrix is positive-definite).

          5.1. Description of the Printed Output

          When MSGLVL >= 5, a line of output is produced for every change
          in the working set (thus, several lines may be printed during a
          single iteration).

          To aid interpretation of the printed results, we mention the
          convention for numbering the constraints: indices 1 through to n
          refer to the bounds on the variables, and when NCLIN > 0 indices
          n+1 through to n + NCLIN refer to the general constraints. When
          the status of a constraint changes, the index of the constraint
          is printed, along with the designation L (lower bound), U (upper
          bound) or E (equality).

          In the LP phase, the printout includes the following:

          ITN            is the iteration count.

          JDEL           is the index of the constraint deleted from the
                         working set. If JDEL is zero, no constraint was
                         deleted.

          JADD           is the index of the constraint added to the
                         working set. If JADD is zero, no constraint was
                         added.

          STEP           is the step taken along the computed search
                         direction.

          COND T         is a lower bound on the condition number of the
                         matrix of predicted active constraints.

          NUMINF         is the number of violated constraints
                         (infeasibilities).

          SUMINF         is a weighted sum of the magnitudes of the
                         constraint violations.

                                                                        T
          LPOBJ          is the value of the linear objective function c x.
                         It is printed only if LP = .TRUE..

          During the QP phase, the printout includes the following:

          ITN            is the iteration count (reset to zero after the LP
                         phase).

          JDEL           is the index of the constraint deleted from the
                         working set. If JDEL is zero, no constraint was
                         deleted.

          JADD           is the index of the constraint added to the
                         working set. If JADD is zero, no constraint was
                         added.

          STEP           is the step (alpha)  taken along the direction of
                                            k
                         search (if STEP is 1.0, the current point is a
                         minimum in the subspace defined by the current
                         working set).

          NHESS          is the number of calls to subroutine QPHESS.

          OBJECTIVE      is the value of the quadratic objective function.

          NCOLZ          is the number of columns of Z (see Section 3). In
                         general, it is the dimension of the subspace in
                         which the quadratic is currently being minimized.

          NORM GFREE     is the Euclidean norm of the gradient of the
                         objective function with respect to the free
                         variables, i.e. variables not currently held at a
                         bound (NORM GFREE is not printed if ORTHOG = .
                         FALSE.). In some cases, the objective function and
                         gradient are updated rather than recomputed. If
                         so, this entry will be -- to indicate that the
                         gradient with respect to the free variables has
                         not been computed.

          NORM QTG       is a weighted norm of the gradient of the
                         objective function with respect to the free
                         variables (NORM QTG is not printed if ORTHOG = .
                         TRUE.). In some cases, the objective function and
                         gradient are updated rather than recomputed. If
                         so, this entry will be -- to indicate that the
                         gradient with respect to the free variables has
                         not been computed.

          NORM ZTG       is the Euclidean norm of the projected gradient
                         (see Section 3).

          COND T         is a lower bound on the condition number of the
                         matrix of constraints in the working set.

          COND ZHZ       is a lower bound on the condition number of the
                         projected Hessian matrix.

          HESS MOD       is the correction added to the diagonal of the
                         projected Hessian to ensure that a satisfactory
                         Cholesky factorization exists (see Section 3).
                         When the projected Hessian is sufficiently
                         positive-definite, HESS MOD will be zero.

          When MSGLVL = 1 or MSGLVL >= 10, the summary printout at the end
          of execution of E04NAF includes a listing of the status of every
          constraint. Note that default names are assigned to all variables
          and constraints.

          The following describes the printout for each variable.

          VARBL          is the name (V) and index j, j=1,2,...,n, of the
                         variable.

          STATE          gives the state of the variable (FR if neither
                         bound is in the working set, EQ if a fixed
                         variable, LL if on its lower bound, UL if on its
                         upper bound, TB if held on a temporary bound). If
                         VALUE lies outside the upper or lower bounds by
                         more than FEATOL(j), STATE will be ++ or --
                         respectively.

          VALUE          is the value of the variable at the final
                         iteration.

          LOWER BOUND    is the lower bound specified for the variable.

          UPPER BOUND    is the upper bound specified for the variable.

          LAGR MULT      is the value of the Lagrange multiplier for the
                         associated bound constraint. This will be zero if
                         STATE is FR. If x is optimal and STATE is LL, the
                         multiplier should be non-negative; if STATE is UL,
                         the multiplier should be non-positive.

          RESIDUAL       is the difference between the variable and the
                         nearer of its bounds BL(j) and BU(j).

          For each of the general constraints the printout is as above with
          refers to the jth element of Ax, except that VARBL is replaced by

          LNCON          The name (L) and index j, j=1,2,...,NCLIN, of the
                         constraint.

          6. Error Indicators and Warnings

          Errors or warnings specified by the routine:

          IFAIL= 1
               x is a weak local minimum (the projected gradient is
               negligible, the Lagrange multipliers are optimal, but the
               projected Hessian is only semi-definite). This means that
               the solution is not unique.

          IFAIL= 2
               The solution appears to be unbounded, i.e., the quadratic
               function is unbounded below in the feasible region. This
               value of IFAIL occurs when a step of infinity would have to
               be taken in order to continue the algorithm.

          IFAIL= 3
               x appears to be a local minimum, but optimality cannot be
               verified because some of the Lagrange multipliers are very
               small in magnitude.

               E04NAF has probably found a solution. However, the presence
               of very small Lagrange multipliers means that the predicted
               active set may be incorrect, or that x may be only a
               constrained stationary point rather than a local minimum.
               The method in E04NAF is not guaranteed to find the correct
               active set when there are very small multipliers. E04NAF
               attempts to delete constraints with zero multipliers, but
               this does not necessarily resolve the issue. The
               determination of the correct active set is a combinatorial
               problem that may require an extremely large amount of time.
               The occurrence of small multipliers often (but not always)
               indicates that there are redundant constraints.

          IFAIL= 4
               The iterates of the QP phase could be cycling, since a total
               of 50 changes were made to the working set without altering
               x.

               This value will occur if 50 iterations are performed in the
               QP phase without changing x. The user should check the
               printed output for a repeated pattern of constraint
               deletions and additions. If a sequence of constraint changes
               is being repeated, the iterates are probably cycling.
               (E04NAF  does not contain a method that is guaranteed to
               avoid cycling, which would be combinatorial in nature.)
               Cycling may occur in two circumstances: at a constrained
               stationary point where there are some small or zero Lagrange
               multipliers (see the discussion of IFAIL = 3); or at a point
               (usually a vertex) where the constraints that are satisfied
               exactly are nearly linearly dependent. In the latter case,
               the user has the option of identifying the offending
               dependent constraints and removing them from the problem, or
               restarting the run with larger values of FEATOL for nearly
               dependent constraints. If E04NAF terminates with IFAIL = 4,
               but no suspicious pattern of constraint changes can be
               observed, it may be worthwhile to restart with the final x
               (with or without the warm start option).

          IFAIL= 5
               The limit of ITMAX iterations was reached in the QP phase
               before normal termination occurred.

               The value of ITMAX may be too small. If the method appears
               to be making progress (e.g. the objective function is being
               satisfactorily reduced), increase ITMAX and rerun E04NAF
               (possibly using the warm start facility to specify the
               initial working set). If ITMAX is already large, but some of
               the constraints could be nearly linearly dependent, check
               the output for a repeated pattern of constraints entering
               and leaving the working set. (Near-dependencies are often
               indicated by wide variations in size in the diagonal
               elements of the T matrix, which will be printed if MSGLVL >=
               30.) In this case, the algorithm could be cycling (see the
               comments for IFAIL = 4).

          IFAIL= 6
               The LP phase terminated without finding a feasible point,
               and hence it is not possible to satisfy all the constraints
               to within the tolerances specified by the FEATOL array. In
               this case, the final iterate will reveal values for which
               there will be a feasible point (e.g. a feasible point will
               exist if the feasibility tolerance for each violated
               constraint exceeds its RESIDUAL at the final point). The
               modified problem (with altered values in FEATOL) may then be
               solved using a warm start.

               The user should check that there are no constraint
               redundancies. If the data for the jth constraint are
               accurate only to the absolute precision (delta), the user
               should ensure that the value of FEATOL(j) is greater than
               (delta). For example, if all elements of A are of order
               unity and are accurate only to three decimal places, every
                                                        -3
               component of FEATOL should be at least 10  .

          IFAIL= 7
               The iterates may be cycling during the LP phase; see the
               comments above under IFAIL = 4.

          IFAIL= 8
               The limit of ITMAX iterations was reached during the LP
               phase. See comments above under IFAIL = 5.

          IFAIL= 9
               An input parameter is invalid.

          Overflow
               If the printed output before the overflow error contains a
               warning about serious ill-conditioning in the working set
               when adding the jth constraint, it may be possible to avoid
               the difficulty by increasing the magnitude of FEATOL(j) and
               rerunning the program. If the message recurs even after this
               change, the offending linearly dependent constraint (with
               index j) must be removed from the problem. If a warning
               message did not precede the fatal overflow, the user should
               contact NAG.

          7. Accuracy

          The routine implements a numerically stable active set strategy
          and returns solutions that are as accurate as the condition of
          the QP problem warrants on the machine.

          8. Further Comments

          The number of iterations depends upon factors such as the number
          of variables and the distances of the starting point from the
          solution. The number of operations performed per iteration is
                                         2
          roughly proportional to (NFREE) , where NFREE (NFREE<=n) is the
          number of variables fixed on their upper or lower bounds.

          Sensible scaling of the problem is likely to reduce the number of
          iterations required and make the problem less sensitive to
          perturbations in the data, thus improving the condition of the QP
          problem. See the Chapter Introduction and Gill et al [1] for
          further information and advice.

          9. Example

                                    T   1 T
          To minimize the function c x+ -x Hx, where
                                        2

                                                             T
                      c=[-0.02,-0.2,-0.2,-0.2,-0.2,0.04,0.04]

                                   [2 0 0 0 0  0  0]
                                   [0 2 0 0 0  0  0]
                                   [0 0 2 2 0  0  0]
                                 H=[0 0 2 2 0  0  0]
                                   [0 0 0 0 2  0  0]
                                   [0 0 0 0 0 -2 -2]
                                   [0 0 0 0 0 -2 -2]

          subject to the bounds

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe04ucf}{nage.ht}
{ Minimize an arbitrary smooth constrainted function}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe04ucf}{NAG Documentation: e04ucf}
\beginscroll
\begin{verbatim}

   
   
   
   E04UCF(3NAG)                 E04UCF                  E04UCF(3NAG)
   
   
   
        E04 -- Minimizing or Maximizing a Function                 E04UCF
                E04UCF -- NAG Foundation Library Routine Document
   
        Note: Before using this routine, please read the Users' Note for
        your implementation to check implementation-dependent details.
        The symbol (*) after a NAG routine name denotes a routine that is
        not included in the Foundation Library.
   
        Note for users via the Axiom system: the interface to this routine
        has been enhanced for use with Axiom and is slightly different to
        that offered in the standard version of the Foundation Library.  In
        particular, the optional parameters of the NAG routine are now
        included in the parameter list.  These are described in section
        5.1.2, below.
   
        1. Purpose
   
        E04UCF is designed to minimize an arbitrary smooth function
        subject to constraints, which may include simple bounds on the
        variables, linear constraints and smooth nonlinear constraints.
        (E04UCF  may be used for unconstrained, bound-constrained and
        linearly constrained optimization.) The user must provide
        subroutines that define the objective and constraint functions
        and as many of their first partial derivatives as possible.
        Unspecified derivatives are approximated by finite differences.
        All matrices are treated as dense, and hence E04UCF is not
        intended for large sparse problems.
   
        E04UCF uses a sequential quadratic programming (SQP) algorithm in
        which the search direction is the solution of a quadratic
        programming (QP) problem. The algorithm treats bounds, linear
        constraints and nonlinear constraints separately.
   
        2. Specification
   
               SUBROUTINE E04UCF (N, NCLIN, NCNLN, NROWA, NROWJ, NROWR,
              1                   A, BL, BU, CONFUN, OBJFUN, ITER,
              2                   ISTATE, C, CJAC, CLAMDA, OBJF, OBJGRD,
              3                   R, X, IWORK, LIWORK, WORK, LWORK,
              4                   IUSER, USER, STA, CRA, DER, FEA, FUN,
              5                   HES, INFB, INFS, LINF, LINT, LIST,
              6                   MAJI, MAJP, MINI, MINP, MON, NONF,
              7                   OPT, STE, STAO, STAC, STOO, STOC, VE,
              8                   IFAIL)
               INTEGER          N, NCLIN, NCNLN, NROWA, NROWJ, NROWR,
              1                 ITER, ISTATE(N+NCLIN+NCNLN), IWORK(LIWORK)
              2                 , LIWORK, LWORK, IUSER(*), DER, MAJI,
              3                 MAJP, MINI, MINP, MON, STAO, STAC, STOO,
              4                 STOC, VE, IFAIL
               DOUBLE PRECISION A(NROWA,*), BL(N+NCLIN+NCNLN), BU
              1                 (N+NCLIN+NCNLN), C(*), CJAC(NROWJ,*),
              2                 CLAMDA(N+NCLIN+NCNLN), OBJF, OBJGRD(N), R
              3                 (NROWR,N), X(N), WORK(LWORK), USER(*),
              4                 CRA, FEA, FUN,  INFB, INFS, LINF, LINT,
              5                 NONF, OPT, STE
               LOGICAL          LIST, STA, HES
               EXTERNAL         CONFUN, OBJFUN
   
        3. Description
   
        E04UCF is designed to solve the nonlinear programming problem --
        the minimization of a smooth nonlinear function subject to a set
        of constraints on the variables. The problem is assumed to be
        stated in the following form:
   
                                                   { x  }
               Minimize      F(x)   subject to  l<={A x }<=u,         (1)
                        n                          { L  }
               x is in R                           {c(x)}
   
        where F(x), the objective function, is a nonlinear function, A
                                                                      L
        is an n  by n constant matrix, and c(x) is an n  element vector
               L                                       N
        of nonlinear constraint functions. (The matrix A  and the vector
                                                        L
        c(x) may be empty.) The objective function and the constraint
        functions are assumed to be smooth, i.e., at least twice-
        continuously differentiable. (The method of E04UCF will usually
        solve (1) if there are only isolated discontinuities away from
        the solution.)
   
        This routine is essentially identical to the subroutine SOL/NPSOL
        described in Gill et al [8].
   
        Note that upper and lower bounds are specified for all the
        variables and for all the constraints.
   
        An equality constraint can be specified by setting l =u . If
                                                            i  i
        certain bounds are not present, the associated elements of l or u
        can be set to special values that will be treated as -infty or
        +infty.
   
        If there are no nonlinear constraints in (1) and F is linear or
        quadratic then one of E04MBF, E04NAF or E04NCF(*) will generally
        be more efficient. If the problem is large and sparse the MINOS
        package (see Murtagh and Saunders [13]) should be used, since
        E04UCF treats all matrices as dense.
   
        The user must supply an initial estimate of the solution to (1),
        together with subroutines that define F(x), c(x) and as many
        first partial derivatives as possible; unspecified derivatives
        are approximated by finite differences.
   
        The objective function is defined by subroutine OBJFUN, and the
        nonlinear constraints are defined by subroutine CONFUN. On every
        call, these subroutines must return appropriate values of the
        objective and nonlinear constraints. The user should also provide
        the available partial derivatives. Any unspecified derivatives
        are approximated by finite differences; see Section 5.1 for a
        discussion of the optional parameter Derivative Level. Just
        before either OBJFUN or CONFUN is called, each element of the
        current gradient array OBJGRD or CJAC is initialised to a special
        value. On exit, any element that retains the value is estimated
        by finite differences. Note that if there are nonlinear
        costraints, then the first call to CONFUN will precede the first
        call to OBJFUN.
   
        For maximum reliability, it is preferable for the user to provide
        all partial derivatives (see Chapter 8 of Gill et al [10], for a
        detailed discussion). If all gradients cannot be provided, it is
        similarly advisable to provide as many as possible. While
        developing the subroutines OBJFUN and CONFUN, the optional
        parameter Verify (see Section 5.1) should be used to check the
        calculation of any known gradients.
   
        E04UCF implements a sequential quadratic programming (SQP)
        method. The document for E04NCF(*) should be consulted in
        conjunction with this document.
   
        In the rest of this section we briefly summarize the main
        features of the method of E04UCF. Where possible, explicit
        reference is made to the names of variables that are parameters
        of subroutines E04UCF or appear in the printed output (see
        Section 5.2).
   
        At a solution of (1), some of the constraints will be active,
        i.e., satisfied exactly. An active simple bound constraint
        implies that the corresponding variable is fixed at its bound,
        and hence the variables are partitioned into fixed and free
        variables. Let C denote the m by n matrix of gradients of the
        active general linear and nonlinear constraints. The number of
        fixed variables will be denoted by n  , with n   (n  =n-n  ) the
                                            FX        FR   FR    FX
        number of free variables. The subscripts 'FX' and 'FR' on a
        vector or matrix will denote the vector or matrix composed of the
        components corresponding to fixed or free variables.
   
        A point x is a first-order Kuhn-Tucker point for (1) (see, e.g.,
        Powell [14]) if the following conditions hold:
   
             (i) x is feasible;
   
             (ii) there exist vectors (xi) and (lambda) (the Lagrange
             multiplier vectors for the bound and general constraints)
             such that
                                  T
                               g=C (lambda)+(xi),                    (2)
             where g is the gradient of F evaluated at x, and (xi) =0 if
                                                                  j
             the jth variable is free.
   
             (iii) The Lagrange multiplier corresponding to an
             inequality constraint active at its lower bound must be
             non-negative, and non-positive for an inequality constraint
             active at its upper bound.
   
        Let Z denote a matrix whose columns form a basis for the set of
        vectors orthogonal to the rows of C  ; i.e., C  Z=0. An
                                           FR         FR
        equivalent statement of the condition (2) in terms of Z is
   
                                     T
                                    Z g  =0.
                                       FR
   
                    T
        The vector Z g   is termed the projected gradient of F at x.
                      FR
        Certain additional conditions must be satisfied in order for a
        first-order Kuhn-Tucker point to be a solution of (1) (see, e.g.,
        Powell [14]).
   
        The method of E04UCF is a sequential quadratic programming (SQP)
        method. For an overview of SQP methods, see, for example,
        Fletcher [5], Gill et al [10] and Powell [15].
   
        The basic structure of E04UCF involves major and minor
        iterations. The major iterations generate a sequence of iterates
                               *
        {x } that converge to x , a first-order Kuhn-Tucker point of (1).
          k
                                                      _
        At a typical major iteration, the new iterate x is defined by
   
                                _
                                x=x+(alpha)p                          (3)
   
        where x is the current iterate, the non-negative scalar (alpha)
        is the step length, and p is the search direction. (For
        simplicity, we shall always consider a typical iteration and
        avoid reference to the index of the iteration.) Also associated
        with each major iteration are estimates of the Lagrange
        multipliers and a prediction of the active set.
   
        The search direction p in (3) is the solution of a quadratic
        programming subproblem of the form
   
                         T   1 T                  _  { p }  _
              Minimize  g p+ -p Hp,   subject to  l<={A p}<=u,        (4)
               p             2                       { L }
                                                     {A p}
                                                     { N }
   
        where g is the gradient of F at x, the matrix H is a positive-
        definite quasi-Newton approximation to the Hessian of the
        Lagrangian function (see Section 8.3), and A  is the Jacobian
                                                    N
        matrix of c evaluated at x. (Finite-difference estimates may be
        used for g and A ; see the optional parameter Derivative Level in
                        N
        Section 5.1.) Let l in (1) be partitioned into three sections:
        l , l  and l , corresponding to the bound, linear and nonlinear
         B   L      N
                                _
        constraints. The vector l in (4) is similarly partitioned, and is
        defined as
   
                       _         _               _
                       l =l -x,  l =l -A x,  and l =l -c,
                        B  B      L  L  L         N  N
   
        where c is the vector of nonlinear constraints evaluated at x.
                   _
        The vector u is defined in an analogous fashion.
   
        The estimated Lagrange multipliers at each major iteration are
        the Lagrange multipliers from the subproblem (4) (and similarly
        for the predicted active set). (The numbers of bounds, general
        linear and nonlinear constraints in the QP active set are the
        quantities Bnd, Lin and Nln in the printed output of E04UCF.) In
        E04UCF, (4) is solved using E04NCF(*). Since solving a quadratic
        program as an iterative procedure, the minor iterations of E04UCF
        are the iterations of E04NCF(*). (More details about solving the
        subproblem are given in Section 8.1.)
   
        Certain matrices associated with the QP subproblem are relevant
        in the major iterations. Let the subscripts 'FX' and 'FR' refer
        to the predicted fixed and free variables, and let C denote the m
        by n matrix of gradients of the general linear and nonlinear
        constraints in the predicted active set. First, we have available
        the TQ factorization of C  :
                                 FR
   
                               C  Q  =(0 T),                          (5)
                                FR FR
   
        where T is a nonsingular m by m reverse-triangular matrix (i.e.,
        t  =0 if i+j<m), and the non-singular n   by n   matrix Q   is
         ij                                    FR     FR         FR
        the product of orthogonal transformations (see Gill et al [6]).
        Second, we have the upper-triangular Cholesky factor R of the
        transformed and re-ordered Hessian matrix
   
                                T       T~
                               R R=H ==Q HQ,                          (6)
                                    Q
   
              ~
        where H is the Hessian H with rows and columns permuted so that
        the free variables are first, and Q is the n by n matrix
   
                                   (Q    )
                                   ( FR  )
                                 Q=(  I  ),                           (7)
                                   (   FX)
   
        with I   the identity matrix of order n  . If the columns of Q
              FX                               FX                     FR
        are partitioned so that
   
                                   Q  =(Z Y),
                                    FR
   
        the n (n ==n  -m) columns of Z form a basis for the null space of
             z  z   FR
                                                                     T
        C  . The matrix Z is used to compute the projected gradient Z g
         FR                                                            FR
        at the current iterate. (The values Nz, Norm Gf and Norm Gz
                                                            T
        printed by E04UCF give n  and the norms of g   and Z g  .)
                                z                   FR        FR
   
        A theoretical characteristic of SQP methods is that the predicted
        active set from the QP subproblem (4) is identical to the correct
                                          *
        active set in a neighbourhood of x . In E04UCF, this feature is
        exploited by using the QP active set from the previous iteration
        as a prediction of the active set for the next QP subproblem,
        which leads in practice to optimality of the subproblems in only
        one iteration as the solution is approached. Separate treatment
        of bound and linear constraints in E04UCF also saves computation
        in factorizing C   and H .
                        FR      Q
   
        Once p has been computed, the major iteration proceeds by
        determining a step length (alpha) that produces a 'sufficient
        decrease' in an augmented Lagrangian merit function (see Section
        8.2). Finally, the approximation to the transformed Hessian
        matrix H  is updated using a modified BFGS quasi-Newton update
                Q
        (see Section 8.3) to incorporate new curvature information
                                       _
        obtained in the move from x to x.
   
        On entry to E04UCF, an iterative procedure from E04NCF(*) is
        executed, starting with the user-provided initial point, to find
        a point that is feasible with respect to the bounds and linear
        constraints (using the tolerance specified by Linear Feasibility
        Tolerance see Section 5.1). If no feasible point exists for the
        bound and linear constraints, (1) has no solution and E04UCF
        terminates. Otherwise, the problem functions will thereafter be
        evaluated only at points that are feasible with respect to the
        bounds and linear constraints. The only exception involves
        variables whose bounds differ by an amount comparable to the
        finite-difference interval (see the discussion of Difference
        Interval in Section 5.1). In contrast to the bounds and linear
        constraints, it must be emphasised that the nonlinear constraints
        will not generally be satisfied until an optimal point is
        reached.
   
        Facilities are provided to check whether the user-provided
        gradients appear to be correct (see the optional parameter Verify
        in Section 5.1). In general, the check is provided at the first
        point that is feasible with respect to the linear constraints and
        bounds. However, the user may request that the check be performed
        at the initial point.
   
        In summary, the method of E04UCF first determines a point that
        satisfies the bound and linear constraints. Thereafter, each
        iteration includes:
   
        (a)   the solution of a quadratic programming subproblem;
   
        (b)   a linesearch with an augmented Lagrangian merit function;
              and
   
        (c)   a quasi-Newton update of the approximate Hessian of the
              Lagrangian function.
   
        These three procedures are described in more detail in Section 8.
   
        4. References
   
        [1]   Dennis J E Jr and More J J (1977) Quasi-Newton Methods,
              Motivation and Theory. SIAM Review. 19 46--89.
   
        [2]   Dennis J E Jr and Schnabel R B (1981) A New Derivation of
              Symmetric Positive-Definite Secant Updates. Nonlinear
              Programming 4. (ed O L Mangasarian, R R Meyer and S M.
              Robinson) Academic Press. 167--199.
   
        [3]   Dennis J E Jr and Schnabel R B (1983) Numerical Methods for
              Unconstrained Optimixation and Nonlinear Equations.
              Prentice-Hall.
   
        [4]   Dongarra J J, Du Croz J J, Hammarling S and Hanson R J
              (1985) A Proposal for an Extended set of Fortran Basic
              Linear Algebra Subprograms. SIGNUM Newsletter. 20 (1) 2--18.
   
        [5]   Fletcher R (1981) Practical Methods of Optimization, Vol 2.
              Constrained Optimization. Wiley.
   
        [6]   Gill P E, Murray W, Saunders M A and Wright M H (1984)
              User's Guide for SOL/QPSOL Version 3.2. Report SOL 84-5.
              Department of Operations Research, Stanford University.
   
        [7]   Gill P E, Murray W, Saunders M A and Wright M H (1984)
              Procedures for Optimization Problems with a Mixture of
              Bounds and General Linear Constraints. ACM Trans. Math.
              Softw. 10 282--298.
   
        [8]   Gill P E, Hammarling S, Murray W, Saunders M A and Wright M
              H (1986) User's Guide for LSSOL (Version 1.0). Report SOL
              86-1. Department of Operations Research, Stanford
              University.
   
        [9]   Gill P E, Murray W, Saunders M A and Wright M H (1986) Some
              Theoretical Properties of an Augmented Lagrangian Merit
              Function. Report SOL 86-6R. Department of Operations
              Research, Stanford University.
   
        [10]  Gill P E, Murray W and Wright M H (1981) Practical
              Optimization. Academic Press.
   
        [11]  Hock W and Schittkowski K (1981) Test Examples for Nonlinear
              Programming Codes. Lecture Notes in Economics and
              Mathematical Systems. 187 Springer-Verlag.
   
        [12]  Lawson C L, Hanson R J, Kincaid D R and Krogh F T (1979)
              Basic Linear Algebra Subprograms for Fortran Usage. ACM
              Trans. Math. Softw. 5 308--325.
   
        [13]  Murtagh B A and Saunders M A (1983) MINOS 5.0 User's Guide.
              Report SOL 83-20. Department of Operations Research,
              Stanford University.
   
        [14]  Powell M J D (1974) Introduction to Constrained
              Optimization. Numerical Methods for Constrained
              Optimization. (ed P E Gill and W Murray) Academic Press. 1--
              28.
   
        [15]  Powell M J D (1983) Variable Metric Methods in Constrained
              Optimization. Mathematical Programming: The State of the
              Art. (ed A Bachem, M Groetschel and B Korte) Springer-
              Verlag. 288--311.
   
        5. Parameters
   
         1:  N -- INTEGER                                           Input
             On entry: the number, n, of variables in the problem.
             Constraint: N > 0.
   
         2:  NCLIN -- INTEGER                                       Input
             On entry: the number, n , of general linear constraints in
                                    L
             the problem. Constraint: NCLIN >= 0.
   
         3:  NCNLN -- INTEGER                                       Input
             On entry: the number, n , of nonlinear constraints in the
                                    N
             problem. Constraint: NCNLN >= 0.
   
         4:  NROWA -- INTEGER                                       Input
             On entry:
             the first dimension of the array A as declared in the
             (sub)program from which E04UCF is called.
             Constraint: NROWA >= max(1,NCLIN).
   
         5:  NROWJ -- INTEGER                                       Input
             On entry:
             the first dimension of the array CJAC as declared in the
             (sub)program from which E04UCF is called.
             Constraint: NROWJ >= max(1,NCNLN).
   
         6:  NROWR -- INTEGER                                       Input
             On entry:
             the first dimension of the array R as declared in the
             (sub)program from which E04UCF is called.
             Constraint: NROWR >= N.
   
         7:  A(NROWA,*) -- DOUBLE PRECISION array                   Input
             The second dimension of the array A must be >= N for NCLIN >
             0. On entry: the ith row of the array A must contain the ith
             row of the matrix A  of general linear constraints in (1).
                                L
             That is, the ith row contains the coefficients of the ith
             general linear constraint, for i = 1,2,...,NCLIN.
   
             If NCLIN = 0 then the array A is not referenced.
   
         8:  BL(N+NCLIN+NCNLN) -- DOUBLE PRECISION array            Input
             On entry: the lower bounds for all the constraints, in the
             following order. The first n elements of BL must contain the
             lower bounds on the variables. If NCLIN > 0, the next n
                                                                    L
             elements of BL must contain the lower bounds on the general
             linear constraints. If NCNLN > 0, the next n  elements of BL
                                                         N
             must contain the lower bounds for the nonlinear constraints.
             To specify a non-existent lower bound (i.e., l =-infty), the
                                                           j
             value used must satisfy BL(j)<=-BIGBND, where BIGBND is the
             value of the optional parameter Infinite Bound Size whose
                                10
             default value is 10   (see Section 5.1). To specify the jth
             constraint as an equality, the user must set BL(j) = BU(j) =
             (beta), say, where |(beta)|<BIGBND. Constraint: BL(j) <= BU(
             j), for j=1,2,...,N+NCLIN+NCNLN.
   
         9:  BU(N+NCLIN+NCNLN) -- DOUBLE PRECISION array            Input
             On entry: the upper bounds for all the constraints in the
             following order. The first n elements of BU must contain the
             upper bounds on the variables. If NCLIN > 0, the next n
                                                                    L
             elements of BU must contain the upper bounds on the general
             linear constraints. If NCNLN > 0, the next n  elements of BU
                                                         N
             must contain the upper bounds for the nonlinear constraints.
             To specify a non-existent upper bound (i.e., u =+infty), the
                                                           j
             value used must satisfy BU(j) >= BIGBND, where BIGBND is the
             value of the optional parameter Infinite Bound Size, whose
                                10
             default value is 10   (see Section 5.1). To specify the jth
             constraint as an equality, the user must set BU(j) = BL(j) =
             (beta), say, where |(beta)| < BIGBND. Constraint: BU(j) >=
             BL(j), for j=1,2,...,N+NCLIN+NCNLN.
   
        10:  CONFUN -- SUBROUTINE, supplied by the user.
                                                       External Procedure
             CONFUN must calculate the vector c(x) of nonlinear
             constraint functions and (optionally) its Jacobian for a
             specified n element vector x. If there are no nonlinear
             constraints (NCNLN=0), CONFUN will never be called by E04UCF
             and CONFUN may be the dummy routine E04UDM. (E04UDM is
             included in the NAG Foundation Library and so need not be
             supplied by the user. Its name may be implementation-
             dependent: see the Users' Note for your implementation for
             details.) If there are nonlinear constraints, the first call
             to CONFUN will occur before the first call to OBJFUN.
   
             Its specification is:
   
                    SUBROUTINE CONFUN (MODE, NCNLN, N, NROWJ, NEEDC,
                   1                   X, C, CJAC, NSTATE, IUSER,
                   2                   USER)
                    INTEGER          MODE, NCNLN, N, NROWJ, NEEDC
                   1                 (NCNLN), NSTATE, IUSER(*)
                    DOUBLE PRECISION X(N), C(NCNLN), CJAC(NROWJ,N),
                   1                 USER(*)
   
              1:  MODE -- INTEGER                            Input/Output
                  On entry: MODE indicates the values that must be
                  assigned during each call of CONFUN. MODE will always
                  have the value 2 if all elements of the Jacobian are
                  available, i.e., if Derivative Level is either 2 or 3
                  (see Section 5.1). If some elements of CJAC are
                  unspecified, E04UCF will call CONFUN with MODE = 0, 1,
                  or 2:
   
                  If MODE = 2, only the elements of C corresponding to
                  positive values of NEEDC must be set (and similarly for
                  the available components of the rows of CJAC).
   
                  If MODE = 1, the available components of the rows of
                  CJAC corresponding to positive values in NEEDC must be
                  set. Other rows of CJAC and the array C will be
                  ignored.
   
                  If MODE = 0, the components of C corresponding to
                  positive values in NEEDC must be set. Other components
                  and the array CJAC are ignored. On exit: MODE may be
                  set to a negative value if the user wishes to terminate
                  the solution to the current problem. If MODE is
                  negative on exit from CONFUN then E04UCF will terminate
                  with IFAIL set to MODE.
   
              2:  NCNLN -- INTEGER                                  Input
                  On entry: the number, n , of nonlinear constraints.
                                         N
   
              3:  N -- INTEGER                                      Input
                  On entry: the number, n, of variables.
   
              4:  NROWJ -- INTEGER                                  Input
                  On entry: the first dimension of the array CJAC.
   
              5:  NEEDC(NCNLN) -- INTEGER array                     Input
                  On entry: the indices of the elements of C or CJAC that
                  must be evaluated by CONFUN. If NEEDC(i)>0 then the ith
                  element of C and/or the ith row of CJAC (see parameter
                  MODE above) must be evaluated at x.
   
              6:  X(N) -- DOUBLE PRECISION array                    Input
                  On entry: the vector x of variables at which the
                  constraint functions are to be evaluated.
   
              7:  C(NCNLN) -- DOUBLE PRECISION array               Output
                  On exit: if NEEDC(i)>0 and MODE = 0 or 2, C(i) must
                  contain the value of the ith constraint at x. The
                  remaining components of C, corresponding to the non-
                  positive elements of NEEDC, are ignored.
   
              8:  CJAC(NROWJ,N) -- DOUBLE PRECISION array          Output
                  On exit: if NEEDC(i)>0 and MODE = 1 or 2, the ith row
                  of CJAC must contain the available components of the
                  vector (nabla)c  given by
                                 i
                                      ( ddc   ddc       ddc )
                                      (    i     i         i)T
                            (nabla)c =( ----, ----,..., ----) ,
                                    i ( ddx   ddx       ddx )
                                      (    1     2         n)
                         ddc
                            i
                  where  ---- is the partial derivative of the ith
                         ddx
                            j
                  constraint with respect to the jth variable, evaluated
                  at the point x. See also the parameter NSTATE below.
                  The remaining rows of CJAC, corresponding to non-
                  positive elements of NEEDC, are ignored.
   
                  If all constraint gradients (Jacobian elements) are
                  known (i.e., Derivative Level = 2 or 3; see Section 5.1)
                  any constant elements may be assigned to CJAC one
                  time only at the start of the optimization. An element
                  of CJAC that is not subsequently assigned in CONFUN
                  will retain its initial value throughout. Constant
                  elements may be loaded into CJAC either before the call
                  to E04UCF or during the first call to CONFUN (signalled
                  by the value NSTATE = 1). The ability to preload
                  constants is useful when many Jacobian elements are
                  identically zero, in which case CJAC may be initialised
                  to zero and non-zero elements may be reset by CONFUN.
   
                  Note that constant non-zero elements do affect the
                  values of the constraints. Thus, if CJAC(i,j) is set to
                  a constant value, it need not be reset in subsequent
                  calls to CONFUN, but the value CJAC(i,j)*X(j) must
                  nonetheless be added to C(i).
   
                  It must be emphasized that, if Derivative Level < 2,
                  unassigned elements of CJAC are not treated as
                  constant; they are estimated by finite differences, at
                  non-trivial expense. If the user does not supply a
                  value for Difference Interval (see Section 5.1), an
                  interval for each component of x is computed
                  automatically at the start of the optimization. The
                  automatic procedure can usually identify constant
                  elements of CJAC, which are then computed once only by
                  finite differences.
   
              9:  NSTATE -- INTEGER                                 Input
                  On entry: if NSTATE = 1 then E04UCF is calling CONFUN
                  for the first time. This parameter setting allows the
                  user to save computation time if certain data must be
                  read or calculated only once.
   
             10:  IUSER(*) -- INTEGER array                User Workspace
   
             11:  USER(*) -- DOUBLE PRECISION array        User Workspace
                  CONFUN is called from E04UCF with the parameters IUSER
                  and USER as supplied to E04UCF. The user is free to use
                  the arrays IUSER and USER to supply information to
                  CONFUN as an alternative to using COMMON.
             CONFUN must be declared as EXTERNAL in the (sub)program
             from which E04UCF is called. Parameters denoted as
             Input must not be changed by this procedure.
   
        11:  OBJFUN -- SUBROUTINE, supplied by the user.
                                                       External Procedure
             OBJFUN must calculate the objective function F(x) and
             (optionally) the gradient g(x) for a specified n element
             vector x.
   
             Its specification is:
   
                    SUBROUTINE OBJFUN (MODE, N, X, OBJF, OBJGRD,
                   1                   NSTATE, IUSER, USER)
                    INTEGER          MODE, N, NSTATE, IUSER(*)
                    DOUBLE PRECISION X(N), OBJF, OBJGRD(N), USER(*)
   
              1:  MODE -- INTEGER                            Input/Output
                  On entry: MODE indicates the values that must be
                  assigned during each call of OBJFUN.
   
                  MODE will always have the value 2 if all components of
                  the objective gradient are specified by the user, i.e.,
                  if Derivative Level is either 1 or 3. If some gradient
                  elements are unspecified, E04UCF will call OBJFUN with
                  MODE = 0, 1 or 2.
                       If MODE = 2, compute OBJF and the available
                       components of OBJGRD.
   
                       If MODE = 1, compute all available components of
                       OBJGRD; OBJF is not required.
   
                       If MODE = 0, only OBJF needs to be computed;
                       OBJGRD is ignored.
                  On exit: MODE may be set to a negative value if the
                  user wishes to terminate the solution to the current
                  problem. If MODE is negative on exit from OBJFUN, then
                  E04UCF will terminate with IFAIL set to MODE.
   
              2:  N -- INTEGER                                      Input
                  On entry: the number, n, of variables.
   
              3:  X(N) -- DOUBLE PRECISION array                    Input
                  On entry: the vector x of variables at which the
                  objective function is to be evaluated.
   
              4:  OBJF -- DOUBLE PRECISION                         Output
                  On exit: if MODE = 0 or 2, OBJF must be set to the
                  value of the objective function at x.
   
              5:  OBJGRD(N) -- DOUBLE PRECISION array              Output
                  On exit: if MODE = 1 or 2, OBJGRD must return the
                  available components of the gradient evaluated at x.
   
              6:  NSTATE -- INTEGER                                 Input
                  On entry: if NSTATE = 1 then E04UCF is calling OBJFUN
                  for the first time. This parameter setting allows the
                  user to save computation time if certain data must be
                  read or calculated only once.
   
              7:  IUSER(*) -- INTEGER array                User Workspace
   
              8:  USER(*) -- DOUBLE PRECISION array        User Workspace
                  OBJFUN is called from E04UCF with the parameters IUSER
                  and USER as supplied to E04UCF. The user is free to use
                  the arrays IUSER and USER to supply information to
                  OBJFUN as an alternative to using COMMON.
             OBJFUN must be declared as EXTERNAL in the (sub)program
             from which E04UCF is called. Parameters denoted as
             Input must not be changed by this procedure.
   
        12:  ITER -- INTEGER                                       Output
             On exit: the number of iterations performed.
   
        13:  ISTATE(N+NCLIN+NCNLN) -- INTEGER array          Input/Output
             On entry: ISTATE need not be initialised if E04UCF is called
             with (the default) Cold Start option. The ordering of ISTATE
             is as follows. The first n elements of ISTATE refer to the
             upper and lower bounds on the variables, elements n+1
             through n+n  refer to the upper and lower bounds on A x, and
                        L                                         L
             elements n+n +1 through n+n +n  refer to the upper and lower
                         L              L  N
             bounds on c(x). When a Warm Start option is chosen, the
             elements of ISTATE corresponding to the bounds and linear
             constraints define the initial working set for the procedure
             that finds a feasible point for the linear constraints and
             bounds. The active set at the conclusion of this procedure
             and the elements of ISTATE corresponding to nonlinear
             constraints then define the initial working set for the
             first QP subproblem. Possible values for ISTATE(j) are:
   
             ISTATE(j) Meaning
   
             0         The corresponding constraint is not in the initial
                       QP working set.
   
             1         This inequality constraint should be in the
                       working set at its lower bound.
   
             2         This inequality constraint should be in the
                       working set at its upper bound.
   
             3         This equality constraint should be in the initial
                       working set. This value must not be specified
                       unless BL(j) = BU(j). The values 1,2 or 3 all have
                       the same effect when BL(j) = BU(j).
             Note that if E04UCF has been called previously with the same
             values of N, NCLIN and NCNLN, ISTATE already contains
             satisfactory values. If necessary, E04UCF will override the
             user's specification of ISTATE so that a poor choice will
             not cause the algorithm to fail. On exit: with IFAIL = 0 or
             1, the values in the array ISTATE correspond to the active
             set of the final QP subproblem, and are a prediction of the
             status of the constraints at the solution of the problem.
             Otherwise, ISTATE indicates the composition of the QP
             working set at the final iterate. The significance of each
             possible value of ISTATE(j) is as follows:
             -2        This constraint violates its lower bound by more
                       than the appropriate feasibility tolerance (see
                       the optional parameters LinearFeasibility
                       Tolerance and Nonlinear Feasibility Tolerance in
                       Section 5.1). This value can occur only when no
                       feasible point can be found for a QP subproblem.
   
             -1        This constraint violates its upper bound by more
                       than the appropriate feasibility tolerance (see
                       the optional parameters Linearear Feasibility
                       Tolerance and Nonlinear Feasibility Tolerance in
                       Section 5.1). This value can occur only when no
                       feasible point can be found for a QP subproblem.
   
             0         The constraint is satisfied to within the
                       feasibility tolerance, but is not in the working
                       set.
   
             1         This inequality constraint is included in the QP
                       working set at its upper bound.
   
             2         This inequality constraint is included in the QP
                       working set at its upper bound.
   
             3         This constraint is included in the QP working set
                       as an equality. This value of ISTATE can occur
                       only when BL(j) = BU(j).
   
        14:  C(*) -- DOUBLE PRECISION array                        Output
             Note: the dimension of the array C must be at least
             max(1,NCNLN).
             On exit: if NCNLN > 0, C(i) contains the value of the ith
             nonlinear constraint function c  at the final iterate, for
                                            i
             i=1,2,...,NCNLN. If NCNLN = 0, then the array C is not
             referenced.
   
        15:  CJAC(NROWJ,*) -- DOUBLE PRECISION array         Input/Output
             Note: the second dimension of the array CJAC must be at
             least N for NCNLN >0 and 1 otherwise On entry: in general,
             CJAC need not be initialised before the call to E04UCF.
             However, if Derivative Level = 3, the user may optionally
             set the constant elements of CJAC (see parameter NSTATE in
             the description of CONFUN). Such constant elements need not
             be re-assigned on subsequent calls to CONFUN. If NCNLN = 0,
             then the array CJAC is not referenced. On exit: if NCNLN >
             0, CJAC contains the Jacobian matrix of the nonlinear
             constraint functions at the final iterate, i.e., CJAC(i,j)
             contains the partial derivative of the ith constraint
             function with respect to the jth variable, for i=1,2,...,
             NCNLN; j = 1,2,...,N. (See the discussion of parameter CJAC
             under CONFUN.)
   
        16:  CLAMDA(N+NCLIN+NCNLN) -- DOUBLE PRECISION array Input/Output
             On entry: CLAMDA need not be initialised if E04UCF is called
             with the (default) Cold Start option. With the Warm Start
             option, CLAMDA must contain a multiplier estimate for each
             nonlinear constraint with a sign that matches the status of
             the constraint specified by the ISTATE array (as above). The
             ordering of CLAMDA is as follows; the first n elements
             contain the multipliers for the bound constraints on the
             variables, elements n+1 through n+n  contain the multipliers
                                                L
             for the general linear constraints, and elements n+n +1
                                                                 L
             through n+n +n  contain the multipliers for the nonlinear
                        L  N
             constraints. If the jth constraint is defined as 'inactive'
             by the initial value of the ISTATE array, CLAMDA(j) should
             be zero; if the jth constraint is an inequality active at
             its lower bound, CLAMDA(j) should be non-negative; if the j
             th constraint is an inequality active at its upper bound,
             CLAMDA(j) should be non-positive. On exit: the values of the
             QP multipliers from the last QP subproblem. CLAMDA(j) should
             be non-negative if ISTATE(j) = 1 and non-positive if ISTATE(
             j) = 2.
   
        17:  OBJF -- DOUBLE PRECISION                              Output
             On exit: the value of the objective function, F(x), at the
             final iterate.
   
        18:  OBJGRD(N) -- DOUBLE PRECISION array                   Output
             On exit: the gradient (or its finite-difference
             approximation) of the objective function at the final
             iterate.
   
        19:  R(NROWR,N) -- DOUBLE PRECISION array            Input/Output
             On entry: R need not be initialised if E04UCF is called with
             a Cold Start option (the default), and will be taken as the
             identity. With a Warm Start R must contain the upper-
             triangular Cholesky factor R of the initial approximation of
             the Hessian of the Lagrangian function, with the variables
             in the natural order. Elements not in the upper-triangular
             part of R are assumed to be zero and need not be assigned.
             On exit: if Hessian = No, (the default; see Section 5.1), R
                                                                 T~
             contains the upper-triangular Cholesky factor R of Q HQ, an
             estimate of the transformed and re-ordered Hessian of the
             Lagrangian at x (see (6) in Section 3). If Hessian = Yes, R
             contains the upper-triangular Cholesky factor R of H, the
             approximate (untransformed) Hessian of the Lagrangian, with
             the variables in the natural order.
   
        20:  X(N) -- DOUBLE PRECISION array                  Input/Output
             On entry: an initial estimate of the solution. On exit: the
             final estimate of the solution.
   
        21:  IWORK(LIWORK) -- INTEGER array                     Workspace
   
        22:  LIWORK -- INTEGER                                      Input
             On entry:
             the dimension of the array IWORK as declared in the
             (sub)program from which E04UCF is called.
             Constraint: LIWORK>=3*N+NCLIN+2*NCNLN.
   
        23:  WORK(LWORK) -- DOUBLE PRECISION array              Workspace
   
        24:  LWORK -- INTEGER                                       Input
             On entry:
             the dimension of the array WORK as declared in the
             (sub)program from which E04UCF is called.
             Constraints:
             if NCLIN = NCNLN = 0 then
                   LWORK >=20*N
   
             if NCNLN = 0 and NCLIN > 0 then
                              2
                   LWORK >=2*N +20*N+11*NCLIN
   
             if NCNLN > 0 and NCLIN >= 0 then
                             2
                   LWORK>=2*N +N*NCLIN+20*N*NCNLN+20*N+ 11*NCLIN+21*NCNLN
   
             If Major Print Level > 0, the required amounts of workspace
             are output on the current advisory message channel (see
             X04ABF). As an alternative to computing LIWORK and LWORK
             from the formulas given above, the user may prefer to obtain
             appropriate values from the output of a preliminary run with
             a positive value of Major Print Level and LIWORK and LWORK
             set to 1. (E04UCF will then terminate with IFAIL = 9.)
   
        25:  IUSER(*) -- INTEGER array                     User Workspace
             Note: the dimension of the array IUSER must be at least 1.
             IUSER is not used by E04UCF, but is passed directly to
             routines CONFUN and OBJFUN and may be used to pass
             information to those routines.
   
        26:  USER(*) -- DOUBLE PRECISION array             User Workspace
             Note: the dimension of the array USER must be at least 1.
             USER is not used by E04UCF, but is passed directly to
             routines CONFUN and OBJFUN and may be used to pass
             information to those routines.
   
        27:  IFAIL -- INTEGER                                Input/Output
             On entry: IFAIL must be set to 0, -1 or 1. Users who are
             unfamiliar with this parameter should refer to the Essential
             Introduction for details.
   
             On exit: IFAIL = 0 unless the routine detects an error or
             gives a warning (see Section 6).
   
             For this routine, because the values of output parameters
             may be useful even if IFAIL /=0 on exit, users are
             recommended to set IFAIL to -1 before entry. It is then
             essential to test the value of IFAIL on exit.
   
             E04UCF returns with IFAIL = 0 if the iterates have
             converged to a point x that satisfies the first-order Kuhn-
             Tucker conditions to the accuracy requested by the optional
             parameter Optimality Tolerance (see Section 5.1), i.e., the
             projected gradient and active constraint residuals are
             negligible at x.
   
             The user should check whether the following four conditions
             are satisfied:
             (i)   the final value of Norm Gz is significantly less than
                   that at the starting point;
   
             (ii)  during the final major iterations, the values of Step
                   and ItQP are both one;
   
             (iii) the last few values of both Norm Gz and Norm C become
                   small at a fast linear rate;
   
             (iv)  Cond Hz is small.
             If all these conditions hold, x is almost certainly a local
             minimum of (1). (See Section 9 for a specific example.)
   
        5.1. Optional Input Parameters
   
        Several optional parameters in E04UCF define choices in the
        behaviour of the routine. In order to reduce the number of formal
        parameters of E04UCF these optional parameters have associated
        default values (see Section 5.1.3) that are appropriate for most
        problems. Therefore the user need only specify those optional
        parameters whose values are to be different from their default
        values.
   
        The remainder of this section can be skipped by users who wish to
        use the default values for all optional prameters. A complete
        list of optional parameters and their default values is given in
        Section 5.1.3
   
        5.1.1. Specification of the optional parameters
   
        Optional parameters may be specified by calling one, or both, of
        E04UDF and E04UEF prior to a call to E04UCF.
   
        E04UDF reads options from an external options file, with Begin
        and End as the first and last lines respectively and each
        intermediate line defining a single optional parameter. For
        example,
   
              Begin
                Print Level = 1
              End
   
        The call
   
              CALL E04UDF (IOPTNS, INFORM)
   
        can then be used to read the file on unit IOPTNS. INFORM will be
        zero on successful exit. E04UDF should be consulted for a full
        description of this method of supplying optional parameters.
   
        E04UEF can be called directly to supply options, one call being
        necessary for each optional parameter. For example,
   
              CALL E04UEF (`Print level = 1')
   
        E04UEF should be consulted for a full description of this method
        of supplying optional parameters.
   
        All optional parameters not specified by the user are set to
        their default values. Optional parameters specified by the user
        are unaltered by E04UCF (unless they define invalid values) and
        so remain in effect for subsequent calls to E04UCF, unless
        altered by the user.
   
        5.1.2. Description of the optional parameters
   
        The following list (in alphabetical order) gives the valid
        options. For each option, we give the keyword, any essential
        optional qualifiers, the default value, and the definition. The
        minimum valid abbreviation of each keyword is underlined. If no
        characters of an optional qualifier are underlined, the qualifier
        may be omitted. The letter a denotes a phrase (character string)
        that qualifies an option. The letters i and r denote INTEGER and
        DOUBLE PRECISION values required with certain options. The number
        (epsilon) is a generic notation for machine precision (see
        X02AJF(*) ), and (epsilon)  denotes the relative precision of the
                                  R
        objective function (the optional parameter Function Precision see
        below).
   
        Central Difference Interval r Default values are computed
   
        If the algorithm switches to central differences because the
        forward-difference approximation is not sufficiently accurate,
        the value of r is used as the difference interval for every
        component of x. The use of finite-differences is discussed
        further below under the optional parameter Difference Interval.
   
        Cold Start Default = Cold Start
   
        Warm Start
   
           (Axiom parameter STA, warm start when .TRUE.)
   
        This option controls the specification of the initial working set
        in both the procedure for finding a feasible point for the linear
        constraints and bounds, and in the first QP subproblem
        thereafter. With a Cold Start, the first working set is chosen by
        E04UCF based on the values of the variables and constraints at
        the initial point. Broadly speaking, the initial working set will
        include equality constraints and bounds or inequality constraints
        that violate or 'nearly' satisfy their bounds (within Crash
        Tolerance; see below). With a Warm Start, the user must set the
        ISTATE array and define CLAMDA and R as discussed in Section 5.
        ISTATE values associated with bounds and linear constraints
        determine the initial working set of the procedure to find a
        feasible point with respect to the bounds and linear constraints.
        ISTATE values associated with nonlinear constraints determine the
        initial working set of the first QP subproblem after such a
        feasible point has been found. E04UCF will override the user's
        specification of ISTATE if necessary, so that a poor choice of
        the working set will not cause a fatal error. A warm start will
        be advantageous if a good estimate of the initial working set is
        available - for example, when E04UCF is called repeatedly to
        solve related problems.
   
        Crash Tolerance r Default = 0.01
   
           (Axiom parameter CRA)
   
        This value is used in conjunction with the optional parameter
        Cold Start (the default value). When making a cold start, the QP
        algorithm in E04UCF must select an initial working set. When r>=0
        , the initial working set will include (if possible) bounds or
        general inequality constraints that lie within r of their bounds.
                                                 T
        In particular, a constraint of the form a x>=l will be included
                                                 j
                                        T
        in the initial working set if |a x-l|<=r(1+|l|). If r<0 or r>1,
                                        j
        the default value is used.
   
        Defaults
   
        This special keyword may be used to reset the default values
        following a call to E04UCF.
   
        Derivative Level i Default = 3
   
           (Axiom parameter DER)
   
        This parameter indicates which derivatives are provided by the
        user in subroutines OBJFUN and CONFUN. The possible choices for i
        are the following.
   
            i    Meaning
   
            3    All objective and constraint gradients are provided by
                 the user.
   
            2    All of the Jacobian is provided, but some components of
                 the objective gradient are not specified by the user.
   
            1    All elements of the objective gradient are known, but
                 some elements of the Jacobian matrix are not specified
                 by the user.
   
            0    Some elements of both the objective gradient and the
                 Jacobian matrix are not specified by the user.
   
        The value i=3 should be used whenever possible, since E04UCF is
        more reliable and will usually be more efficient when all
        derivatives are exact.
   
        If i=0 or 2, E04UCF will estimate the unspecified components of
        the objective gradient, using finite differences. The computation
        of finite-difference approximations usually increases the total
        run-time, since a call to OBJFUN is required for each unspecified
        element. Furthermore, less accuracy can be attained in the
        solution (see Chapter 8 of Gill et al [10], for a discussion of
        limiting accuracy).
   
        If i=0 or 1, E04UCF will approximate unspecified elements of the
        Jacobian. One call to CONFUN is needed for each variable for
        which partial derivatives are not available. For example, if the
        Jacobian has the form
   
                                    (* * * *)
                                    (* ? ? *)
                                    (* * ? *)
                                    (* * * *)
   
        where '*' indicates an element provided by the user and '?'
        indicates an unspecified element, E04UCF will call CONFUN twice:
        once to estimate the missing element in column 2, and again to
        estimate the two missing elements in column 3. (Since columns 1
        and 4 are known, they require no calls to CONFUN.)
   
        At times, central differences are used rather than forward
        differences, in which case twice as many calls to OBJFUN and
        CONFUN are needed. (The switch to central differences is not
        under the user's control.)
   
        Difference Interval r Default values are computed
   
           (Axiom parameter DIF)
   
        This option defines an interval used to estimate gradients by
        finite differences in the following circumstances:
   
        (a)   For verifying the objective and/or constraint gradients
              (see the description of Verify, below).
   
        (b)   For estimating unspecified elements of the objective
              gradient of the Jacobian matrix.
   
        In general, a derivative with respect to the jth variable is
                                                                      ^
        approximated using the interval (delta) , where (delta) =r(1+|x |)
                                               j               j       j
                ^
        with x the first point feasible with respect to the bounds and
        linear constraints. If the functions are well scaled, the
        resulting derivative approximation should be accurate to O(r).
   
        See Gill et al [10] for a discussion of the accuracy in finite-
        difference approximations.
   
        If a difference interval is not specified by the user, a finite-
        difference interval will be computed automatically for each
        variable by a procedure that requires up to six calls of CONFUN
        and OBJFUN for each component. This option is recommended if the
        function is badly scaled or the user wishes to have E04UCF
        determine constant elements in the objective and constraint
        gradients (see the descriptions of CONFUN and OBJFUN in
        Section 5).
   
                                            _________
        Feasibility Tolerance r Default = \/(epsilon)
   
           (Axiom parameter FEA)
   
        The scalar r defines the maximum acceptable absolute violations
        in linear and nonlinear constraints at a 'feasible' point; i.e.,
        a constraint is considered satisfied if its violation does not
        exceed r. If r<(epsilon) or r>=1, the default value is used.
        Using this keyword sets both optional parameters Linear
        Feasibility Tolerance and Nonlinear Feasibility Tolerance to r,
        if (epsilon)<=r<1. (Additional details are given below under the
        descriptions of these parameters.)
   
                                                0.9
        Function Precision r Default = (epsilon)
   
           (Axiom parameter FUN)
   
        This parameter defines (epsilon) , which is intended to be a
                                        R
        measure of the accuracy with which the problem functions f and c
        can be computed. If r<(epsilon) or r>=1, the default value is
        used. The value of (epsilon)  should reflect the relative
                                    R
        precision of 1+|F(x)|; i.e., (epsilon)  acts as a relative
                                              R
        precision when |F| is large, and as an absolute precision when
        |F| is small. For example, if F(x) is typically of order 1000 and
        the first six significant digits are known to be correct, an
        appropriate value for (epsilon)  would be 1.0E-6. In contrast, if
                                       R
                                     -4
        F(x) is typically of order 10   and the first six significant
        digits are known to be correct, an appropriate value for
        (epsilon)  would be 1.0E-10. The choice of (epsilon)  can be
                 R                                          R
        quite complicated for badly scaled problems; see Chapter 8 of
        Gill et al [10] for a discussion of scaling techniques. The
        default value is appropriate for most simple functions that are
        computed with full accuracy. However, when the accuracy of the
        computed function values is known to be significantly worse than
        full precision, the value of (epsilon)  should be large enough so
                                              R
        that E04UCF will not attempt to distinguish between function
        values that differ by less than the error inherent in the
        calculation.
   
        Hessian No Default = No
   
        Hessian Yes
   
           (No Axiom parameter - fixed as Yes)
   
        This option controls the contents of the upper-triangular matrix
        R (see Section 5). E04UCF works exclusively with the transformed
        and re-ordered Hessian H  (6), and hence extra computation is
                                Q
        required to form the Hessian itself. If Hessian = No, R contains
        the Cholesky factor of the transformed and re-ordered Hessian. If
        Hessian = Yes the Cholesky factor of the approximate Hessian
        itself is formed and stored in R. The user should select Hessian
        = Yes if a warm start will be used for the next call to E04UCF.
   
                                          10
        Infinite Bound Size r Default = 10
   
           (Axiom parameter INFB)
   
        If r>0, r defines the 'infinite' bound BIGBND in the definition
        of the problem constraints. Any upper bound greater than or equal
        to BIGBND will be regarded as plus infinity (and similarly for a
        lower bound less than or equal to -BIGBND). If r<=0, the default
        value is used.
   
                                                    10
        Infinite Step Size r Default = max(BIGBND,10  )
   
           (Axiom parameter INFS)
   
        If r>0, r specifies the magnitude of the change in variables that
        is treated as a step to an unbounded solution. If the change in x
        during an iteration would exceed the value of Infinite Step Size,
        the objective function is considered to be unbounded below in the
        feasible region. If r<=0, the default value is used.
   
        Iteration limit i Default = max(50,3(n+n )+10n )
                                                L     N
   
        See Major Iteration Limit below.
   
                                                    _________
        Linear Feasibility Tolerance r  Default = \/(epsilon)
                                      1
   
           (Axiom parameter LINF)
   
                                                       _________
        Nonlinear Feasibility Tolerance r  Default = \/(epsilon) if
                                         2
   
           (Axiom parameter NONF)
                                           0.33
        Derivative Level >= 2 and (epsilon)     otherwise
   
        The scalars r  and r  define the maximum acceptable absolute
                     1      2
        violations in linear and nonlinear constraints at a 'feasible'
        point; i.e., a linear constraint is considered satisfied if its
        violation does not exceed r , and similarly for a nonlinear
                                   1
        constraint and r . If r <(epsilon) or r >=1, the default value is
                        2      i               i
        used, for i=1,2.
   
        On entry to E04UCF, an iterative procedure is executed in order
        to find a point that satisfies the linear constraint and bounds
        on the variables to within the tolerance r . All subsequent
                                                  1
        iterates will satisfy the linear constraints to within the same
        tolerance (unless r  is comparable to the finite-difference
                           1
        interval).
   
        For nonlinear constraints, the feasibility tolerance r  defines
                                                              2
        the largest constraint violation that is acceptable at an optimal
        point. Since nonlinear constraints are generally not satisfied
        until the final iterate, the value of Nonlinear Feasibility
        Tolerance acts as a partial termination criterion for the
        iterative sequence generated by E04UCF (see the discussion of
        Optimality Tolerance).
   
        These tolerances should reflect the precision of the
        corresponding constraints. For example, if the variables and the
        coefficients in the linear constraints are of order unity, and
        the latter are correct to about 6 decimal digits, it would be
                                       - 6
        appropriate to specify r  as 10   .
                                1
   
        Linesearch Tolerance r Default = 0.9
   
           (Axiom parameter LINT)
   
   
        The value r (0 <= r < 1) controls the accuracy with which the
        step (alpha) taken during each iteration approximates a minimum
        of the merit function along the search direction (the smaller the
        value of r, the more accurate the linesearch). The default value
        r=0.9 requests an inaccurate search, and is appropriate for most
        problems, particularly those with any nonlinear constraints.
   
        If there are no nonlinear constraints, a more accurate search may
        be appropriate when it is desirable to reduce the number of major
        iterations - for example, if the objective function is cheap to
        evaluate, or if a substantial number of gradients are
        unspecified.
   
        List Default = List
   
        Nolist
   
           (Axiom parameter LIST)
   
        Normally each optional parameter specification is printed as it
        is supplied. Nolist may be used to suppress the printing and List
        may be used to restore printing.
   
        Major Iteration Limit i Default = max(50,3(n+n )+10n )
                                                      L     N
   
        Iteration Limit
   
        Iters
   
        Itns
   
           (Axiom parameter MAJI)
   
        The value of i specifies the maximum number of major iterations
        allowed before termination. Setting i=0 and Major Print Level> 0
        means that the workspace needed will be computed and printed, but
        no iterations will be performed.
   
        Major Print level i Default = 10
   
        Print Level
   
           (Axiom parameter MAJP)
   
        The value of i controls the amount of printout produced by the
        major iterations of E04UCF. (See also Minor Print level below.)
        The levels of printing are indicated below.
   
        i        Output
   
        0        No output.
   
        1        The final solution only.
   
        5        One line for each major iteration (no printout of the
                 final solution).
   
        >=10     The final solution and one line of output for each
                 iteration.
   
        >=20     At each major iteration, the objective function, the
                 Euclidean norm of the nonlinear constraint violations,
                 the values of the nonlinear constraints (the vector c),
                 the values of the linear constraints (the vector A x),
                                                                   L
                 and the current values of the variables (the vector x).
   
        >=30     At each major iteration, the diagonal elements of the
                 matrix T associated with the TQ factorization (5) of the
                 QP working set, and the diagonal elements of R, the
                 triangular factor of the transformed and re-ordered
                 Hessian (6).
   
        Minor Iteration Limit i Default = max(50,3(n+n +n ))
                                                      L  N
   
           (Axiom parameter MINI)
   
        The value of i specifies the maximum number of iterations for the
        optimality phase of each QP subproblem.
   
        Minor Print Level i Default = 0
   
           (Axiom parameter MINP)
   
        The value of i controls the amount of printout produced by the
        minor iterations of E04UCF, i.e., the iterations of the quadratic
        programming algorithm. (See also Major Print Level, above.) The
        following levels of printing are available.
   
        i        Output
   
        0        No output.
   
        1        The final QP solution.
   
        5        One line of output for each minor iteration (no printout
                 of the final QP solution).
   
        >=10     The final QP solution and one brief line of output for
                 each minor iteration.
   
        >=20     At each minor iteration, the current estimates of the QP
                 multipliers, the current estimate of the QP search
                 direction, the QP constraint values, and the status of
                 each QP constraint.
   
        >=30     At each minor iteration, the diagonal elements of the
                 matrix T associated with the TQ factorization (5) of the
                 QP working set, and the diagonal elements of the
                 Cholesky factor R of the transformed Hessian (6).
   
                                                      _________
        Nonlinear Feasibility Tolerance r Default = \/(epsilon)
   
        See Linear Feasibility Tolerance, above.
   
                                                  0.8
        Optimality Tolerance r Default = (epsilon)
   
           (Axiom parameter OPT)
   
        The parameter r ((epsilon) <=r<1) specifies the accuracy to which
                                  R
        the user wishes the final iterate to approximate a solution of
        the problem. Broadly speaking, r indicates the number of correct
        figures desired in the objective function at the solution. For
                           - 6
        example, if r is 10    and E04UCF terminates successfully, the
        final value of F should have approximately six correct figures.
        If r<(epsilon)  or r>=1 the default value is used.
                      R
   
        E04UCF will terminate successfully if the iterative sequence of x
        -values is judged to have converged and the final point satisfies
        the first-order Kuhn-Tucker conditions (see Section 3). The
        sequence of iterates is considered to have converged at x if
   
                                        _
                       (alpha) ||p||<=\/r(1+||x||),                  (8a)
   
        where p is the search direction and (alpha) the step length from
        (3). An iterate is considered to satisfy the first-order
        conditions for a minimum if
   
                     T         _
                  ||Z g  ||<=\/r(1+max(1+|F(x)|,||g  ||))            (8b)
                       FR                          FR
   
        and
   
                          |res |<=ftol for all j,                    (8c)
                              j
   
               T
        where Z g   is the projected gradient (see Section 3), g   is the
                 FR                                             FR
        gradient of F(x) with respect to the free variables, res  is the
                                                                j
        violation of the jth active nonlinear constraint, and ftol is the
        Nonlinear Feasibility Tolerance.
   
        Step Limit r Default = 2.0
   
           (Axiom parameter STE)
   
        If r>0, r specifies the maximum change in variables at the first
                                                              bx
        step of the linesearch. In some cases, such as F(x)=ae   or
               b
        F(x)=ax , even a moderate change in the components of x can lead
        to floating-point overflow. The parameter r is therefore used to
        encourage evaluation of the problem functions at meaningful
                                                           ~
        points. Given any major iterate x, the first point x at which F
        and c are evaluated during the linesearch is restricted so that
   
                               ~
                             ||x-x|| <=r(1+||x|| ).
                                    2           2
   
        The linesearch may go on and evaluate F and c at points further
        from x if this will result in a lower value of the merit
        function. In this case, the character L is printed at the end of
        the optional line of printed output, (see Section 5.2). If L is
        printed for most of the iterations, r should be set to a larger
        value.
   
        Wherever possible, upper and lower bounds on x should be used to
        prevent evaluation of nonlinear functions at wild values. The
        default value Step Limit = 2.0 should not affect progress on
        well-behaved functions, but values 0.1 or 0.01 may be helpful
        when rapidly varying functions are present. If a small value of
        Step Limit is selected, a good starting point may be required. An
        important application is to the class of nonlinear least-squares
        problems. If r<=0, the default value is used.
   
        Start Objective Check At Variable k Default = 1
   
           (Axiom parameter STAO)
   
        Start Constraint Check At Variable k Default = 1
   
           (Axiom parameter STAC)
   
        Stop Objective Check At Variable l Default = n
   
           (Axiom parameter STOO)
   
        Stop Constraint Check At Variable l Default = n
   
           (Axiom parameter STOC)
   
        These keywords take effect only if Verify Level > 0 (see below).
        They may be used to control the verification of gradient elements
        computed by subroutines OBJFUN and CONFUN. For example, if the
        first 30 components of the objective gradient appeared to be
        correct in an earlier run, so that only component 31 remains
        questionable, it is reasonable to specify Start Objective Check
        At Variable 31. If the first 30 variables appear linearly in the
        objective, so that the corresponding gradient elements are
        constant, the above choice would also be appropriate.
   
        Verify Level i Default = 0
   
        Verify No
   
        Verify Level - 1
   
        Verify Level 0
   
        Verify Objective Gradients
   
        Verify Level 1
   
        Verify Constraint Gradients
   
        Verify Level 2
   
        Verify
   
        Verify Yes
   
        Verify Gradients
   
        Verify Level 3
   
           (Axiom parameter VE)
   
        These keywords refer to finite-difference checks on the gradient
        elements computed by the user-provided subroutines OBJFUN and
        CONFUN. (Unspecified gradient components are not checked.) It is
        possible to specify Verify Levels 0-3 in several ways, as
        indicated above. For example, the nonlinear objective gradient
        (if any) will be verified if either Verify Objective Gradients or
        Verify Level 1 is specified. Similarly, the objective and the
        constraint gradients will be verified if Verify Yes or Verify
        Level 3 or Verify is specified.
   
        If 0<=i<=3, gradients will be verified at the first point that
        satisfies the linear constraints and bounds. If i=0, only a '
        cheap' test will be performed, requiring one call to OBJFUN and
        one call to CONFUN. If 1<=i<=3, a more reliable (but more
        expensive) check will be made on individual gradient components,
        within the ranges specified by the Start and Stop keywords
        described above. A result of the form OK or BAD? is printed by
        E04UCF to indicate whether or not each component appears to be
        correct.
   
        If 10<=i<=13, the action is the same as for i - 10, except that
        it will take place at the user-specified initial value of x.
   
        We suggest that Verify Level 3 be specified whenever a new
        function routine is being developed.
   
        5.1.3. Optional parameter checklist and default values
   
        For easy reference, the following list shows all the valid
        keywords and their default values. The symbol (epsilon)
        represents the machine precision (see X02AJF(*) ).
   
        Optional Parameters      Default Values
   
   
   
        Central difference       Computed automatically
        interval
   
        Cold/Warm start          Cold start
   
        Crash tolerance          0.01
   
        Defaults
   
        Derivative level         3
   
        Difference interval      Computed automatically
   
                                   _________
        Feasibility tolerance    \/(epsilon)
   
                                          0.9
        Function precision       (epsilon)
   
        Hessian                  No
   
                                   10
        Infinite bound size      10
   
                                   10
        Infinite step size       10
   
                                   _________
        Linear feasibility       \/(epsilon)
        tolerance
   
        Linesearch tolerance     0.9
   
        List/Nolist              List
   
        Major iteration limit    max(50,3(n+n )+10n )
                                             L     N
   
        Major print level        10
   
        Minor iteration limit    max(50,3(n+n +n ))
                                             L  N
   
        Minor print level        0
   
                                   _________
        Nonlinear feasibility    \/(epsilon) if Derivative Level >= 2
        tolerance                                   0.33
                                 otherwise (epsilon)
   
                                          0.8
        Optimality tolerance     (epsilon)
                                          R
   
        Step limit               2.0
   
        Start objective check    1
   
        Start constraint check   1
   
        Stop objective check     n
   
        Stop constraint check    n
   
        Verify level             0
   
        5.2. Description of Printed Output
   
        The level of printed output from E04UCF is controlled by the user
        (see the description of Major Print Level and Minor Print Level
        in Section 5.1). If Minor Print Level > 0, output is obtained
        from the subroutines that solve the QP subproblem. For a detailed
        description of this information the reader should refer to
        E04NCF(*).
   
        When Major Print Level >= 5, the following line of output is
        produced at every major iteration of E04UCF. In all cases, the
        values of the quantities printed are those in effect on
        completion of the given iteration.
   
        Itn            is the iteration count.
   
        ItQP           is the sum of the iterations required by the
                       feasibility and optimality phases of the QP
                       subproblem. Generally, ItQP will be 1 in the later
                       iterations, since theoretical analysis predicts
                       that the correct active set will be identified
                       near the solution (see Section 3).
   
                       Note that ItQP may be greater than the Minor
                       Iteration Limit if some iterations are required
                       for the feasibility phase.
   
        Step           is the step (alpha) taken along the computed
                       search direction. On reasonably well-behaved
                       problems, the unit step will be taken as the
                       solution is approached.
   
        Nfun           is the cumulative number of evaluations of the
                       objective function needed for the linesearch.
                       Evaluations needed for the estimation of the
                       gradients by finite differences are not included.
                       Nfun is printed as a guide to the amount of work
                       required for the linesearch.
   
        Merit          is the value of the augmented Lagrangian merit
                       function (12) at the current iterate. This
                       function will decrease at each iteration unless it
                       was necessary to increase the penalty parameters
                       (see Section 8.2). As the solution is approached,
                       Merit will converge to the value of the objective
                       function at the solution.
   
                       If the QP subproblem does not have a feasible
                       point (signified by I at the end of the current
                       output line), the merit function is a large
                       multiple of the constraint violations, weighted by
                       the penalty parameters. During a sequence of major
                       iterations with infeasible subproblems, the
                       sequence of Merit values will decrease
                       monotonically until either a feasible subproblem
                       is obtained or E04UCF terminates with IFAIL = 3
                       (no feasible point could be found for the
                       nonlinear constraints).
   
                       If no nonlinear constraints are present (i.e.,
                       NCNLN = 0), this entry contains Objective, the
                       value of the objective function F(x). The
                       objective function will decrease monotonically to
                       its optimal value when there are no nonlinear
                       constraints.
   
        Bnd            is the number of simple bound constraints in the
                       predicted active set.
   
        Lin            is the number of general linear constraints in the
                       predicted active set.
   
        Nln            is the number of nonlinear constraints in the
                       predicted active set (not printed if NCNLN is
                       zero).
   
        Nz             is the number of columns of Z (see Section 8.1).
                       The value of Nz is the number of variables minus
                       the number of constraints in the predicted active
                       set; i.e., Nz = n-(Bnd + Lin + Nln).
   
        Norm Gf        is the Euclidean norm of g  , the gradient of the
                                                 FR
                       objective function with respect to the free
                       variables, i.e.,variables not currently held at a
                       bound.
   
                             T
        Norm Gz        is ||Z g  ||, the Euclidean norm of the projected
                               FR
                       gradient (see Section 8.1). Norm  Gz will be
                       approximately zero in the neighbourhood of a
                       solution.
   
        Cond H         is a lower bound on the condition number of the
                       Hessian approximation H.
   
        Cond Hz        is a lower bound on the condition number of the
                       projected Hessian approximation H  (
                                                        z
                            T      T
                       (H =Z H  Z=R R ; see (6) and (12) in Sections 3
                         z    FR   z z
                       and 8.1). The larger this number, the more
                       difficult the problem.
   
        Cond T         is a lower bound on the condition number of the
                       matrix of predicted active constraints.
   
        Norm C         is the Euclidean norm of the residuals of
                       constraints that are violated or in the predicted
                       active set (not printed if NCNLN is zero). Norm C
                       will be approximately zero in the neighbourhood of
                       a solution.
   
        Penalty        is the Euclidean norm of the vector of penalty
                       parameters used in the augumented Lagrangian merit
                       function (not printed if NCNLN is zero).
   
        Conv           is a three-letter indication of the status of the
                       three convergence tests (8a)-(8c) defined in the
                       description of the optional parameter Optimality
                       Tolerance in Section 5.1 Each letter is T if the
                       test is satisfied, and F otherwise. The three
                       tests indicate whether:
                       (a)   the sequence of iterates has converged;
   
                       (b)   the projected gradient (Norm  Gz) is
                             sufficiently small; and
   
                       (c)   the norm of the residuals of constraints in
                             the predicted active set (Norm  C) is small
                             enough.
                       If any of these indicators is F when E04UCF
                       terminates with IFAIL = 0, the user should check
                       the solution carefully.
   
        M              is printed if the Quasi-Newton update was modified
                       to ensure that the Hessian approximation is
                       positive-definite (see Section 8.3).
   
        I              is printed if the QP subproblem has no feasible
                       point.
   
        C              is printed if central differences were used to
                       compute the unspecified objective and constraint
                       gradients. If the value of Step is zero, the
                       switch to central differences was made because no
                       lower point could be found in the linesearch. (In
                       this case, the QP subproblem is resolved with the
                       central-difference gradient and Jacobian.) If the
                       value of Step is non-zero, central differences
                       were computed because Norm  Gz and Norm  C imply
                       that x is close to a Kuhn-Tucker point.
   
        L              is printed if the linesearch has produced a
                       relative change in x greater than the value
                       defined by the optional parameter Step Limit. If
                       this output occurs frequently during later
                       iterations of the run, Step Limit should be set to
                       a larger value.
   
        R              is printed if the approximate Hessian has been
                       refactorized. If the diagonal condition estimator
                       of R indicates that the approximate Hessian is
                       badly conditioned, the approximate Hessian is
                       refactorized using column interchanges. If
                       necessary, R is modified so that its diagonal
                       condition estimator is bounded.
   
        When Major Print Level = 1 or Major Print Level >= 10, the
        summary printout at the end of execution of E04UCF includes a
        listing of the status of every variable and constraint. Note that
        default names are assigned to all variables and constraints.
   
        The following describes the printout for each variable.
   
        Varbl          gives the name (V) and index j=1,2,...,n of the
                       variable.
   
        State          gives the state of the variable in the predicted
                       active set (FR if neither bound is in the active
                       set, EQ if a fixed variable, LL if on its lower
                       bound, UL if on its upper bound). If the variable
                       is predicted to lie outside its upper or lower
                       bound by more than the feasibility tolerance,
                       State will be ++ or -- respectively. (The latter
                       situation can occur only when there is no feasible
                       point for the bounds and linear constraints.)
   
        Value          is the value of the variable at the final
                       iteration.
   
        Lower bound    is the lower bound specified for the variable.
                       (None indicates that BL(j)<=- BIGBND.)
   
        Upper bound    is the upper bound specified for the variable.
                       (None indicates that BL(j)>=BIGBND.)
   
        Lagr Mult      is the value of the Lagrange-multiplier for the
                       associated bound constraint. This will be zero if
                       State is FR. If x is optimal, the multiplier
                       should be non-negative if State is LL, and non-
                       positive if State is UL.
   
        Residual       is the difference between the variable Value and
                       the nearer of its bounds BL(j) and BU(j).
   
        The printout for general constraints is the same as for
        variables, except for the following:
   
        L Con      is the name (L) and index i, for i = 1,2,...,NCLIN of
                   a linear constraint.
   
        N Con      is the name (N) and index i, for i = 1,2,...,NCNLN of
                   a nonlinear constraint.
   
        6. Error Indicators and Warnings
   
        Errors or warnings specified by the routine:
   
        If on entry IFAIL = 0 or -1, explanatory error messages are
        output on the current error message unit (as defined by X04AAF).
   
        The input data for E04UCF should always be checked (even if
        E04UCF terminates with IFAIL=0).
   
        Note that when Print Level>0, a short description of IFAIL is
        printed.
   
        Errors and diagnostics indicated by IFAIL, together with some
        recommendations for recovery are indicated below.
   
        IFAIL= 1
             The final iterate x satisfies the first-order Kuhn-Tucker
             conditions to the accuracy requested, but the sequence of
             iterates has not yet converged. E04UCF was terminated
             because no further improvement could be made in the merit
             function.
   
             This value of IFAIL may occur in several circumstances. The
             most common situation is that the user asks for a solution
             with accuracy that is not attainable with the given
             precision of the problem (as specified by Function Precision
             see Section 5). This condition will also occur if, by
             chance, an iterate is an 'exact' Kuhn-Tucker point, but the
             change in the variables was significant at the previous
             iteration. (This situation often happens when minimizing
             very simple functions, such as quadratics.)
   
             If the four conditions listed in Section 5 for IFAIL = 0 are
             satisfied, x is likely to be a solution of (1) even if IFAIL
             = 1.
   
        IFAIL= 2
             E04UCF has terminated without finding a feasible point for
             the linear constraints and bounds, which means that no
             feasible point exists for the given value of Linear
             Feasibility Tolerance (see Section 5.1). The user should
             check that there are no constraint redundancies. If the data
             for the constraints are accurate only to an absolute
             precision (sigma), the user should ensure that the value of
             the optional parameter Linear Feasibility Tolerance is
             greater than (sigma). For example, if all elements of A are
             of order unity and are accurate to only three decimal
                                                                       -3
             places, Linear Feasibility Tolerance should be at least 10  .
   
        IFAIL= 3
             No feasible point could be found for the nonlinear
             constraints. The problem may have no feasible solution. This
             means that there has been a sequence of QP subproblems for
             which no feasible point could be found (indicated by I at
             the end of each terse line of output). This behaviour will
             occur if there is no feasible point for the nonlinear
             constraints. (However, there is no general test that can
             determine whether a feasible point exists for a set of
             nonlinear constraints.) If the infeasible subproblems occur
             from the very first major iteration, it is highly likely
             that no feasible point exists. If infeasibilities occur when
             earlier subproblems have been feasible, small constraint
             inconsistencies may be present. The user should check the
             validity of constraints with negative values of ISTATE. If
             the user is convinced that a feasible point does exist,
             E04UCF should be restarted at a different starting point.
   
        IFAIL= 4
             The limiting number of iterations (determined by the
             optional parameter Major Iteration Limit see Section 5.1)
             has been reached.
   
             If the algorithm appears to be making progress, Major
             Iteration Limit may be too small. If so, increase its value
             and rerun E04UCF (possibly using the Warm Start option). If
             the algorithm seems to be 'bogged down', the user should
             check for incorrect gradients or ill-conditioning as
             described below under IFAIL = 6.
   
             Note that ill-conditioning in the working set is sometimes
             resolved automatically by the algorithm, in which case
             performing additional iterations may be helpful. However,
             ill-conditioning in the Hessian approximation tends to
             persist once it has begun, so that allowing additional
             iterations without altering R is usually inadvisable. If the
             quasi-Newton update of the Hessian approximation was
             modified during the latter iterations (i.e., an M occurs at
             the end of each terse line), it may be worthwhile to try a
             warm start at the final point as suggested above.
   
        IFAIL= 6
             x does not satisfy the first-order Kuhn-Tucker conditions,
             and no improved point for the merit function could be found
             during the final line search.
   
             A sufficient decrease in the merit function could not be
             attained during the final line search. This sometimes occurs
             because an overly stringent accuracy has been requested,
             i.e., Optimality Tolerance is too small. In this case the
             user should apply the four tests described under IFAIL = 0
             above to determine whether or not the final solution is
             acceptable (see Gill et al [10], for a discussion of the
             attainable accuracy).
   
             If many iterations have occurred in which essentially no
             progress has been made and E04UCF has failed completely to
             move from the initial point then subroutines OBJFUN or
             CONFUN may be incorrect. The user should refer to comments
             below under IFAIL = 7 and check the gradients using the
             Verify parameter. Unfortunately, there may be small errors
             in the objective and constraint gradients that cannot be
             detected by the verification process. Finite-difference
             approximations to first derivatives are catastrophically
             affected by even small inaccuracies. An indication of this
             situation is a dramatic alteration in the iterates if the
             finite-difference interval is altered. One might also
             suspect this type of error if a switch is made to central
             differences even when Norm Gz and Norm C are large.
   
             Another possibility is that the search direction has become
             inaccurate because of ill-conditioning in the Hessian
             approximation or the matrix of constraints in the working
             set; either form of ill-conditioning tends to be reflected
             in large values of ItQP (the number of iterations required
             to solve each QP subproblem).
   
             If the condition estimate of the projected Hessian (Cond Hz)
             is extremely large, it may be worthwhile to rerun E04UCF
             from the final point with the Warm Start option. In this
             situation, ISTATE should be left unaltered and R should be
             reset to the identity matrix.
   
             If the matrix of constraints in the working set is ill-
             conditioned (i.e., Cond T is extremely large), it may be
             helpful to run E04UCF with a relaxed value of the
             Feasibility Tolerance (Constraint dependencies are often
             indicated by wide variations in size in the diagonal
             elements of the matrix T, whose diagonals will be printed
             for Major Print Level >= 30).
   
        IFAIL= 7
             The user-provided derivatives of the objective function
             and/or nonlinear constraints appear to be incorrect.
   
             Large errors were found in the derivatives of the objective
             function and/or nonlinear constraints. This value of IFAIL
             will occur if the verification process indicated that at
             least one gradient or Jacobian component had no correct
             figures. The user should refer to the printed output to
             determine which elements are suspected to be in error.
   
             As a first-step, the user should check that the code for the
             objective and constraint values is correct - for example, by
             computing the function at a point where the correct value is
             known. However, care should be taken that the chosen point
             fully tests the evaluation of the function. It is remarkable
             how often the values x=0 or x=1 are used to test function
             evaluation procedures, and how often the special properties
             of these numbers make the test meaningless.
   
             Special care should be used in this test if computation of
             the objective function involves subsidiary data communicated
             in COMMON storage. Although the first evaluation of the
             function may be correct, subsequent calculations may be in
             error because some of the subsidiary data has accidently
             been overwritten.
   
             Errors in programming the function may be quite subtle in
             that the function value is 'almost' correct. For example,
             the function may not be accurate to full precision because
             of the inaccurate calculation of a subsidiary quantity, or
             the limited accuracy of data upon which the function
             depends. A common error on machines where numerical
             calculations are usually performed in double precision is to
             include even one single-precision constant in the
             calculation of the function; since some compilers do not
             convert such constants to double precision, half the correct
             figures may be lost by such a seemingly trivial error.
   
        IFAIL= 9
             An input parameter is invalid. The user should refer to the
             printed output to determine which parameter must be
             redefined.
   
        IFAILOverflow
             If the printed output before the overflow error contains a
             warning about serious ill-conditioning in the working set
             when adding the jth constraint, it may be possible to avoid
             the difficulty by increasing the magnitude of the optional
             parameter Linear Feasiblity Tolerance or Nonlinear
             Feasiblity Tolerance, and rerunning the program. If the
             message recurs even after this change, the offending
             linearly dependent constraint (with index 'j') must be
             removed from the problem. If overflow occurs in one of the
             user-supplied routines (e.g. if the nonlinear functions
             involve exponentials or singularities), it may help to
             specify tighter bounds for some of the variables (i.e.,
             reduce the gap between appropriate l  and u ).
                                                 j      j
   
        7. Accuracy
   
        If IFAIL = 0 on exit then the vector returned in the array X is
        an estimate of the solution to an accuracy of approximately
        Feasiblity Tolerance (see Section 5.1), whose default value is
                 0.8
        (epsilon)   , where (epsilon) is the machine precision (see
        X02AJF(*)).
   
        8. Further Comments
   
        In this section we give some further details of the method used
        by E04UCF.
   
        8.1. Solution of the Quadratic Programming Subproblem
   
        The search direction p is obtained by solving (4) using the
        method of E04NCF(*) (Gill et al [8]), which was specifically
        designed to be used within an SQP algorithm for nonlinear
        programming.
   
        The method of E04UCF is a two-phase (primal) quadratic
        programming method. The two phases of the method are: finding an
        initial feasible point by minimizing the sum of infeasibilities
        (the feasibility phase), and minimizing the quadratic objective
        function within the feasible region (the optimality phase). The
        computations in both phases are perfomed by the same subroutines.
        The two-phase nature of the algorithm is reflected by changing
        the function being minimized from the sum of infeasibilities to
        the quadratic objective function.
   
        In general, a quadratic program must be solved by iteration. Let
        p denote the current estimate of the solution of (4); the new
                _
        iterate p is defined by
   
                               _
                               p=p+(sigma)d,                          (9)
   
        where, as in (3), (sigma) is a non-negative step length and d is
        a search direction.
   
        At the beginning of each iteration of E04UCF, a working set is
        defined of constraints (general and bound) that are satisfied
        exactly. The vector d is then constructed so that the values of
        constraints in the working set remain unaltered for any move
        along d. For a bound constraint in the working set, this property
        is achieved by setting the corresponding component of d to zero,
        i.e., by fixing the variable at its bound. As before, the
        subscripts 'FX' and 'FR' denote selection of the components
        associated with the fixed and free variables.
   
        Let C denote the sub-matrix of rows of
   
                                      (A )
                                      ( L)
                                      (A )
                                      ( N)
   
        corresponding to general constraints in the working set. The
        general constraints in the working set will remain unaltered if
   
                                 C  d  =0,                           (10)
                                  FR FR
   
        which is equivalent to defining d   as
                                         FR
   
                                  d  =Zd                             (11)
                                   FR   z
   
        for some vector d , where Z is the matrix associated with the TQ
                         z
        factorization (5) of C  .
                              FR
   
        The definition of d  in (11) depends on whether the current p is
                           z
        feasible. If not, d  is zero except for a component (gamma) in
                           z
        the jth position, where j and (gamma) are chosen so that the sum
        of infeasibilities is decreasing along d. (For further details,
        see Gill et al [8].) In the feasible case, d  satisfies the
                                                    z
        equations
   
                               T       T
                              R R d =-Z q  ,                         (12)
                               z z z     FR
   
                                            T
        where R  is the Cholesky factor of Z H  Z and q is the gradient
               z                              FR
                                                                   T
        of the quadratic objective function (q=g+Hp). (The vector Z q
                                                                     FR
        is the projected gradient of the QP.) With (12), P+d is the
        minimizer of the quadratic objective function subject to treating
        the constraints in the working set as equalities.
   
        If the QP projected gradient is zero, the current point is a
        constrained stationary point in the subspace defined by the
        working set. During the feasiblity phase, the projected gradient
        will usually be zero only at a vertex (although it may vanish at
        non-vertices in the presence of constraint dependencies). During
        the optimality phase, a zero projected gradient implies that p
        minimizes the quadratic objective function when the constraints
        in the working set are treated as equalities. In either case,
        Lagrange multipliers are computed. Given a positive constant
        (delta) of the order of the machine precision, the Lagrange
        multiplier (mu)  corresponding to an inequality constraint in the
                       j
        working set at its upper bound is said to be optimal if
        (mu) <=(delta) when the jth constraint is at its upper bound, or
            j
        if (mu) >=-(delta) when the associated constraint is at its lower
               j
        bound. If any multiplier is non-optimal, the current objective
        function (either the true objective or the sum of
        infeasibilities) can be reduced by deleting the corresponding
        constraint from the working set.
   
        If optimal multipliers occur during the feasibility phase and the
        sum of infeasibilities is non-zero, no feasible point exists. The
        QP algorithm will then continue iterating to determine the
        minimum sum of infeasibilities. At this point, the Lagrange
        multiplier (mu)  will satisfy -(1+(delta))<=(mu) <=(delta) for an
                       j                                j
        inequality constraint at its upper bound, and
        -(delta)<=(mu) <=1+(delta) for an inequality at its lower bound.
                      j
        The Lagrange multiplier for an equality constraint will satisfy
        |(mu) |<=1+(delta).
             j
   
        The choice of step length (sigma) in the QP iteration (9) is
        based on remaining feasible with respect to the satisfied
        constraints. During the optimality phase, if p+d is feasible,
        (sigma) will be taken as unity. (In this case, the projected
                    _
        gradient at p will be zero.) Otherwise, (sigma) is set to
        (sigma) , the step to the 'nearest'constraint, which is added to
               M
        the working set at the next iteration.
   
        Each change in the working set leads to a simple change to C  :
                                                                    FR
        if the status of a general constraint changes, a row of C   is
                                                                 FR
        altered; if a bound constraint enters or leaves the working set,
        a column of C   changes. Explicit representations are recurred of
                     FR
                                                       T       T
        the matrices T, Q   and R, and of the vectors Q q and Q g.
                         FR
   
        8.2. The Merit Function
   
        After computing the search direction as described in Section 3,
        each major iteration proceeds by determining a step length
        (alpha) in (3) that produces a 'sufficient decrease' in the
        augmented Lagrangian merit function
   
   
                              --
        L(x,(lambda),s)=F(x)- > (lambda) (c (x)-s )
                              --        i  i     i
                              i
   
                              1 --                2
                            + - > (rho) (c (x)-s ) ,                 (13)
                              2 --     i  i     i
                                i
   
        where x, (lambda) and s vary during the linsearch. The summation
        terms in (13) involve only the nonlinear constraints. The vector
        (lambda) is an estimate of the Lagrange multipliers for the
        nonlinear constraints of (1). The non-negative slack variables
        {s } allow nonlinear inequality constraints to be treated without
          i
        introducing discontinuities. The solution of the QP subproblem
        (4) provides a vector triple that serves as a direction of search
        for the three sets of variables. The non-negative vector (rho) of
        penalty parameters is initialised to zero at the beginning of the
        first major iteration. Thereafter, selected components are
        increased whenever necessary to ensure descent for the merit
        function. Thus, the sequence of norms of (rho) (the printed
        quantity Penalty, see Section 5.2) is generally non-decreasing,
        although each (rho)  may be reduced a limited number of times.
                           i
   
        The merit function (13) and its global convergence properties are
        described in Gill et al [9].
   
        8.3. The Quasi-Newton Update
   
        The matrix H in (4) is a positive-definite quasi-Newton
        approximation to the Hessian of the Lagrangian function. (For a
        review of quasi-Newton methods, see Dennis and Schnabel [3].) At
                                                                     _
        the end of each major iteration, a new Hessian approximation H is
        defined as a rank-two modification of H. In E04UCF, the BFGS
        quasi-Newton update is used:
   
                          _     1     T    1   T
                          H=H- ----Hss H+ ---yy ,                    (14)
                                T          T
                               s Hs       y s
   
                _
        where s=x-x (the change in x).
   
        In E04UCF, H is required to be positive-definite. If H is
                           _
        positive-definite, H defined by (14) will be positive-definite if
                     T
        and only if y s is positive (see, e.g. Dennis and More [1]).
        Ideally, y in (14) would be taken as y , the change in gradient
                                              L
        of the Lagrangian function
   
                             _ _T         T
                          y =g-A (mu) -g+A (mu) ,                    (15)
                           L    N    N    N    N
   
        where (mu)  denotes the QP multipliers associated with the
                  N
                                                           T
        nonlinear constraints of the original problem. If y s is not
                                                           L
        sufficiently positive, an attempt is made to perform the update
        with a vector y of the form
   
                          m
                           N
                          --             _    _
                    y=y + >  (omega) (a (x)c (x)-a (x)c (x)),
                       L  --        i  i    i     i    i
                          i=1
   
        where (omega) >=0. If no such vector can be found, the update is
                     i
        perfomed with a scaled y ; in this case, M is printed to indicate
                                L
        that the update is modified.
   
        Rather than modifying H itself, the Cholesky factor of the
        transformed Hessian H  (6) is updated, where Q is the matrix from
                             Q
        (5) associated with the active set of the QP subproblem. The
        update (13) is equivalent to the following update to H :
                                                              Q
   
                     _        1        T     1     T
                     H =H - ------H s s H + ----y y ,                (16)
                      Q  Q   T     Q Q Q Q   T   Q Q
                            s H s           y s
                             Q Q Q           Q Q
   
                  T           T
        where y =Q y, and s =Q s. This update may be expressed as a rank-
               Q           Q
        one update to R (see Dennis and Schnabel [2]).
   
        9. Example
   
        This section describes one version of the so-called 'hexagon'
        problem (a different formulation is given as Problem 108 in Hock
        and Schittkowski [11]). The problem is to determine the hexagon
        of maximum area such that no two of its vertices are more than
        one unit apart (the solution is not a regular hexagon).
   
        All constraint types are included (bounds, linear, nonlinear),
        and the Hessian of the Lagrangian function is not positive-
        definite at the solution. The problem has nine variables, non-
        infinite bounds on seven of the variables, four general linear
        constraints, and fourteen nonlinear constraints.
   
        The objective function is
   
                      F(x)=-x x +x x -x x -x x +x x +x x .
                             2 6  1 7  3 7  5 8  4 9  3 8
   
        The bounds on the variables are
   
             x >=0, -1<=x <=1, x >=0,x >=0, x >=0,x <=0, and x <=0.
              1          3      5     6      7     8          9
   
        Thus,
   
                                                             T
                  l =(0,-infty,-1,-infty,0,0,0,-infty,-infty)
                   B
   
                                                               T
                 u =(infty,infty,1,infty,infty,infty,infty,0,0)
                  B
   
        The general linear constraints are
   
             x -x >=0,x -x >=0, x -x >=0,and x -x >=0.
              2  1     3  2      3  4         4  5
   
        Hence,
   
                  (0)     (-1  1 0  0  0 0 0 0 0)        (infty)
                  (0)     ( 0 -1 1  0  0 0 0 0 0)        (infty)
               l =(0), A =( 0  0 1 -1  0 0 0 0 0) and u =(infty).
                L (0)   L ( 0  0 0  1 -1 0 0 0 0)      L (infty)
   
        The nonlinear constraints are all of the form c (x)<=1, for
                                                       i
        i=1,2,...,14; hence, all components of l  are -infty, and all
                                                N
        components of u  are 1. The fourteen functions {c (x)} are
                       N                                 i
   
                    2  2
             c (x)=x +x ,
              1     1  6
   
                          2        2
             c (x)=(x -x ) +(x -x ) ,
              2      2  1     7  6
   
                          2  2
             c (x)=(x -x ) +x ,
              3      3  1    6
   
                          2        2
             c (x)=(x -x ) +(x -x ) ,
              4      1  4     6  8
   
                          2        2
             c (x)=(x -x ) +(x -x ) ,
              5      1  5     6  9
   
                    2  2
             c (x)=x +x ,
              6     2  7
   
                          2  2
             c (x)=(x -x ) +x ,
              7      3  2    7
   
                          2        2
             c (x)=(x -x ) +(x -x ) ,
              8      4  2     8  7
   
                          2        2
             c (x)=(x -x ) +(x -x ) ,
              9      2  5     7  9
   
                           2  2
             c  (x)=(x -x ) +x ,
              10      4  3    8
   
                           2  2
             c  (x)=(x -x ) +x ,
              11      5  3    9
   
                     2  2
             c  (x)=x +x ,
              12     4  8
   
                           2        2
             c  (x)=(x -x ) +(x -x ) ,
              13      4  5     9  8
   
                     2  2
             c  (x)=x +x .
              14     5  9
   
        An optimal solution (to five figures) is
   
   
         *
        x =(0.060947,0.59765,1.0,0.59765,0.060947,0.34377,0.5,
                         T
            -0.5,0.34377) ,
   
               *
        and F(x )=-1.34996. (The optimal objective function is unique,
        but is achieved for other values of x.) Five nonlinear
                                                        *
        constraints and one simple bound are active at x . The sample
        solution output is given later in this section, following the
        sample main program and problem definition.
   
        Two calls are made to E04UCF in order to demonstrate some of its
        features. For the first call, the starting point is:
   
                                                                      T
         x =(0.1,0.125,0.666666,0.142857,0.111111,0.2,0.25,-0.2,-0.25) .
          0
   
        All objective and constraint derivatives are specified in the
        user-provided subroutines OBJFN1 and CONFN1, i.e., the default
        option Derivative Level =3 is used.
   
        On completion of the first call to E04UCF, the optimal variables
        are perturbed to produce the initial point for a second run in
        which the problem functions are defined by the subroutines OBJFN2
        and CONFN2. To illustrate one of the finite-difference options in
        E04UCF, these routines are programmed so that the first six
        components of the objective gradient and the constant elements of
        the Jacobian matrix are not specified; hence, the option
        Derivative Level =0 is chosen. During computation of the finite-
        difference intervals, the constant Jacobian elements are
        identified and set, and E04UCF automatically increases the
        derivative level to 2.
   
        The second call to E04UCF illustrates the use of the Warm Start
        Level option to utilize the final active set, nonlinear
        multipliers and approximate Hessian from the first run. Note that
        Hessian = Yes was specified for the first run so that the array R
        would contain the Cholesky factor of the approximate Hessian of
        the Lagrangian.
   
        The two calls to E04UCF illustrate the alternative methods of
        assigning default parameters. (There is no special significance
        in the order of these assignments; an options file may just as
        easily be used to modify parameters set by E04UEF.)
   
        The results are typical of those obtained from E04UCF when
        solving well behaved (non-trivial) nonlinear problems. The
        approximate Hessian and working set remain relatively well-
        conditioned. Similarly the penalty parameters remain small and
        approximately constant. The numerical results illustrate much of
        the theoretically predicted behaviour of a quasi-Newton SQP
        method. As x approaches the solution, only one minor iteration is
        perfomed per major iteration, and the Norm Gz and Norm C columns
        exhibit the fast linear convergence rate mentioned in Sections 5
        and 6. Note that the constraint violations converge earlier than
        the projected gradient. The final values of the project gradient
        norm and constraint norm reflect the limiting accuracy of the two
        quantities. It is possible to achieve almost full precision in
        the constraint norm but only half precision in the projected
        gradient norm. Note that the final accuracy in the nonlinear
        constraints is considerably better than the feasibility
        tolerance, because the constraint violations are being refined
        during the last few iterations while the algorithm is working to
        reduce the projected gradient norm. In this problem, the
        constraint values and Lagrange multipliers at the solution are '
        well balanced', i.e., all the multipliers are approximately the
        same order of magnitude. The behaviour is typical of a well-
        scaled problem.
   
        The example program is not reproduced here. The source code for
        all example programs is distributed with the NAG Foundation
        Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe04udf}{nage.ht}
{ Supply optional parameters to E04UCF from file}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe04udf}{NAG Documentation: e04udf}
\beginscroll
\begin{verbatim}



     E04UDF(3NAG)      Foundation Library (12/10/92)      E04UDF(3NAG)



          E04 -- Minimizing or Maximizing a Function                 E04UDF
                  E04UDF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          To supply optional parameters to E04UCF from an external file.

          2. Specification

                 SUBROUTINE E04UDF (IOPTNS, INFORM)
                 INTEGER          IOPTNS, INFORM

          3. Description

          E04UDF may be used to supply values for optional parameters to
          E04UCF. E04UDF reads an external file and each line of the file
          defines a single optional parameter. It is only necessary to
          supply values for those parameters whose values are to be
          different from their default values.

          Each optional parameter is defined by a single character string
          of up to 72 characters, consisting of one or more items. The
          items associated with a given option must be separated by spaces,
          or equal signs (=). Alphabetic characters may be upper or lower
          case. The string

                 Print level = 1

          is an example of a string used to set an optional parameter. For
          each option the string contains one or more of the following
          items:

          (a)   A mandatory keyword.

          (b)   A phrase that qualifies the keyword.

          (c)   A number that specifies an INTEGER or real value. Such
                numbers may be up to 16 contiguous characters in Fortran
                77's I, F, E or D formats, terminated by a space if this is
                not the last item on the line.

          Blank strings and comments are ignored. A comment begins with an
          asterisk (*) and all subsequent characters in the string are
          regarded as part of the comment.

          The file containing the options must start with begin and must
          finish with end An example of a valid options file is:

                Begin * Example options file
                 Print level =10
                End

          Normally each line of the file is printed as it is read, on the
          current advisory message unit (see X04ABF), but printing may be
          suppressed using the keyword nolist To suppress printing of begin,
          nolist must be the first option supplied as in the file:

                Begin
                  Nolist
                  Print level = 10
                End

          Printing will automatically be turned on again after a call to
          E04UCF and may be turned on again at any time by the user by
          using the keyword list.

          Optional parameter settings are preserved following a call to
          E04UCF, and so the keyword defaults is provided to allow the user
          to reset all the optional parameters to their default values
          prior to a subsequent call to E04UCF.

          A complete list of optional parameters, their abbreviations,
          synonyms and default values is given in Section 5.1 of the
          document for E04UCF.

          4. References

          None.

          5. Parameters

           1:  IOPTNS -- INTEGER                                      Input
               On entry: IOPTNS must be the unit number of the options
               file. Constraint: 0 <= IOPTNS <= 99.

           2:  INFORM -- INTEGER                                     Output
               On exit: INFORM will be zero, if an options file with the
               current structure has been read. Otherwise INFORM will be
               positive. Positive values of INFORM indicate that an options
               file may not have been successfully read as follows:
               INFORM = 1
                     IOPTNS is not in the range [0,99].

               INFORM = 2
                     begin was found, but end-of-file was found before end
                     was found.

               INFORM = 3
                     end-of-file was found before begin was found.

          6. Error Indicators and Warnings

          If a line is not recognised as a valid option, then a warning
          message is output on the current advisory message unit (X04ABF).

          7. Accuracy

          Not applicable.

          8. Further Comments

          E04UEF may also be used to supply optional parameters to E04UCF.

          9. Example

          See the example for E04UCF.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe04uef}{nage.ht}
{ Supply individual optional params to E04UCF}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe04uef}{NAG Documentation: e04uef}
\beginscroll
\begin{verbatim}



     E04UEF(3NAG)      Foundation Library (12/10/92)      E04UEF(3NAG)



          E04 -- Minimizing or Maximizing a Function                 E04UEF
                  E04UEF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          To supply individual optional parameters to E04UCF.

          2. Specification

                 SUBROUTINE E04UEF (STRING)
                 CHARACTER*(*)    STRING

          3. Description

          E04UEF may be used to supply values for optional parameters to
          E04UCF. It is only necessary to call E04UEF for those parameters
          whose values are to be different from their default values. One
          call to E04UEF sets one parameter value.

          Each optional parameter is defined by a single character string
          of up to 72 characters, consisting of one or more items. The
          items associated with a given option must be separated by spaces,
          or equal signs (=). Alphabetic characters may be upper or lower
          case. The string

                Print level = 1

          is an example of a string used to set an optional parameter. For
          each option the string contains one or more of the following
          items:

          (a)   A mandatory keyword.

          (b)   A phrase that qualifies the keyword.

          (c)   A number that specifies an INTEGER or real value. Such
                numbers may be up to 16 contiguous characters in Fortran
                77's I, F, E or D formats, terminated by a space if this is
                not the last item on the line.

          Blank strings and comments are ignored. A comment begins with an
          asterisk (*) and all subsequent characters in the string are
          regarded as part of the comment.

          Normally, each user-specified option is printed as it is defined,
          on the current advisory message unit (see X04ABF), but this
          printing may be suppressed using the keyword nolist Thus the
          statement

                CALL E04UEF (`Nolist')

          suppresses printing of this and subsequent options. Printing will
          automatically be turned on again after a call to E04UCF, and may
          be turned on again at any time by the user, by using the keyword
          list.

          Optional parameter settings are preserved following a call to
          E04UCF, and so the keyword defaults is provided to allow the user
          to reset all the optional parameters to their default values by
          the statement,

                CALL E04UEF (`Defaults')

          prior to a subsequent call to E04UCF.

          A complete list of optional parameters, their abbreviations,
          synonyms and default values is given in Section 5.1 of the
          document for E04UCF.

          4. References

          None.

          5. Parameters

           1:  STRING -- CHARACTER*(*)                                Input
               On entry: STRING must be a single valid option string. See
               Section 3 above and Section 5.1 of the routine document for
               E04UCF. On entry: STRING must be a single valid option
               string. See Section 3 above and Section 5.1 of the routine
               document for E04UCF.

          6. Error Indicators and Warnings

          If the parameter STRING is not recognised as a valid option
          string, then a warning message is output on the current advisory
          message unit (X04ABF).

          7. Accuracy

          Not applicable.

          8. Further Comments

          E04UDF may also be used to supply optional parameters to E04UCF.

          9. Example

          See the example for E04UCF.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXe04ycf}{nage.ht}
{ Estimates of elements of the variance-covariance matrix}
\begin{chunk}{nage.ht}
\begin{page}{manpageXXe04ycf}{NAG Documentation: e04ycf}
\beginscroll
\begin{verbatim}



     E04YCF(3NAG)      Foundation Library (12/10/92)      E04YCF(3NAG)



          E04 -- Minimizing or Maximizing a Function                 E04YCF
                  E04YCF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          E04YCF returns estimates of elements of the variance-covariance
          matrix of the estimated regression coefficients for a nonlinear
          least squares problem. The estimates are derived from the
          Jacobian of the function f(x) at the solution.

          This routine may be used following any one of the nonlinear
          least-squares routines E04FCF(*), E04FDF, E04GBF(*), E04GCF,
          E04GDF(*), E04GEF(*), E04HEF(*), E04HFF(*).

          2. Specification

                 SUBROUTINE E04YCF (JOB, M, N, FSUMSQ, S, V, LV, CJ, WORK,
                1                   IFAIL)
                 INTEGER          JOB, M, N, LV, IFAIL
                 DOUBLE PRECISION FSUMSQ, S(N), V(LV,N), CJ(N), WORK(N)

          3. Description

          E04YCF is intended for use when the nonlinear least-squares
                          T
          function, F(x)=f (x)f(x), represents the goodness of fit of a
          nonlinear model to observed data. The routine assumes that the
          Hessian of F(x), at the solution, can be adequately approximated
               T
          by 2J J, where J is the Jacobian of f(x) at the solution. The
          estimated variance-covariance matrix C is then given by

                                 2  T  -1    T
                        C=(sigma) (J J)     J J non-singular,

                       2
          where (sigma)  is the estimated variance of the residual at the
                    

          solution, x, given by

                                               

                                          2  F(x)
                                   (sigma) = ----,
                                             m-n

          m being the number of observations and n the number of variables.

          The diagonal elements of C are estimates of the variances of the
          estimated regression coefficients. See the Chapter Introduction
          E04 and Bard [1] and Wolberg [2] for further information on the
          use of C.

                T
          When J J is singular then C is taken to be

                                           2  T  *
                                  C=(sigma) (J J) ,

                  T  *                           T
          where (J J)  is the pseudo-inverse of J J, but in this case the
          parameter IFAIL is returned as non-zero as a warning to the user
          that J has linear dependencies in its columns. The assumed rank
          of J can be obtained from IFAIL.

          The routine can be used to find either the diagonal elements of
          C, or the elements of the jth column of C, or the whole of C.

          E04YCF must be preceded by one of the nonlinear least-squares
          routines mentioned in Section 1, and requires the parameters
          FSUMSQ, S and V to be supplied by those routines. FSUMSQ is the
                                    

          residual sum of squares F(x), and S and V contain the singular
          values and right singular vectors respectively in the singular
          value decomposition of J. S and V are returned directly by the
          comprehensive routines E04FCF(*), E04GBF(*), E04GDF(*) and
          E04HEF(*), but are returned as part of the workspace parameter W
          from the easy-to-use routines E04FDF, E04GCF, E04GEF(*) and
          E04HFF(*). In the case of E04FDF, S starts at W(NS), where

                          NS=6*N+2*M+M*N+1+max(1,N*(N-1)/2)

          and in the cases of the remaining easy-to-use routines, S starts
          at W(NS), where

                     NS=7*N+2*M+M*N+N*(N+1)/2+1+max(1,N*(N-1)/2)

          The parameter V starts immediately following the elements of S,
          so that V starts at W(NV), where

                                      NV=NS+N.

          For all the easy-to-use routines the parameter LV must be
          supplied as N. Thus a call to E04YCF following E04FDF can be
          illustrated as


                 CALL E04FDF (M, N, X, FSUMSQ, IW, LIW, W, LW, IFAIL)
                 NS = 6*N + 2*M + M*N + 1 + MAX((1,(N*(N-1))/2)
                 NV = NS + N
                 CALL E04YCF (JOB, M, N, FSUMSQ, W(NS), W(NV),
                *             N, CJ, WORK, IFAIL)

                                                        2
          where the parameters M, N, FSUMSQ and the (n+n ) elements W(NS),
          WS(NS+1),..., W(NV+N*N-1) must not be altered between the calls
          to E04FDF and E04YCF. The above illustration also holds for a
          call to E04YCF following a call to one of E04GCF, E04GEF(*),
          E04HFF(*) except that NS must be computed as

                NS = 7*N + 2*M + M*N + (N*(N+1))/2 + 1 + MAX((1,N*(N-1))/2)

          4. References

          [1]   Bard Y (1974) Nonlinear Parameter Estimation. Academic
                Press.

          [2]   Wolberg J R (1967) Prediction Analysis. Van Nostrand.

          5. Parameters

           1:  JOB -- INTEGER                                         Input
               On entry: which elements of C are returned as follows:
               JOB = -1
                     The n by n symmetric matrix C is returned.

               JOB = 0
                     The diagonal elements of C are returned.

               JOB > 0
                     The elements of column JOB of C are returned.
                Constraint: -1 <= JOB <= N.

           2:  M -- INTEGER                                           Input
               On entry: the number m of observations (residuals f (x)).
                                                                  i
               Constraint: M >= N.

           3:  N -- INTEGER                                           Input
               On entry: the number n of variables (x ). Constraint: 1 <=
                                                     j
               N <= M.

           4:  FSUMSQ -- DOUBLE PRECISION                             Input
                                                                

               On entry: the sum of squares of the residuals, F(x), at the
                        

               solution x, as returned by the nonlinear least-squares
               routine. Constraint: FSUMSQ >= 0.0.

           5:  S(N) -- DOUBLE PRECISION array                         Input
               On entry: the n singular values of the Jacobian as returned
               by the nonlinear least-squares routine. See Section 3 for
               information on supplying S following one of the easy-to-use
               routines.

           6:  V(LV,N) -- DOUBLE PRECISION array               Input/Output
               On entry: the n by n right-hand orthogonal matrix (the
               right singular vectors) of J as returned by the nonlinear
               least-squares routine. See Section 3 for information on
               supplying V following one of the easy-to-use routines. On
               exit: when JOB >= 0 then V is unchanged.

               When JOB = -1 then the leading n by n part of V is
               overwritten by the n by n matrix C. When E04YCF is called
               with JOB = -1 following an easy-to-use routine this means
                                                             2
               that C is returned, column by column, in the n  elements of
                                                  2
               W given by W(NV),W(NV+1),...,W(NV+N -1). (See Section 3 for
               the definition of NV).

           7:  LV -- INTEGER                                          Input
               On entry:
               the first dimension of the array V as declared in the
               (sub)program from which E04YCF is called.
               When V is passed in the workspace parameter W following one
               of the easy-to-use least-square routines, LV must be the
               value N.

           8:  CJ(N) -- DOUBLE PRECISION array                       Output
               On exit: with JOB = 0, CJ returns the n diagonal elements
               of C.

               With JOB = j>0, CJ returns the n elements of the jth column
               of C.

               When JOB = -1, CJ is not referenced.

           9:  WORK(N) -- DOUBLE PRECISION array                  Workspace
               When JOB = -1 or 0 then WORK is used as internal workspace.

               When JOB > 0, WORK is not referenced.

          10:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. Users who are
               unfamiliar with this parameter should refer to the Essential
               Introduction for details.

               On exit: IFAIL = 0 unless the routine detects an error or
               gives a warning (see Section 6).

               For this routine, because the values of output parameters
               may be useful even if IFAIL /=0 on exit, users are
               recommended to set IFAIL to -1 before entry. It is then
               essential to test the value of IFAIL on exit. To suppress
               the output of an error message when soft failure occurs, set
               IFAIL to 1.

          6. Error Indicators and Warnings

          Errors or warnings specified by the routine:

          IFAIL= 1
               On entry JOB < -1,

               or       JOB > N,

               or       N < 1,

               or       M < N,

               or       FSUMSQ < 0.0.

          IFAIL= 2
               The singular values are all zero, so that at the solution
               the Jacobian matrix J has rank 0.

          IFAIL> 2
               At the solution the Jacobian matrix contains linear, or near
               linear, dependencies amongst its columns. In this case the
               required elements of C have still been computed based upon J
               having an assumed rank given by (IFAIL-2). The rank is
               computed by regarding singular values SV(j) that are not
               larger than 10*(epsilon)*SV(1) as zero, where (epsilon) is
               the machine precision (see X02AJF(*)). Users who expect near
               linear dependencies at the solution and are happy with this
               tolerance in determining rank should call E04YCF with IFAIL
               = 1 in order to prevent termination by P01ABF(*). It is then
               essential to test the value of IFAIL on exit from E04YCF.

          IFAILOverflow
               If overflow occurs then either an element of C is very
               large, or the singular values or singular vectors have been
               incorrectly supplied.

          7. Accuracy

          The computed elements of C will be the exact covariances
          corresponding to a closely neighbouring Jacobian matrix J.

          8. Further Comments

          When JOB = -1 the time taken by the routine is approximately
                           3
          proportional to n . When JOB >= 0 the time taken by the routine
                                            2
          is approximately proportional to n .

          9. Example

          To estimate the variance-covariance matrix C for the least-
          squares estimates of x , x  and x  in the model
                                1   2      3

                                            t
                                             1
                                   y=x + ---------
                                      1  x t +x t
                                          2 2  3 3

          using the 15 sets of data given in the following table:

                                  y    t   t    t
                                        1   2    3
                                 0.14  1.0 15.0 1.0
                                 0.18  2.0 14.0 2.0
                                 0.22  3.0 13.0 3.0
                                 0.25  4.0 12.0 4.0
                                 0.29  5.0 11.0 5.0
                                 0.32  6.0 10.0 6.0
                                 0.35  7.0  9.0 7.0
                                 0.39  8.0  8.0 8.0
                                 0.37  9.0  7.0 7.0
                                 0.58 10.0  6.0 6.0
                                 0.73 11.0  5.0 5.0
                                 0.96 12.0  4.0 4.0
                                 1.34 13.0  3.0 3.0
                                 2.10 14.0  2.0 2.0
                                 4.39 15.0  1.0 1.0

          The program uses (0.5,1.0,1.5) as the initial guess at the
          position of the minimum and computes the least-squares solution
          using E04FDF. See the routine document E04FDF for further
          information.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\section{nagf.ht}
\pagetitle{manpageXXf}{nagf.ht}{ Linear Algebra}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf}{NAG Documentation: f}
\beginscroll
\begin{verbatim}



     F(3NAG)           Foundation Library (12/10/92)           F(3NAG)



          F -- Linear Algebra                             Introduction -- F
                                     Chapter F
                                  Linear Algebra

          1. Introduction

          The F Chapters of the Library are concerned with linear algebra
          and cover a large area. This general introduction is intended to
          help users decide which particular F Chapter is relevant to their
          problem. There are F Chapters with the following titles:

               F01 -- Matrix Factorizations

               F02 -- Eigenvalues and Eigenvectors

               F04 -- Simultaneous Linear Equations

               F06 -- Linear Algebra Support Routines

               F07 -- Linear Equations (LAPACK)

          The principal problem areas addressed by the above Chapters are:

               Systems of linear equations

               Linear least-squares problems

               Eigenvalue and singular value problems

          The solution of these problems usually involves several matrix
          operations, such as a matrix factorization followed by the
          solution of the factorized form, and the routines for these
          operations themselves utilize lower level support routines;
          typically routines from Chapter F06. Most users will not normally
          need to be concerned with these support routines.

          NAG has been involved in a project, called LAPACK [1], to develop
          a linear algebra package for modern high-performance computers
          and some of the routines developed within that project are
          incorporated into the Library as Chapter F07. It should be
          emphasised that, while the LAPACK project has been concerned with
          high-performance computers, the routines do not compromise
          efficiency on conventional machines.

          For background information on numerical algorithms for the
          solution of linear algebra problems see Golub and Van Loan [4].
          For some problem areas the user has the choice of selecting a
          single routine to solve the problem, a so-called Black Box
          routine, or selecting more than one routine to solve the problem,
          such as a factorization routine followed by a solve routine, so-
          called General Purpose routines. The following sections indicate
          which chapters are relevant to particular problem areas.

          2. Linear Equations

          The Black Box routines for solving linear equations of the form

                                  Ax=b  and  AX=B,

          where A is an n by n real or complex, non-singular matrix, are to
          be found in Chapter F04. Such equations can also be solved by
          selecting a General Purpose factorization routine from Chapter
          F01 and combining it with a solve routine in Chapter F04, or by
          selecting a factorization and a solve routine from Chapter F07.

          There are routines to cater for a variety of types of matrix,
          including general, symmetric or Hermitian, symmetric or Hermitian
          positive definite, tridiagonal, skyline and sparse matrices.

          In order to select the appropriate routine, users are recommended
          to consult the F04 Chapter Introduction in the first instance.

          3. Linear Least-squares

          Routines for solving linear least-squares problems of the form


                                      T
                            minimize r r,  where  r=b-Ax,
                             x

          where A is an m by n, possibly rank deficient, matrix are to be
          found in Chapter F04. Linear least-squares problems can also be
          solved by routines in the statistical Chapter G02.

          In order to select the appropriate routine, users are recommended
          to consult the F04 Chapter Introduction in the first instance,
          but users with additional statistical requirements may prefer to
          consult the G02 Chapter Introduction.

          4. Eigenvalue Problems and Singular Value Problems

          Routines for solving standard matrix eigenvalue problems of the
          form


                                    Ax=(lambda)x,

          where A is an n by n real or complex matrix, and generalized
          matrix eigenvalue problems of the form


                                    Ax=(lambda)Bx

          where B is also an n by n matrix are to be found in Chapter F02.

          There are routines to cater for various types of matrices,
          including general, symmetric or Hermitian and sparse matrices.

          Similarly, the routines for finding singular values and/or
          singular vectors of an m by n real or complex matrix A are to be
          found in Chapter F02.

          In order to select the appropriate routine, users are recommended
          to consult the F02 Chapter Introduction in the first instance.

          5. Matrix Factorizations

          Routines for various sorts of matrix factorization are to be
          found in Chapters F01 and F07 together with associated
          transformation routines. In order to select the appropriate
          routine users are recommended to consult the F01 Chapter
          Introduction in the first instance.

          6. Support Routines

          Chapter F06 contains a variety of routines to perform elementary
          algebraic operations involving scalars, vectors and matrices,
          such as setting up a plane rotation, performing a dot product and
          computing a matrix-vector product. Chapter F06 contains routines
          that meet the specification of the BLAS (Basic Linear Algebra
          Subprograms) [5, 3, 2]. The routines in this chapter will not
          normally be required by the general user, but are intended for
          use by those who require to build specialist linear algebra
          modules. The BLAS are extensively used by other NAG Foundation
          Library routines.

          References

          [1]   Anderson E, Bai Z, Bischof C, Demmel J, Dongarra J J, Du
                Croz J, Greenbaum A, Hammarling S, McKenney A, Ostrouchov S
                and Sorensen D (1992) LAPACK Users' Guide. SIAM
                Philadelphia.

          [2]   Dongarra J J, Du Croz J J, Duff I S and Hammarling S (1990)
                A Set of Level 3 Basic Linear Algebra Subprograms. ACM
                Trans. Math. Softw. 16 1--28.

          [3]   Dongarra J J, Du Croz J J, Hammarling S and Hanson R J
                (1988) An Extended Set of FORTRAN Basic Linear Algebra
                Subprograms. ACM Trans. Math. Softw. 14 1--32.

          [4]   Golub G H and Van Loan C F (1989) Matrix Computations (2nd
                Edition). Johns Hopkins University Press, Baltimore,
                Maryland.

          [5]   Lawson C L, Hanson R J, Kincaid D R and Krogh F T (1979)
                Basic Linear Algebra Subprograms for Fortran Usage. ACM
                Trans. Math. Softw. 5 308--325.

          [6]   Parlett B N (1980) The Symmetric Eigenvalue Problem.
                Prentice-Hall.

          [7]   Wilkinson J H (1965) The Algebraic Eigenvalue Problem.
                Clarendon Press.

          [8]   Wilkinson J H (1977) Some Recent Advances in Numerical
                Linear Algebra. The State of the Art in Numerical Analysis.
                (ed D A H Jacobs) Academic Press.

          [9]   Wilkinson J H (1978) Singular Value Decomposition -- Basic
                Aspects. Numerical Software -- Needs and Availability. (ed D
                A H Jacobs) Academic Press.

          [10]  Wilkinson J H and Reinsch C (1971) Handbook for Automatic
                Computation II, Linear Algebra. Springer-Verlag.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf01}{nagf.ht}{ Matrix Factorization}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf01}{NAG Documentation: f01}
\beginscroll
\begin{verbatim}



     F01(3NAG)         Foundation Library (12/10/92)         F01(3NAG)



          F01 -- Matrix Factorization                   Introduction -- F01
                                    Chapter F01
                               Matrix Factorization

          1. Scope of the Chapter

          This chapter provides facilities for matrix factorizations and
          associated transformations.

          2. Background to the Problems

          An n by n matrix may be factorized as

                                            T
                                      A=PLUQ ,

          where L and U are respectively lower and uper triangular
          matrices, and P and Q are permutation matrices. This is called an
          LU factorization. For general dense matrices it is usual to
          choose Q=I and to then choose P to ensure that the factorization
          is numerically stable. For sparse matrices, judicious choice of P
          and Q ensures numerical stability as well as maintaining as much
          sparsity as possible in the factors L and U. The LU factorization
          is normally used in connection with the solution of the linear
          equations


                                        Ax=b,

          whose solution, x, may then be obtained by solving in succession
          the simpler equations

                                    T
                                Ly=P b,  Uz=y,  x=Qz

          the first by forward substitution and the second by backward
          substitution. Routines to perform this solution are to be found
          in Chapter F04.

                                                                      T
          When A is symmetric positive-definite then we can choose U=L  and
          Q=P, to give the Cholesky factorization. This factorization is
          numerically stable without permutations, but in the sparse case
          the permutations can again be used to try to maintain sparsity.
          The Cholesky factorization is sometimes expressed as

                                           T T
                                     A=PLDL P ,

          where D is a diagonal matrix with positive diagonal elements and
          L is unit lower triangular.

          The LU factorization can also be performed on rectangular
          matrices, but in this case it is more usual to perform a QR
          factorization. When A is an m by n (m>=n) matrix this is given by


                                          (R)
                                       A=Q(0),

          where R is an n by n upper triangular matrix and Q is an
          orthogonal (unitary in the complex case) matrix.

          3. Recommendations on Choice and Use of Routines

          Routine F07ADF performs the LU factorization of a real m by n
          dense matrix.

          The LU factorization of a sparse matrix is performed by routine
          F01BRF. Following the use of F01BRF, matrices with the same
          sparsity pattern may be factorized by routine F01BSF.

          The Cholesky factorization of a real symmetric positive-definite
          dense matrix is performed by routine F07FDF.

          Routine F01MCF performs the Cholesky factorization of a real
          symmetric positive-definite variable band (skyline) matrix, and a
          general sparse symmetric positive-definite matrix may be
          factorized using routine F01MAF.

          The QR factorization of an m by n (m>=n) matrix is performed by
          routine F01QCF in the real case, and F01RCF in the complex case.
          Following the use of F01QCF, operations with Q may be performed
          using routine F01QDF and some, or all, of the columns of Q may be
          formed using routine F01QEF. Routines F01RDF and F01REF perform
          the same tasks following the use of F01RCF.


          F01 -- Matrix Factorizations                      Contents -- F01
          Chapter F01

          Matrix Factorizations

          F01BRF  LU factorization of real sparse matrix

          F01BSF  LU factorization of real sparse matrix with known
                  sparsity pattern

                    T
          F01MAF  LL  factorization of real sparse symmetric positive-
                  definite matrix

                     T
          F01MCF  LDL  factorization of real symmetric positive-definite
                  variable-bandwidth matrix

          F01QCF  QR factorization of real m by n matrix (m>=n)

                                                                      T
          F01QDF  Operations with orthogonal matrices, compute QB or Q B
                  after factorization by F01QCF

          F01QEF  Operations with orthogonal matrices, form columns of Q
                  after factorization by F01QCF

          F01RCF  QR factorization of complex m by n matrix (m>=n)

                                                                   H
          F01RDF  Operations with unitary matrices, compute QB or Q B after
                  factorization by F01RCF

          F01REF  Operations with unitary matrices, form columns of Q after
                  factorization by F01RCF

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf01brf}{nagf.ht}{ Factorizes a real sparse matrix}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf01brf}{NAG Documentation: f01brf}
\beginscroll
\begin{verbatim}



     F01BRF(3NAG)      Foundation Library (12/10/92)      F01BRF(3NAG)



          F01 -- Matrix Factorizations                               F01BRF
                  F01BRF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F01BRF factorizes a real sparse matrix. The routine either forms
          the LU factorization of a permutation of the entire matrix, or,
          optionally, first permutes the matrix to block lower triangular
          form and then only factorizes the diagonal blocks.

          2. Specification

                 SUBROUTINE F01BRF (N, NZ, A, LICN, IRN, LIRN, ICN, PIVOT,
                1                   IKEEP, IW, W, LBLOCK, GROW, ABORT,
                2                   IDISP, IFAIL)
                 INTEGER          N, NZ, LICN, IRN(LIRN), LIRN, ICN(LICN),
                1                 IKEEP(5*N), IW(8*N), IDISP(10), IFAIL
                 DOUBLE PRECISION A(LICN), PIVOT, W(N)
                 LOGICAL          LBLOCK, GROW, ABORT(4)

          3. Description

          Given a real sparse matrix A, this routine may be used to obtain
          the LU factorization of a permutation of A,

                                       PAQ=LU

          where P and Q are permutation matrices, L is unit lower
          triangular and U is upper triangular. The routine uses a sparse
          variant of Gaussian elimination, and the pivotal strategy is
          designed to compromise between maintaining sparsity and
          controlling loss of accuracy through round-off.

          Optionally the routine first permutes the matrix into block lower
          triangular form and then only factorizes the diagonal blocks. For
          some matrices this gives a considerable saving in storage and
          execution time.

          Extensive data checks are made; duplicated non-zeros can be
          accumulated.

          The factorization is intended to be used by F04AXF to solve
                                                      T
          sparse systems of linear equations Ax=b or A x=b. If several
          matrices of the same sparsity pattern are to be factorized,
          F01BSF should be used for the second and subsequent matrices.

          The method is fully described by Duff [1].

          4. References

          [1]   Duff I S (1977) MA28 -- a set of Fortran subroutines for
                sparse unsymmetric linear equations. A.E.R.E. Report R.8730.
                HMSO.

          5. Parameters

           1:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A. Constraint: N > 0.

           2:  NZ -- INTEGER                                          Input
               On entry: the number of non-zero elements in the matrix A.
               Constraint: NZ > 0.

           3:  A(LICN) -- DOUBLE PRECISION array               Input/Output
               On entry: A(i), for i = 1,2,...,NZ must contain the non-
               zero elements of the sparse matrix A. They can be in any
               order since the routine will reorder them. On exit: the non-
               zero elements in the LU factorization. The array must not be
               changed by the user between a call of this routine and a
               call of F04AXF.

           4:  LICN -- INTEGER                                        Input
               On entry:
               the dimension of the arrays A and ICN as declared in the
               (sub)program from which F01BRF is called.
               Since the factorization is returned in A and ICN, LICN
               should be large enough to accommodate this and should
               ordinarily be 2 to 4 times as large as NZ. Constraint: LICN
               >= NZ.

           5:  IRN(LIRN) -- INTEGER array                      Input/Output
               On entry: IRN(i), for i = 1,2,...,NZ must contain the row
               index of the non-zero element stored in A(i). On exit: the
               array is overwritten and is not needed for subsequent calls
               of F01BSF or F04AXF.

           6:  LIRN -- INTEGER                                        Input
               On entry:
               the dimension of the array IRN as declared in the
               (sub)program from which F01BRF is called.
               It need not be as large as LICN; normally it will not need
               to be very much greater than NZ. Constraint: LIRN >= NZ.

           7:  ICN(LICN) -- INTEGER array                      Input/Output
               On entry: ICN(i), for i = 1,2,...,NZ must contain the
               column index of the non-zero element stored in A(i). On
               exit: the column indices of the non-zero elements in the
               factorization. The array must not be changed by the user
               between a call of this routine and subsequent calls of
               F01BSF or F04AXF.

           8:  PIVOT -- DOUBLE PRECISION                              Input
               On entry: PIVOT should have a value in the range 0.0 <=
               PIVOT <= 0.9999 and is used to control the choice of pivots.
               If PIVOT < 0.0, the value 0.0 is assumed, and if PIVOT > 0.
               9999, the value 0.9999 is assumed. When searching a row for
               a pivot, any element is excluded which is less than PIVOT
               times the largest of those elements in the row available as
               pivots. Thus decreasing PIVOT biases the algorithm to
               maintaining sparsity at the expense of stability. Suggested
               value: PIVOT = 0.1 has been found to work well on test
               examples.

           9:  IKEEP(5*N) -- INTEGER array                           Output
               On exit: indexing information about the factorization. The
               array must not be changed by the user between a call of this
               routine and calls of F01BSF or F04AXF.

          10:  IW(8*N) -- INTEGER array                           Workspace

          11:  W(N) -- DOUBLE PRECISION array                        Output
               On exit: if GROW = .TRUE., W(1) contains an estimate (an
               upper bound) of the increase in size of elements encountered
               during the factorization (see GROW); the rest of the array
               is used as workspace.

               If GROW = .FALSE., the array is not used.

          12:  LBLOCK -- LOGICAL                                      Input
               On entry: if LBLOCK = .TRUE., the matrix is pre-ordered
               into block lower triangular form before the LU factorization
               is performed; otherwise the entire matrix is factorized.
               Suggested value: LBLOCK = .TRUE. unless the matrix is known
               to be irreducible.

          13:  GROW -- LOGICAL                                        Input
               On entry: if GROW = .TRUE., then on exit W(1) contains an
               estimate (an upper bound) of the increase in size of
               elements encountered during the factorization. If the matrix
               is well-scaled (see Section 8.2), then a high value for W(1)
               indicates that the LU factorization may be inaccurate and
               the user should be wary of the results and perhaps increase
               the parameter PIVOT for subsequent runs (see Section 7).
               Suggested value: GROW = .TRUE..

          14:  ABORT(4) -- LOGICAL array                              Input
               On entry:
                    if ABORT(1) = .TRUE., the routine will exit
                    immediately on detecting a structural singularity (one
                    that depends on the pattern of non-zeros) and return

                    IFAIL = 1; otherwise it will complete the
                    factorization (see Section 8.3).

                    If ABORT(2) = .TRUE., the routine will exit
                    immediately on detecting a numerical singularity (one
                    that depends on the numerical values) and return IFAIL
                    = 2; otherwise it will complete the factorization (see
                    Section 8.3).

                    If ABORT(3) = .TRUE., the routine will exit
                    immediately (with IFAIL = 5) when the arrays A and ICN
                    are filled up by the previously factorized, active and
                    unfactorized parts of the matrix; otherwise it
                    continues so that better guidance on necessary array
                    sizes can be given in IDISP(6) and IDISP(7), and will
                    exit with IFAIL in the range 4 to 6. Note that there
                    is always an immediate error exit if the array IRN is
                    too small.

                    If ABORT(4) = .TRUE., the routine exits immediately
                    (with IFAIL = 13) if it finds duplicate elements in
                    the input matrix. If ABORT(4) = .FALSE., the routine
                    proceeds using a value equal to the sum of the
                    duplicate elements. In either case details of each
                    duplicate element are output on the current advisory
                    message unit (see X04ABF), unless suppressed by the
                    value of IFAIL on entry.
                Suggested values:
                    ABORT(1) = .TRUE.

                    ABORT(2) = .TRUE.

                    ABORT(3) = .FALSE.

                    ABORT(4) = .TRUE..

          15:  IDISP(10) -- INTEGER array                            Output
               On exit: IDISP is used to communicate information about the
               factorization to the user and also between a call of F01BRF
               and subsequent calls to F01BSF or F04AXF.
                    IDISP(1) and IDISP(2), indicate the position in arrays
                    A and ICN of the first and last elements in the LU
                    factorization of the diagonal blocks. (IDISP(2) gives
                    the number of non-zeros in the factorization.)

                    IDISP(3) and IDISP(4), monitor the adequacy of 'elbow
                    room' in the arrays IRN and A/ICN respectively, by
                    giving the number of times that the data in these
                    arrays has been compressed during the factorization to
                    release more storage. If either IDISP(3) or IDISP(4)
                    is quite large (say greater than 10), it will probably
                    pay the user to increase the size of the corresponding
                    array(s) for subsequent runs. If either is very low or
                    zero, then the user can perhaps save storage by
                    reducing the size of the corresponding array(s).

                    IDISP(5), gives an upper bound on the rank of the
                    matrix.

                    IDISP(6) and IDISP(7), give the minimum size of arrays
                    IRN and A/ICN respectively which would enable a
                    successful run on an identical matrix (but some '
                    elbow-room' should be allowed - see Section 8).

                    IDISP(8) to (10), are only used if LBLOCK = .TRUE..

                    IDISP(8), gives the structural rank of the matrix.

                    IDISP(9), gives the number of diagonal blocks.

                    IDISP(10), gives the size of the largest diagonal
                    block.

                    IDISP(1) and IDISP(2), must not be changed by the user
                    between a call of F01BRF and subsequent calls to
                    F01BSF or F04AXF.

          16:  IFAIL -- INTEGER                                Input/Output
               For this routine, the normal use of IFAIL is extended to
               control the printing of error and warning messages as well
               as specifying hard or soft failure (see the Essential
               Introduction).

               Before entry, IFAIL must be set to a value with the decimal
               expansion cba, where each of the decimal digits c, b and a
               must have a value of 0 or 1.
               a=0   specifies hard failure, otherwise soft failure;

               b=0   suppresses error messages, otherwise error messages
                     will be printed (see Section 6);

               c=0   suppresses warning messages, otherwise warning
                     messages will be printed (see Section 6).
               The recommended value for inexperienced users is 110 (i.e.,
               hard failure with all messages printed).

               Unless the routine detects an error (see Section 6), IFAIL
               contains 0 on exit.

          6. Error Indicators and Warnings

          Errors detected by the routine:

          For each error, an explanatory error message is output on the
          current error message unit (as defined by X04AAF), unless
          suppressed by the value of IFAIL on entry.

          IFAIL=-2
               Successful factorization of a numerically singular matrix
               (which may also be structurally singular) (see Section 8.3).

          IFAIL=-1
               Successful factorization of a structurally singular matrix
               (see Section 8.3).

          IFAIL= 1
               The matrix is structurally singular and the factorization
               has been abandoned (ABORT(1) was .TRUE. on entry).

          IFAIL= 2
               The matrix is numerically singular and the factorization has
               been abandoned (ABORT(2) was .TRUE. on entry).

          IFAIL= 3
               LIRN is too small: there is not enough space in the array
               IRN to continue the factorization. The user is recommended
               to try again with LIRN (and the length of IRN) equal to at
               least IDISP(6) + N/2.

          IFAIL= 4
               LICN is much too small: there is much too little space in
               the arrays A and ICN to continue the factorization.

          IFAIL= 5
               LICN is too small: there is not enough space in the arrays A
               and ICN to store the factorization. If ABORT(3) was .FALSE.
               on entry, the factorization has been completed but some of
               the LU factors have been discarded to create space, IDISP(7)
               then gives the minimum value of LICN (i.e., the minimum
               length of A and ICN) required for a successful factorization
               of the same matrix.

          IFAIL= 6
               LICN and LIRN are both too small: effectively this is a
               combination of IFAIL = 3 and IFAIL = 5 (with ABORT(3) = .
               FALSE.).

          IFAIL= 7
               LICN is too small: there is not enough space in the arrays A
               and ICN for the permutation to block triangular form.

          IFAIL= 8
               On entry N <= 0.

          IFAIL= 9
               On entry NZ <= 0.

          IFAIL= 10
               On entry LICN < NZ.

          IFAIL= 11
               On entry LIRN < NZ.

          IFAIL= 12
               On entry an element of the input matrix has a row or column
               index (i.e., an element of IRN or ICN) outside the range 1
               to N.

          IFAIL= 13
               Duplicate elements have been found in the input matrix and
               the factorization has been abandoned (ABORT(4) = .TRUE. on
               entry).

          7. Accuracy

          The factorization obtained is exact for a perturbed matrix whose
          (i,j)th element differs from a   by less than 3(epsilon)(rho)m
                                        ij                              ij
          where (epsilon) is the machine precision, (rho) is the growth
          value returned in W(1) if GROW = .TRUE., and m   the number of
                                                        ij
          Gaussian elimination operations applied to element (i,j). The
          value of m   is not greater than n and is usually much less.
                    ij
          Small (rho) values therefore guarantee accurate results, but
          unfortunately large (rho) values may give a very pessimistic
          indication of accuracy.

          8. Further Comments

          8.1. Timing

          The time required may be estimated very roughly from the number
          (tau) of non-zeros in the factorized form (output as IDISP(2))
          and for this routine and its associates is

                             2
               F01BRF: 5(tau) /n units

                            2
               F01BSF: (tau) /n units

               F04AXF: 2(tau) units

          where our unit is the time for the inner loop of a full matrix
                                                                  1 3
          code (e.g. solving a full set of equations takes about  -n
                                                                  3
          units). Note that the faster F01BSF time makes it well worthwhile
          to use this for a sequence of problems with the same pattern.

          It should be appreciated that (tau) varies widely from problem to
          problem. For network problems it may be little greater than NZ,
          the number of non-zeros in A; for discretisation of 2-dimensional
          and 3-dimensional partial differential equations it may be about
                       1 5/3
          3nlog n and  -n   , respectively.
               2       2

          The time taken to find the block lower triangular form (LBLOCK =
          it is not found (LBLOCK = .FALSE.). If the matrix is irreducible
          (IDISP(9) = 1 after a call with LBLOCK = .TRUE.) then this time
          is wasted. Otherwise, particularly if the largest block is small
          (IDISP(10)<<n), the consequent savings are likely to be greater.

          The time taken to estimate growth (GROW = .TRUE.) is typically
          under 2% of the overall time.

          The overall time may be substantially increased if there is
          inadequate 'elbow-room' in the arrays A, IRN and ICN. When the
          sizes of the arrays are minimal (IDISP(6) and IDISP(7)) it can
          execute as much as three times slower. Values of IDISP(3) and
          IDISP(4) greater than about 10 indicate that it may be worthwhile
          to increase array sizes.

          8.2. Scaling

          The use of a relative pivot tolerance PIVOT essentially
          presupposes that the matrix is well-scaled, i.e., that the matrix
          elements are broadly comparable in size. Practical problems are
          often naturally well-scaled but particular care is needed for
          problems containing mixed types of variables (for example
          millimetres and neutron fluxes).

          8.3. Singular and Rectangular Systems

          It is envisaged that this routine will almost always be called
          for square non-singular matrices and that singularity indicates
          an error condition. However, even if the matrix is singular it is
          possible to complete the factorization. It is even possible for
          F04AXF to solve a set of equations whose matrix is singular
          provided the set is consistent.

          Two forms of singularity are possible. If the matrix would be
          singular for any values of the non-zeros (e.g. if it has a whole
          row of zeros), then we say it is structurally singular, and
          continue only if ABORT(1) = .FALSE.. If the matrix is non-
          singular by virtue of the particular values of the non-zeros,
          then we say that it is numerically singular and continue only if
          ABORT(2) = .FALSE..

          Rectangular matrices may be treated by setting N to the larger of
          the number of rows and numbers of columns and setting ABORT(1) =

          Note: the soft failure option should be used (last digit of IFAIL
          = 1) if the user wishes to factorize singular matrices with ABORT
          (1) or ABORT(2) set to .FALSE..

          8.4. Duplicated Non-zeros

          The matrix A may consist of a sum of contributions from different
          sub-systems (for example finite elements). In such cases the user
          may rely on this routine to perform assembly, since duplicated
          elements are summed.

          9. Example

          To factorize the real sparse matrix:

                                 ( 5  0  0  0 0  0)
                                 ( 0  2 -1  2 0  0)
                                 ( 0  0  3  0 0  0)
                                 (-2  0  0  1 1  0).
                                 (-1  0  0 -1 2 -3)
                                 (-1 -1  0  0 0  6)

          This example program simply prints out some information about the
          factorization as returned by F01BRF in W(1) and IDISP. Normally
          the call of F01BRF would be followed by a call of F04AXF (see
          Example for F04AXF).

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf01bsf}{nagf.ht}{ Factorizes a real sparse matrix}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf01bsf}{NAG Documentation: f01bsf}
\beginscroll
\begin{verbatim}



     F01BSF(3NAG)      Foundation Library (12/10/92)      F01BSF(3NAG)



          F01 -- Matrix Factorizations                               F01BSF
                  F01BSF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F01BSF factorizes a real sparse matrix using the pivotal sequence
          previously obtained by F01BRF when a matrix of the same sparsity
          pattern was factorized.

          2. Specification

                 SUBROUTINE F01BSF (N, NZ, A, LICN, IVECT, JVECT, ICN,
                1                   IKEEP, IW, W, GROW, ETA, RPMIN, ABORT,
                2                   IDISP, IFAIL)
                 INTEGER          N, NZ, LICN, IVECT(NZ), JVECT(NZ), ICN
                1                 (LICN), IKEEP(5*N), IW(8*N), IDISP(2),
                2                 IFAIL
                 DOUBLE PRECISION A(LICN), W(N), ETA, RPMIN
                 LOGICAL          GROW, ABORT

          3. Description

          This routine accepts as input a real sparse matrix of the same
          sparsity pattern as a matrix previously factorized by a call of
          F01BRF. It first applies to the matrix the same permutations as
          were used by F01BRF, both for permutation to block triangular
          form and for pivoting, and then performs Gaussian elimination to
          obtain the LU factorization of the diagonal blocks.

          Extensive data checks are made; duplicated non-zeros can be
          accumulated.

          The factorization is intended to be used by F04AXF to solve
                                                      T
          sparse systems of linear equations Ax=b or A x=b.

          F01BSF is much faster than F01BRF and in some applications it is
          expected that there will be many calls of F01BSF for each call of
          F01BRF.

          The method is fully described in Duff [1].

          4. References

          [1]   Duff I S (1977) MA28 -- a set of Fortran subroutines for
                sparse unsymmetric linear equations. A.E.R.E. Report R.8730.
                HMSO.

          5. Parameters

           1:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A. Constraint: N > 0.

           2:  NZ -- INTEGER                                          Input
               On entry: the number of non-zeros in the matrix A.
               Constraint: NZ > 0.

           3:  A(LICN) -- DOUBLE PRECISION array               Input/Output
               On entry: A(i), for i = 1,2,...,NZ must contain the non-
               zero elements of the sparse matrix A. They can be in any
               order since the routine will reorder them. On exit: the non-
               zero elements in the factorization. The array must not be
               changed by the user between a call of this routine and a
               call of F04AXF.

           4:  LICN -- INTEGER                                        Input
               On entry:
               the dimension of the arrays A and ICN as declared in the
               (sub)program from which F01BSF is called.
               It should have the same value as it had for F01BRF.
               Constraint: LICN >= NZ.

           5:  IVECT(NZ) -- INTEGER array                             Input

           6:  JVECT(NZ) -- INTEGER array                             Input
               On entry: IVECT(i) and JVECT(i), for i = 1,2,...,NZ must
               contain the row index and the column index respectively of
               the non-zero element stored in A(i).

           7:  ICN(LICN) -- INTEGER array                             Input
               On entry: the same information as output by F01BRF. It must
               not be changed by the user between a call of this routine
               and a call of F04AXF.

           8:  IKEEP(5*N) -- INTEGER array                            Input
               On entry: the same indexing information about the
               factorization as output from F01BRF. It must not be changed
               between a call of this routine and a call of F04AXF.

           9:  IW(8*N) -- INTEGER array                           Workspace

          10:  W(N) -- DOUBLE PRECISION array                        Output
               On exit: if GROW = .TRUE., W(1) contains an estimate (an
               upper bound) of the increase in size of elements encountered
               during the factorization (see GROW); the rest of the array
               is used as workspace.

               If GROW = .FALSE., the array is not used.

          11:  GROW -- LOGICAL                                        Input
               On entry: if GROW = .TRUE., then on exit W(1) contains an
               estimate (an upper bound) of the increase in size of
               elements encountered during the factorization. If the matrix
               is well-scaled (see Section 8.2), then a high value for W(1)
               indicates that the LU factorization may be inaccurate and
               the user should be wary of the results and perhaps increase
               the parameter PIVOT for subsequent runs (see Section 7).

          12:  ETA -- DOUBLE PRECISION                                Input
               On entry: the relative pivot threshold below which an error
               diagnostic is provoked and IFAIL is set to 7. If ETA is
               greater than 1.0, then no check on pivot size is made.
                                        -4
               Suggested value: ETA = 10  .

          13:  RPMIN -- DOUBLE PRECISION                             Output
               On exit: if ETA is less than 1.0, then RPMIN gives the
               smallest ratio of the pivot to the largest element in the
               row of the corresponding upper triangular factor thus
               monitoring the stability of the factorization. If RPMIN is
               very small it may be advisable to perform a new
               factorization using F01BRF.

          14:  ABORT -- LOGICAL                                       Input
               On entry: if ABORT = .TRUE., the routine exits immediately
               (with IFAIL = 8) if it finds duplicate elements in the input
               matrix. If ABORT = .FALSE., the routine proceeds using a
               value equal to the sum of the duplicate elements. In either
               case details of each duplicate element are output on the
               current advisory message unit (see X04ABF), unless
               suppressed by the value of IFAIL on entry. Suggested value:
               ABORT = .TRUE..

          15:  IDISP(2) -- INTEGER array                              Input
               On entry: IDISP(1) and IDISP(2) must be unchanged since the
               previous call of F01BRF.

          16:  IFAIL -- INTEGER                                Input/Output
               For this routine, the normal use of IFAIL is extended to
               control the printing of error and warning messages as well
               as specifying hard or soft failure (see the Essential
               Introduction).

               Before entry, IFAIL must be set to a value with the decimal
               expansion cba, where each of the decimal digits c, b and a
               must have a value of 0 or 1.
               a=0   specifies hard failure, otherwise soft failure;

               b=0   suppresses error messages, otherwise error messages
                     will be printed (see Section 6);

               c=0   suppresses warning messages, otherwise warning
                     messages will be printed (see Section 6).
               The recommended value for inexperienced users is 110 (i.e.,
               hard failure with all messages printed).

               Unless the routine detects an error (see Section 6), IFAIL
               contains 0 on exit.

          6. Error Indicators and Warnings

          Errors detected by the routine:

          For each error, an explanatory error message is output on the
          current error message unit (as defined by X04AAF), unless
          suppressed by the value of IFAIL on entry.

          IFAIL= 1
               On entry N <= 0.

          IFAIL= 2
               On entry NZ <= 0.

          IFAIL= 3
               On entry LICN < NZ.

          IFAIL= 4
               On entry an element of the input matrix has a row or column
               index (i.e., an element of IVECT or JVECT) outside the range
               1 to N.

          IFAIL= 5
               The input matrix is incompatible with the matrix factorized
               by the previous call of F01BRF (see Section 8).

          IFAIL= 6
               The input matrix is numerically singular.

          IFAIL= 7
               A very small pivot has been detected (see Section 5, ETA).
               The factorization has been completed but is potentially
               unstable.

          IFAIL= 8
               Duplicate elements have been found in the input matrix and
               the factorization has been abandoned (ABORT = .TRUE. on
               entry).

          7. Accuracy

          The factorization obtained is exact for a perturbed matrix whose
          (i,j)th element differs from a   by less than 3(epsilon)(rho)m
                                        ij                              ij
          where (epsilon) is the machine precision, (rho) is the growth
          value returned in W(1) if GROW = .TRUE., and m   the number of
                                                        ij
          Gaussian elimination operations applied to element (i,j).

          If (rho) = W(1) is very large or RPMIN is very small, then a
          fresh call of F01BRF is recommended.

          8. Further Comments

          If the user has a sequence of problems with the same sparsity
          pattern then this routine is recommended after F01BRF has been
          called for one such problem. It is typically 4 to 7 times faster
          but is potentially unstable since the previous pivotal sequence
          is used. Further details on timing are given in document F01BRF.

          If growth estimation is performed (GROW = .TRUE.), then the time
          increases by between 5% and 10%. Pivot size monitoring (ETA <= 1.
          0) involves a similar overhead.

          We normally expect this routine to be entered with a matrix
          having the same pattern of non-zeros as was earlier presented to
          F01BRF. However there is no record of this pattern, but rather a
          record of the pattern including all fill-ins. Therefore we permit
          additional non-zeros in positions corresponding to fill-ins.

          If singular matrices are being treated then it is also required
          that the present matrix be sufficiently like the previous one for
          the same permutations to be suitable for factorization with the
          same set of zero pivots.

          9. Example

          To factorize the real sparse matrices

                                 ( 5  0  0  0 0  0)
                                 ( 0  2 -1  2 0  0)
                                 ( 0  0  3  0 0  0)
                                 (-2  0  0  1 1  0)
                                 (-1  0  0 -1 2 -3)
                                 (-1 -1  0  0 0  6)

          and

                                (10  0  0  0  0  0)
                                ( 0 12 -3 -1  0  0)
                                ( 0  0 15  0  0  0)
                                (-2  0  0 10 -1  0).
                                (-1  0  0 -5  1 -1)
                                (-1 -2  0  0  0  6)

          This example program simply prints the values of W(1) and RPMIN
          returned by F01BSF. Normally the calls of F01BRF and F01BSF would
          be followed by calls of F04AXF.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf01maf}{nagf.ht}{ Incomplete Cholesky factorization}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf01maf}{NAG Documentation: f01maf}
\beginscroll
\begin{verbatim}



     F01MAF(3NAG)      Foundation Library (12/10/92)      F01MAF(3NAG)



          F01 -- Matrix Factorizations                               F01MAF
                  F01MAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F01MAF computes an incomplete Cholesky factorization of a real
          sparse symmetric positive-definite matrix A.

          2. Specification

                 SUBROUTINE F01MAF (N, NZ, A, LICN, IRN, LIRN, ICN, DROPTL,
                1                   DENSW, WKEEP, IKEEP, IWORK, ABORT,
                2                   INFORM, IFAIL)
                 INTEGER          N, NZ, LICN, IRN(LIRN), LIRN, ICN(LICN),
                1                 IKEEP(2*N), IWORK(6*N), INFORM(4), IFAIL
                 DOUBLE PRECISION A(LICN), DROPTL, DENSW, WKEEP(3*N)
                 LOGICAL          ABORT(3)

          3. Description

          F01MAF computes an incomplete Cholesky factorization

                                      T T
                                C=PLDL P ,   WAW=C+E

          for the sparse symmetric positive-definite matrix A, where P is a
          permutation matrix, L is a unit lower triangular matrix, D is a
          diagonal matrix with positive diagonal elements, E is an error
          matrix representing elements dropped during the factorization and
          diagonal elements that have been modified to ensure that C is
          positive-definite, and W is a diagonal matrix, chosen to make the
          diagonal elements of WAW unity.

           -1  -1
          W  CW   is a pre-conditioning matrix for A, and the factorization
          of C is intended to be used by F04MAF to solve systems of linear
          equations Ax=b.

          The permutation matrix P is chosen to reduce the amount of fill-
          in that occurs in L and the user-supplied parameter DROPTL can
          also be used to control the amount of fill-in that occurs.

          Full details on the factorization can be found in Munksgaard [1].

          F01MAF is based on the Harwell Library routine MA31A.

          4. References

          [1]   Munksgaard N (1980) Solving Sparse Symmetric Sets of Linear
                Equations by Pre-conditioned Conjugate Gradients. ACM Trans.
                Math. Softw. 6 206--219.

          5. Parameters

           1:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A. Constraint: N >= 1.

           2:  NZ -- INTEGER                                          Input
               On entry: the number of non-zero elements in the upper
               triangular part of the matrix A, including the number of
               elements on the leading diagonal. Constraint: NZ >= N.

           3:  A(LICN) -- DOUBLE PRECISION array               Input/Output
               On entry: the first NZ elements of the array A must contain
               the non-zero elements of the upper triangular part of the
               sparse positive-definite symmetric matrix A, including the
               elements on the leading diagonal. On exit: the first (NZ-N)
               elements of A contain the elements above the diagonal of the
               matrix WAW, where W is a diagonal matrix whose ith diagonal
                              -1/2
               element is w =a    . These elements are returned in order by
                           i  ii
               rows and the value returned in ICN(k) gives the column index
               of the element returned in A(k). The value w  is returned in
                                                           i
               the ith element of the array WKEEP. The remaining LROW-NZ+N
               elements of A, where LROW is the value returned in INFORM(1),
               return details of the factorization for use by F04MAF.

           4:  LICN -- INTEGER                                        Input
               On entry:
               the dimension of the array A as declared in the (sub)program
               from which F01MAF is called.
               If fill-in is expected during the factorization, then a
               larger value of LICN will allow fewer elements to be dropped
               during the factorization, thus giving a more accurate
               factorization, which in turn will almost certainly mean that
               fewer iterations will be required by F04MAF. Constraint:
               LICN>=2*NZ.

           5:  IRN(LIRN) -- INTEGER array                      Input/Output
               On entry: IRN(k), for k = 1,2,...,NZ must contain the row
               index of the non-zero element of the matrix A supplied in A
               (k). On exit: the first LCOL elements of IRN, where LCOL is
               the value returned in INFORM(2), return details of the
               factorization for use by F04MAF.

           6:  LIRN -- INTEGER                                        Input
               On entry:
               the dimension of the array IRN as declared in the
               (sub)program from which F01MAF is called.
               LIRN must be at least NZ, but, as with LICN, if fill-in is
               expected then a larger value of LIRN will allow a more
               accurate factorization. For this purpose LIRN should exceed
               NZ by the same amount that LICN exceeds 2*NZ. Constraint:
               LIRN >= NZ.

           7:  ICN(LICN) -- INTEGER array                      Input/Output
               On entry: ICN(k), for k = 1,2,...,NZ must contain the column
               index of the non-zero element of the matrix A supplied in A
               (k). Thus a  =A(k), where i = IRN(k) and j = ICN(k). On
                          ij
               exit: the first (NZ-N) elements of ICN give the column
               indices of the first (NZ-N) elements returned in A. The
               remaining LROW - NZ + N elements of ICN return details of
               the factorization for use by F04MAF.

           8:  DROPTL -- DOUBLE PRECISION                      Input/Output
               On entry: a value in the range [-1.0,1.0] to be used as a
               tolerance in deciding whether or not to drop elements during
                                                                     (k+1)
               the factorization. At the kth pivot step the element a
                                                                     ij
               is dropped if it would cause fill-in and if
                                                   

                               (k+1)              / (k) (k)
                             |a     |<|DROPTL|*  / a   a   .
                               ij              \/   ii  jj
               If DROPTL is supplied as negative, then it is not altered
               during the factorization and so is unchanged on exit, but if
               DROPTL is supplied as positive then it may be altered by the
               routine with the aim of obtaining an accurate factorization
               in the space available. If DROPTL is supplied as -1.0, then
               no fill-in will occur during the factorization; and if
               DROPTL is supplied as 0.0 then a complete factorization is
               performed. On exit: may be overwritten with the value used
               by the routine in order to obtain an accurate factorization
               in the space available, if DROPTL > 0.0 on entry.

           9:  DENSW -- DOUBLE PRECISION                       Input/Output
               On entry: a value in the range [0.0,1.0] to be used in
               deciding whether or not to regard the active part of the
               matrix at the kth pivot step as being full. If the ratio of
               non-zero elements to the total number of elements is greater
               than or equal to DENSW, then the active part is regarded as
               full. If DENSW < 1.0, then the storage used is likely to
               increase compared to the case where DENSW = 0, but the
               execution time is likely to decrease. Suggested value: DENSW
               = 0.8. On exit: if on entry DENSW is not in the range
               [0.0,1.0], then it is set to 0.8. Otherwise it is unchanged.

          10:  WKEEP(3*N) -- DOUBLE PRECISION array                  Output
               On exit: information which must be passed unchanged to
               F04MAF. The first N elements contain the values w , for
                                                                i
               i=1,2,...,n, and the next N elements contain the diagonal
               elements of D.

          11:  IKEEP(2*N) -- INTEGER array                           Output
               On exit: information which must be passed unchanged to
               F04MAF.

          12:  IWORK(6*N) -- INTEGER array                        Workspace

          13:  ABORT(3) -- LOGICAL array                              Input
               On entry:
                    if ABORT(1) = .TRUE., the routine will exit
                    immediately on detecting duplicate elements and return
                    IFAIL = 5. Otherwise when ABORT(1) = .FALSE., the
                    calculations will continue using the sum of the
                    duplicate entries. In either case details of the
                    duplicate elements are output on the current advisory
                    message unit (see X04ABF), unless suppressed by the
                    value of IFAIL on entry.

                    If ABORT(2) = .TRUE., the routine will exit
                    immediately on detecting a zero or negative pivot
                    element and return IFAIL = 6. Otherwise when ABORT(2)
                    = .FALSE., the zero or negative pivot element will be
                    modified to ensure positive-definiteness and a message
                    will be printed on the current advisory message unit,
                    unless suppressed by the value of IFAIL on entry.

                    If ABORT(3) = .TRUE., the routine will exit
                    immediately if the arrays A and ICN have been filled
                    up and return IFAIL = 7. Otherwise when ABORT(3) = .
                    FALSE., the data in the arrays is compressed to
                    release more storage and a message will be printed on
                    the current advisory message unit, unless suppressed
                    by the value of IFAIL on entry. If DROPTL is positive
                    on entry, it may be modified in order to allow a
                    factorization to be completed in the available space.
               Suggested values:
                    ABORT(1) = .TRUE.,

                    ABORT(2) = .TRUE.,

                    ABORT(3) = .TRUE..

          14:  INFORM(4) -- INTEGER array                            Output
               On exit:
                    INFORM(1) returns the number of elements of A and ICN
                    that have been used by the routine. Thus at least the
                    first INFORM(1) elements of A and of ICN must be
                    supplied to F04MAF.

                    Similarly, INFORM(2) returns the number of elements of
                    IRN that have been used by the routine and so at least
                    the first INFORM(2) elements must be supplied to
                    F04MAF.

                    INFORM(3) returns the number of entries supplied in A
                    that corresponded to diagonal and duplicate elements.
                    If no duplicate entries were found, then INFORM(3)
                    will return the value of N.

                    INFORM(4) returns the value k of the pivot step from
                    which the active matrix was regarded as full.
               INFORM must be passed unchanged to F04MAF.

          15:  IFAIL -- INTEGER                                Input/Output
               For this routine, the normal use of IFAIL is extended to
               control the printing of error and warning messages as well
               as specifying hard or soft failure (see the Essential
               Introduction).

               Before entry, IFAIL must be set to a value with the decimal
               expansion cba, where each of the decimal digits c, b and a
               must have a value of 0 or 1.
               a=0   specifies hard failure, otherwise soft failure;

               b=0   suppresses error messages, otherwise error messages
                     will be printed (see Section 6);

               c=0   suppresses warning messages, otherwise warning
                     messages will be printed (see Section 6).
               The recommended value for inexperienced users is 110 (i.e.,
               hard failure with all messages printed).

               Unless the routine detects an error (see Section 6), IFAIL
               contains 0 on exit.

          6. Error Indicators and Warnings

          Errors detected by the routine:

          For each error, an explanatory error message is output on the
          current error message unit (as defined by X04AAF), unless
          suppressed by the value of IFAIL on entry.

          IFAIL= 1
               On entry N < 1,

               or       NZ < N,

               or       LIRN < NZ,

               or       LICN<2*NZ.

          IFAIL= 2
               One of the conditions 0 < IRN(k) <= ICN(k) <= N is not
               satisfied so that A(k) is not in the upper triangle of the
               matrix. No further computation is attempted.

          IFAIL= 3
               One of the diagonal elements of the matrix A is zero or
               negative so that A is not positive-definite. No further
               computation is attempted.

          IFAIL= 4
               The available space has been used and no further
               compressions are possible. The user should either increase
               DROPTL, or allocate more space to A, IRN and ICN.

               For all the remaining values of IFAIL the computations will
               continue in the case of soft failure, so that more than one
               advisory message may be printed.

          IFAIL= 5
               Duplicate elements have been detected and ABORT(1) = .TRUE..

          IFAIL= 6
               A zero or negative pivot element has been detected during
               the factorization and ABORT(2) = .TRUE..

               This should not happen if A is an M-matrix (see Munksgaard
               [1]), but may occur for other types of positive-definite
               matrix.

          IFAIL= 7
               The available space has been used and ABORT(3) = .TRUE..

          7. Accuracy

          The accuracy of the factorization will be determined by the size
          of the elements that are dropped and the size of the
          modifications made to the diagonal elements. If these sizes are
          small then the computed factors will correspond to a matrix close
          to A and the number of iterations required by F04MAF will be
          small. The more incomplete the factorization, the higher the
          number of iterations required by F04MAF.

          8. Further Comments

          The time taken by the routine will depend upon the sparsity
          pattern of the matrix and the number of fill-ins that occur
          during the factorization. At the very least the time taken can be
          expected to be roughly proportional to n(tau), where (tau) is the
          number of non-zeros.
          The routine is intended for use with positive-definite matrices,
          but the user is warned that it will not necessarily detect non-
          positive-definiteness. Indeed the routine may return a
          factorization that can satisfactorily be used by F04MAF even when
          A is not positive-definite, but this should not be relied upon as
          F04MAF may not converge.

          9. Example

          The example program illustrates the use of F01MAF in conjunction
          with F04MAF to solve the 16 linear equations Ax=b, where

                          (1 z     z                      )
                          (z 1 z     z                    )
                          (  z 1 z     z                  )
                          (    z 1 0     z                )
                          (z     0 1 z     z              )
                          (  z     z 1 z     z            )
                          (    z     z 1 z     z          )
                          (      z     z 1 0     z        )
                        A=(        z     0 1 z     z      ).
                          (          z     z 1 z     z    )
                          (            z     z 1 z     z  )
                          (              z     z 1 0     z)
                          (                z     0 1 z    )
                          (                  z     z 1 z  )
                          (                    z     z 1 z)
                          (                      z     z 1)

           T ( 1  1  1  1  1      1  1      1  1  1  1  1)
          b =( -  -  -  -  - 0 0  -  - 0 0  -  -  -  -  -),
             ( 2  4  4  2  4      4  4      4  2  4  4  2)

                    1
          where z=- -.
                    4

          The n by n matrix A arises in the solution of Laplace's equation
          in a unit square, using a 5-point formula with a 6 by 6
          discretisation, with unity on the boundaries.

          The drop tolerance, DROPTL, is taken as 0.1, and the density
          factor, DENSW, is taken as 0.8. The value IFAIL = 111 is used so
          that advisory and error messages will be printed, but soft
          failure would occur if IFAIL were returned as non-zero.

          A relative accuracy of about 0.0001 is requested in the solution
          from F04MAF, with a maximum of 50 iterations.

          The example program for F02FJF illustrates the use of F01MAF and
          F04MAF in solving an eigenvalue problem.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf01mcf}{nagf.ht}
{ Cholesky factor of a symmetric positive-definite matrix}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf01mcf}{NAG Documentation: f01mcf}
\beginscroll
\begin{verbatim}



     F01MCF(3NAG)      Foundation Library (12/10/92)      F01MCF(3NAG)



          F01 -- Matrix Factorizations                               F01MCF
                  F01MCF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F01MCF computes the Cholesky factorization of a real symmetric
          positive-definite variable-bandwidth matrix.

          2. Specification

                 SUBROUTINE F01MCF (N, A, LAL, NROW, AL, D, IFAIL)
                 INTEGER          N, LAL, NROW(N), IFAIL
                 DOUBLE PRECISION A(LAL), AL(LAL), D(N)

          3. Description

          This routine determines the unit lower triangular matrix L and
                                                                   T
          the diagonal matrix D in the Cholesky factorization A=LDL  of a
          symmetric positive-definite variable-bandwidth matrix A of order
          n. (Such a matrix is sometimes called a 'sky-line' matrix.)

          The matrix A is represented by the elements lying within the
          envelope of its lower triangular part, that is, between the first
          non-zero of each row and the diagonal (see Section 9 for an
          example). The width NROW(i) of the ith row is the number of
          elements between the first non-zero element and the element on
          the diagonal, inclusive. Although, of course, any matrix
          possesses an envelope as defined, this routine is primarily
          intended for the factorization of symmetric positive-definite
          matrices with an average bandwidth which is small compared with n
          (also see Section 8).

          The method is based on the property that during Cholesky
          factorization there is no fill-in outside the envelope.

          The determination of L and D is normally the first of two steps
          in the solution of the system of equations Ax=b. The remaining
                                        T
          step, viz. the solution of LDL x=b may be carried out using
          F04MCF.

          4. References

          [1]   Jennings A (1966) A Compact Storage Scheme for the Solution
                of Symmetric Linear Simultaneous Equations. Comput. J. 9
                281--285.

          [2]   Wilkinson J H and Reinsch C (1971) Handbook for Automatic
                Computation II, Linear Algebra. Springer-Verlag.

          5. Parameters

           1:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A. Constraint: N >= 1.

           2:  A(LAL) -- DOUBLE PRECISION array                       Input
               On entry: the elements within the envelope of the lower
               triangle of the positive-definite symmetric matrix A, taken
               in row by row order. The following code assigns the matrix
               elements within the envelope to the correct elements of the
               array:

                     K = 0
                     DO 20 I = 1, N
                     DO 10 J = I-NROW(I)+1, I
                     K = K + 1
                     A(K) = matrix (I,J)
                     10    CONTINUE
                     20 CONTINUE

               See also Section 8.

           3:  LAL -- INTEGER                                         Input
               On entry: the smaller of the dimensions of the arrays A and
               AL as declared in the calling (sub)program from which F01MCF
               is called. Constraint: LAL >= NROW(1) + NROW(2) +... + NROW(
               n).

           4:  NROW(N) -- INTEGER array                               Input
               On entry: NROW(i) must contain the width of row i of the
               matrix A, i.e., the number of elements between the first
               (leftmost) non-zero element and the element on the diagonal,
               inclusive. Constraint: 1 <= NROW(i) <= i, for i=1,2,...,n.

           5:  AL(LAL) -- DOUBLE PRECISION array                     Output
               On exit: the elements within the envelope of the lower
               triangular matrix L, taken in row by row order. The envelope
               of L is identical to that of the lower triangle of A. The
               unit diagonal elements of L are stored explicitly. See also
               Section 8.

           6:  D(N) -- DOUBLE PRECISION array                        Output
               On exit: the diagonal elements of the the diagonal matrix D
               . Note that the determinant of A is equal to the product of
               these diagonal elements. If the value of the determinant is
               required it should not be determined by forming the product
               explicitly, because of the possibility of overflow or
               underflow. The logarithm of the determinant may safely be
               formed from the sum of the logarithms of the diagonal
               elements.

           7:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               On entry N < 1,

               or       for some i, NROW(i) < 1 or NROW(i) > i,

               or       LAL < NROW(1) + NROW(2) +... + NROW(N).

          IFAIL= 2
               A is not positive-definite, or this property has been
               destroyed by rounding errors. The factorization has not been
               completed.

          IFAIL= 3
               A is not positive-definite, or this property has been
               destroyed by rounding errors. The factorization has been
               completed but may be very inaccurate (see Section 7).

          7. Accuracy

          If IFAIL = 0 on exit, then the computed L and D satisfy the
                      T
          relation LDL =A+F, where

                                        2
                              ||F|| <=km (epsilon)max a
                                   2                 i ii

          and

                                       2
                             ||F|| <=km (epsilon)||A|| ,
                                  2                   2

          where k is a constant of order unity, m is the largest value of
          NROW(i), and (epsilon) is the machine precision. See Wilkinson
          and Reinsch [2], pp 25--27, 54--55. If IFAIL = 3 on exit, then
          the factorization has been completed although the matrix was not
          positive-definite. However the factorization may be very
          inaccurate and should be used only with great caution. For
          instance, if it is used to solve a set of equations Ax=b using
          F04MCF, the residual vector b-Ax should be checked.

          8. Further Comments

          The time taken by the routine is approximately proportional to
          the sum of squares of the values of NROW(i).

          The distribution of row widths may be very non-uniform without
          undue loss of efficiency. Moreover, the routine has been designed
          to be as competitive as possible in speed with routines designed
          for full or uniformly banded matrices, when applied to such
          matrices.

          Unless otherwise stated in the Users' Note for your
          implementation, the routine may be called with the same actual
          array supplied for parameters A and AL, in which case L
          overwrites the lower triangle of A. However this is not standard
          Fortran 77 and may not work in all implementations.

          9. Example

          To obtain the Cholesky factorization of the symmetric matrix,
          whose lower triangle is:

                                 (1               )
                                 (2  5            )
                                 (0  3 13         )
                                 (0  0  0 16      ).
                                 (5 14 18  8 55   )
                                 (0  0  0 24 17 77)

          For this matrix, the elements of NROW must be set to 1, 2, 2, 1,
          5, 3, and the elements within the envelope must be supplied in
          row order as:

          1, 2, 5, 3, 13, 16, 5, 14, 18, 8, 55, 24, 17, 77.


          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf01qcf}{nagf.ht}
{ QR factorization of the real m by n matrix A}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf01qcf}{NAG Documentation: f01qcf}
\beginscroll
\begin{verbatim}



     F01QCF(3NAG)      Foundation Library (12/10/92)      F01QCF(3NAG)



          F01 -- Matrix Factorizations                               F01QCF
                  F01QCF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F01QCF finds the QR factorization of the real m by n matrix A,
          where m>=n.

          2. Specification

                 SUBROUTINE F01QCF (M, N, A, LDA, ZETA, IFAIL)
                 INTEGER          M, N, LDA, IFAIL
                 DOUBLE PRECISION A(LDA,*), ZETA(*)

          3. Description

          The m by n matrix A is factorized as

                    (R)
                 A=Q(0)       when m>n,

                 A=QR         when m=n,

          where Q is an m by m orthogonal matrix and R is an n by n upper
          triangular matrix. The factorization is obtained by Householder's
          method. The kth transformation matrix, Q , which is used to
                                                  k
          introduce zeros into the kth column of A is given in the form

                                         (I 0 )
                                      Q =(0 T )
                                       k (   k)

          where

                                             T
                                     T =I-u u ,
                                      k    k k

                                       ((zeta) )
                                       (      k)
                                    u =(z      ),
                                     k ( k     )

          (zeta)  is a scalar and z  is an (m-k) element vector. (zeta)
                k                  k                                   k
          and z  are chosen to annihilate the elements below the triangular
               k
          part of A.

          The vector u  is returned in the kth element of the array ZETA
                      k
          and in the kth column of A, such that (zeta)  is in ZETA(k) and
                                                      k
          the elements of z  are in A(k+1,k),...,A(m,k). The elements of R
                           k
          are returned in the upper triangular part of A.

          Q is given by

                                                 T
                                  Q=(Q Q   ...Q ) .
                                      n n-1    1

          Good background descriptions to the QR factorization are given in
          Dongarra et al [1] and Golub and Van Loan [2], but note that this
          routine is not based upon LINPACK routine DQRDC.

          4. References

          [1]   Dongarra J J, Moler C B, Bunch J R and Stewart G W (1979)
                LINPACK Users' Guide. SIAM, Philadelphia.

          [2]   Golub G H and Van Loan C F (1989) Matrix Computations (2nd
                Edition). Johns Hopkins University Press, Baltimore,
                Maryland.

          [3]   Wilkinson J H (1965) The Algebraic Eigenvalue Problem.
                Oxford University Press.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: m, the number of rows of A. Constraint: M >= N.

           2:  N -- INTEGER                                           Input
               On entry: n, the number of columns of A.

               When N = 0 then an immediate return is effected.
               Constraint: N >= 0.

           3:  A(LDA,*) -- DOUBLE PRECISION array              Input/Output
               Note: the second dimension of the array A must be at least
               max(1,n).
               On entry: the leading m by n part of the array A must
               contain the matrix to be factorized. On exit: the n by n
               upper triangular part of A will contain the upper triangular
               matrix R and the m by n strictly lower triangular part of A
               will contain details of the factorization as described in
               Section 3.

           4:  LDA -- INTEGER                                         Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F01QCF is called.
               Constraint: LDA >= max(1,M).

           5:  ZETA(*) -- DOUBLE PRECISION array                     Output
               Note: the dimension of the array ZETA must be at least max
               (1,n) On exit: ZETA(k) contains the scalar (zeta)  for the k
                                                                k
               th transformation. If T =I then ZETA(k)=0.0, otherwise ZETA(
                                      k
               k) contains (zeta)  as described in Section 3 and (zeta)  is
                                 k                                     k

               always in the range (1.0, \/2.0).

           6:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL=-1
               On entry M < N,

               or       N < 0,

               or       LDA < M.

          7. Accuracy

          The computed factors Q and R satisfy the relation

                                       (R)
                                      Q(0)=A+E,

          where

                             |||E|||<=c(epsilon)|||A|||,

          and (epsilon) is the machine precision (see X02AJF(*)), c is a
          modest function of m and n and |||.||| denotes the spectral (two)
          norm.

          8. Further Comments

          The approximate number of floating-point operations is given by
            2
          2n (3m-n)/3.

          Following the use of this routine the operations

                                                 T
                                 B:=QB  and  B:=Q B,

          where B is an m by k matrix, can be performed by calls to F01QDF.
          The operation B:=QB can be obtained by the call:


                IFAIL = 0
                CALL F01QDF('No transpose', 'Separate', M, N, A, LDA, ZETA,
               *            K, B, LDB, WORK, IFAIL)

                  T
          and B:=Q B can be obtained by the call:


                IFAIL = 0
                CALL F01QDF('Transpose', 'Separate', M, N, A, LDA, ZETA,
               *            K, B, LDB, WORK, IFAIL)

          In both cases WORK must be a k element array that is used as
          workspace. If B is a one-dimensional array (single column) then
          the parameter LDB can be replaced by M. See F01QDF for further
          details.

          The first k columns of the orthogonal matrix Q can either be
          obtained by setting B to the first k columns of the unit matrix
          and using the first of the above two calls, or by calling F01QEF,
          which overwrites the k columns of Q on the first k columns of the
          array A. Q is obtained by the call:


               CALL F01QEF('Separate', M, N, K, A, LDA, ZETA, WORK, IFAIL)

          As above WORK must be a k element array. If k is larger than N,
          then A must have been declared to have at least k columns.

          Operations involving the matrix R can readily be performed by the
          Level 2 BLAS routines DTRSV and DTRMV (see Chapter F06), but note
          that no test for near singularity of R is incorporated in DTRSV.
          If R is singular, or nearly singular then F02WUF(*) can be used
          to determine the singular value decomposition of R.

          9. Example

          To obtain the QR factorization of the 5 by 3 matrix

                                   (2.0  2.5  2.5)
                                   (2.0  2.5  2.5)
                                 A=(1.6 -0.4  2.8).
                                   (2.0 -0.5  0.5)
                                   (1.2 -0.3 -2.9)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf01qdf}{nagf.ht}{ $B:=QB$ or $B:=Q^T B$}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf01qdf}{NAG Documentation: f01qdf}
\beginscroll
\begin{verbatim}



     F01QDF(3NAG)      Foundation Library (12/10/92)      F01QDF(3NAG)



          F01 -- Matrix Factorizations                               F01QDF
                  F01QDF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F01QDF performs one of the transformations

                                               T
                                  B:=QB or B:=Q B,

          where B is an m by ncolb real matrix and Q is an m by m
          orthogonal matrix, given as the product of Householder
          transformation matrices.

          This routine is intended for use following F01QCF or F01QFF(*).

          2. Specification

                 SUBROUTINE F01QDF (TRANS, WHERET, M, N, A, LDA, ZETA,
                1                   NCOLB, B, LDB, WORK, IFAIL)
                 INTEGER          M, N, LDA, NCOLB, LDB, IFAIL
                 DOUBLE PRECISION A(LDA,*), ZETA(*), B(LDB,*), WORK(*)
                 CHARACTER*1      TRANS, WHERET

          3. Description

          Q is assumed to be given by

                                                 T
                                  Q=(Q Q   ...Q ) ,
                                      n n-1    1

          Q  being given in the form
           k

                                         (I 0 )
                                      Q =(0 T )
                                       k (   k)

          where

                                             T
                                     T =I-u u ,
                                      k    k k

                                       ((zeta) )
                                       (      k)
                                    u =(z      ),
                                     k ( k     )

          (zeta)  is a scalar and z  is an (m-k) element vector. z  must be
                k                  k                              k
          supplied in the kth column of A in elements A(k+1,k),...,A(m,k)
          and (zeta)  must be supplied either in A(k,k) or in ZETA(k),
                    k
          depending upon the parameter WHERET.

          To obtain Q explicitly B may be set to I and pre-multiplied by Q.
                                                 T
          This is more efficient than obtaining Q .

          4. References

          [1]   Golub G H and Van Loan C F (1989) Matrix Computations (2nd
                Edition). Johns Hopkins University Press, Baltimore,
                Maryland.

          [2]   Wilkinson J H (1965) The Algebraic Eigenvalue Problem.
                Oxford University Press.

          5. Parameters

           1:  TRANS -- CHARACTER*1                                   Input
               On entry: the operation to be performed as follows:
               TRANS = 'N' (No transpose)
                     Perform the operation B:=QB.

               TRANS = 'T' or 'C' (Transpose)
                                               T
                     Perform the operation B:=Q B.
                Constraint: TRANS must be one of 'N', 'T' or 'C'.

           2:  WHERET -- CHARACTER*1                                  Input
               On entry: indicates where the elements of (zeta) are to be
               found as follows:
               WHERET = 'I' (In A)
                     The elements of (zeta) are in A.

               WHERET = 'S' (Separate)
                     The elements of (zeta) are separate from A, in ZETA.
               Constraint: WHERET must be one of 'I' or 'S'.

           3:  M -- INTEGER                                           Input
               On entry: m, the number of rows of A. Constraint: M >= N.

           4:  N -- INTEGER                                           Input
               On entry: n, the number of columns of A.

               When N = 0 then an immediate return is effected.
               Constraint: N >= 0.

           5:  A(LDA,*) -- DOUBLE PRECISION array                     Input
               Note: the second dimension of the array A must be at least
               max(1,N).
               On entry: the leading m by n strictly lower triangular part
               of the array A must contain details of the matrix Q. In
               addition, when WHERET = 'I', then the diagonal elements of A
               must contain the elements of (zeta) as described under the
               argument ZETA below.

               When WHERET = 'S', the diagonal elements of the array A are
               referenced, since they are used temporarily to store the
               (zeta) , but they contain their original values on return.
                     k

           6:  LDA -- INTEGER                                         Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F01QDF is called.
               Constraint: LDA >= max(1,M).

           7:  ZETA(*) -- DOUBLE PRECISION array                      Input
               Note: when WHERET = 'S', the dimension of the array ZETA
               must be greater than or equal to max(1,N). On entry: if
               WHERET = 'S', the array ZETA must contain the elements of
               (zeta). If ZETA(k) = 0.0 then T  is assumed to be I
                                              k
               otherwise ZETA(k) is assumed to contain (zeta) .
                                                             k

               When WHERET = 'I', ZETA is not referenced.

           8:  NCOLB -- INTEGER                                       Input
               On entry: ncolb, number of columns of B.

               When NCOLB = 0 then an immediate return is effected.
               Constraint: NCOLB >= 0.

           9:  B(LDB,*) -- DOUBLE PRECISION array              Input/Output
               Note: the second dimension of the array B must be at least
               max(1,NCOLB).
               On entry: the leading m by ncolb part of the array B must
               contain the matrix to be transformed. On exit: B is
               overwritten by the transformed matrix.

          10:  LDB -- INTEGER                                         Input
               On entry:
               the first dimension of the array B as declared in the
               (sub)program from which F01QDF is called.
               Constraint: LDB >= max(1,M).

          11:  WORK(*) -- DOUBLE PRECISION array                  Workspace
               Note: the dimension of the array WORK must be at least
               max(1,NCOLB).

          12:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL=-1
               On entry TRANS /= 'N', 'T' or 'C',

               or       WHERET /= 'I' or 'S',

               or       M < N,

               or       N < 0,

               or       LDA < M,

               or       NCOLB < 0,

               or       LDB < M.

          7. Accuracy

                                                T
          Letting C denote the computed matrix Q B, C satisfies the
          relation

                                       QC=B+E,

          where

                               ||E||<=c(epsilon)||B||,

          and (epsilon) the machine precision (see X02AJF(*)), c is a
          modest function of m and |||.||| denotes the spectral (two) norm.
          An equivalent result holds for the computed matrix QB. See also
          Section 7 of F01QCF.

          8. Further Comments

          The approximate number of floating-point operations is given by
          2n(2m-n)ncolb.

          9. Example

                                T
          To obtain the matrix Q B for the matrix B given by

                                     ( 1.1  0.00)
                                     ( 0.9  0.00)
                                   B=( 0.6  1.32)
                                     ( 0.0  1.10)
                                     (-0.8 -0.26)

          following the QR factorization of the 5 by 3 matrix A given by

                                   (2.0  2.5  2.5)
                                   (2.0  2.5  2.5)
                                 A=(1.6 -0.4  2.8).
                                   (2.0 -0.5  0.5)
                                   (1.2 -0.3 -2.9)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf01qef}{nagf.ht}
{ First ncolq columns of the real m by m orthogonal matrix}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf01qef}{NAG Documentation: f01qef}
\beginscroll
\begin{verbatim}



     F01QEF(3NAG)      Foundation Library (12/10/92)      F01QEF(3NAG)



          F01 -- Matrix Factorizations                               F01QEF
                  F01QEF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F01QEF returns the first ncolq columns of the real m by m
          orthogonal matrix Q, where Q is given as the product of
          Householder transformation matrices.

          This routine is intended for use following F01QCF or F01QFF(*).

          2. Specification

                 SUBROUTINE F01QEF (WHERET, M, N, NCOLQ, A, LDA, ZETA,
                1                   WORK, IFAIL)
                 INTEGER          M, N, NCOLQ, LDA, IFAIL
                 DOUBLE PRECISION A(LDA,*), ZETA(*), WORK(*)
                 CHARACTER*1      WHERET

          3. Description

          Q is assumed to be given by

                                                 T
                                  Q=(Q Q   ...Q ) ,
                                      n n-1    1

          Q  being given in the form
           k

                                         (I 0 )
                                      Q =(0 T )
                                       k (   k)

          where

                                             T
                                     T =I-u u ,
                                      k    k k

                                       ((zeta) )
                                       (      k)
                                    u =(z      ),
                                     k ( k     )

          (zeta)  is a scalar and z  is an (m-k) element vector. z  must be
                k                  k                              k
          supplied in the kth column of A in elements A(k+1,k),...,A(m,k)
          and (zeta)  must be supplied either in A(k,k) or in ZETA(k),
                    k
          depending upon the parameter WHERET.

          4. References

          [1]   Golub G H and Van Loan C F (1989) Matrix Computations (2nd
                Edition). Johns Hopkins University Press, Baltimore,
                Maryland.

          [2]   Wilkinson J H (1965) The Algebraic Eigenvalue Problem.
                Oxford University Press.

          5. Parameters

           1:  WHERET -- CHARACTER*1                                  Input
               On entry: indicates where the elements of (zeta) are to be
               found as follows:
               WHERET = 'I' (In A)
                     The elements of (zeta) are in A.

               WHERET = 'S' (Separate)
                     The elements of (zeta) are separate from A, in ZETA.
               Constraint: WHERET must be one of 'I' or 'S'.

           2:  M -- INTEGER                                           Input
               On entry: m, the number of rows of A. Constraint: M >= N.

           3:  N -- INTEGER                                           Input
               On entry: n, the number of columns of A. Constraint: N >=
               0.

           4:  NCOLQ -- INTEGER                                       Input
               On entry: ncolq, the required number of columns of Q.
               Constraint: 0 <= NCOLQ <= M.

               When NCOLQ = 0 then an immediate return is effected.

           5:  A(LDA,*) -- DOUBLE PRECISION array              Input/Output
               Note: the second dimension of the array A must be at least
               max(1,N,NCOLQ).
               On entry: the leading m by n strictly lower triangular part
               of the array A must contain details of the matrix Q. In
               addition, when WHERET = 'I', then the diagonal elements of A
               must contain the elements of (zeta) as described under the
               argument ZETA below. On exit: the first NCOLQ columns of the
               array A are overwritten by the first NCOLQ columns of the m
               by m orthogonal matrix Q. When N = 0 then the first NCOLQ
               columns of A are overwritten by the first NCOLQ columns of
               the identity matrix.

           6:  LDA -- INTEGER                                         Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F01QEF is called.
               Constraint: LDA >= max(1,M).

           7:  ZETA(*) -- DOUBLE PRECISION array                      Input
               Note: the dimension of the array ZETA must be at least
               max(1,N).
               On entry: with WHERET = 'S', the array ZETA must contain the
               elements of (zeta). If ZETA(k) = 0.0 then T  is assumed to
                                                          k
               be I, otherwise ZETA(k) is assumed to contain (zeta) .
                                                                   k

               When WHERET = 'I', the array ZETA is not referenced.

           8:  WORK(*) -- DOUBLE PRECISION array                  Workspace
               Note: the dimension of the array WORK must be at least
               max(1,NCOLQ).

           9:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL=-1
               On entry WHERET /= 'I' or 'S',

               or       M < N,

               or       N < 0,

               or       NCOLQ < 0 or NCOLQ > M,

               or       LDA < M.

          7. Accuracy

          The computed matrix Q satisfies the relation

                                       Q=P+E,

          where P is an exactly orthogonal matrix and

                                 ||E||<=c(epsilon)

          (epsilon) is the machine precision (see X02AJF(*)), c is a modest
          function of m and |||.||| denotes the spectral (two) norm. See
          also Section 7 of F01QCF.

          8. Further Comments

          The approximate number of floating-point operations required is
          given by

               2
               -n{(3m-n)(2ncolq-n)-n(ncolq-n)},    ncolq>n,
               3

               2     2
               -ncolq (3m-ncolq),                  ncolq<=n.
               3

          9. Example

          To obtain the 5 by 5 orthogonal matrix Q following the QR
          factorization of the 5 by 3 matrix A given by

                                   (2.0  2.5  2.5)
                                   (2.0  2.5  2.5)
                                 A=(1.6 -0.4  2.8).
                                   (2.0 -0.5  0.5)
                                   (1.2 -0.3 -2.9)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf01rcf}{nagf.ht}
{ QR factorization of the complex m by n matrix A}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf01rcf}{NAG Documentation: f01rcf}
\beginscroll
\begin{verbatim}



     F01RCF(3NAG)      Foundation Library (12/10/92)      F01RCF(3NAG)



          F01 -- Matrix Factorizations                               F01RCF
                  F01RCF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F01RCF finds the QR factorization of the complex m by n matrix A,
          where m>=n.

          2. Specification

                 SUBROUTINE   F01RCF (M, N, A, LDA, THETA, IFAIL)
                 INTEGER              M, N, LDA, IFAIL
                 COMPLEX(KIND(1.0D0)) A(LDA,*), THETA(*)

          3. Description

          The m by n matrix A is factorized as

                    (R)
                 A=Q(0)       when m>n,

                 A=QR         when m=n,

          where Q is an m by m unitary matrix and R is an n by n upper
          triangular matrix with real diagonal elements.

          The factorization is obtained by Householder's method. The kth
          transformation matrix, Q , which is used to introduce zeros into
                                  k
          the kth column of A is given in the form

                                        (I 0 )
                                     Q =(0 T ),
                                      k (   k)

          where

                                                 H
                                 T =I-(gamma) u u ,
                                  k          k k k

                                       ((zeta) )
                                       (      k)
                                    u =(z      ),
                                     k ( k     )

          (gamma)  is a scalar for which Re (gamma) =1.0, (zeta)  is a real
                 k                                 k            k
          scalar and z  is an (m-k) element vector. (gamma) , (zeta)  and
                      k                                    k        k
          z  are chosen to annihilate the elements below the triangular
           k
          part of A and to make the diagonal elements real.

          The scalar (gamma)  and the vector u  are returned in the kth
                            k                 k
          element of the array THETA and in the kth column of A, such that
          (theta) , given by
                 k

                           (theta) =((zeta) ,Im(gamma) ),
                                  k        k          k

          is in THETA(k) and the elements of z  are in a     ,...,a   . The
                                              k         k+1,k      m,k
          elements of R are returned in the upper triangular part of A.

          Q is given by

                                                 H
                                  Q=(Q Q   ...Q ) .
                                      n n-1    1

          A good background description to the QR factorization is given in
          Dongarra et al [1], but note that this routine is not based upon
          LINPACK routine ZQRDC.

          4. References

          [1]   Dongarra J J, Moler C B, Bunch J R and Stewart G W (1979)
                LINPACK Users' Guide. SIAM, Philadelphia.

          [2]   Wilkinson J H (1965) The Algebraic Eigenvalue Problem.
                Oxford University Press.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: m, the number of rows of A. Constraint: M >= N.

           2:  N -- INTEGER                                           Input
               On entry: n, the number of columns of A. Constraint: N >=
               0.

               When N = 0 then an immediate return is effected.

           3:  A(LDA,*) -- COMPLEX(KIND(1.0D0)) array          Input/Output
               Note: the second dimension of the array A must be at least
               max(1,N).
               On entry: the leading m by n part of the array A must
               contain the matrix to be factorized. On exit: the n by n
               upper triangular part of A will contain the upper triangular
               matrix R, with the imaginary parts of the diagonal elements
               set to zero, and the m by n strictly lower triangular part
               of A will contain details of the factorization as described
               above.

           4:  LDA -- INTEGER                                         Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F01RCF is called.
               Constraint: LDA >= max(1,M).

           5:  THETA(*) -- COMPLEX(KIND(1.0D)) array                 Output
               Note: the dimension of the array THETA must be at least
               max(1,N).
               On exit: the scalar (theta)  for the kth transformation. If
                                          k
               T =I then THETA(k) = 0.0; if
                k
                                ((alpha) 0)
                             T =(      0 I)   Re(alpha)<0.0,
                              k
               then THETA(k)=(alpha); otherwise THETA(k) contains THETA(k)
               as described in Section 3 and Re(THETA(k)) is always in the
                             

               range (1.0, \/2.0).

           6:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL=-1
               On entry M < N,

               or       N < 0,

               or       LDA < M.

          7. Accuracy
          The computed factors Q and R satisfy the relation

                                       (R)
                                      Q(0)=A+E,

          where

                             ||E||<=c(epsilon)||A||,

          (epsilon) being the machine precision, c is a modest function of
          m and n and ||.|| denotes the spectral (two) norm.

          8. Further Comments

          The approximate number of real floating-point operations is given
               2
          by 8n (3m-n)/3.

          Following the use of this routine the operations

                                                 H
                                 B:=QB  and  B:=Q B,

          where B is an m by k matrix, can be performed by calls to F01RDF.
          The operation B:=QB can be obtained by the call:


                IFAIL = 0
                CALL F01RDF(`No conjugate', 'Separate', M, N, A, LDA, THETA,
               *            K, B, LDB, WORK, IFAIL)

                  H
          and B:=Q B can be obtained by the call:


                IFAIL = 0
                CALL F01RDF(`Conjugate', 'Separate', M, N, A, LDA, THETA,
               *            K, B, LDB, WORK, IFAIL)

          In both cases WORK must be a k element array that is used as
          workspace. If B is a one-dimensional array (single column) then
          the parameter LDB can be replaced by M. See F01RDF for further
          details.

          The first k columns of the unitary matrix Q can either be
          obtained by setting B to the first k columns of the unit matrix
          and using the first of the above two calls, or by calling F01REF,
          which overwrites the k columns of Q on the first k columns of the
          array A. Q is obtained by the call:


                CALL F01REF(`Separate', M, N, K, A, LDA, THETA, WORK, IFAIL)

          As above, WORK must be a k element array. If k is larger than n,
          then A must have been declared to have at least k columns.

          Operations involving the matrix R can readily be performed by the
          Level 2 BLAS routines ZTRSV and ZTRMV (see Chapter F06), but note
          that no test for near singularity of R is incorporated in ZTRSV.
          If R is singular, or nearly singular, then F02XUF(*) can be used
          to determine the singular value decomposition of R.

          9. Example

          To obtain the QR factorization of the 5 by 3 matrix

                             (  0.5i -0.5+1.5i -1.0+1.0i)
                             (0.4+0.3i 0.9+1.3i 0.2+1.4i)
                           A=(  0.4 -0.4+0.4i    1.8    ).
                             (0.3-0.4i 0.1+0.7i    0.0  )
                             ( -0.3i 0.3+0.3i   2.4i    )

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf01rdf}{nagf.ht}{ $B:=QB$ or $B:=Q^H B$}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf01rdf}{NAG Documentation: f01rdf}
\beginscroll
\begin{verbatim}



     F01RDF(3NAG)      Foundation Library (12/10/92)      F01RDF(3NAG)



          F01 -- Matrix Factorizations                               F01RDF
                  F01RDF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F01RDF performs one of the transformations

                                               H
                                  B:=QB or B:=Q B,

          where B is an m by ncolb complex matrix and Q is an m by m
          unitary matrix, given as the product of Householder
          transformation matrices.

          This routine is intended for use following F01RCF or F01RFF(*).

          2. Specification

                 SUBROUTINE F01RDF (TRANS, WHERET, M, N, A, LDA, THETA,
                1                   NCOLB, B, LDB, WORK, IFAIL)
                 INTEGER              M, N, LDA, NCOLB, LDB, IFAIL
                 COMPLEX(KIND(1.0D0)) A(LDA,*), THETA(*), B(LDB,*), WORK(*)
                 CHARACTER*1          TRANS, WHERET

          3. Description

          The unitary matrix Q is assumed to be given by

                                                 H
                                  Q=(Q Q   ...Q ) ,
                                      n n-1    1

          Q  being given in the form
           k

                                        (I 0 )
                                     Q =(0 T ),
                                      k (   k)

          where

                                                 H
                                 T =I-(gamma) u u ,
                                  k          k k k

                                       ((zeta) )
                                       (      k)
                                    u =(z      ),
                                     k ( k     )

          (gamma)  is a scalar for which Re (gamma) =1.0, (zeta)  is a real
                 k                                 k            k
          scalar and z  is an (m-k) element vector.
                      k

          z  must be supplied in the kth column of A in elements
           k
          a     ,...,a    and (theta) , given by
           k+1,k      m,k            k

                           (theta) =((zeta) ,Im (gamma) ),
                                  k        k           k

          must be supplied either in a    or in THETA(k), depending upon
                                      k,k
          the parameter WHERET.

          To obtain Q explicitly B may be set to I and pre-multiplied by Q.
                                                 H
          This is more efficient than obtaining Q . Alternatively, F01REF
          may be used to obtain Q overwritten on A.

          4. References

          [1]   Wilkinson J H (1965) The Algebraic Eigenvalue Problem.
                Oxford University Press.

          5. Parameters

           1:  TRANS -- CHARACTER*1                                   Input
               On entry: the operation to be performed as follows:
               TRANS = 'N' (No transpose)
                     Perform the operation B:=QB.

               TRANS = 'C' (Conjugate transpose)
                                               H
                     Perform the operation B:=Q B.
               Constraint: TRANS must be one of 'N' or 'C'.

           2:  WHERET -- CHARACTER*1                                  Input
               On entry: the elements of (theta) are to be found as
               follows:
               WHERET = 'I' (In A)
                     The elements of (theta) are in A.

               WHERET = 'S' (Separate)
                     The elements of (theta) are separate from A, in THETA.
               Constraint: WHERET must be one of 'I' or 'S'.

           3:  M -- INTEGER                                           Input
               On entry: m, the number of rows of A. Constraint: M >= N.

           4:  N -- INTEGER                                           Input
               On entry: n, the number of columns of A. Constraint: N >=
               0.

               When N = 0 then an immediate return is effected.

           5:  A(LDA,*) -- COMPLEX(KIND(1.0D)) array                  Input
               Note: the second dimension of the array A must be at least
               max(1,N).
               On entry: the leading m by n strictly lower triangular part
               of the array A must contain details of the matrix Q. In
               addition, when WHERET = 'I', then the diagonal elements of A
               must contain the elements of (theta) as described under the
               argument THETA below.

               When WHERET = 'S', then the diagonal elements of the array A
               are referenced, since they are used temporarily to store the
               (zeta) , but they contain their original values on return.
                     k

           6:  LDA -- INTEGER                                         Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F01RDF is called.
               Constraint: LDA >= max(1,M).

           7:  THETA(*) -- COMPLEX(KIND(1.0D)) array                  Input
               Note: the dimension of the array THETA must be at least
               max(1,N).
               On entry: with WHERET = 'S', the array THETA must contain
               the elements of (theta). If THETA(k)=0.0 then T  is assumed
                                                              k
               to be I; if THETA(k)=(alpha), with Re(alpha)<0.0, then T  is
                                                                       k
               assumed to be of the form
                                        ((alpha) 0)
                                     T =(0       I);
                                      k
               otherwise THETA(k) is assumed to contain (theta)  given by
                                                               k
               (theta) =((zeta) ,Im(gamma) ).
                      k        k          k

               When WHERET = 'I', the array THETA is not referenced, and
               may be dimensioned of length 1.

           8:  NCOLB -- INTEGER                                       Input
               On entry: ncolb, the number of columns of B. Constraint:
               NCOLB >= 0.
               When NCOLB = 0 then an immediate return is effected.

           9:  B(LDB,*) -- COMPLEX(KIND(1.0D)) array           Input/Output
               Note: the second dimension of the array B must be at least
               max(1,NCOLB).
               On entry: the leading m by ncolb part of the array B must
               contain the matrix to be transformed. On exit: B is
               overwritten by the transformed matrix.

          10:  LDB -- INTEGER                                         Input
               On entry:
               the first dimension of the array B as declared in the
               (sub)program from which F01RDF is called.
               Constraint: LDB >= max(1,M).

          11:  WORK(*) -- COMPLEX(KIND(1.0D)) array               Workspace
               Note: the dimension of the array WORK must be at least
               max(1,NCOLB).

          12:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL=-1
               On entry TRANS /= 'N' or 'C',

               or       WHERET /= 'I' or 'S',

               or       M < N,

               or       N < 0,

               or       LDA < M,

               or       NCOLB < 0,

               or       LDB < M.

          7. Accuracy

          Letting C denote the computed matrix Q B, C satisfies the
          relation

                                       QC=B+E,

          where

                             ||E||<=c(epsilon)||B||,

          (epsilon) being the machine precision, c is a modest function of
          m and |||.||| denotes the spectral (two) norm. An equivalent
          result holds for the computed matrix QB. See also Section 7 of
          F01RCF.

          8. Further Comments

          The approximate number of real floating-point operations is given
          by 8n(2m-n)ncolb.

          9. Example

                                H
          To obtain the matrix Q B for the matrix B given by

                               (-0.55+1.05i  0.45+1.05i)
                               ( 0.49+0.93i  1.09+0.13i)
                             B=( 0.56-0.16i  0.64+0.16i)
                               ( 0.39+0.23i -0.39-0.23i)
                               ( 1.13+0.83i -1.13+0.77i)

          following the QR factorization of the 5 by 3 matrix A given by

                             (  0.5i   -0.5+1.5i -1.0+1.0i)
                             (0.4+0.3i  0.9+1.3i  0.2+1.4i)
                           A=(  0.4    -0.4+0.4i  1.8     ).
                             (0.3-0.4i  0.1+0.7i  0.0     )
                             ( -0.3i    0.3+0.3i      2.4i)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf01ref}{nagf.ht}
{ First ncolq columns of the complex m by m unitary matrix}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf01ref}{NAG Documentation: f01ref}
\beginscroll
\begin{verbatim}



     F01REF(3NAG)      Foundation Library (12/10/92)      F01REF(3NAG)



          F01 -- Matrix Factorizations                               F01REF
                  F01REF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F01REF returns the first ncolq columns of the complex m by m
          unitary matrix Q, where Q is given as the product of Householder
          transformation matrices.

          This routine is intended for use following F01RCF.

          2. Specification

                 SUBROUTINE F01REF (WHERET, M, N, NCOLQ, A, LDA, THETA,
                1                   WORK, IFAIL)
                 INTEGER              M, N, NCOLQ, LDA, IFAIL
                 COMPLEX(KIND(1.0D0)) A(LDA,*), THETA(*), WORK(*)
                 CHARACTER*1          WHERET

          3. Description

          The unitary matrix Q is assumed to be given by

                                                 H
                                  Q=(Q Q   ...Q ) ,
                                      n n-1    1

          Q  being given in the form
           k

                                        (I 0 )
                                     Q =(0 T ),
                                      k (   k)

          where

                                                 H
                                 T =I-(gamma) u u ,
                                  k          k k k

                                       ((zeta) )
                                       (      k)
                                    u =(z      ),
                                     k ( k     )

          (gamma)  is a scalar for which Re (gamma) =1.0, (zeta)  is a real
                 k                                 k            k

          scalar and z  is an (m-k) element vector.
                      k

          z  must be supplied in the kth column of A in elements
           k
          a     ,...,a    and (theta) , given by
           k+1,k      m,k            k

                           (theta) =((zeta) ,Im (gamma) ),
                                  k        k           k

          must be supplied either in a    or in THETA(k) depending upon the
                                      k,k
          parameter WHERET.

          4. References

          [1]   Wilkinson J H (1965) The Algebraic Eigenvalue Problem.
                Oxford University Press.

          5. Parameters

           1:  WHERET -- CHARACTER*1                                  Input
               On entry: the elements of (theta) are to be found as
               follows:
               WHERET = 'I' (In A)
                     The elements of (theta) are in A.

               WHERET = 'S' (Separate)
                     The elements of (theta) are separate from A, in THETA.
               Constraint: WHERET must be one of 'I' or 'S'.

           2:  M -- INTEGER                                           Input
               On entry: m, the number of rows of A. Constraint: M >= N.

           3:  N -- INTEGER                                           Input
               On entry: n, the number of columns of A. Constraint: N >=
               0.

           4:  NCOLQ -- INTEGER                                       Input
               On entry: ncolq, the required number of columns of Q.
               Constraint: 0 <= NCOLQ <= M.

               When NCOLQ = 0 then an immediate return is effected.

           5:  A(LDA,*) -- COMPLEX(KIND(1.0D)) array           Input/Output
               Note: the second dimension of the array A must be at least
               max(1,N,NCOLQ).
               On entry: the leading m by n strictly lower triangular part
               of the array A must contain details of the matrix Q. In
               addition, when WHERET = 'I', then the diagonal elements of A
               must contain the elements of (theta) as described under the
               argument THETA below. On exit: the first NCOLQ columns of
               the array A are overwritten by the first NCOLQ columns of
               the m by m unitary matrix Q. When N = 0 then the first NCOLQ
               columns of A are overwritten by the first NCOLQ columns of
               the unit matrix.

           6:  LDA -- INTEGER                                         Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F01REF is called.
               Constraint: LDA >= max(1,M).

           7:  THETA(*) -- COMPLEX(KIND(1.0D)) array                  Input
               Note: the dimension of the array THETA must be at least
               max(1,N).
               On entry: if WHERET = 'S', the array THETA must contain the
               elements of (theta). If THETA(k)=0.0 then T  is assumed to
                                                          k
               be I; if THETA(k)=(alpha), with Re(alpha)<0.0, then T  is
                                                                    k
               assumed to be of the form
                                        ((alpha) 0)
                                     T =(   0    I);
                                      k
               otherwise THETA(k) is assumed to contain (theta)  given by
                                                               k
               (theta) =((zeta) ,Im(gamma) ).
                      k        k          k

               When WHERET = 'I', the array THETA is not referenced.

           8:  WORK(*) -- COMPLEX(KIND(1.0D)) array               Workspace
               Note: the dimension of the array WORK must be at least
               max(1,NCOLQ).

           9:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL=-1
               On entry WHERET /= 'I' or 'S',

               or       M < N,

               or       N < 0,

               or       NCOLQ < 0 or NCOLQ > M,

               or       LDA < M.

          7. Accuracy

          The computed matrix Q satisfies the relation

                                       Q=P+E,

          where P is an exactly unitary matrix and

                                ||E||<=c(epsilon),

          (epsilon) being the machine precision, c is a modest function of
          m and |||.||| denotes the spectral (two) norm. See also Section 7
          of F01RCF.

          8. Further Comments

          The approximate number of real floating-point operations required
          is given by

               8
               -n{(3m-n)(2ncolq-n)-n(ncolq-n)},  ncolq>n
               3

               8     2
               -ncolq (3m-ncolq),                ncolq<=n
               3

          9. Example

          To obtain the 5 by 5 unitary matrix Q following the QR
          factorization of the 5 by 3 matrix A given by

                             (    0.5i -0.5+1.5i -1.0+1.4i)
                             (0.4+0.3i  0.9+1.3i  0.2+1.4i)
                           A=(0.4      -0.4+0.4i  1.8     ).
                             (0.3-0.4i  0.1+0.7i  0.0     )
                             (   -0.3i  0.3+0.3i      2.4i)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf02}{nagf.ht}{ Eigenvalues and Eigenvectors}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf02}{NAG Documentation: f02}
\beginscroll
\begin{verbatim}



     F02(3NAG)         Foundation Library (12/10/92)         F02(3NAG)



          F02 -- Eigenvalues and Eigenvectors           Introduction -- F02
                                    Chapter F02
                           Eigenvalues and Eigenvectors

          1. Scope of the Chapter

          This chapter is concerned with computing

          --    eigenvalues and eigenvectors of a matrix

          --    eigenvalues and eigenvectors of generalized matrix
                eigenvalue problems

          --    singular values and singular vectors of a matrix.

          2. Background to the Problems

          2.1. Eigenvalue Problems

          In the most usual form of eigenvalue problem we are given a
          square n by n matrix A and wish to compute (lambda) (an
          eigenvalue) and x/=0 (an eigenvector) which satisfy the equation

                                    Ax=(lambda)x

          Such problems are called 'standard' eigenvalue problems in
          contrast to 'generalized' eigenvalue problems where we wish to
          satisfy the equation

                                    Ax=(lambda)Bx

          B also being a square n by n matrix.

          Section 2.1.1 and Section 2.1.2 discuss, respectively, standard
          and generalized eigenvalue problems where the matrices involved
          are dense; Section 2.1.3 discusses both types of problem in the
          case where A and B are sparse (and symmetric).

          2.1.1.  Standard eigenvalue problems

          Some of the routines in this chapter find all the n eigenvalues,
          some find all the n eigensolutions (eigenvalues and corresponding
          eigenvectors), and some find a selected group of eigenvalues
          and/or eigenvectors. The matrix A may be:

          (i)   general (real or complex)

          (ii)  real symmetric, or

          (iii) complex Hermitian (so that if a  =(alpha)+i(beta) then
                                               ij
                a  =(alpha)-i(beta)).
                 ji

          In all cases the computation starts with a similarity
                          -1
          transformation S  AS=T, where S is non-singular and is the
          product of fairly simple matrices, and T has an 'easier form'
          than A so that its eigensolutions are easily determined. The
          matrices A and T, of course, have the same eigenvalues, and if y
          is an eigenvector of T then Sy is the corresponding eigenvector
          of A.

          In case (i) (general real or complex A), the selected form of T
          is an upper Hessenberg matrix (t  =0 if i-j>1) and S is the
                                          ij
          product of n-2 stabilised elementary transformation matrices.
          There is no easy method of computing selected eigenvalues of a
          Hessenberg matrix, so that all eigenvalues are always calculated.
          In the real case this computation is performed via the Francis QR
          algorithm with double shifts, and in the complex case by means of
          the LR algorithm. If the eigenvectors are required they are
          computed by back-substitution following the QR and LR algorithm.

          In case (ii) (real and symmetric A) the selected simple form of T
          is a tridiagonal matrix (t  =0 if |i-j|>1), and S is the product
                                    ij
          of n-2 orthogonal Householder transformation matrices. If only
          selected eigenvalues are required, they are obtained by the
          method of bisection using the Sturm sequence property, and the
          corresponding eigenvectors of T are computed by inverse
          iteration. If all eigenvalues are required, they are computed
          from T via the QL algorithm (an adaptation of the QR algorithm),
          and the corresponding eigenvectors of T are the product of the
          transformations for the QL reduction. In all cases the
          corresponding eigenvectors of A are recovered from the
          computation of x=Sy.

          In case (iii) (complex Hermitian A) analogous transformations as
          in case (ii) are used. T has complex elements in off-diagonal
          positions, but a simple diagonal similarity transformation is
          then used to produce a real tridiagonal form, after which the QL
          algorithm and succeeding methods described in the previous
          paragraph are used to complete the solution.

          2.1.2.  Generalized eigenvalue problems

          Here we distinguish as a special case those problems in which
          both A and B are symmetric and B is positive-definite and well-
          conditioned with respect to inversion (i.e., all the eigenvalues
          of B are significantly greater than zero). Such problems can be
          satisfactorily treated by first reducing them to case (ii) of
          Section 2.1.1 and then using the methods described there to
                                                              T
          compute the eigensolutions. If B is factorized as LL  (L lower
          triangular), then Ax=(lambda)Bx is equivalent to the standard
                                                   -1   T -1        T
          symmetric problem Ry=(lambda)y, where R=L  A(L )   and y=L x.
          After finding an eigenvector y of R, the required x is computed
                                     T
          by back-substitution in y=L x.

          For generalized problems of the form Ax=(lambda)Bx which do not
          fall into the special case, the QZ algorithm is provided.

          In order to appreciate the domain in which this algorithm is
          appropriate we remark first that when B is non-singular the
          problem Ax=(lambda)Bx is fully equivalent to the problem
            -1
          (B  A)x=(lambda)x; both the eigenvalues and eigenvectors being
          the same. When A is non-singular Ax=(lambda)Bx is equivalent to
                        -1
          the problem (A  B)x=(mu)x; the eigenvalues (mu) being the
          reciprocals of the required eigenvalues and the eigenvectors
          remaining the same. In theory then, provided at least one of the
          matrices A and B is non-singular, the generalized problem
          Ax=(lambda)Bx could be solved via the standard problem
          Cx=(lambda)x with an appropriate matrix C, and as far as economy
          of effort is concerned this is quite satisfactory. However, in
          practice, for this reduction to be satisfactory from the
          standpoint of numerical stability, one requires more than the
                                                                -1
          mere non-singularity of A or B. It is necessary that B  A (or
           -1
          A  B) should not only exist but that B (or A) should be well-
          conditioned with respect to inversion. The nearer B (or A) is to
                                               -1       -1
          singularity the more unsatisfactory B  A (or A  B) will be as a
          vehicle for determining the required eigenvalues. Unfortunately
                                                                        -1
          one cannot counter ill-conditioning in B (or A) by computing B  A
               -1
          (or A  B) accurately to single precision using iterative
          refinement. Well-determined eigenvalues of the original
          Ax=(lambda)Bx may be poorly determined even by the correctly
                              -1       -1
          rounded version of B  A (or A  B). The situation may in some
          instances be saved by the observation that if Ax=(lambda)Bx then
          (A-kB)x=((lambda)-k)Bx. Hence if A-kB is non-singular we may
                                            -1
          solve the standard problem [(A-kB)  B]x=(mu)x and for numerical
          stability we require only that (A-kB) be well-conditioned with
          respect to inversion.

          In practice one may well be in a situation where no k is known
          for which (A-kB) is well-conditioned with respect to inversion
          and indeed (A-kB) may be singular for all k. The QZ algorithm is
          designed to deal directly with the problem Ax=(lambda)Bx itself
          and its performance is unaffected by singularity or near-
          singularity of A, B or A-kB.

          2.1.3.  Sparse symmetric problems

          If the matrices A and B are large and sparse (i.e., only a small
          proportion of the elements are non-zero), then the methods
          described in the previous Section are unsuitable, because in
          reducing the problem to a simpler form, much of the sparsity of
          the problem would be lost; hence the computing time and the
          storage required would be very large. Instead, for symmetric
          problems, the method of simultaneous iteration may be used to
          determine selected eigenvalues and the corresponding
          eigenvectors. The routine provided has been designed to handle
          both symmetric and generalized symmetric problems.

          2.2. Singular Value Problems

          The singular value decomposition of an m by n real matrix A is
          given by

                                            T
                                       A=QDP ,

          where Q is an m by m orthogonal matrix, P is an n by n orthogonal
          matrix and D is an m by n diagonal matrix with non-negative
          diagonal elements. The first k==min(m,n) columns of Q and P are
          the left- and right-hand singular vectors of A and the k diagonal
          elements of D are the singular values.

          When A is complex then the singular value decomposition is given
          by

                                            H
                                       A=QDP ,

                                      H                                   T
          where Q and P are unitary, P  denotes the complex conjugate of P
          and D is as above for the real case.

          If the matrix A has column means of zero, then AP is the matrix
          of principal components of A and the singular values are the
          square roots of the sample variances of the observations with
          respect to the principal components. (See also Chapter G03.)

          Routines are provided to return the singular values and vectors
          of a general real or complex matrix.

          3. Recommendations on Choice and Use of Routines

          3.1. General Discussion

          There is one routine, F02FJF, which is designed for sparse
          symmetric eigenvalue problems, either standard or generalized.
          The remainder of the routines are designed for dense matrices.

          3.2. Eigenvalue and Eigenvector Routines

          These reduce the matrix A to a simpler form by a similarity
                          -1
          transformation S  AS=T where T is an upper Hessenberg or
          tridiagonal matrix, compute the eigensolutions of T, and then
          recover the eigenvectors of A via the matrix S. The eigenvectors
          are normalised so that

                                      n
                                      --     2
                                      >  |x | =1
                                      --   r
                                      r=1

          x  being the rth component of the eigenvector x, and so that the
           r
          element of largest modulus is real if x is complex. For problems
          of the type Ax=(lambda)Bx with A and B symmetric and B positive-
                                                             T
          definite, the eigenvectors are normalised so that x Bx=1, x
          always being real for such problems.

          3.3. Singular Value and Singular Vector Routines

          These reduce the matrix A to real bidiagonal form, B say, by
                                      T
          orthogonal transformations Q AP=B in the real case, and by
                                   H
          unitary transformations Q AP=B in the complex case, and the
          singular values and vectors are computed via this bidiagonal
          form. The singular values are returned in descending order.

          3.4. Decision Trees

          (i)  Eigenvalues and Eigenvectors


                   Please see figure in printed Reference Manual


          (ii)  Singular Values and Singular Vectors


                   Please see figure in printed Reference Manual

          F02 -- Eigenvalues and Eigenvectors               Contents -- F02
          Chapter F02

          Eigenvalues and Eigenvectors

          F02AAF  All eigenvalues of real symmetric matrix

          F02ABF  All eigenvalues and eigenvectors of real symmetric matrix

          F02ADF  All eigenvalues of generalized real symmetric-definite
                  eigenproblem

          F02AEF  All eigenvalues and eigenvectors of generalized real
                  symmetric-definite eigenproblem

          F02AFF  All eigenvalues of real matrix

          F02AGF  All eigenvalues and eigenvectors of real matrix

          F02AJF  All eigenvalues of complex matrix

          F02AKF  All eigenvalues and eigenvectors of complex matrix

          F02AWF  All eigenvalues of complex Hermitian matrix

          F02AXF  All eigenvalues and eigenvectors of complex Hermitian
                  matrix

          F02BBF  Selected eigenvalues and eigenvectors of real symmetric
                  matrix

          F02BJF  All eigenvalues and optionally eigenvectors of
                  generalized eigenproblem by QZ algorithm, real matrices

          F02FJF  Selected eigenvalues and eigenvectors of sparse symmetric
                  eigenproblem

          F02WEF  SVD of real matrix

          F02XEF  SVD of complex matrix

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf02aaf}{nagf.ht}
{ Calculates all the eigenvalues of a real symmetric matrix}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf02aaf}{NAG Documentation: f02aaf}
\beginscroll
\begin{verbatim}



     F02AAF(3NAG)      Foundation Library (12/10/92)      F02AAF(3NAG)



          F02 -- Eigenvalue and Eigenvectors                         F02AAF
                  F02AAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F02AAF calculates all the eigenvalues of a real symmetric matrix.

          2. Specification

                 SUBROUTINE F02AAF (A, IA, N, R, E, IFAIL)
                 INTEGER          IA, N, IFAIL
                 DOUBLE PRECISION A(IA,N), R(N), E(N)

          3. Description

          This routine reduces the real symmetric matrix A to a real
          symmetric tridiagonal matrix using Householder's method. The
          eigenvalues of the tridiagonal matrix are then determined using
          the QL algorithm.

          4. References

          [1]   Wilkinson J H and Reinsch C (1971) Handbook for Automatic
                Computation II, Linear Algebra. Springer-Verlag.

          5. Parameters

           1:  A(IA,N) -- DOUBLE PRECISION array               Input/Output
               On entry: the lower triangle of the n by n symmetric matrix
               A. The elements of the array above the diagonal need not be
               set. On exit: the elements of A below the diagonal are
               overwritten, and the rest of the array is unchanged.

           2:  IA -- INTEGER                                          Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F02AAF is called.
               Constraint: IA >= N.

           3:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A.

           4:  R(N) -- DOUBLE PRECISION array                        Output
               On exit: the eigenvalues in ascending order.

           5:  E(N) -- DOUBLE PRECISION array                     Workspace

           6:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               Failure in F02AVF(*) indicating that more than 30*N
               iterations are required to isolate all the eigenvalues.

          7. Accuracy

          The accuracy of the eigenvalues depends on the sensitivity of the
          matrix to rounding errors produced in tridiagonalisation. For a
          detailed error analysis see Wilkinson and Reinsch [1] pp 222 and
          235.

          8. Further Comments

                                                                          3
          The time taken by the routine is approximately proportional to n

          9. Example

          To calculate all the eigenvalues of the real symmetric matrix:

                               ( 0.5  0.0  2.3 -2.6)
                               ( 0.0  0.5 -1.4 -0.7)
                               ( 2.3 -1.4  0.5  0.0).
                               (-2.6 -0.7  0.0  0.5)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf02abf}{nagf.ht}
{ Eigenvalues and eigenvectors of a real symmetric matrix}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf02abf}{NAG Documentation: f02abf}
\beginscroll
\begin{verbatim}



     F02ABF(3NAG)      Foundation Library (12/10/92)      F02ABF(3NAG)



          F02 -- Eigenvalue and Eigenvectors                         F02ABF
                  F02ABF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F02ABF calculates all the eigenvalues and eigenvectors of a real
          symmetric matrix.

          2. Specification

                 SUBROUTINE F02ABF (A, IA, N, R, V, IV, E, IFAIL)
                 INTEGER          IA, N, IV, IFAIL
                 DOUBLE PRECISION A(IA,N), R(N), V(IV,N), E(N)

          3. Description

          This routine reduces the real symmetric matrix A to a real
          symmetric tridiagonal matrix by Householder's method. The
          eigenvalues and eigenvectors are calculated using the QL
          algorithm.

          4. References

          [1]   Wilkinson J H and Reinsch C (1971) Handbook for Automatic
                Computation II, Linear Algebra. Springer-Verlag.

          5. Parameters

           1:  A(IA,N) -- DOUBLE PRECISION array                      Input
               On entry: the lower triangle of the n by n symmetric matrix
               A. The elements of the array above the diagonal need not be
               set. See also Section 8.

           2:  IA -- INTEGER                                          Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F02ABF is called.
               Constraint: IA >= N.

           3:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A.

           4:  R(N) -- DOUBLE PRECISION array                        Output
               On exit: the eigenvalues in ascending order.

           5:  V(IV,N) -- DOUBLE PRECISION array                     Output
               On exit: the normalised eigenvectors, stored by columns;
               the ith column corresponds to the ith eigenvalue. The
               eigenvectors are normalised so that the sum of squares of
               the elements is equal to 1.

           6:  IV -- INTEGER                                          Input
               On entry:
               the first dimension of the array V as declared in the
               (sub)program from which F02ABF is called.
               Constraint: IV >= N.

           7:  E(N) -- DOUBLE PRECISION array                     Workspace

           8:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               Failure in F02AMF(*) indicating that more than 30*N
               iterations are required to isolate all the eigenvalues.

          7. Accuracy

          The eigenvectors are always accurately orthogonal but the
          accuracy of the individual eigenvectors is dependent on their
          inherent sensitivity to changes in the original matrix. For a
          detailed error analysis see Wilkinson and Reinsch [1] pp 222 and
          235.

          8. Further Comments

                                                                          3
          The time taken by the routine is approximately proportional to n

          Unless otherwise stated in the Users' Note for your
          implementation, the routine may be called with the same actual
          array supplied for parameters A and V, in which case the
          eigenvectors will overwrite the original matrix. However this is
          not standard Fortran 77, and may not work on all systems.

          9. Example

          To calculate all the eigenvalues and eigenvectors of the real
          symmetric matrix:

                               ( 0.5  0.0  2.3 -2.6)
                               ( 0.0  0.5 -1.4 -0.7)
                               ( 2.3 -1.4  0.5  0.0).
                               (-2.6 -0.7  0.0  0.5)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf02adf}{nagf.ht}
{ Calculates all the eigenvalues of  $Ax=\lambda Bx$}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf02adf}{NAG Documentation: f02adf}
\beginscroll
\begin{verbatim}



     F02ADF(3NAG)      Foundation Library (12/10/92)      F02ADF(3NAG)



          F02 -- Eigenvalue and Eigenvectors                         F02ADF
                  F02ADF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F02ADF calculates all the eigenvalues of  Ax=(lambda)Bx,  where A
          is a real symmetric matrix and B is a real symmetric positive-
          definite matrix.

          2. Specification

                 SUBROUTINE F02ADF (A, IA, B, IB, N, R, DE, IFAIL)
                 INTEGER          IA, IB, N, IFAIL
                 DOUBLE PRECISION A(IA,N), B(IB,N), R(N), DE(N)

          3. Description

          The problem is reduced to the standard symmetric eigenproblem
          using Cholesky's method to decompose B into triangular matrices,
              T
          B=LL , where L is lower triangular. Then Ax=(lambda)Bx implies
            -1  -T   T             T
          (L  AL  )(L x)=(lambda)(L x); hence the eigenvalues of
          Ax=(lambda)Bx are those of Py=(lambda)y where P is the symmetric
                  -1  -T
          matrix L  AL  . Householder's method is used to tridiagonalise
          the matrix P and the eigenvalues are then found using the QL
          algorithm.

          4. References

          [1]   Wilkinson J H and Reinsch C (1971) Handbook for Automatic
                Computation II, Linear Algebra. Springer-Verlag.

          5. Parameters

           1:  A(IA,N) -- DOUBLE PRECISION array               Input/Output
               On entry: the upper triangle of the n by n symmetric matrix
               A. The elements of the array below the diagonal need not be
               set. On exit: the lower triangle of the array is
               overwritten. The rest of the array is unchanged.

           2:  IA -- INTEGER                                          Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F02ADF is called.
               Constraint: IA >= N.

           3:  B(IB,N) -- DOUBLE PRECISION array               Input/Output
               On entry: the upper triangle of the n by n symmetric
               positive-definite matrix B. The elements of the array below
               the diagonal need not be set. On exit: the elements below
               the diagonal are overwritten. The rest of the array is
               unchanged.

           4:  IB -- INTEGER                                          Input
               On entry:
               the first dimension of the array B as declared in the
               (sub)program from which F02ADF is called.
               Constraint: IB >= N.

           5:  N -- INTEGER                                           Input
               On entry: n, the order of the matrices A and B.

           6:  R(N) -- DOUBLE PRECISION array                        Output
               On exit: the eigenvalues in ascending order.

           7:  DE(N) -- DOUBLE PRECISION array                    Workspace

           8:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               Failure in F01AEF(*); the matrix B is not positive-definite
               possibly due to rounding errors.

          IFAIL= 2
               Failure in F02AVF(*), more than 30*N iterations are required
               to isolate all the eigenvalues.

          7. Accuracy

          In general this routine is very accurate. However, if B is ill-
          conditioned with respect to inversion, the eigenvalues could be
          inaccurately determined. For a detailed error analysis see
          Wilkinson and Reinsch [1] pp 310, 222 and 235.

          8. Further Comments

                                                                          3
          The time taken by the routine is approximately proportional to n

          9. Example

          To calculate all the eigenvalues of the general symmetric
          eigenproblem Ax=(lambda) Bx where A is the symmetric matrix:

                                (0.5  1.5  6.6   4.8)
                                (1.5  6.5 16.2   8.6)
                                (6.6 16.2 37.6   9.8)
                                (4.8  8.6  9.8 -17.1)

          and B is the symmetric positive-definite matrix:

                                    (1  3  4  1)
                                    (3 13 16 11)
                                    (4 16 24 18).
                                    (1 11 18 27)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf02aef}{nagf.ht}
{ Eigenvalues and eigenvectors of $Ax=\lambda Bx$}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf02aef}{NAG Documentation: f02aef}
\beginscroll
\begin{verbatim}



     F02AEF(3NAG)      Foundation Library (12/10/92)      F02AEF(3NAG)



          F02 -- Eigenvalue and Eigenvectors                         F02AEF
                  F02AEF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F02AEF calculates all the eigenvalues and eigenvectors of
          Ax=(lambda)Bx,  where A is a real symmetric matrix and B is a
          real symmetric positive-definite matrix.

          2. Specification

                 SUBROUTINE F02AEF (A, IA, B, IB, N, R, V, IV, DL, E, IFAIL)
                 INTEGER          IA, IB, N, IV, IFAIL
                 DOUBLE PRECISION A(IA,N), B(IB,N), R(N), V(IV,N), DL(N), E
                1                 (N)

          3. Description

          The problem is reduced to the standard symmetric eigenproblem
          using Cholesky's method to decompose B into triangular matrices
              T
          B=LL , where L is lower triangular. Then Ax=(lambda)Bx implies
            -1  -T   T             T
          (L  AL  )(L x)=(lambda)(L x); hence the eigenvalues of
          Ax=(lambda)Bx are those of Py=(lambda)y, where P is the symmetric
                  -1  -T
          matrix L  AL  . Householder's method is used to tridiagonalise
          the matrix P and the eigenvalues are found using the QL
          algorithm. An eigenvector z of the derived problem is related to
                                                         T
          an eigenvector x of the original problem by z=L x. The
          eigenvectors z are determined using the QL algorithm and are
                              T
          normalised so that z z=1; the eigenvectors of the original
                                                  T
          problem are then determined by solving L x=z, and are normalised
                   T
          so that x Bx=1.

          4. References

          [1]   Wilkinson J H and Reinsch C (1971) Handbook for Automatic
                Computation II, Linear Algebra. Springer-Verlag.

          5. Parameters

           1:  A(IA,N) -- DOUBLE PRECISION array               Input/Output

               On entry: the upper triangle of the n by n symmetric matrix
               A. The elements of the array below the diagonal need not be
               set. On exit: the lower triangle of the array is
               overwritten. The rest of the array is unchanged. See also
               Section 8.

           2:  IA -- INTEGER                                          Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F02AEF is called.
               Constraint: IA >= N.

           3:  B(IB,N) -- DOUBLE PRECISION array               Input/Output
               On entry: the upper triangle of the n by n symmetric
               positive-definite matrix B. The elements of the array below
               the diagonal need not be set. On exit: the elements below
               the diagonal are overwritten. The rest of the array is
               unchanged.

           4:  IB -- INTEGER                                          Input
               On entry:
               the first dimension of the array B as declared in the
               (sub)program from which F02AEF is called.
               Constraint: IB >= N.

           5:  N -- INTEGER                                           Input
               On entry: n, the order of the matrices A and B.

           6:  R(N) -- DOUBLE PRECISION array                        Output
               On exit: the eigenvalues in ascending order.

           7:  V(IV,N) -- DOUBLE PRECISION array                     Output
               On exit: the normalised eigenvectors, stored by columns;
               the ith column corresponds to the ith eigenvalue. The
                                                      T
               eigenvectors x are normalised so that x Bx=1. See also
               Section 8.

           8:  IV -- INTEGER                                          Input
               On entry:
               the first dimension of the array V as declared in the
               (sub)program from which F02AEF is called.
               Constraint: IV >= N.

           9:  DL(N) -- DOUBLE PRECISION array                    Workspace

          10:  E(N) -- DOUBLE PRECISION array                     Workspace

          11:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.
               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               Failure in F01AEF(*); the matrix B is not positive-definite,
               possibly due to rounding errors.

          IFAIL= 2
               Failure in F02AMF(*); more than 30*N iterations are required
               to isolate all the eigenvalues.

          7. Accuracy

          In general this routine is very accurate. However, if B is ill-
          conditioned with respect to inversion, the eigenvectors could be
          inaccurately determined. For a detailed error analysis see
          Wilkinson and Reinsch [1] pp 310, 222 and 235.

          8. Further Comments

                                                                          3
          The time taken by the routine is approximately proportional to n

          Unless otherwise stated in the Users' Note for your
          implementation, the routine may be called with the same actual
          array supplied for parameters A and V, in which case the
          eigenvectors will overwrite the original matrix A. However this
          is not standard Fortran 77, and may not work on all systems.

          9. Example

          To calculate all the eigenvalues and eigenvectors of the general
          symmetric eigenproblem Ax=(lambda) Bx where A is the symmetric
          matrix:

                                (0.5  1.5  6.6   4.8)
                                (1.5  6.5 16.2   8.6)
                                (6.6 16.2 37.6   9.8)
                                (4.8  8.6  9.8 -17.1)

          and B is the symmetric positive-definite matrix:

                                    (1  3  4  1)
                                    (3 13 16 11)
                                    (4 16 24 18).
                                    (1 11 18 27)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf02aff}{nagf.ht}
{ Calculates all the eigenvalues of a real unsymmetric matrix}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf02aff}{NAG Documentation: f02aff}
\beginscroll
\begin{verbatim}



     F02AFF(3NAG)      Foundation Library (12/10/92)      F02AFF(3NAG)



          F02 -- Eigenvalue and Eigenvectors                         F02AFF
                  F02AFF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F02AFF calculates all the eigenvalues of a real unsymmetric
          matrix.

          2. Specification

                 SUBROUTINE F02AFF (A, IA, N, RR, RI, INTGER, IFAIL)
                 INTEGER          IA, N, INTGER(N), IFAIL
                 DOUBLE PRECISION A(IA,N), RR(N), RI(N)

          3. Description

          The matrix A is first balanced and then reduced to upper
          Hessenberg form using stabilised elementary similarity
          transformations. The eigenvalues are then found using the QR
          algorithm for real Hessenberg matrices.

          4. References

          [1]   Wilkinson J H and Reinsch C (1971) Handbook for Automatic
                Computation II, Linear Algebra. Springer-Verlag.

          5. Parameters

           1:  A(IA,N) -- DOUBLE PRECISION array               Input/Output
               On entry: the n by n matrix A. On exit: the array is
               overwritten.

           2:  IA -- INTEGER                                          Input
               On entry:
               the dimension of the array A as declared in the (sub)program
               from which F02AFF is called.
               Constraint: IA >= N.

           3:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A.

           4:  RR(N) -- DOUBLE PRECISION array                       Output
               On exit: the real parts of the eigenvalues.

           5:  RI(N) -- DOUBLE PRECISION array                       Output
               On exit: the imaginary parts of the eigenvalues.

           6:  INTGER(N) -- INTEGER array                            Output
               On exit: INTGER(i) contains the number of iterations used
               to find the ith eigenvalue. If INTGER(i) is negative, the i
               th eigenvalue is the second of a pair found simultaneously.

               Note that the eigenvalues are found in reverse order,
               starting with the nth.

           7:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               More than 30*N iterations are required to isolate all the
               eigenvalues.

          7. Accuracy

          The accuracy of the results depends on the original matrix and
          the multiplicity of the roots. For a detailed error analysis see
          Wilkinson and Reinsch [1] pp 352 and 367.

          8. Further Comments

                                                                          3
          The time taken by the routine is approximately proportional to n

          9. Example

          To calculate all the eigenvalues of the real matrix:

                               (  1.5 0.1  4.5 -1.5)
                               (-22.5 3.5 12.5 -2.5)
                               ( -2.5 0.3  4.5 -2.5).
                               ( -2.5 0.1  4.5  2.5)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf02agf}{nagf.ht}
{ Eigenvalues and eigenvectors of a real unsymmetric matrix}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf02agf}{NAG Documentation: f02agf}
\beginscroll
\begin{verbatim}



     F02AGF(3NAG)      Foundation Library (12/10/92)      F02AGF(3NAG)



          F02 -- Eigenvalue and Eigenvectors                         F02AGF
                  F02AGF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F02AGF calculates all the eigenvalues and eigenvectors of a real
          unsymmetric matrix.

          2. Specification

                 SUBROUTINE F02AGF (A, IA, N, RR, RI, VR, IVR, VI, IVI,
                1                   INTGER, IFAIL)
                 INTEGER          IA, N, IVR, IVI, INTGER(N), IFAIL
                 DOUBLE PRECISION A(IA,N), RR(N), RI(N), VR(IVR,N), VI
                1                 (IVI,N)

          3. Description

          The matrix A is first balanced and then reduced to upper
          Hessenberg form using real stabilised elementary similarity
          transformations. The eigenvalues and eigenvectors of the
          Hessenberg matrix are calculated using the QR algorithm. The
          eigenvectors of the Hessenberg matrix are back-transformed to
          give the eigenvectors of the original matrix A.

          4. References

          [1]   Wilkinson J H and Reinsch C (1971) Handbook for Automatic
                Computation II, Linear Algebra. Springer-Verlag.

          5. Parameters

           1:  A(IA,N) -- DOUBLE PRECISION array               Input/Output
               On entry: the n by n matrix A. On exit: the array is
               overwritten.

           2:  IA -- INTEGER                                          Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F02AGF is called.
               Constraint: IA >= N.

           3:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A.

           4:  RR(N) -- DOUBLE PRECISION array                       Output
               On exit: the real parts of the eigenvalues.

           5:  RI(N) -- DOUBLE PRECISION array                       Output
               On exit: the imaginary parts of the eigenvalues.

           6:  VR(IVR,N) -- DOUBLE PRECISION array                   Output
               On exit: the real parts of the eigenvectors, stored by
               columns. The ith column corresponds to the ith eigenvalue.
               The eigenvectors are normalised so that the sum of the
               squares of the moduli of the elements is equal to 1 and the
               element of largest modulus is real. This ensures that real
               eigenvalues have real eigenvectors.

           7:  IVR -- INTEGER                                         Input
               On entry:
               the first dimension of the array VR as declared in the
               (sub)program from which F02AGF is called.
               Constraint: IVR >= N.

           8:  VI(IVI,N) -- DOUBLE PRECISION array                   Output
               On exit: the imaginary parts of the eigenvectors, stored by
               columns. The ith column corresponds to the ith eigenvalue.

           9:  IVI -- INTEGER                                         Input
               On entry:
               the first dimension of the array VI as declared in the
               (sub)program from which F02AGF is called.
               Constraint: IVI >= N.

          10:  INTGER(N) -- INTEGER array                            Output
               On exit: INTGER(i) contains the number of iterations used
               to find the ith eigenvalue. If INTGER(i) is negative, the i
               th eigenvalue is the second of a pair found simultaneously.

               Note that the eigenvalues are found in reverse order,
               starting with the nth.

          11:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               More than 30*N iterations are required to isolate all the
               eigenvalues.

          7. Accuracy

          The accuracy of the results depends on the original matrix and
          the multiplicity of the roots. For a detailed error analysis see
          Wilkinson and Reinsch [1] pp 352 and 390.

          8. Further Comments

                                                                          3
          The time taken by the routine is approximately proportional to n

          9. Example

          To calculate all the eigenvalues and eigenvectors of the real
          matrix:

                               (  1.5 0.1  4.5 -1.5)
                               (-22.5 3.5 12.5 -2.5)
                               ( -2.5 0.3  4.5 -2.5).
                               ( -2.5 0.1  4.5  2.5)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf02ajf}{nagf.ht}
{ Calculates all the eigenvalues of a complex matrix}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf02ajf}{NAG Documentation: f02ajf}
\beginscroll
\begin{verbatim}



     F02AJF(3NAG)      Foundation Library (12/10/92)      F02AJF(3NAG)



          F02 -- Eigenvalue and Eigenvectors                         F02AJF
                  F02AJF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F02AJF calculates all the eigenvalues of a complex matrix.

          2. Specification

                 SUBROUTINE F02AJF (AR, IAR, AI, IAI, N, RR, RI, INTGER,
                1                   IFAIL)
                 INTEGER          IAR, IAI, N, INTGER(N), IFAIL
                 DOUBLE PRECISION AR(IAR,N), AI(IAI,N), RR(N), RI(N)

          3. Description

          The complex matrix A is first balanced and then reduced to upper
          Hessenberg form using stabilised elementary similarity
          transformations. The eigenvalues are then found using the
          modified LR algorithm for complex Hessenberg matrices.

          4. References

          [1]   Wilkinson J H and Reinsch C (1971) Handbook for Automatic
                Computation II, Linear Algebra. Springer-Verlag.

          5. Parameters

           1:  AR(IAR,N) -- DOUBLE PRECISION array             Input/Output
               On entry: the real parts of the elements of the n by n
               complex matrix A. On exit: the array is overwritten.

           2:  IAR -- INTEGER                                         Input
               On entry:
               the first dimension of the array AR as declared in the
               (sub)program from which F02AJF is called.
               Constraint: IAR >= N.

           3:  AI(IAI,N) -- DOUBLE PRECISION array             Input/Output
               On entry: the imaginary parts of the elements of the n by n
               complex matrix A. On exit: the array is overwritten.

           4:  IAI -- INTEGER                                         Input
               On entry:
               the first dimension of the array AI as declared in the
               (sub)program from which F02AJF is called.
               Constraint: IAI >= N.

           5:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A.

           6:  RR(N) -- DOUBLE PRECISION array                       Output
               On exit: the real parts of the eigenvalues.

           7:  RI(N) -- DOUBLE PRECISION array                       Output
               On exit: the imaginary parts of the eigenvalues.

           8:  INTGER(N) -- INTEGER array                         Workspace

           9:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               More than 30*N iterations are required to isolate all the
               eigenvalues.

          7. Accuracy

          The accuracy of the results depends on the original matrix and
          the multiplicity of the roots. For a detailed error analysis see
          Wilkinson and Reinsch [1] pp 352 and 401.

          8. Further Comments

                                                                          3
          The time taken by the routine is approximately proportional to n

          9. Example

          To calculate all the eigenvalues of the complex matrix:

                     (-21.0-5.0i      24.60i 13.6+10.2i     4.0i)
                     (     22.5i 26.00-5.00i  7.5-10.0i 2.5     )
                     ( -2.0+1.5i  1.68+2.24i  4.5-5.0i  1.5+2.0i).
                     (     -2.5i -2.60       -2.7+3.6i  2.5-5.0i)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf02akf}{nagf.ht}
{ Eigenvalues and eigenvectors of a complex matrix}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf02akf}{NAG Documentation: f02akf}
\beginscroll
\begin{verbatim}



     F02AKF(3NAG)      Foundation Library (12/10/92)      F02AKF(3NAG)



          F02 -- Eigenvalue and Eigenvectors                         F02AKF
                  F02AKF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F02AKF calculates all the eigenvalues and eigenvectors of a
          complex matrix.

          2. Specification

                 SUBROUTINE F02AKF (AR, IAR, AI, IAI, N, RR, RI, VR, IVR,
                1                   VI, IVI, INTGER, IFAIL)
                 INTEGER          IAR, IAI, N, IVR, IVI, INTGER(N), IFAIL
                 DOUBLE PRECISION AR(IAR,N), AI(IAI,N), RR(N), RI(N), VR
                1                 (IVR,N), VI(IVI,N)

          3. Description

          The complex matrix A is first balanced and then reduced to upper
          Hessenberg form by stabilised elementary similarity
          transformations. The eigenvalues and eigenvectors of the
          Hessenberg matrix are calculated using the LR algorithm. The
          eigenvectors of the Hessenberg matrix are back-transformed to
          give the eigenvectors of the original matrix.

          4. References

          [1]   Wilkinson J H and Reinsch C (1971) Handbook for Automatic
                Computation II, Linear Algebra. Springer-Verlag.

          5. Parameters

           1:  AR(IAR,N) -- DOUBLE PRECISION array             Input/Output
               On entry: the real parts of the elements of the n by n
               complex matrix A. On exit: the array is overwritten.

           2:  IAR -- INTEGER                                         Input
               On entry:
               the first dimension of the array AR as declared in the
               (sub)program from which F02AKF is called.
               Constraint: IAR >= N.

           3:  AI(IAI,N) -- DOUBLE PRECISION array             Input/Output
               On entry: the imaginary parts of the elements of the n by n
               complex matrix A. On exit: the array is overwritten.

           4:  IAI -- INTEGER                                         Input
               On entry:
               the first dimension of the array AI as declared in the
               (sub)program from which F02AKF is called.
               Constraint: IAI >= N.

           5:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A.

           6:  RR(N) -- DOUBLE PRECISION array                       Output
               On exit: the real parts of the eigenvalues.

           7:  RI(N) -- DOUBLE PRECISION array                       Output
               On exit: the imaginary parts of the eigenvalues.

           8:  VR(IVR,N) -- DOUBLE PRECISION array                   Output
               On exit: the real parts of the eigenvectors, stored by
               columns. The ith column corresponds to the ith eigenvalue.
               The eigenvectors are normalised so that the sum of squares
               of the moduli of the elements is equal to 1 and the element
               of largest modulus is real.

           9:  IVR -- INTEGER                                         Input
               On entry:
               the first dimension of the array VR as declared in the
               (sub)program from which F02AKF is called.
               Constraint: IVR >= N.

          10:  VI(IVI,N) -- DOUBLE PRECISION array                   Output
               On exit: the imaginary parts of the eigenvectors, stored by
               columns. The ith column corresponds to the ith eigenvalue.

          11:  IVI -- INTEGER                                         Input
               On entry:
               the first dimension of the array VI as declared in the
               (sub)program from which F02AKF is called.
               Constraint: IVI >= N.

          12:  INTGER(N) -- INTEGER array                         Workspace

          13:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               More than 30*N iterations are required to isolate all the
               eigenvalues.

          7. Accuracy

          The accuracy of the results depends on the conditioning of the
          original matrix and the multiplicity of the roots. For a detailed
          error analysis see Wilkinson and Reinsch [1] pp 352 and 390.

          8. Further Comments

                                                                          3
          The time taken by the routine is approximately proportional to n

          9. Example

          To calculate all the eigenvalues and eigenvectors of the complex
          matrix:

                     (-21.0-5.0i      24.60i 13.6+10.2i     4.0i)
                     (     22.5i 26.00-5.00i  7.5-10.0i 2.5     )
                     ( -2.0+1.5i  1.68+2.24i  4.5-5.0i  1.5+2.0i).
                     (     -2.5i -2.60       -2.7+3.6i  2.5-5.0i)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf02awf}{nagf.ht}
{ Eigenvalues of a complex Hermitian matrix}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf02awf}{NAG Documentation: f02awf}
\beginscroll
\begin{verbatim}



     F02AWF(3NAG)      Foundation Library (12/10/92)      F02AWF(3NAG)



          F02 -- Eigenvalue and Eigenvectors                         F02AWF
                  F02AWF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F02AWF calculates all the eigenvalues of a complex Hermitian
          matrix.

          2. Specification

                 SUBROUTINE F02AWF (AR, IAR, AI, IAI, N, R, WK1, WK2, WK3,
                1                   IFAIL)
                 INTEGER          IAR, IAI, N, IFAIL
                 DOUBLE PRECISION AR(IAR,N), AI(IAI,N), R(N), WK1(N),
                1                 WK2(N), WK3(N)

          3. Description

          The complex Hermitian matrix A is first reduced to a real
          tridiagonal matrix by n-2 unitary transformations, and a
          subsequent diagonal transformation. The eigenvalues are then
          derived using the QL algorithm, an adaptation of the QR
          algorithm.

          4. References

          [1]   Peters G (1967) NPL Algorithms Library. Document No.
                F1/04/A.

          [2]   Wilkinson J H and Reinsch C (1971) Handbook for Automatic
                Computation II, Linear Algebra. Springer-Verlag.

          5. Parameters

           1:  AR(IAR,N) -- DOUBLE PRECISION array             Input/Output
               On entry: the real parts of the elements of the lower
               triangle of the n by n complex Hermitian matrix A. Elements
               of the array above the diagonal need not be set. On exit:
               the array is overwritten.

           2:  IAR -- INTEGER                                         Input
               On entry:
               the first dimension of the array AR as declared in the
               (sub)program from which F02AWF is called.
               Constraint: IAR >= N.

           3:  AI(IAI,N) -- DOUBLE PRECISION array             Input/Output
               On entry: the imaginary parts of the elements of the lower
               triangle of the n by n complex Hermitian matrix A. Elements
               of the array above the diagonal need not be set. On exit:
               the array is overwritten.

           4:  IAI -- INTEGER                                         Input
               On entry:
               the first dimension of the array AI as declared in the
               (sub)program from which F02AWF is called.
               Constraint: IAI >= N.

           5:  N -- INTEGER                                           Input
               On entry: n, the order of the complex Hermitian matrix, A.

           6:  R(N) -- DOUBLE PRECISION array                        Output
               On exit: the eigenvalues in ascending order.

           7:  WK1(N) -- DOUBLE PRECISION array                   Workspace

           8:  WK2(N) -- DOUBLE PRECISION array                   Workspace

           9:  WK3(N) -- DOUBLE PRECISION array                   Workspace

          10:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               More than 30*N iterations are required to isolate all the
               eigenvalues.

          7. Accuracy

          For a detailed error analysis see Peters [1] page 3 and Wilkinson
          and Reinsch [2] page 235.

          8. Further Comments

                                                                          3
          The time taken by the routine is approximately proportional to n

          9. Example

          To calculate all the eigenvalues of the complex Hermitian matrix:

                      (0.50        0.00       1.84+1.38i  2.08-1.56i)
                      (0.00        0.50       1.12+0.84i -0.56+0.42i)
                      (1.84-1.38i  1.12-0.84i 0.50        0.00      ).
                      (2.08+1.56i -0.56-0.42i 0.00        0.50      )

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf02axf}{nagf.ht}
{ Eigenvalues/eigenvectors complex Hermitian matrix}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf02axf}{NAG Documentation: f02axf}
\beginscroll
\begin{verbatim}



     F02AXF(3NAG)      Foundation Library (12/10/92)      F02AXF(3NAG)



          F02 -- Eigenvalue and Eigenvectors                         F02AXF
                  F02AXF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F02AXF calculates all the eigenvalues and eigenvectors of a
          complex Hermitian matrix.

          2. Specification

                 SUBROUTINE F02AXF (AR, IAR, AI, IAI, N, R, VR, IVR, VI,
                1                   IVI, WK1, WK2, WK3, IFAIL)
                 INTEGER          IAR, IAI, N, IVR, IVI, IFAIL
                 DOUBLE PRECISION AR(IAR,N), AI(IAI,N), R(N), VR(IVR,N), VI
                1                 (IVI,N), WK1(N), WK2(N), WK3(N)

          3. Description

          The complex Hermitian matrix is first reduced to a real
          tridiagonal matrix by n-2 unitary transformations and a
          subsequent diagonal transformation. The eigenvalues and
          eigenvectors are then derived using the QL algorithm, an
          adaptation of the QR algorithm.

          4. References

          [1]   Peters G (1967) NPL Algorithms Library. Document No.
                F2/03/A.

          [2]   Peters G (1967) NPL Algorithms Library. Document No.
                F1/04/A.

          5. Parameters

           1:  AR(IAR,N) -- DOUBLE PRECISION array                    Input
               On entry: the real parts of the elements of the lower
               triangle of the n by n complex Hermitian matrix A. Elements
               of the array above the diagonal need not be set. See also
               Section 8.

           2:  IAR -- INTEGER                                         Input
               On entry:
               the first dimension of the array AR as declared in the
               (sub)program from which F02AXF is called.
               Constraint: IAR >= N.

           3:  AI(IAI,N) -- DOUBLE PRECISION array                    Input
               On entry: the imaginary parts of the elements of the lower
               triangle of the n by n complex Hermitian matrix A. Elements
               of the array above the diagonal need not be set. See also
               Section 8.

           4:  IAI -- INTEGER                                         Input
               On entry:
               the first dimension of the array AI as declared in the
               (sub)program from which F02AXF is called.
               Constraint: IAI >= N.

           5:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix, A.

           6:  R(N) -- DOUBLE PRECISION array                        Output
               On exit: the eigenvalues in ascending order.

           7:  VR(IVR,N) -- DOUBLE PRECISION array                   Output
               On exit: the real parts of the eigenvectors, stored by
               columns. The ith column corresponds to the ith eigenvector.
               The eigenvectors are normalised so that the sum of the
               squares of the moduli of the elements is equal to 1 and the
               element of largest modulus is real. See also Section 8.

           8:  IVR -- INTEGER                                         Input
               On entry:
               the first dimension of the array VR as declared in the
               (sub)program from which F02AXF is called.
               Constraint: IVR >= N.

           9:  VI(IVI,N) -- DOUBLE PRECISION array                   Output
               On exit: the imaginary parts of the eigenvectors, stored by
               columns. The ith column corresponds to the ith eigenvector.
               See also Section 8.

          10:  IVI -- INTEGER                                         Input
               On entry:
               the first dimension of the array VI as declared in the
               (sub)program from which F02AXF is called.
               Constraint: IVI >= N.

          11:  WK1(N) -- DOUBLE PRECISION array                   Workspace

          12:  WK2(N) -- DOUBLE PRECISION array                   Workspace

          13:  WK3(N) -- DOUBLE PRECISION array                   Workspace

          14:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               More than 30*N iterations are required to isolate all the
               eigenvalues.

          IFAIL= 2
               The diagonal elements of AI are not all zero, i.e., the
               complex matrix is not Hermitian.

          7. Accuracy

          The eigenvectors are always accurately orthogonal but the
          accuracy of the individual eigenvalues and eigenvectors is
          dependent on their inherent sensitivity to small changes in the
          original matrix. For a detailed error analysis see Peters [1]
          page 3 and [2] page 3.

          8. Further Comments

                                                                          3
          The time taken by the routine is approximately proportional to n

          Unless otherwise stated in the implementation document, the
          routine may be called with the same actual array supplied for
          parameters AR and VR, and for AI and VI, in which case the
          eigenvectors will overwrite the original matrix A. However this
          is not standard Fortran 77, and may not work on all systems.

          9. Example

          To calculate the eigenvalues and eigenvectors of the complex
          Hermitian matrix:

                      (0.50        0.00       1.84+1.38i  2.08-1.56i)
                      (0.00        0.50       1.12+0.84i -0.56+0.42i)
                      (1.84-1.38i  1.12-0.84i 0.50        0.00      ).
                      (2.08+1.56i -0.56-0.42i 0.00        0.50      )

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf02bbf}{nagf.ht}
{ Eigenvalues and eigenvectors of a real symmetric matrix}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf02bbf}{NAG Documentation: f02bbf}
\beginscroll
\begin{verbatim}



     F02BBF(3NAG)      Foundation Library (12/10/92)      F02BBF(3NAG)



          F02 -- Eigenvalue and Eigenvectors                         F02BBF
                  F02BBF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F02BBF calculates selected eigenvalues and eigenvectors of a real
          symmetric matrix by reduction to tridiagonal form, bisection and
          inverse iteration, where the selected eigenvalues lie within a
          given interval.

          2. Specification

                 SUBROUTINE F02BBF (A, IA, N, ALB, UB, M, MM, R, V, IV, D,
                1                   E, E2, X, G, C, ICOUNT, IFAIL)
                 INTEGER          IA, N, M, MM, IV, ICOUNT(M), IFAIL
                 DOUBLE PRECISION A(IA,N), ALB, UB, R(M), V(IV,M), D(N), E
                1                 (N), E2(N), X(N,7), G(N)
                 LOGICAL          C(N)

          3. Description

          The real symmetric matrix A is reduced to a symmetric tridiagonal
          matrix T by Householder's method. The eigenvalues which lie
          within a given interval [l,u], are calculated by the method of
          bisection. The corresponding eigenvectors of T are calculated by
          inverse iteration. A back-transformation is then performed to
          obtain the eigenvectors of the original matrix A.

          4. References

          [1]   Wilkinson J H and Reinsch C (1971) Handbook for Automatic
                Computation II, Linear Algebra. Springer-Verlag.

          5. Parameters

           1:  A(IA,N) -- DOUBLE PRECISION array               Input/Output
               On entry: the lower triangle of the n by n symmetric matrix
               A. The elements of the array above the diagonal need not be
               set. On exit: the elements of A below the diagonal are
               overwritten, and the rest of the array is unchanged.

           2:  IA -- INTEGER                                          Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F02BBF is called.
               Constraint: IA >= N.

           3:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A.

           4:  ALB -- DOUBLE PRECISION                                Input

           5:  UB -- DOUBLE PRECISION                                 Input
               On entry: l and u, the lower and upper end-points of the
               interval within which eigenvalues are to be calculated.

           6:  M -- INTEGER                                           Input
               On entry: an upper bound for the number of eigenvalues
               within the interval.

           7:  MM -- INTEGER                                         Output
               On exit: the actual number of eigenvalues within the
               interval.

           8:  R(M) -- DOUBLE PRECISION array                        Output
               On exit: the eigenvalues, not necessarily in ascending
               order.

           9:  V(IV,M) -- DOUBLE PRECISION array                     Output
               On exit: the eigenvectors, stored by columns. The ith
               column corresponds to the ith eigenvalue. The eigenvectors
               are normalised so that the sum of the squares of the
               elements are equal to 1.

          10:  IV -- INTEGER                                          Input
               On entry:
               the first dimension of the array V as declared in the
               (sub)program from which F02BBF is called.
               Constraint: IV >= N.

          11:  D(N) -- DOUBLE PRECISION array                     Workspace

          12:  E(N) -- DOUBLE PRECISION array                     Workspace

          13:  E2(N) -- DOUBLE PRECISION array                    Workspace

          14:  X(N,7) -- DOUBLE PRECISION array                   Workspace

          15:  G(N) -- DOUBLE PRECISION array                     Workspace

          16:  C(N) -- LOGICAL array                              Workspace

          17:  ICOUNT(M) -- INTEGER array                            Output
               On exit: ICOUNT(i) contains the number of iterations for
               the ith eigenvalue.

          18:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               M is less than the number of eigenvalues in the given
               interval. On exit MM contains the number of eigenvalues in
               the interval. Rerun with this value for M.

          IFAIL= 2
               More than 5 iterations are required to determine any one
               eigenvector.

          7. Accuracy

          There is no guarantee of the accuracy of the eigenvectors as the
          results depend on the original matrix and the multiplicity of the
          roots. For a detailed error analysis see Wilkinson and Reinsch
          [1] pp 222 and 436.

          8. Further Comments

                                                                          3
          The time taken by the routine is approximately proportional to n

          This subroutine should only be used when less than 25% of the
          eigenvalues and the corresponding eigenvectors are required. Also
          this subroutine is less efficient with matrices which have
          multiple eigenvalues.

          9. Example

          To calculate the eigenvalues lying between -2.0 and 3.0, and the
          corresponding eigenvectors of the real symmetric matrix:

                               ( 0.5  0.0  2.3 -2.6)
                               ( 0.0  0.5 -1.4 -0.7)
                               ( 2.3 -1.4  0.5  0.0).
                               (-2.6 -0.7  0.0  0.5)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf02bjf}{nagf.ht}
{ Eigenvalues of generalized eigenproblem  $Ax=\lambda Bx$}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf02bjf}{NAG Documentation: f02bjf}
\beginscroll
\begin{verbatim}



     F02BJF(3NAG)      Foundation Library (12/10/92)      F02BJF(3NAG)



          F02 -- Eigenvalue and Eigenvectors                         F02BJF
                  F02BJF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F02BJF calculates all the eigenvalues and, if required, all the
          eigenvectors of the generalized eigenproblem  Ax=(lambda)Bx
          where A and B are real, square matrices, using the QZ algorithm.

          2. Specification

                 SUBROUTINE F02BJF (N, A, IA, B, IB, EPS1, ALFR, ALFI,
                1                   BETA, MATV, V, IV, ITER, IFAIL)
                 INTEGER          N, IA, IB, IV, ITER(N), IFAIL
                 DOUBLE PRECISION A(IA,N), B(IB,N), EPS1, ALFR(N), ALFI(N),
                1                 BETA(N), V(IV,N)
                 LOGICAL          MATV

          3. Description

          All the eigenvalues and, if required, all the eigenvectors of the
          generalized eigenproblem Ax=(lambda)Bx where A and B are real,
          square matrices, are determined using the QZ algorithm. The QZ
          algorithm consists of 4 stages:

          (a)   A is reduced to upper Hessenberg form and at the same time
                B is reduced to upper triangular form.

          (b)   A is further reduced to quasi-triangular form while the
                triangular form of B is maintained.

          (c)   The quasi-triangular form of A is reduced to triangular
                form and the eigenvalues extracted. This routine does not
                actually produce the eigenvalues (lambda) , but instead
                                                         j
                returns (alpha)  and (beta)  such that

                               j           j
                        (lambda) =(alpha) /(beta) ,   j=1,2,...,.n
                                j        j       j
                The division by (beta)  becomes the responsibility of the
                                      j
                user's program, since (beta)  may be zero indicating an
                                            j
                infinite eigenvalue. Pairs of complex eigenvalues occur
                with (alpha) /(beta)  and (alpha)   /(beta)    complex
                            j       j            j+1       j+1

                conjugates, even though (alpha)  and (alpha)    are not
                                               j            j+1
                conjugate.

          (d)   If the eigenvectors are required (MATV = .TRUE.), they are
                obtained from the triangular matrices and then transformed
                back into the original co-ordinate system.

          4. References

          [1]   Moler C B and Stewart G W (1973) An Algorithm for
                Generalized Matrix Eigenproblems. SIAM J. Numer. Anal. 10
                241--256.

          [2]   Ward R C (1975) The Combination Shift QZ Algorithm. SIAM J.
                Numer. Anal. 12 835--853.

          [3]   Wilkinson J H (1979) Kronecker's Canonical Form and the QZ
                Algorithm. Linear Algebra and Appl. 28 285--303.

          5. Parameters

           1:  N -- INTEGER                                           Input
               On entry: n, the order of the matrices A and B.

           2:  A(IA,N) -- DOUBLE PRECISION array               Input/Output
               On entry: the n by n matrix A. On exit: the array is
               overwritten.

           3:  IA -- INTEGER                                          Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F02BJF is called.
               Constraint: IA >= N.

           4:  B(IB,N) -- DOUBLE PRECISION array               Input/Output
               On entry: the n by n matrix B. On exit: the array is
               overwritten.

           5:  IB -- INTEGER                                          Input
               On entry:
               the first dimension of the array B as declared in the
               (sub)program from which F02BJF is called.
               Constraint: IB >= N.

           6:  EPS1 -- DOUBLE PRECISION                               Input
               On entry: the tolerance used to determine negligible
               elements. If EPS1 > 0.0, an element will be considered
               negligible if it is less than EPS1 times the norm of its
               matrix. If EPS1 <= 0.0, machine precision is used in place
               of EPS1. A positive value of EPS1 may result in faster
               execution but less accurate results.

           7:  ALFR(N) -- DOUBLE PRECISION array                     Output

           8:  ALFI(N) -- DOUBLE PRECISION array                     Output
               On exit: the real and imaginary parts of (alpha) , for
                                                               j
               j=1,2,...,n.

           9:  BETA(N) -- DOUBLE PRECISION array                     Output
               On exit: (beta) , for j=1,2,...,n.
                               j

          10:  MATV -- LOGICAL                                        Input
               On entry: MATV must be set .TRUE. if the eigenvectors are
               required, otherwise .FALSE..

          11:  V(IV,N) -- DOUBLE PRECISION array                     Output
               On exit: if MATV = .TRUE., then
                    (i)if the jth eigenvalue is real, the jth column of V
                    contains its eigenvector;

                    (ii) if the jth and (j+1)th eigenvalues form a complex
                    pair, the jth and (j+1)th columns of V contain the
                    real and imaginary parts of the eigenvector associated
                    with the first eigenvalue of the pair. The conjugate
                    of this vector is the eigenvector for the conjugate
                    eigenvalue.
               Each eigenvector is normalised so that the component of
               largest modulus is real and the sum of squares of the moduli
               equal one.

               If MATV = .FALSE., V is not used.

          12:  IV -- INTEGER                                          Input
               On entry:
               the first dimension of the array V as declared in the
               (sub)program from which F02BJF is called.
               Constraint: IV >= N.

          13:  ITER(N) -- INTEGER array                              Output
               On exit: ITER(j) contains the number of iterations needed
               to obtain the jth eigenvalue. Note that the eigenvalues are
               obtained in reverse order, starting with the nth.

          14:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= i
               More than 30*N iterations are required to determine all the
               diagonal 1 by 1 or 2 by 2 blocks of the quasi-triangular
               form in the second step of the QZ algorithm. IFAIL is set to
               the index i of the eigenvalue at which this failure occurs.
               If the soft failure option is used, (alpha)  and (beta)  are
                                                          j           j
               correct for j=i+1,i+2,...,n, but V does not contain any
               correct eigenvectors.

          7. Accuracy

          The computed eigenvalues are always exact for a problem
          (A+E)x=(lambda)(B+F)x where ||E||/||A|| and ||F||/||B||
          are both of the order of max(EPS1,(epsilon)), EPS1 being defined
          as in Section 5 and (epsilon) being the machine precision.

          Note: interpretation of results obtained with the QZ algorithm
          often requires a clear understanding of the effects of small
          changes in the original data. These effects are reviewed in
          Wilkinson [3], in relation to the significance of small values of
          (alpha)  and (beta) . It should be noted that if (alpha)  and
                 j           j                                    j
          (beta)  are both small for any j, it may be that no reliance can
                j
          be placed on any of the computed eigenvalues
          (lambda) =(alpha) /(beta) . The user is recommended to study [3]
                  i        i       i
          and, if in difficulty, to seek expert advice on determining the
          sensitivity of the eigenvalues to perturbations in the data.

          8. Further Comments

                                                                          3
          The time taken by the routine is approximately proportional to n
          and also depends on the value chosen for parameter EPS1.

          9. Example

          To find all the eigenvalues and eigenvectors of Ax=(lambda) Bx
          where

                                 (3.9 12.5 -34.5 -0.5)
                                 (4.3 21.5 -47.5  7.5)
                               A=(4.3 21.5 -43.5  3.5)
                                 (4.4 26.0 -46.0  6.0)

          and

                                      (1 2 -3 1)
                                      (1 3 -5 4)
                                    B=(1 3 -4 3).
                                      (1 3 -4 4)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf02fjf}{nagf.ht}
{ Eigenvalues and eigenvectors of real sparse symmetric problem}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf02fjf}{NAG Documentation: f02fjf}
\beginscroll
\begin{verbatim}



     F02FJF(3NAG)      Foundation Library (12/10/92)      F02FJF(3NAG)



          F02 -- Eigenvalue and Eigenvectors                         F02FJF
                  F02FJF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          To find eigenvalues and eigenvectors of a real sparse symmetric
          or generalized symmetric eigenvalue problem.

          2. Specification

                 SUBROUTINE F02FJF (N, M, K, NOITS, TOL, DOT, IMAGE, MONIT,
                1                   NOVECS, X, NRX, D, WORK, LWORK, RWORK,
                2                   LRWORK, IWORK, LIWORK, IFAIL)
                 INTEGER          N, M, K, NOITS, NOVECS, NRX, LWORK,
                1                 LRWORK, IWORK(LIWORK), LIWORK, IFAIL
                 DOUBLE PRECISION TOL, DOT, X(NRX,K), D(K), WORK(LWORK),
                1                 RWORK(LRWORK)
                 EXTERNAL         DOT, IMAGE, MONIT

          3. Description

          F02FJF finds the m eigenvalues of largest absolute value and the
          corresponding eigenvectors for the real eigenvalue problem

                                  Cx=(lambda)x                          (1)

          where C is an n by n matrix such that

                                         T
                                     BC=C B                             (2)

          for a given positive-definite matrix B. C is said to be B-
          symmetric. Different specifications of C allow for the solution
          of a variety of eigenvalue problems. For example, when

                                                     T
                              C=A and B=I where   A=A

          the routine finds the m eigenvalues of largest absolute magnitude
          for the standard symmetric eigenvalue problem

                                 Ax=(lambda)x.                          (3)

          The routine is intended for the case where A is sparse.

          As a second example, when

                                          -1
                                       C=B  A

          where

                                           T
                                        A=A

          the routine finds the m eigenvalues of largest absolute magnitude
          for the generalized symmetric eigenvalue problem

                                 Ax=(lambda)Bx.                         (4)

          The routine is intended for the case where A and B are sparse.

          The routine does not require C explicitly, but C is specified via
          a user-supplied routine IMAGE which, given an n element vector z,
          computes the image w given by

                                        w=Cz.

                                                       -1
          For instance, in the above example, where C=B  A, routine IMAGE
          will need to solve the positive-definite system of equations
          Bw=Az for w.

          To find the m eigenvalues of smallest absolute magnitude of (3)
                           -1
          we can choose C=A   and hence find the reciprocals of the
          required eigenvalues, so that IMAGE will need to solve Aw=z for
                                                         -1
          w, and correspondingly for (4) we can choose C=A  B and solve
          Aw=Bz for w.

          A table of examples of choice of IMAGE is given in Table 3.1. It
          should be remembered that the routine also returns the
          corresponding eigenvectors and that B is positive-definite.
          Throughout A is assumed to be symmetric and, where necessary,
          non-singularity is also assumed.

          Eigenvalues             Problem
          Required

                      Ax=(lambda)x     (B=I)Ax=(lambda)Bx ABx=(lambda)x

          Largest     Compute          Solve              Compute
                      w=Az             Bw=Az              w=ABz

          Smallest    Solve            Solve              Solve
          (Find       Aw=z             Aw=Bz              Av=z,  Bw=(nu)
          1/(lambda))

          Furthest    Compute          Solve              Compute
          from        w=(A-(sigma)I)z  Bw=(A-(sigma)B)z   w=(AB-(sigma)I)z
          (sigma)
          (Find
          (lambda)-
          (sigma))

          Closest to Solve             Solve              Solve
          (sigma)    (A-(sigma)I)w=z   (A-(sigma)B)w=Bz   (AB-(sigma)I)w=z
          (Find 1/((
          lambda)-
          (sigma)))


                                     Table 3.1
                   The Requirement of IMAGE for Various Problems

          The matrix B also need not be supplied explicitly, but is
          specified via a user-supplied routine DOT which, given n element
                                                                 T
          vectors z and w, computes the generalized dot product w Bz.

          F02FJF is based upon routine SIMITZ (see Nikolai [1]), which is
          itself a derivative of the Algol procedure ritzit (see
          Rutishauser [4]), and uses the method of simultaneous (subspace)
          iteration. (See Parlett [2] for description, analysis and advice
          on the use of the method.)

          The routine performs simultaneous iteration on k>m vectors.
          Initial estimates to p<=k eigenvectors, corresponding to the p
          eigenvalues of C of largest absolute value, may be supplied by
          the user to F02FJF. When possible k should be chosen so that the
          kth eigenvalue is not too close to the m required eigenvalues,
          but if k is initially chosen too small then F02FJF may be re-
          entered, supplying approximations to the k eigenvectors found so
          far and with k then increased.

          At each major iteration F02FJF solves an r by r (r<=k) eigenvalue
          sub-problem in order to obtain an approximation to the
          eigenvalues for which convergence has not yet occurred. This
          approximation is refined by Chebyshev acceleration.

          4. References

          [1]   Nikolai P J (1979) Algorithm 538: Eigenvectors and
                eigenvalues of real generalized symmetric matrices by
                simultaneous iteration. ACM Trans. Math. Softw. 5 118--125.

          [2]   Parlett B N (1980) The Symmetric Eigenvalue Problem.
                Prentice-Hall.

          [3]   Rutishauser H (1969) Computational aspects of F L Bauer's
                simultaneous iteration method. Num. Math. 13 4--13.

          [4]   Rutishauser H (1970) Simultaneous iteration method for
                symmetric matrices. Num. Math. 16 205--223.

          5. Parameters

           1:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix C. Constraint: N >= 1.

           2:  M -- INTEGER                                    Input/Output
               On entry: m, the number of eigenvalues required.
                                            '
               Constraint: M >= 1. On exit: m, the number of eigenvalues
               actually found. It is equal to m if IFAIL = 0 on exit, and
               is less than m if IFAIL = 2, 3 or 4. See Section 6 and
               Section 8 for further information.

           3:  K -- INTEGER                                           Input
               On entry: the number of simultaneous iteration vectors to be
               used. Too small a value of K may inhibit convergence, while
               a larger value of K incurs additional storage and additional
               work per iteration. Suggested value: K = M + 4 will often be
               a reasonable choice in the absence of better information.
               Constraint: M < K <= N.

           4:  NOITS -- INTEGER                                Input/Output
               On entry: the maximum number of major iterations (eigenvalue
               sub-problems) to be performed. If NOITS <= 0, then the value
               100 is used in place of NOITS. On exit: the number of
               iterations actually performed.

           5:  TOL -- DOUBLE PRECISION                                Input
               On entry: a relative tolerance to be used in accepting
               eigenvalues and eigenvectors. If the eigenvalues are
               required to about t significant figures, then TOL should be
                              -t
               set to about 10  . d  is accepted as an eigenvalue as soon
                                   i
               as two successive approximations to d  differ by less than
                                                    i
                 ~                   ~
               (|d |*TOL)/10,  where d  is the latest aproximation to d .
                  i                   i                                i
               Once an eigenvalue has been accepted, then an eigenvector is
               accepted as soon as  (d f )/(d -d )<TOL, where f  is the
                                      i i    i  k              i
               normalised residual of the current approximation to the
               eigenvector (see Section 8 for further information). The
               values of the f  and d  can be printed from routine MONIT.
                              i      i
               If TOL is supplied outside the range ((epsilon), 1.0), where
               (epsilon) is the machine precision, then the value (epsilon)
               is used in place of TOL.

           6:  DOT -- DOUBLE PRECISION FUNCTION, supplied by the user.
                                                         External Procedure
                                          T
               DOT must return the value w Bz for given vectors w and z.
               For the standard eigenvalue problem, where B=I, DOT must
                                       T
               return the dot product w z.

               Its specification is:

                      DOUBLE PRECISION FUNCTION DOT (IFLAG, N, Z, W,
                     1                               RWORK, LRWORK,
                     2                               IWORK, LIWORK)
                      INTEGER          IFLAG, N, LRWORK, IWORK(LIWORK),
                     1                 LIWORK
                      DOUBLE PRECISION Z(N), W(N), RWORK(LRWORK)

                1:  IFLAG -- INTEGER                           Input/Output
                    On entry: IFLAG is always non-negative. On exit: IFLAG
                    may be used as a flag to indicate a failure in the
                                    T
                    computation of w Bz. If IFLAG is negative on exit from
                    DOT, then F02FJF will exit immediately with IFAIL set
                    to IFLAG. Note that in this case DOT must still be
                    assigned a value.

                2:  N -- INTEGER                                      Input
                    On entry: the number of elements in the vectors z and w
                    and the order of the matrix B.

                3:  Z(N) -- DOUBLE PRECISION array                    Input
                                                      T
                    On entry: the vector z for which w Bz is required.

                4:  W(N) -- DOUBLE PRECISION array                    Input
                                                      T
                    On entry: the vector w for which w Bz is required.

                5:  RWORK(LRWORK) -- DOUBLE PRECISION array  User Workspace


                6:  LRWORK -- INTEGER                                 Input


                7:  IWORK(LIWORK) -- INTEGER array           User Workspace


                8:  LIWORK -- INTEGER                                 Input
                    DOT is called from F02FJF with the parameters RWORK,
                    LRWORK, IWORK and LIWORK as supplied to F02FJF. The
                    user is free to use the arrays RWORK and IWORK to
                    supply information to DOT and to IMAGE as an
                    alternative to using COMMON.
               DOT must be declared as EXTERNAL in the (sub)program
               from which F02FJF is called. Parameters denoted as
               Input must not be changed by this procedure.

           7:  IMAGE -- SUBROUTINE, supplied by the user.
                                                         External Procedure
               IMAGE must return the vector w=Cz for a given vector z.

               Its specification is:

                      SUBROUTINE IMAGE (IFLAG, N, Z, W, RWORK, LRWORK,
                     1                  IWORK, LIWORK)
                      INTEGER          IFLAG, N, LRWORK, IWORK(LIWORK),
                     1                 LIWORK
                      DOUBLE PRECISION Z(N), W(N), RWORK(LRWORK)

                1:  IFLAG -- INTEGER                           Input/Output
                    On entry: IFLAG is always non-negative. On exit: IFLAG
                    may be used as a flag to indicate a failure in the
                    computation of w. If IFLAG is negative on exit from
                    IMAGE, then F02FJF will exit immediately with IFAIL set
                    to IFLAG.

                2:  N -- INTEGER                                      Input
                    On entry: n, the number of elements in the vectors w
                    and z, and the order of the matrix C.

                3:  Z(N) -- DOUBLE PRECISION array                    Input
                    On entry: the vector z for which Cz is required.

                4:  W(N) -- DOUBLE PRECISION array                   Output
                    On exit: the vector w=Cz.

                5:  RWORK(LRWORK) -- DOUBLE PRECISION array  User Workspace

                6:  LRWORK -- INTEGER                                 Input

                7:  IWORK(LIWORK) -- INTEGER array           User Workspace

                8:  LIWORK -- INTEGER                                 Input
                    IMAGE is called from F02FJF with the parameters RWORK,
                    LRWORK, IWORK and LIWORK as supplied to F02FJF. The
                    user is free to use the arrays RWORK and IWORK to
                    supply information to IMAGE and DOT as an alternative
                    to using COMMON.
               IMAGE must be declared as EXTERNAL in the (sub)program
               from which F02FJF is called. Parameters denoted as
               Input must not be changed by this procedure.

           8:  MONIT -- SUBROUTINE, supplied by the user.
                                                         External Procedure
               MONIT is used to monitor the progress of F02FJF. MONIT may
               be the dummy subroutine F02FJZ if no monitoring is actually
               required. (F02FJZ is included in the NAG Foundation Library
               and so need not be supplied by the user. The routine name
               F02FJZ may be implementation dependent: see the Users' Note
               for your implementation for details.) MONIT is called after
               the solution of each eigenvalue sub-problem and also just
               prior to return from F02FJF. The parameters ISTATE and
               NEXTIT allow selective printing by MONIT.

               Its specification is:

                      SUBROUTINE MONIT (ISTATE, NEXTIT, NEVALS,
                     1                  NEVECS, K, F, D)
                      INTEGER          ISTATE, NEXTIT, NEVALS, NEVECS,
                     1                 K
                      DOUBLE PRECISION F(K), D(K)

                1:  ISTATE -- INTEGER                                 Input
                    On entry: ISTATE specifies the state of F02FJF and will
                    have values as follows:
                    ISTATE = 0
                          No eigenvalue or eigenvector has just been
                          accepted.

                    ISTATE = 1
                          One or more eigenvalues have been accepted since
                          the last call to MONIT.

                    ISTATE = 2
                          One or more eigenvectors have been accepted since
                          the last call to MONIT.

                    ISTATE = 3
                          One or more eigenvalues and eigenvectors have
                          been accepted since the last call to MONIT.

                    ISTATE = 4
                          Return from F02FJF is about to occur.

                2:  NEXTIT -- INTEGER                                 Input
                    On entry: the number of the next iteration.

                3:  NEVALS -- INTEGER                                 Input
                    On entry: the number of eigenvalues accepted so far.

                4:  NEVECS -- INTEGER                                 Input
                    On entry: the number of eigenvectors accepted so far.

                5:  K -- INTEGER                                      Input
                    On entry: k, the number of simultaneous iteration
                    vectors.

                6:  F(K) -- DOUBLE PRECISION array                    Input
                    On entry: a vector of error quantities measuring the
                    state of convergence of the simultaneous iteration
                    vectors. See the parameter TOL of F02FJF above and
                    Section 8 for further details. Each element of F is
                    initially set to the value 4.0 and an element remains
                    at 4.0 until the corresponding vector is tested.

                7:  D(K) -- DOUBLE PRECISION array                    Input
                    On entry: D(i) contains the latest approximation to the
                    absolute value of the ith eigenvalue of C.
               MONIT must be declared as EXTERNAL in the (sub)program
               from which F02FJF is called. Parameters denoted as
               Input must not be changed by this procedure.

           9:  NOVECS -- INTEGER                                      Input
               On entry: the number of approximate vectors that are being
               supplied in X. If NOVECS is outside the range (0,K), then
               the value 0 is used in place of NOVECS.

          10:  X(NRX,K) -- DOUBLE PRECISION array              Input/Output
               On entry: if 0 < NOVECS <= K, the first NOVECS columns of X
               must contain approximations to the eigenvectors
               corresponding to the NOVECS eigenvalues of largest absolute
               value of C. Supplying approximate eigenvectors can be useful
               when reasonable approximations are known, or when the
               routine is being restarted with a larger value of K.
               Otherwise it is not necessary to supply approximate vectors,
               as simultaneous iteration vectors will be generated randomly
               by the routine. On exit: if IFAIL = 0, 2, 3 or 4, the first
               m' columns contain the eigenvectors corresponding to the
               eigenvalues returned in the first m' elements of D (see
               below); and the next k-m'-1 columns contain approximations
               to the eigenvectors corresponding to the approximate
               eigenvalues returned in the next k-m'-1 elements of D. Here
               m' is the value returned in M (see above), the number of
               eigenvalues actually found. The kth column is used as
               workspace.

          11:  NRX -- INTEGER                                         Input
               On entry:
               the first dimension of the array X as declared in the
               (sub)program from which F02FJF is called.
               Constraint: NRX >= N.

          12:  D(K) -- DOUBLE PRECISION array                        Output
               On exit: if IFAIL = 0, 2, 3 or 4, the first m' elements
               contain the first m' eigenvalues in decreasing order of
               magnitude; and the next k-m'-1 elements contain
               approximations to the next k-m'-1 eigenvalues. Here m' is
               the value returned in M (see above), the number of
               eigenvalues actually found. D(k) contains the value e where
               (-e,e) is the latest interval over which Chebyshev
               acceleration is performed.

          13:  WORK(LWORK) -- DOUBLE PRECISION array              Workspace

          14:  LWORK -- INTEGER                                       Input
               On entry: the length of the array WORK, as declared in the
               (sub)program from which F02FJF is called. Constraint:
               LWORK>=3*K+max(K*K,2*N).

          15:  RWORK(LRWORK) -- DOUBLE PRECISION array       User Workspace
               RWORK is not used by F02FJF, but is passed directly to
               routines DOT and IMAGE and may be used to supply information
               to these routines.

          16:  LRWORK -- INTEGER                                      Input
               On entry: the length of the array RWORK, as declared in the
               (sub)program from which F02FJF is called. Constraint: LRWORK
               >= 1.

          17:  IWORK(LIWORK) -- INTEGER array                User Workspace
               IWORK is not used by F02FJF, but is passed directly to
               routines DOT and IMAGE and may be used to supply information
               to these routines.

          18:  LIWORK -- INTEGER                                      Input
               On entry: the length of the array IWORK, as declared in the
               (sub)program from which F02FJF is called. Constraint: LIWORK
               >= 1.

          19:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. Users who are
               unfamiliar with this parameter should refer to the Essential
               Introduction for details.

               On exit: IFAIL = 0 unless the routine detects an error or
               gives a warning (see Section 6).

               For this routine, because the values of output parameters
               may be useful even if IFAIL /=0 on exit, users are
               recommended to set IFAIL to -1 before entry. It is then
               essential to test the value of IFAIL on exit. To suppress
               the output of an error message when soft failure occurs, set
               IFAIL to 1.

          6. Error Indicators and Warnings

          Errors or warnings specified by the routine:


          IFAIL< 0
               A negative value of IFAIL indicates an exit from F02FJF
               because the user has set IFLAG negative in DOT or IMAGE. The
               value of IFAIL will be the same as the user's setting of
               IFLAG.

          IFAIL= 1
               On entry N < 1,

               or       M < 1,

               or       M >= K,

               or       K > N,

               or       NRX < N,

               or       LWORK <3*K+max(K*K*N),

               or       LRWORK < 1,

               or       LIWORK < 1.

          IFAIL= 2
               Not all the requested eigenvalues and vectors have been
               obtained. Approximations to the rth eigenvalue are
               oscillating rapidly indicating that severe cancellation is
               occurring in the rth eigenvector and so M is returned as (r-
               1). A restart with a larger value of K may permit
               convergence.

          IFAIL= 3
               Not all the requested eigenvalues and vectors have been
               obtained. The rate of convergence of the remaining
               eigenvectors suggests that more than NOITS iterations would
               be required and so the input value of M has been reduced. A
               restart with a larger value of K may permit convergence.

          IFAIL= 4
               Not all the requested eigenvalues and vectors have been
               obtained. NOITS iterations have been performed. A restart,
               possibly with a larger value of K, may permit convergence.

          IFAIL= 5
               This error is very unlikely to occur, but indicates that
               convergence of the eigenvalue sub-problem has not taken
               place. Restarting with a different set of approximate
               vectors may allow convergence. If this error occurs the user
               should check carefully that F02FJF is being called
               correctly.

          7. Accuracy

          Eigenvalues and eigenvectors will normally be computed to the
          accuracy requested by the parameter TOL, but eigenvectors
          corresponding to small or to close eigenvalues may not always be
          computed to the accuracy requested by the parameter TOL. Use of
          the routine MONIT to monitor acceptance of eigenvalues and
          eigenvectors is recommended.

          8. Further Comments

          The time taken by the routine will be principally determined by
          the time taken to solve the eigenvalue sub-problem and the time
          taken by the routines DOT and IMAGE. The time taken to solve an
                                                                    2
          eigenvalue sub-problem is approximately proportional to nk . It
          is important to be aware that several calls to DOT and IMAGE may
          occur on each major iteration.

          As can be seen from Table 3.1, many applications of F02FJF will
          require routine IMAGE to solve a system of linear equations. For
          example, to find the smallest eigenvalues of Ax=(lambda)Bx, IMAGE
          needs to solve equations of the form Aw=Bz for w and routines
          from Chapters F01 and F04 of the NAG Foundation Library will
          frequently be useful in this context. In particular, if A is a
          positive-definite variable band matrix, F04MCF may be used after
          A has been factorized by F01MCF. Thus factorization need be
          performed only once prior to calling F02FJF. An illustration of
          this type of use is given in the example program in Section 9.

                           ~
          An approximation d , to the ith eigenvalue, is accepted as soon
                            h
             ~
          as d  and the previous approximation differ by less than
              h
           ~
          |d |*TOL/10. Eigenvectors are accepted in groups corresponding to
            h
          clusters of eigenvalues that are equal, or nearly equal, in
          absolute value and that have already been accepted. If d  is the
                                                                  r
          last eigenvalue in such a group and we define the residual r  as
                                                                      j

                                      r =Cx -y
                                       j   j  r

          where y  is the projection of Cx , with respect to B, onto the
                 r                        j
          space spanned by x ,x ,...,x  and x  is the current approximation
                            1  2      r      j
          to the jth eigenvector, then the value f  returned in MONIT is
                                                  i
          given by

                                                       2  T
                        f =max||r || /||Cx ||     ||x|| =x Bx
                         i       j  B     j  B         B

          and each vector in the group is accepted as an eigenvector if

                                (|d |f )/(|d |-e)<TOL
                                   r  r     r

                                                   ~
          where e is the current approximation to |d |. The values of the
                                                    k
          f  are systematically increased if the convergence criteria
           i
          appear to be too strict. See Rutishauser [4] for further details.

          The algorithm implemented by F02FJF differs slightly from SIMITZ
          (Nikolai [1]) in that the eigenvalue sub-problem is solved using
          the singular value decomposition of the upper triangular matrix R
                                                                         T
          of the Gram-Schmidt factorization of Cx , rather than forming R R
                                                 r

          9. Example

          To find the four eigenvalues of smallest absolute value and
          corresponding eigenvectors for the generalized symmetric
          eigenvalue problem Ax=(lambda)Bx, where A and B are the 16 by 16
          matrices

                           (1 a     a                      )
                           (a 1 a     a                    )
                           (  a 1 a     a                  )
                           (    a 1 a     a                )
                           (a     a 1 a     a              )
                           (  a     a 1 a     a            )
                           (    a     a 1 a     a          )
                           (      a     a 1 a     a        )
                         A=(        a     a 1 a     a      )
                           (          a     a 1 a     a    )
                           (            a     a 1 a     a  )
                           (              a     a 1 a     a)
                           (                a     a 1 a    )
                           (                  a     a 1 a  )
                           (                    a     a 1 a)
                           (                      a     a 1)

                    1
          where a=- -
                    4

                           (1 b                            )
                           (b 1 b                          )
                           (  b 1 b                        )
                           (    b 1 b                      )
                           (      b 1 b                    )
                           (        b 1 b                  )
                           (          b 1 b                )
                         B=(            b 1 b              )
                           (              b 1 b            )
                           (                b 1 b          )
                           (                  b 1 b        )
                           (                    b 1 b      )
                           (                      b 1 b    )
                           (                        b 1 b  )
                           (                          b 1 b)

                    1
          where b=- -
                    2

          TOL is taken as 0.0001 and 6 iteration vectors are used. F01MAF
          is used to factorize the matrix A, prior to calling F02FJF, and
          F04MAF is used within IMAGE to solve the equations Aw=Bz for w.
          Details of the factorization of A are passed from F01MAF to
          F04MAF by means of the COMMON block BLOCK1.

          Output from MONIT occurs each time ISTATE is non-zero. Note that
          the required eigenvalues are the reciprocals of the eigenvalues
          returned by F02FJF.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf02wef}{nagf.ht}
{ Singular value decomposition of a general real matrix}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf02wef}{NAG Documentation: f02wef}
\beginscroll
\begin{verbatim}



     F02WEF(3NAG)      Foundation Library (12/10/92)      F02WEF(3NAG)



          F02 -- Eigenvalue and Eigenvectors                         F02WEF
                  F02WEF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F02WEF returns all, or part, of the singular value decomposition
          of a general real matrix.

          2. Specification

                 SUBROUTINE F02WEF (M, N, A, LDA, NCOLB, B, LDB, WANTQ, Q,
                1                   LDQ, SV, WANTP, PT, LDPT, WORK, IFAIL)
                 INTEGER          M, N, LDA, NCOLB, LDB, LDQ, LDPT, IFAIL
                 DOUBLE PRECISION A(LDA,*), B(LDB,*), Q(LDQ,*), SV(*), PT
                1                 (LDPT,*), WORK(*)
                 LOGICAL          WANTQ, WANTP

          3. Description

          The m by n matrix A is factorized as

                                            T
                                       A=QDP ,

          where

                (S)
              D=(0),          m>n,

              D=S,            m=n,

              D=(S 0),        m<n,

          Q is an m by m orthogonal matrix, P is an n by n orthogonal
          matrix and S is a min(m,n) by min(m,n) diagonal matrix with non-
          negative diagonal elements, sv ,sv ,...,sv        , ordered such
                                        1   2       min(m,n)
          that

                            sv >=sv >=...>=sv        >=0.
                              1    2         min(m,n)

          The first min(m,n) columns of Q are the left-hand singular
          vectors of A, the diagonal elements of S are the singular values
          of A and the first min(m,n) columns of P are the right-hand
          singular vectors of A.

          Either or both of the left-hand and right-hand singular vectors
          of A may be requested and the matrix C given by

                                          T
                                       C=Q B,

          where B is an m by ncolb given matrix, may also be requested.

          The routine obtains the singular value decomposition by first
          reducing A to upper triangular form by means of Householder
          transformations, from the left when m>=n and from the right when
          m<n. The upper triangular form is then reduced to bidiagonal form
          by Givens plane rotations and finally the QR algorithm is used to
          obtain the singular value decomposition of the bidiagonal form.

          Good background descriptions to the singular value decomposition
          are given in Dongarra et al [1], Hammarling [2] and Wilkinson [3]
          DSVDC.

          Note that if K is any orthogonal diagonal matrix so that

                                         T
                                       KK =I,

          (so that K has elements +1 or -1 on the diagonal)

          then

                                               T
                                    A=(QK)D(PK)

          is also a singular value decomposition of A.

          4. References

          [1]   Dongarra J J, Moler C B, Bunch J R and Stewart G W (1979)
                LINPACK Users' Guide. SIAM, Philadelphia.

          [2]   Hammarling S (1985) The Singular Value Decomposition in
                Multivariate Statistics. ACM Signum Newsletter. 20, 3 2--25.

          [3]   Wilkinson J H (1978) Singular Value Decomposition -- Basic
                Aspects. Numerical Software -- Needs and Availability. (ed D
                A H Jacobs) Academic Press.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: the number of rows, m, of the matrix A.
               Constraint: M >= 0.

               When M = 0 then an immediate return is effected.

           2:  N -- INTEGER                                           Input
               On entry: the number of columns, n, of the matrix A.
               Constraint: N >= 0.

               When N = 0 then an immediate return is effected.

           3:  A(LDA,*) -- DOUBLE PRECISION array              Input/Output
               Note: the second dimension of the array A must be at least
               max(1,N).
               On entry: the leading m by n part of the array A must
               contain the matrix A whose singular value decomposition is
               required. On exit: if M >= N and WANTQ = .TRUE., then the
               leading m by n part of A will contain the first n columns of
               the orthogonal matrix Q.

               If M < N and WANTP = .TRUE., then the leading m by n part of
                                                                         T
               A will contain the first m rows of the orthogonal matrix P .

               If M >= N and WANTQ = .FALSE. and WANTP = .TRUE., then the
               leading n by n part of A will contain the first n rows of
                                      T
               the orthogonal matrix P .

               Otherwise the leading m by n part of A is used as internal
               workspace.

           4:  LDA -- INTEGER                                         Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F02WEF is called.
               Constraint: LDA >= max(1,M).

           5:  NCOLB -- INTEGER                                       Input
               On entry: ncolb, the number of columns of the matrix B.
               When NCOLB = 0 the array B is not referenced. Constraint:
               NCOLB >= 0.

           6:  B(LDB,*) -- DOUBLE PRECISION array              Input/Output
               Note: the second dimension of the array B must be at least
               max(1,ncolb) On entry: if NCOLB > 0, the leading m by ncolb
               part of the array B must contain the matrix to be
               transformed. On exit: B is overwritten by the m by ncolb
                        T
               matrix  Q B.

           7:  LDB -- INTEGER                                         Input
               On entry:
               the first dimension of the array B as declared in the
               (sub)program from which F02WEF is called.
               Constraint: if NCOLB > 0 then LDB >= max(1,M).

           8:  WANTQ -- LOGICAL                                       Input
               On entry: WANTQ must be .TRUE., if the left-hand singular
               vectors are required. If WANTQ = .FALSE., then the array Q
               is not referenced.

           9:  Q(LDQ,*) -- DOUBLE PRECISION array                    Output
               Note: the second dimension of the array Q must be at least
               max(1,M).
               On exit: if M < N and WANTQ = .TRUE., the leading m by m
               part of the array Q will contain the orthogonal matrix Q.
               Otherwise the array Q is not referenced.

          10:  LDQ -- INTEGER                                         Input
               On entry:
               the first dimension of the array Q as declared in the
               (sub)program from which F02WEF is called.
               Constraint: if M < N and WANTQ = .TRUE., LDQ >= max(1,M).

          11:  SV(*) -- DOUBLE PRECISION array                       Output
               Note: the length of SV must be at least min(M,N). On exit:
               the min(M,N) diagonal elements of the matrix S.

          12:  WANTP -- LOGICAL                                       Input
               On entry: WANTP must be .TRUE. if the right-hand singular
               vectors are required. If WANTP = .FALSE., then the array PT
               is not referenced.

          13:  PT(LDPT,*) -- DOUBLE PRECISION array                  Output
               Note: the second dimension of the array PT must be at least
               max(1,N).
               On exit: if M >= N and WANTQ and WANTP are .TRUE., the
               leading n by n part of the array PT will contain the
                                  T
               orthogonal matrix P . Otherwise the array PT is not
               referenced.

          14:  LDPT -- INTEGER                                        Input
               On entry:
               the first dimension of the array PT as declared in the
               (sub)program from which F02WEF is called.
               Constraint: if M >= N and WANTQ and WANTP are .TRUE., LDPT
               >= max(1,N).

          15:  WORK(*) -- DOUBLE PRECISION array                     Output
               Note: the length of WORK must be at least max(1,lwork),
               where lwork must be as given in the following table:

               M >= N
               WANTQ is .TRUE. and WANTP = .TRUE.
                                2
                     lwork=max(N +5*(N-1),N+NCOLB,4)

               WANTQ = .TRUE. and WANTP = .FALSE.
                                2
                     lwork=max(N +4*(N-1),N+NCOLB,4)

               WANTQ = .FALSE. and WANTP = .TRUE.
                     lwork=max(3*(N-1),2) when NCOLB = 0

                     lwork=max(5*(N-1),2) when NCOLB > 0

               WANTQ = .FALSE. and WANTP = .FALSE.
                     lwork=max(2*(N-1),2) when NCOLB = 0

                     lwork=max(3*(N-1),2) when NCOLB > 0

               M < N
               WANTQ = .TRUE. and WANTP = .TRUE.
                                2
                     lwork=max(M +5*(M-1),2)

               WANTQ = .TRUE. and WANTP = .FALSE.
                     lwork=max(3*(M-1),1)

               WANTQ = .FALSE. and WANTP = .TRUE.
                                2
                     lwork=max(M +3*(M-1),2) when NCOLB = 0

                                2
                     lwork=max(M +5*(M-1),2) when NCOLB > 0

               WANTQ = .FALSE. and WANTP = .FALSE.
                     lwork=max(2*(M-1),1) when NCOLB = 0

                     lwork=max(3*(M-1),1) when NCOLB > 0
               On exit: WORK(min(M,N)) contains the total number of
               iterations taken by the R algorithm.

               The rest of the array is used as workspace.

          16:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL=-1
               One or more of the following conditions holds:
                    M < 0,

                    N < 0,

                    LDA < M,

                    NCOLB < 0,

                    LDB < M and NCOLB > 0,

                    LDQ < M and M < N and WANTQ = .TRUE.,

                    LDPT < N and M >= N and WANTQ = .TRUE., and WANTP = .
                    TRUE..

          IFAIL> 0
               The QR algorithm has failed to converge in 50*min(m,n)
               iterations. In this case SV(1), SV(2),..., SV(IFAIL) may not
               have been found correctly and the remaining singular values
               may not be the smallest. The matrix A will nevertheless have
                                        T
               been factorized as  A=QEP ,  where the leading min(m,n) by
               min(m,n) part of E is a bidiagonal matrix with SV(1), SV(2),
               ..., SV(min(m,n)) as the diagonal elements and WORK(1), WORK
               (2),..., WORK(min(m,n)-1) as the super-diagonal elements.

               This failure is not likely to occur.

          7. Accuracy

          The computed factors Q, D and P satisfy the relation

                                         T
                                      QDP =A+E,

          where

                             ||E||<=c(epsilon)||A||,

          (epsilon) being the machine precision, c is a modest function of
          m and n and ||.|| denotes the spectral (two) norm. Note that
          ||A||=sv .
                  1

          8. Further Comments

          Following the use of this routine the rank of A may be estimated
          by a call to the INTEGER FUNCTION F06KLF(*). The statement:

                 IRANK = F06KLF(MIN(M, N), SV, 1, TOL)

          returns the value (k-1) in IRANK, where k is the smallest integer
          for which SV(k)<tol*SV(1), where tol is the tolerance supplied in
          TOL, so that IRANK is an estimate of the rank of S and thus also
          of A. If TOL is supplied as negative then the machine precision
          is used in place of TOL.

          9. Example

          9.1. Example 1

          To find the singular value decomposition of the 5 by 3 matrix

                                    (2.0  2.5  2.5)
                                    (2.0  2.5  2.5)
                                  A=(1.6 -0.4  2.8)
                                    (2.0 -0.5  0.5)
                                    (1.2 -0.3 -2.9)

                                    T
          together with the vector Q b for the vector

                                        ( 1.1)
                                        ( 0.9)
                                      b=( 0.6)
                                        ( 0.0)
                                        (-0.8)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

          9.2. Example 2

          To find the singular value decomposition of the 3 by 5 matrix

                               (2.0 2.0  1.6  2.0  1.2)
                             A=(2.5 2.5 -0.4 -0.5 -0.3)
                               (2.5 2.5  2.8  0.5 -2.9)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf02xef}{nagf.ht}
{ Singular value decomposition of a general complex matrix}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf02xef}{NAG Documentation: f02xef}
\beginscroll
\begin{verbatim}



     F02XEF(3NAG)      Foundation Library (12/10/92)      F02XEF(3NAG)



          F02 -- Eigenvalue and Eigenvectors                         F02XEF
                  F02XEF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F02XEF returns all, or part, of the singular value decomposition
          of a general complex matrix.

          2. Specification

                 SUBROUTINE F02XEF (M, N, A, LDA, NCOLB, B, LDB, WANTQ, Q,
                1                   LDQ, SV, WANTP, PH, LDPH, RWORK, CWORK,
                2                   IFAIL)
                 INTEGER                   M, N, LDA, NCOLB, LDB, LDQ, LDPH,
                1                          IFAIL
                 DOUBLE PRECISION          SV(*), RWORK(*)
                 COMPLEX(KIND=KIND(1.0D0)) A(LDA,*), B(LDB,*), Q(LDQ,*),
                1                          PH(LDPH,*), CWORK(*)
                 LOGICAL                   WANTQ, WANTP

          3. Description

          The m by n matrix A is factorized as

                                            H
                                       A=QDP ,

          where

                (S)
              D=(0)           m>n,

              D=S,            m=n,

              D=(S 0),        m<n,

          Q is an m by m unitary matrix, P is an n by n unitary matrix and
          S is a min(m,n) by min(m,n) diagonal matrix with real non-
          negative diagonal elements, sv ,sv ,...,sv        , ordered such
                                        1   2       min(m,n)
          that

                            sv >=sv >=...>=sv        >=0.
                              1    2         min(m,n)

          The first min(m,n) columns of Q are the left-hand singular
          vectors of A, the diagonal elements of S are the singular values
          of A and the first min(m,n) columns of P are the right-hand
          singular vectors of A.

          Either or both of the left-hand and right-hand singular vectors
          of A may be requested and the matrix C given by

                                          H
                                       C=Q B,

          where B is an m by ncolb given matrix, may also be requested.

          The routine obtains the singular value decomposition by first
          reducing A to upper triangular form by means of Householder
          transformations, from the left when m>=n and from the right when
          m<n. The upper triangular form is then reduced to bidiagonal form
          by Givens plane rotations and finally the QR algorithm is used to
          obtain the singular value decomposition of the bidiagonal form.

          Good background descriptions to the singular value decomposition
          are given in Dongarra et al [1], Hammarling [2] and Wilkinson [3]
          ZSVDC.

          Note that if K is any unitary diagonal matrix so that

                                         H
                                       KK =I,

          then

                                               H
                                    A=(QK)D(PK)

          is also a singular value decomposition of A.

          4. References

          [1]   Dongarra J J, Moler C B, Bunch J R and Stewart G W (1979)
                LINPACK Users' Guide. SIAM, Philadelphia.

          [2]   Hammarling S (1985) The Singular Value Decomposition in
                Multivariate Statistics. ACM Signum Newsletter. 20, 3 2--25.

          [3]   Wilkinson J H (1978) Singular Value Decomposition -- Basic
                Aspects. Numerical Software -- Needs and Availability. (ed D
                A H Jacobs) Academic Press.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: the number of rows, m, of the matrix A.
               Constraint: M >= 0.

               When M = 0 then an immediate return is effected.

           2:  N -- INTEGER                                           Input
               On entry: the number of columns, n, of the matrix A.
               Constraint: N >= 0.

               When N = 0 then an immediate return is effected.

           3:  A(LDA,*) -- COMPLEX(KIND(1.0D)) array           Input/Output
               Note: the second dimension of the array A must be at least
               max(1,N).
               On entry: the leading m by n part of the array A must
               contain the matrix A whose singular value decomposition is
               required. On exit: if M >= N and WANTQ = .TRUE., then the
               leading m by n part of A will contain the first n columns of
               the unitary matrix Q.
               If M < N and WANTP = .TRUE., then the leading m by n part of
                                                                      H
               A will contain the first m rows of the unitary matrix P .
               will contain the first m rows of the unitary matrix P If M
               >= N and WANTQ = .FALSE. and WANTP = .TRUE., then the
               leading n by n part of A will contain the first n
                                           H
               rows of the unitary matrix P . Otherwise the leading m by n
               part of A is used as internal workspace.

           4:  LDA -- INTEGER                                         Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F02XEF is called.
               Constraint: LDA >= max(1,M).

           5:  NCOLB -- INTEGER                                       Input
               On entry: ncolb, the number of columns of the matrix B.
               When NCOLB = 0 the array B is not referenced. Constraint:
               NCOLB >= 0.

           6:  B(LDB,*) -- COMPLEX(KIND(1.0D)) array           Input/Output
               Note: the second dimension of the array B must be at least
               max(1,NCOLB).
               On entry: if NCOLB > 0, the leading m by ncolb part of the
               array B must contain the matrix to be transformed. On exit:
                                                          H
               B is overwritten by the m by ncolb matrix Q B.

           7:  LDB -- INTEGER                                         Input
               On entry:
               the first dimension of the array B as declared in the
               (sub)program from which F02XEF is called.
               Constraint: if NCOLB > 0, then LDB >= max(1,M).

           8:  WANTQ -- LOGICAL                                       Input
               On entry: WANTQ must be .TRUE. if the left-hand singular
               vectors are required. If WANTQ = .FALSE. then the array Q is
               not referenced.

           9:  Q(LDQ,*) -- COMPLEX(KIND(1.0D)) array                 Output
               Note: the second dimension of the array Q must be at least
               max(1,M).
               On exit: if M < N and WANTQ = .TRUE., the leading m by m
               part of the array Q will contain the unitary matrix Q.
               Otherwise the array Q is not referenced.

          10:  LDQ -- INTEGER                                         Input
               On entry:
               the first dimension of the array Q as declared in the
               (sub)program from which F02XEF is called.
               Constraint: if M < N and WANTQ = .TRUE., LDQ >= max(1,M).

          11:  SV(*) -- DOUBLE PRECISION array                       Output
               Note: the length of SV must be at least min(M,N). On exit:
               the min(m,n) diagonal elements of the matrix S.

          12:  WANTP -- LOGICAL                                       Input
               On entry: WANTP must be .TRUE. if the right-hand singular
               vectors are required. If WANTP = .FALSE. then the array PH
               is not referenced.

          13:  PH(LDPH,*) -- DOUBLE PRECISION array                  Output
               Note: the second dimension of the array PH must be at least
               max(1,N).
               On exit: if M >= N and WANTQ and WANTP are .TRUE., the
               leading n by n part of the array PH will contain the unitary
                       H
               matrix P . Otherwise the array PH is not referenced.

          14:  LDPH -- INTEGER                                        Input
               On entry:
               the first dimension of the array PH as declared in the
               (sub)program from which F02XEF is called.
               Constraint: if M >= N and WANTQ and WANTP are .TRUE.,  LDPH
               >= max(1,N).

          15:  RWORK(*) -- DOUBLE PRECISION array                    Output
               Note: the length of RWORK must be at least max(1,lrwork),
               where lrwork must satisfy:
               lrwork=2*(min(M,N)-1) when
                     NCOLB = 0 and WANTQ and WANTP are .FALSE.,

               lrwork=3*(min(M,N)-1) when
                     either NCOLB = 0 and WANTQ = .FALSE. and WANTP = .
                     TRUE., or WANTP = .FALSE. and one or both of NCOLB > 0
                     and WANTQ = .TRUE.

               lrwork=5*(min(M,N)-1)
                     otherwise.
               On exit: RWORK(min(M,N)) contains the total number of
               iterations taken by the QR algorithm.

               The rest of the array is used as workspace.

          16:  CWORK(*) -- COMPLEX(KIND(1.0D)) array              Workspace
               Note: the length of CWORK must be at least max(1,lcwork),
               where lcwork must satisfy:
                             2
               lcwork=N+max(N ,NCOLB) when
                     M >= N and WANTQ and WANTP are both .TRUE.

                             2
               lcwork=N+max(N +N,NCOLB) when
                     M >= N and WANTQ = .TRUE., but WANTP = .FALSE.

               lcwork=N+max(N,NCOLB) when
                     M >= N and WANTQ = .FALSE.

                       2
               lcwork=M +M when
                     M < N and WANTP = .TRUE.

               lcwork = M when
                     M < N and WANTP = .FALSE.

          17:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL=-1
               One or more of the following conditions holds:
                    M < 0,

                    N < 0,

                    LDA < M,

                    NCOLB < 0,

                    LDB < M and NCOLB > 0,

                    LDQ < M and M < N and WANTQ = .TRUE.,

                    LDPH < N and M >= N and WANTQ = .TRUE. and WANTP = .
                    TRUE..

          IFAIL> 0
               The QR algorithm has failed to converge in 50*min(m,n)
               iterations. In this case SV(1), SV(2),..., SV(IFAIL) may not
               have been found correctly and the remaining singular values
               may not be the smallest. The matrix A will nevertheless have
                                        H
               been factorized as  A=QEP   where the leading min(m,n) by
               min(m,n) part of E is a bidiagonal matrix with SV(1), SV(2),
               ..., SV(min(m,n)) as the diagonal elements and RWORK(1),
               RWORK(2),..., RWORK(min(m,n)-1) as the super-diagonal
               elements.

               This failure is not likely to occur.

          7. Accuracy

          The computed factors Q, D and P satisfy the relation

                                         H
                                      QDP =A+E,

          where

                             ||E||<=c(epsilon)||A||,

          (epsilon) being the machine precision, c is a modest function of
          m and n and ||.|| denotes the spectral (two) norm. Note that
          ||A||=sv .
                  1

          8. Further Comments

          Following the use of this routine the rank of A may be estimated
          by a call to the INTEGER FUNCTION F06KLF(*). The statement:


                  IRANK = F06KLF(MIN(M, N), SV, 1, TOL)

          returns the value (k-1) in IRANK, where k is the smallest integer
          for which SV(k)<tol*SV(1), where tol is the tolerance supplied in
          TOL, so that IRANK is an estimate of the rank of S and thus also
          of A. If TOL is supplied as negative then the machine precision
          is used in place of TOL.

          9. Example

          9.1. Example 1

          To find the singular value decomposition of the 5 by 3 matrix

                             (    0.5i -0.5+1.5i -1.0+1.0i)
                             (0.4+0.3i  0.9+1.3i  0.2+1.4i)
                           A=(0.4      -0.4+0.4i  1.8     )
                             (0.3-0.4i  0.1+0.7i  0.0     )
                             (   -0.3i  0.3+0.3i      2.4i)

                                    H
          together with the vector Q b for the vector

                                     (-0.55+1.05i)
                                     ( 0.49+0.93i)
                                   b=( 0.56-0.16i)
                                     ( 0.39+0.23i)
                                     ( 1.13+0.83i)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

          9.2. Example 2

          To find the singular value decompostition of the 3 by 5 matrix

                   (     0.5i 0.4-0.3i  0.4      0.3+0.4i     0.3i)
                 A=(-0.5-1.5i 0.9-1.3i -0.4-0.4i 0.1-0.7i 0.3-0.3i)
                   (-1.0-1.0i 0.2-1.4i  1.8      0.0         -2.4i)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf04}{nagf.ht}{ Simultaneous Linear Equations}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf04}{NAG Documentation: f04}
\beginscroll
\begin{verbatim}



     F04(3NAG)         Foundation Library (12/10/92)         F04(3NAG)



          F04 -- Simultaneous Linear Equations          Introduction -- F04
                                    Chapter F04
                           Simultaneous Linear Equations

          1. Scope of the Chapter

          This chapter, together with two routines in Chapter F07, is
          concerned with the solution of the matrix equation AX=B, where B
          may be a single vector or a matrix of multiple right-hand sides.
          The matrix A may be real, complex, symmetric, Hermitian positive-
          definite, or sparse. It may also be rectangular, in which case a
          least-squares solution is obtained.

          2. Background to the Problems

          A set of linear equations may be written in the form

                                        Ax=b

          where the known matrix A, with real or complex coefficients, is
          of size m by n, (m rows and n columns), the known right-hand
          vector b has m components (m rows and one column), and the
          required solution vector x has n components (n rows and one
          column). There may sometimes be p vectors b , i=1,2,...,p on the
                                                     i
          right-hand side and the equations may then be written as

                                        AX=B

          the required matrix X having as its p columns the solutions of
          Ax =b , i=1,2,...,p. Some routines deal with the latter case, but
            i  i
          for clarity only the case p=1 is discussed here.

          The most common problem, the determination of the unique solution
          of Ax=b, occurs when m=n and A is non-singular, that is rank(A)=n
          problem, discussed in Section 2.2 below, is the determination of
          the least-squares solution of Ax~=b, i.e., the determination of a
          vector x which minimizes the Euclidean length (two norm) of the
          residual vector r=b-Ax. The usual case has m>n and rank(A)=n, in
          which case x is unique.

          2.1. Unique Solution of Ax=b

          Most of the routines in this chapter, as well as two routines in
          Chapter F07, solve this particular problem. The solution is
          obtained by performing either an LU factorization, or a Cholesky
          factorization, as discussed in Section 2 of the F01 Chapter
          Introduction.

          Two of the routines in this chapter use a process called
          iterative refinement to improve the initial solution in order to
          obtain a solution that is correct to working accuracy. It should
          be emphasised that if A and b are not known exactly then not all
          the figures in this solution may be meaningful. To be more
          precise, if x is the exact solution of the equations


                                        Ax=b

              

          and x is the solution of the perturbed equations

                                          

                                     (A+E)x=b+e,

                                         ||E||
          then, provided that (kappa)(A) -------<=1,
                                         ||A||

                   

                 ||x-x||        (kappa)(A)      ( ||E||   ||e|| )
                 ------- <= --------------------( ----- + ----- ),
                  ||x||                  ||E||  ( ||A||   ||b|| )
                            1-(kappa)(A) -----
                                         ||A||

                                   -1
          where (kappa)(A)=||A||||A  || is the condition number of A
          with respect to inversion. Thus, if A is ill-conditioned (
                                

          (kappa)(A) is large), x may differ significantly from x. Often
                     ||E||
          (kappa)(A) -----<<1 in which case the above bound effectively
                     ||A||
          reduces to


                        

                      ||x-x||              ( ||E||   ||e|| )
                      ------- <= (kappa)(A)( ----- + ----- ).
                       ||x||               ( ||A||   ||b|| )

          2.2. The Least-squares Solution of Ax~=b

          The least-squares problem is to find a vector x to minimize


                                  T
                                 r r,  where r=b-Ax.

          When m>=n and rank(A)=n then the solution vector x is unique. For
          the cases where x is not unique the routines in this chapter
          obtain the minimal length solution, that is the vector x for
                 T
          which x x is a minimum.

          2.3. Calculating the Inverse of a Matrix

          The routines in this chapter can also be used to calculate the
          inverse of a square matrix A by solving the equation

                                        AX=I,

          where I is the identity matrix.

          3. Recommendations on Choice and Use of Routines

          3.1. General Purpose Routines

          Many of the routines in this chapter perform the complete
          solution of the required equations, but some of the routines, as
          well as the routines in Chapter F07, assume that a prior
          factorization has been performed, using the appropriate
          factorization routine from Chapter F01 or Chapter F07. These, so-
          called, general purpose routines can be useful when explicit
          information on the factorization is required, as well as the
          solution of the equations, or when the solution is required for
          multiple right-hand sides, or for a sequence of right-hand sides.

          Note that some of the routines that perform a complete solution
          also allow multiple right-hand sides.

          3.2. Iterative Refinement

          The routines that perform iterative refinement are more costly
          than those that do not perform iterative refinement, both in
          terms of time and storage, and should only be used if the problem
          really warrants the additional accuracy provided by these
          routines. The storage requirements are approximately doubled,
          while the additional time is not usually prohibitive since the
          initial factorization is used at each iteration.

          3.3. Sparse Matrix Routines

          The routines for sparse matrices should usually be used only when
          the number of non-zero elements is very small, less than 10% of
          the total number of elements of A. Additionally, when the matrix
          is symmetric positive-definite the sparse routines should
          generally be used only when A does not have a (variable) band
          structure.

          There are four routines for solving sparse linear equations, two
          for solving general real systems (F04AXF and F04QAF), one for
          solving symmetric positive-definite systems (F04MAF) and one for
          solving symmetric systems that may, or may not, be positive-
          definite (F04MBF). F04AXF and F04MAF utilise factorizations of
          the matrix A obtained by routines in Chapter F01, while the other
          two routines use iterative techniques and require a user-supplied
                                                             T
          function to compute matrix-vector products Ac and A c for any
          given vector c. The routines requiring factorizations will
          usually be faster and the factorization can be utilised to solve
          for several right-hand sides, but the original matrix has to be
          explicitly supplied and is overwritten by the factorization, and
          the storage requirements will usually be substantially more than
          those of the iterative routines.

          Routines F04MBF and F04QAF both allow the user to supply a pre-
          conditioner.

          F04MBF can be used to solve systems of the form (A-(lambda)I)x=b,
          which can be useful in applications such as Rayleigh quotient
          iteration.

          F04QAF also solves sparse least-squares problems and allows the
          solution of damped (regularized) least-squares problems.

          3.4. Decision Trees

          If at any stage the answer to a question is 'Don't know' this
          should be read as 'No'.

          For those routines that need to be preceded by a factorization
          routine, the appropriate routine name is given in brackets after
          the name of the routine for solving the equations. Note also that
          you may be directed to a routine in Chapter F07.


          3.4.1. Routines for unique solution of Ax=b


                   Please see figure in printed Reference Manual



          3.4.2.  Routines for Least-squares problems


                   Please see figure in printed Reference Manual




          F04 -- Simultaneous Linear Equations              Contents -- F04
          Chapter F04

          Eigenvalues and Eigenvectors

          F04ADF  Approximate solution of complex simultaneous linear
                  equations with multiple right-hand sides

          F04ARF  Approximate solution of real simultaneous linear
                  equations, one right-hand side

          F04ASF  Accurate solution of real symmetric positive-definite
                  simultaneous linear equations, one right-hand side

          F04ATF  Accurate solution of real simultaneous linear equations,
                  one right-hand side

          F04AXF  Approximate solution of real sparse simultaneous linear
                  equations (coefficient matrix already factorized by
                  F01BRF or F01BSF)

          F04FAF  Approximate solution of real symmetric positive-definite
                  tridiagonal simultaneous linear equations, one right-hand
                  side

          F04JGF  Least-squares (if rank = n) or minimal least-squares (if
                  rank <n) solution of m real equations in n unknowns, rank
                  <=n, m>=n

          F04MAF  Real sparse symmetric positive-definite simultaneous
                  linear equations (coefficient matrix already factorized)

          F04MBF  Real sparse symmetric simultaneous linear equations

          F04MCF  Approximate solution of real symmetric positive-definite
                  variable-bandwidth simultaneous linear equations
                  (coefficient matrix already factorized)

          F04QAF  Sparse linear least-squares problem, m real equations in
                  n unknowns

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf04adf}{nagf.ht}
{ Approximate solution of a set of complex linear equations}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf04adf}{NAG Documentation: f04adf}
\beginscroll
\begin{verbatim}



     F04ADF(3NAG)      Foundation Library (12/10/92)      F04ADF(3NAG)



          F04 -- Simultaneous Linear Equations                       F04ADF
                  F04ADF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F04ADF calculates the approximate solution of a set of complex
          linear equations with multiple right-hand sides, using an LU
          factorization with partial pivoting.

          2. Specification

                 SUBROUTINE F04ADF (A, IA, B, IB, N, M, C, IC, WKSPCE,
                1                   IFAIL)
                 INTEGER              IA, IB, N, M, IC, IFAIL
                 DOUBLE PRECISION     WKSPCE(*)
                 COMPLEX(KIND(1.0D0)) A(IA,*), B(IB,*), C(IC,*)

          3. Description

          Given a set of complex linear equations AX=B, the routine first
          computes an LU factorization of A with partial pivoting, PA=LU,
          where P is a permutation matrix, L is lower triangular and U is
          unit upper triangular. The columns x of the solution X are found
          by forward and backward substitution in Ly=Pb and Ux=y, where b
          is a column of the right-hand side matrix B.

          4. References

          [1]   Wilkinson J H and Reinsch C (1971) Handbook for Automatic
                Computation II, Linear Algebra. Springer-Verlag.

          5. Parameters

           1:  A(IA,*) -- COMPLEX(KIND(1.0D)) array            Input/Output
               Note: the second dimension of the array A must be at least
               max(1,N).
               On entry: the n by n matrix A. On exit: A is overwritten by
               the lower triangular matrix L and the off-diagonal elements
               of the upper triangular matrix U. The unit diagonal elements
               of U are not stored.

           2:  IA -- INTEGER                                          Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F04ADF is called.
               Constraint: IA >= max(1,N).

           3:  B(IB,*) -- COMPLEX(KIND(1.0D)) array                   Input
               Note: the second dimension of the array B must be at least
               max(1,M).
               On entry: the n by m right-hand side matrix B. See also
               Section 8.

           4:  IB -- INTEGER                                          Input
               On entry:
               the first dimension of the array B as declared in the
               (sub)program from which F04ADF is called.
               Constraint: IB >= max(1,N).

           5:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A. Constraint: N >= 0.

           6:  M -- INTEGER                                           Input
               On entry: m, the number of right-hand sides. Constraint: M
               >= 0.

           7:  C(IC,*) -- COMPLEX(KIND(1.0D)) array                  Output
               Note: the second dimension of the array C must be at least
               max(1,M).
               On exit: the n by m solution matrix X. See also Section 8.

           8:  IC -- INTEGER                                          Input
               On entry:
               the first dimension of the array C as declared in the
               (sub)program from which F04ADF is called.
               Constraint: IC >= max(1,N).

           9:  WKSPCE(*) -- DOUBLE PRECISION array                Workspace
               Note: the dimension of the array WKSPCE must be at least
               max(1,N).

          10:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               The matrix A is singular, possibly due to rounding errors.

          IFAIL= 2
               On entry N < 0,

               or       M < 0,

               or       IA < max(1,N),

               or       IB < max(1,N),

               or       IC < max(1,N).

          7. Accuracy

          The accuracy of the computed solution depends on the conditioning
          of the original matrix. For a detailed error analysis see
          Wilkinson and Reinsch [1] page 106.

          8. Further Comments

                                                                          3
          The time taken by the routine is approximately proportional to n

          Unless otherwise stated in the Users' Note for your
          implementation, the routine may be called with the same actual
          array supplied for parameters B and C, in which case the solution
          vectors will overwrite the right-hand sides. However this is not
          standard Fortran 77, and may not work on all systems.

          9. Example

          To solve the set of linear equations AX=B where

                                   (1  1+2i  2+10i)
                                 A=(1+i  3i -5+14i)
                                   (1+i  5i -8+20i)

          and


                                         (1)
                                       B=(0).
                                         (0)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf04arf}{nagf.ht}
{ Approximate solution of a set of real linear equations}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf04arf}{NAG Documentation: f04arf}
\beginscroll
\begin{verbatim}



     F04ARF(3NAG)      Foundation Library (12/10/92)      F04ARF(3NAG)



          F04 -- Simultaneous Linear Equations                       F04ARF
                  F04ARF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F04ARF calculates the approximate solution of a set of real
          linear equations with a single right-hand side, using an LU
          factorization with partial pivoting.

          2. Specification

                 SUBROUTINE F04ARF (A, IA, B, N, C, WKSPCE, IFAIL)
                 INTEGER          IA, N, IFAIL
                 DOUBLE PRECISION A(IA,*), B(*), C(*), WKSPCE(*)

          3. Description

          Given a set of linear equations, Ax=b, the routine first computes
          an LU factorization of A with partial pivoting, PA=LU, where P is
          a permutation matrix, L is lower triangular and U is unit upper
          triangular. The approximate solution x is found by forward and
          backward substitution in Ly=Pb and Ux=y, where b is the right-
          hand side.

          4. References

          [1]   Wilkinson J H and Reinsch C (1971) Handbook for Automatic
                Computation II, Linear Algebra. Springer-Verlag.

          5. Parameters

           1:  A(IA,*) -- DOUBLE PRECISION array               Input/Output
               Note: the second dimension of the array A must be at least
               max(1,N).
               On entry: the n by n matrix A. On exit: A is overwritten by
               the lower triangular matrix L and the off-diagonal elements
               of the upper triangular matrix U. The unit diagonal elements
               of U are not stored.

           2:  IA -- INTEGER                                          Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F04ARF is called.
               Constraint: IA >= max(1,N).

           3:  B(*) -- DOUBLE PRECISION array                         Input
               Note: the dimension of the array B must be at least
               max(1,N).
               On entry: the right-hand side vector b.

           4:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A. Constraint: N >= 0.

           5:  C(*) -- DOUBLE PRECISION array                        Output
               Note: the dimension of the array C must be at least
               max(1,N).
               On exit: the solution vector x.

           6:  WKSPCE(*) -- DOUBLE PRECISION array                Workspace
               Note: the dimension of the array WKSPCE must be at least
               max(1,N).

           7:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               The matrix A is singular, possibly due to rounding errors.

          IFAIL= 2
               On entry N < 0,

               or       IA < max(1,N).

          7. Accuracy

          The accuracy of the computed solution depends on the conditioning
          of the original matrix. For a detailed error analysis see
          Wilkinson and Reinsch [1] page 107.

          8. Further Comments

                                                                          3
          The time taken by the routine is approximately proportional to n

          Unless otherwise stated in the Users' Note for your
          implementation, the routine may be called with the same actual
          array supplied for parameters B and C, in which case the solution
          vector will overwrite the right-hand side. However this is not
          standard Fortran 77, and may not work on all systems.

          9. Example

          To solve the set of linear equations Ax=b where

                                     ( 33  16  72)
                                   A=(-24 -10 -57)
                                     ( -8  -4 -17)

          and


                                        (-359)
                                      b=( 281).
                                        (  85)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf04asf}{nagf.ht}
{ Real symmetric positive-definite linear equations}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf04asf}{NAG Documentation: f04asf}
\beginscroll
\begin{verbatim}



     F04ASF(3NAG)      Foundation Library (12/10/92)      F04ASF(3NAG)



          F04 -- Simultaneous Linear Equations                       F04ASF
                  F04ASF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F04ASF calculates the accurate solution of a set of real
          symmetric positive-definite linear equations with a single right-
          hand side,  Ax=b, using a Cholesky factorization and iterative
          refinement.

          2. Specification

                 SUBROUTINE F04ASF (A, IA, B, N, C, WK1, WK2, IFAIL)
                 INTEGER          IA, N, IFAIL
                 DOUBLE PRECISION A(IA,*), B(*), C(*), WK1(*), WK2(*)

          3. Description

          Given a set of real linear equations Ax=b, where A is a symmetric
          positive-definite matrix, the routine first computes a Cholesky
                                    T
          factorization of A as A=LL  where L is lower triangular. An
          approximation to x is found by forward and backward substitution.
          The residual vector r=b-Ax is then calculated using additional
                                                                  T
          precision and a correction d to x is found by solving LL d=r. x
          is then replaced by x+d, and this iterative refinement of the
          solution is repeated until machine accuracy is obtained.

          4. References

          [1]   Wilkinson J H and Reinsch C (1971) Handbook for Automatic
                Computation II, Linear Algebra. Springer-Verlag.

          5. Parameters

           1:  A(IA,*) -- DOUBLE PRECISION array               Input/Output
               Note: the second dimension of the array A must be at least
               max(1,N).
               On entry: the upper triangle of the n by n positive-definite
               symmetric matrix A. The elements of the array below the
               diagonal need not be set. On exit: the elements of the array
               below the diagonal are overwritten; the upper triangle of A
               is unchanged.

           2:  IA -- INTEGER                                          Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F04ASF is called.
               Constraint: IA >= max(1,N).

           3:  B(*) -- DOUBLE PRECISION array                         Input
               Note: the dimension of the array B must be at least
               max(1,N).
               On entry: the right-hand side vector b.

           4:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A. Constraint: N >= 0.

           5:  C(*) -- DOUBLE PRECISION array                        Output
               Note: the dimension of the array C must be at least
               max(1,N).
               On exit: the solution vector x.

           6:  WK1(*) -- DOUBLE PRECISION array                   Workspace
               Note: the dimension of the array WK1 must be at least
               max(1,N).

           7:  WK2(*) -- DOUBLE PRECISION array                   Workspace
               Note: the dimension of the array WK2 must be at least
               max(1,N).

           8:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               The matrix A is not positive-definite, possibly due to
               rounding errors.

          IFAIL= 2
               Iterative refinement fails to improve the solution, i.e.,
               the matrix A is too ill-conditioned.

          IFAIL= 3
               On entry N < 0,

               or       IA < max(1,N).

          7. Accuracy

          The computed solutions should be correct to full machine
          accuracy. For a detailed error analysis see Wilkinson and Reinsch
          [1] page 39.

          8. Further Comments

                                                                          3
          The time taken by the routine is approximately proportional to n

          The routine must not be called with the same name for parameters
          B and C.

          9. Example

          To solve the set of linear equations Ax=b where

                                     (5  7  6  5)
                                     (7 10  8  7)
                                   A=(6  8 10  9)
                                     (5  7  9 10)

          and


                                         (23)
                                         (32)
                                       b=(33).
                                         (31)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf04atf}{nagf.ht}
{ Set of real linear equations with a single right-hand side}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf04atf}{NAG Documentation: f04atf}
\beginscroll
\begin{verbatim}



     F04ATF(3NAG)      Foundation Library (12/10/92)      F04ATF(3NAG)



          F04 -- Simultaneous Linear Equations                       F04ATF
                  F04ATF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F04ATF calculates the accurate solution of a set of real linear
          equations with a single right-hand side, using an LU
          factorization with partial pivoting, and iterative refinement.

          2. Specification

                 SUBROUTINE F04ATF (A, IA, B, N, C, AA, IAA, WKS1, WKS2,
                1                   IFAIL)
                 INTEGER          IA, N, IAA, IFAIL
                 DOUBLE PRECISION A(IA,*), B(*), C(*), AA(IAA,*), WKS1(*),
                1                 WKS2(*)

          3. Description

          Given a set of real linear equations, Ax=b, the routine first
          computes an LU factorization of A with partial pivoting, PA=LU,
          where P is a permutation matrix, L is lower triangular and U is
          unit upper triangular. An approximation to x is found by forward
          and backward substitution in Ly=Pb and Ux=y. The residual vector
          r=b-Ax is then calculated using additional precision, and a
          correction d to x is found by solving LUd=r. x is replaced by x+d
          , and this iterative refinement of the solution is repeated until
          full machine accuracy is obtained.

          4. References

          [1]   Wilkinson J H and Reinsch C (1971) Handbook for Automatic
                Computation II, Linear Algebra. Springer-Verlag.

          5. Parameters

           1:  A(IA,*) -- DOUBLE PRECISION array                      Input
               Note: the second dimension of the array A must be at least
               max(1,N).
               On entry: the n by n matrix A.

           2:  IA -- INTEGER                                          Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F04ATF is called.
               Constraint: IA >= max(1,N).

           3:  B(*) -- DOUBLE PRECISION array                         Input
               Note: the dimension of the array B must be at least
               max(1,N).
               On entry: the right-hand side vector b.

           4:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A. Constraint: N >= 0.

           5:  C(*) -- DOUBLE PRECISION array                        Output
               Note: the dimension of the array C must be at least
               max(1,N).
               On exit: the solution vector x.

           6:  AA(IAA,*) -- DOUBLE PRECISION array                   Output
               Note: the second dimension of the array AA must be at least
               max(1,N).
               On exit: the triangular factors L and U, except that the
               unit diagonal elements of U are not stored.

           7:  IAA -- INTEGER                                         Input
               On entry:
               the first dimension of the array AA as declared in the
               (sub)program from which F04ATF is called.
               Constraint: IAA >= max(1,N).

           8:  WKS1(*) -- DOUBLE PRECISION array                  Workspace
               Note: the dimension of the array WKS1 must be at least
               max(1,N).

           9:  WKS2(*) -- DOUBLE PRECISION array                  Workspace
               Note: the dimension of the array WKS2 must be at least
               max(1,N).

          10:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               The matrix A is singular, possibly due to rounding errors.

          IFAIL= 2

               Iterative refinement fails to improve the solution, i.e.,
               the matrix A is too ill-conditioned.

          IFAIL= 3
               On entry N < 0,

               or       IA < max(1,N),

               or       IAA < max(1,N).

          7. Accuracy

          The computed solutions should be correct to full machine
          accuracy. For a detailed error analysis see Wilkinson and Reinsch
          [1] page 107.

          8. Further Comments

                                                                          3
          The time taken by the routine is approximately proportional to n

          The routine must not be called with the same name for parameters
          B and C.

          9. Example

          To solve the set of linear equations Ax=b where

                                     ( 33  16  72)
                                   A=(-24 -10 -57)
                                     ( -8  -4 -17)

          and


                                        (-359)
                                      b=( 281).
                                        (  85)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf04axf}{nagf.ht}
{ Solution of a set of real sparse linear equations}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf04axf}{NAG Documentation: f04axf}
\beginscroll
\begin{verbatim}



     F04AXF(3NAG)      Foundation Library (12/10/92)      F04AXF(3NAG)



          F04 -- Simultaneous Linear Equations                       F04AXF
                  F04AXF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F04AXF calculates the approximate solution of a set of real
          sparse linear equations with a single right-hand side, Ax=b or
           T
          A x=b, where A has been factorized by F01BRF or F01BSF.

          2. Specification

                 SUBROUTINE F04AXF (N, A, LICN, ICN, IKEEP, RHS, W, MTYPE,
                1                   IDISP, RESID)
                 INTEGER          N, LICN, ICN(LICN), IKEEP(5*N), MTYPE,
                1                 IDISP(2)
                 DOUBLE PRECISION A(LICN), RHS(N), W(N), RESID

          3. Description

                                                              T
          To solve a system of real linear equations Ax=b or A x=b, where A
          is a general sparse matrix, A must first be factorized by F01BRF
          or F01BSF. F04AXF then computes x by block forward or backward
          substitution using simple forward and backward substitution
          within each diagonal block.

          The method is fully described in Duff [1].

          4. References

          [1]   Duff I S (1977) MA28 -- a set of Fortran subroutines for
                sparse unsymmetric linear equations. A.E.R.E. Report R.8730.
                HMSO.

          5. Parameters

           1:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A.

           2:  A(LICN) -- DOUBLE PRECISION array                      Input
               On entry: the non-zero elements in the factorization of the
               matrix A, as returned by F01BRF or F01BSF.

           3:  LICN -- INTEGER                                        Input
               On entry:
               the dimension of the arrays A and ICN as declared in the
               (sub)program from which F04AXF is called.

           4:  ICN(LICN) -- INTEGER array                             Input
               On entry: the column indices of the non-zero elements of
               the factorization, as returned by F01BRF or F01BSF.

           5:  IKEEP(5*N) -- INTEGER array                            Input
               On entry: the indexing information about the factorization,
               as returned by F01BRF or F01BSF.

           6:  RHS(N) -- DOUBLE PRECISION array                Input/Output
               On entry: the right-hand side vector b. On exit: RHS is
               overwritten by the solution vector x.

           7:  W(N) -- DOUBLE PRECISION array                     Workspace

           8:  MTYPE -- INTEGER                                       Input
               On entry: MTYPE specifies the task to be performed:
                    if MTYPE = 1, solve Ax=b,

                                          T
                    if MTYPE /= 1, solve A x=b.

           9:  IDISP(2) -- INTEGER array                              Input
               On entry: the values returned in IDISP by F01BRF.

          10:  RESID -- DOUBLE PRECISION                             Output
               On exit: the value of the maximum residual,
                        --
               max(|b - > a  x |), over all the unsatisfied equations, in
                     i  -- ij j
                        j
               case F01BRF or F01BSF has been used to factorize a singular
               or rectangular matrix.

          6. Error Indicators and Warnings

          None.

          7. Accuracy

          The accuracy of the computed solution depends on the conditioning
          of the original matrix. Since F04AXF is always used with either
          F01BRF or F01BSF, the user is recommended to set GROW = .TRUE. on
          entry to these routines and to examine the value of W(1) on exit
          (see the routine documents for F01BRF and F01BSF). For a detailed
          error analysis see Duff [1] page 17.

          If storage for the original matrix is available then the error
          can be estimated by calculating the residual

                                                T
                                 r=b-Ax  (or b-A x)

          and calling F04AXF again to find a correction (delta) for x by
          solving

                                             T
                            A(delta)=r  (or A (delta)=r).

          8. Further Comments

          If the factorized form contains (tau) non-zeros (IDISP(2) = (tau)
          ) then the time taken is very approximately 2(tau) times longer
          than the inner loop of full matrix code. Some advantage is taken
                                                        T
          of zeros in the right-hand side when solving A x=b (MTYPE /= 1).

          9. Example

          To solve the set of linear equations Ax=b where

                                  ( 5  0  0  0 0  0)
                                  ( 0  2 -1  2 0  0)
                                  ( 0  0  3  0 0  0)
                                A=(-2  0  0  1 1  0)
                                  (-1  0  0 -1 2 -3)
                                  (-1 -1  0  0 0  6)

          and


                                         (15)
                                         (12)
                                         (18)
                                       b=( 3).
                                         (-6)
                                         ( 0)

          The non-zero elements of A and indexing information are read in
          by the program, as described in the document for F01BRF.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf04faf}{nagf.ht}
{ Real symmetric positive-definite tridiagonal linear equations}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf04faf}{NAG Documentation: f04faf}
\beginscroll
\begin{verbatim}



     F04FAF(3NAG)      Foundation Library (12/10/92)      F04FAF(3NAG)



          F04 -- Simultaneous Linear Equations                       F04FAF
                  F04FAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F04FAF calculates the approximate solution of a set of real
          symmetric positive-definite tridiagonal linear equations.

          2. Specification

                 SUBROUTINE F04FAF (JOB, N, D, E, B, IFAIL)
                 INTEGER          JOB, N, IFAIL
                 DOUBLE PRECISION D(N), E(N), B(N)

          3. Description

          F04FAF is based upon the Linpack routine DPTSL (see Dongarra et
          al [1]) and solves the equations

                                        Tx=b,

          where T is a real n by n symmetric positive-definite tridiagonal
          matrix, using a modified symmetric Gaussian elimination algorithm
                                 T
          to factorize T as T=MKM , where K is diagonal and M is a matrix
          of multipliers as described in Section 8.

          When the input parameter JOB is supplied as 1, then the routine
          assumes that a previous call to F04FAF has already factorized T;
          otherwise JOB must be supplied as 0.

          4. References

          [1]   Dongarra J J, Moler C B, Bunch J R and Stewart G W (1979)
                LINPACK Users' Guide. SIAM, Philadelphia.

          5. Parameters

           1:  JOB -- INTEGER                                         Input
               On entry: specifies the job to be performed by F04FAF as
               follows:
               JOB = 0
                     The matrix T is factorized and the equations Tx=b are
                     solved for x.

               JOB = 1
                     The matrix T is assumed to have already been
                     factorized by a previous call to F04FAF with JOB = 0;
                     the equations Tx=b are solved for x.

           2:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix T. Constraint: N >= 1.

           3:  D(N) -- DOUBLE PRECISION array                  Input/Output
               On entry: if JOB = 0, D must contain the diagonal elements
               of T. If JOB = 1, D must contain the diagonal matrix K, as
               returned by a previous call of F04FAF with JOB = 0. On
               exit: if JOB = 0, D is overwritten by the diagonal matrix K
               of the factorization. If JOB = 1, D is unchanged.

           4:  E(N) -- DOUBLE PRECISION array                  Input/Output
               On entry: if JOB = 0, E must contain the super-diagonal
               elements of T, stored in E(2) to E(n). If JOB = 1, E must
               contain the off-diagonal elements of the matrix M, as
               returned by a previous call of F04FAF with JOB = 0. E(1) is
               not used. On exit: if JOB = 0, E(2) to E(n) are overwritten
               by the off-diagonal elements of the matrix M of the
               factorization. If JOB = 1, E is unchanged.

           5:  B(N) -- DOUBLE PRECISION array                  Input/Output
               On entry: the right-hand side vector b. On exit: B is
               overwritten by the solution vector x.

           6:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               On entry N < 1,

               or       JOB /= 0 or 1.

          IFAIL= 2
               The matrix T is either not positive-definite or is nearly
               singular. This failure can only occur when JOB = 0 and
               inspection of the elements of D will give an indication of
               why failure has occurred. If an element of D is close to
               zero, then T is probably nearly singular; if an element of D
               is negative but not close to zero, then T is not positive-
               definite.

          IFAILOverflow
               If overflow occurs during the execution of this routine,
               then either T is very nearly singular or an element of the
               right-hand side vector b is very large. In this latter case
               the equations should be scaled so that no element of b is
               very large. Note that to preserve symmetry it is necessary
                                                            T
               to scale by a transformation of the form (PTP )b=Px, where P
               is a diagonal matrix.

          IFAILUnderflow
               Any underflows that occur during the execution of this
               routine are harmless.

          7. Accuracy

          The computed factorization (see Section 8) will satisfy the
          equation

                                         T
                                      MKM =T+E

          where ||E|| <=2(epsilon)||T|| , p=1,F,infty,
                     p                 p

          (epsilon) being the machine precision. The computed solution of
                                  

          the equations Tx=b, say x, will satisfy an equation of the form

                                           

                                      (T+F)x=b,

          where F can be expected to satisfy a bound of the form

                          ||F||<=(alpha)(epsilon)||T||,

          (alpha) being a modest constant. This implies that the relative
                   

          error in x satisfies

                              

                           ||x-x||
                           -------<=c(T)(alpha)(epsilon),
                            ||x||

          where c(T) is the condition number of T with respect to
                                                   

          inversion. Thus if T is nearly singular, x can be expected to
          have a large relative error.

          8. Further Comments

          The time taken by the routine is approximately proportional to n.

          The routine eliminates the off-diagonal elements of T by
          simultaneously performing symmetric Gaussian elimination from the
          top and the bottom of T. The result is that T is factorized as

                                            T
                                       T=MKM ,

          where K is a diagonal matrix and M is a matrix of the form

                           (1  0  0 ..  0    0 0    .. 0 0    0 )
                           (m  1  0 ..  0    0 0    .. 0 0    0 )
                           ( 2                                  )
                           (0  m  1 ..  0    0 0    .. 0 0    0 )
                           (    3                               )
                           (.  .  . ..  .    . .    .. . .    . )
                           (.  .  . ..  .    . .    .. . .    . )
                           (0  0  0 ..  1    0 0    .. 0 0    0 )
                         M=(0  0  0 ..  m    1 m    .. 0 0    0 )
                           (             j+1    j+2             )
                           (0  0  0 ..  0    0 ..   1 0  0    0 )
                           (.  .  . ..  .    . .    .. . .    . )
                           (.  .  . ..  .    . .    .. . .    . )
                           (0  0  0 ..  0    0 0    .. 1 m    0 )
                           (                              n-1   )
                           (0  0  0 ..  0    0 0    .. 0 1    m )
                           (                                   n)
                           (0  0  0 ..  0    0 0 .   . 0 0    1 )

          j being the integer part of n/2. (For example when n=5,j=2.) The
          diagonal elements of K are returned in D with k  in the ith
                                                         i
          element of D and m  is returned in the ith element of E.
                            i

          The routine fails with IFAIL = 2 if any diagonal element of K is
          non-positive. It should be noted that T may be nearly singular
          even if all the diagonal elements of K are positive, but in this
          case at least one element of K is almost certain to be small
          relative to |||T|||. If there is any doubt as to whether or not T
          is nearly singular, then the user should consider examining the
          diagonal elements of K.

          9. Example

          To solve the symmetric positive-definite equations

                                       Tx =b
                                         1  1

          and

                                       Tx =b
                                         2  2

          where

                         ( 4 -2  0  0 0)       ( 6)      (10)
                         (-2 10 -6  0 0)       ( 9)      ( 4)
                       T=( 0 -6 29 15 0),   b =( 2),  b =( 9).
                         ( 0  0 15 25 8)     1 (14)    2 (65)
                         ( 0  0  0  8 5)       ( 7)      (23)

          The equations are solved by two calls to F04FAF, the first with
          JOB = 0 and the second, using the factorization from the first
          call, with JOB = 1.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf04jgf}{nagf.ht}
{ Solution of a linear least-squares problem, $Ax=b$}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf04jgf}{NAG Documentation: f04jgf}
\beginscroll
\begin{verbatim}



     F04JGF(3NAG)      Foundation Library (12/10/92)      F04JGF(3NAG)



          F04 -- Simultaneous Linear Equations                       F04JGF
                  F04JGF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F04JGF finds the solution of a linear least-squares problem, Ax=b
          , where A is a real m by n (m>=n) matrix and b is an m element
          vector. If the matrix of observations is not of full rank, then
          the minimal least-squares solution is returned.

          2. Specification

                 SUBROUTINE F04JGF (M, N, A, NRA, B, TOL, SVD, SIGMA,
                1                   IRANK, WORK, LWORK, IFAIL)
                 INTEGER          M, N, NRA, IRANK, LWORK, IFAIL
                 DOUBLE PRECISION A(NRA,N), B(M), TOL, SIGMA, WORK(LWORK)
                 LOGICAL          SVD

          3. Description

          The minimal least-squares solution of the problem Ax=b is the
          vector x of minimum (Euclidean) length which minimizes the length
          of the residual vector r=b-Ax.

          The real m by n (m>=n) matrix A is factorized as

                                          (U)
                                       A=Q(0)

          where Q is an m by m orthogonal matrix and U is an n by n upper
          triangular matrix. If U is of full rank, then the least-squares
          solution is given by

                                        -1    T
                                    x=(U   0)Q b.

          If U is not of full rank, then the singular value decomposition
          of U is obtained so that U is factorized as

                                            T
                                       U=RDP ,

          where R and P are n by n orthogonal matrices and D is the n by n
          diagonal matrix

                       D=diag((sigma) ,(sigma) ,...,(sigma) ),
                                     1        2            n

          with (sigma) >=(sigma) >=...(sigma) >=0, these being the singular
                      1         2            n
          values of A. If the singular values (sigma)   ,...,(sigma)  are
                                                     k+1            n
          negligible, but (sigma)  is not negligible, relative to the data
                                 k
          errors in A, then the rank of A is taken to be k and the minimal
          least-squares solution is given by

                                   ( -1  )( T  )
                                   (S   0)(R  0) T
                                x=P(0 0  )(0 I )Q b,

          where S=diag((sigma) ,(sigma) ,...,(sigma) ).
                              1        2            k

          This routine obtains the factorizations by a call to F02WDF(*).

          The routine also returns the value of the standard error


                      /  T
                     /  r r
          (sigma)=  /   --- ,     if m>k,
                  \/    m-k

                                           T
                 =  0,            if m=k, r r being the residual sum of
                                  squares and k the rank of A.

          4. References

          [1]   Lawson C L and Hanson R J (1974) Solving Least-squares
                Problems. Prentice-Hall.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: m, the number of rows of A. Constraint: M >= N.

           2:  N -- INTEGER                                           Input
               On entry: n, the number of columns of A. Constraint: 1 <= N
               <= M.

           3:  A(NRA,N) -- DOUBLE PRECISION array              Input/Output
               On entry: the m by n matrix A. On exit: if SVD is returned
               as .FALSE., A} is overwritten by details of the QU
               factorization of A (see F02WDF(*) for further details). If
               SVD is returned as .TRUE., the first n rows of A are
               overwritten by the right-hand singular vectors, stored by
               rows; and the remaining rows of the array are used as
               workspace.

           4:  NRA -- INTEGER                                         Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F04JGF is called.
               Constraint: NRA >= M.

           5:  B(M) -- DOUBLE PRECISION array                  Input/Output
               On entry: the right-hand side vector b. On exit: the first
               n elements of B contain the minimal least-squares solution
               vector x. The remaining m-n elements are used for workspace.

           6:  TOL -- DOUBLE PRECISION                                Input
               On entry: a relative tolerance to be used to determine the
               rank of A. TOL should be chosen as approximately the largest
               relative error in the elements of A. For example, if the
               elements of A are correct to about 4 significant figures
                                                   -4
               then TOL should be set to about 5*10  . See Section 8 for a
               description of how TOL is used to determine rank. If TOL is
               outside the range ((epsilon),1.0), where (epsilon) is the
               machine precision, then the value (epsilon) is used in place
               of TOL. For most problems this is unreasonably small.

           7:  SVD -- LOGICAL                                        Output
               On exit: SVD is returned as .FALSE. if the least-squares
               solution has been obtained from the QU factorization of A.
               In this case A is of full rank. SVD is returned as .TRUE. if
               the least-squares solution has been obtained from the
               singular value decomposition of A.

           8:  SIGMA -- DOUBLE PRECISION                             Output
                                                               

                                                              / T
               On exit: the standard error, i.e., the value \/ r r/(m-k)
               when m>k, and the value zero when m=k. Here r is the
               residual vector b-Ax and k is the rank of A.

           9:  IRANK -- INTEGER                                      Output
               On exit: k, the rank of the matrix A. It should be noted
               that it is possible for IRANK to be returned as n and SVD to
               be returned as .TRUE.. This means that the matrix U only
               just failed the test for non-singularity.

          10:  WORK(LWORK) -- DOUBLE PRECISION array                 Output
               On exit: if SVD is returned as .FALSE., then the first n
               elements of WORK contain information on the QU factorization
               of A (see parameter A above and F02WDF(*)), and WORK(n+1)
                                                      -1
               contains the condition number ||U|| ||U  ||  of the
                                                  E       E
               upper triangular matrix U.

               If SVD is returned as .TRUE., then the first n elements of
               WORK contain the singular values of A arranged in descending
               order and WORK(n+1) contains the total number of iterations
               taken by the QR algorithm. The rest of WORK is used as
               workspace.

          11:  LWORK -- INTEGER                                       Input
               On entry:
               the dimension of the array WORK as declared in the
               (sub)program from which F04JGF is called.
               Constraint: LWORK >= 4*N.

          12:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               On entry N < 1,

               or       M < N,

               or       NRA < M,

               or       LWORK < 4*N.

          IFAIL= 2
               The QR algorithm has failed to converge to the singular
               values in 50*N iterations. This failure can only happen when
               the singular value decomposition is employed, but even then
               it is not likely to occur.

          7. Accuracy

                                               T
          The computed factors Q, U, R, D and P  satisfy the relations

                              (U)        (R 0)(D) T
                             Q(0)=A+E , Q(0 I)(0)P =A+F,

          where

                           ||E|| <=c (epsilon)||A|| ,
                                2   1              2


                           ||F|| <=c (epsilon)||A|| ,
                                2   2              2

          (epsilon) being the machine precision, and c  and c  being modest
                                                      1      2
          functions of m and n. Note that ||A|| =(sigma) .
                                               2        1

          For a fuller discussion, covering the accuracy of the solution x
          see Lawson and Hanson [1], especially pp 50 and 95.

          8. Further Comments

          If the least-squares solution is obtained from the QU
          factorization then the time taken by the routine is approximately
                           2
          proportional to n (3m-n). If the least-squares solution is
          obtained from the singular value decomposition then the time
                                                  2
          taken is approximately proportional to n (3m+19n). The
          approximate proportionality factor is the same in each case.

          This routine is column biased and so is suitable for use in paged
          environments.

          Following the QU factorization of A the condition number

                                             -1
                               c(U)=||U|| ||U  ||
                                         E       E

          is determined and if c(U) is such that

                                    c(U)*TOL>1.0

          then U is regarded as singular and the singular values of A are
          computed. If this test is not satisfied, U is regarded as non-
          singular and the rank of A is set to n. When the singular values
          are computed the rank of A, say k, is returned as the largest
          integer such that

                               (sigma) >TOL*(sigma) ,
                                      k            1

          unless (sigma) =0 in which case k is returned as zero. That is,
                        1
          singular values which satisfy (sigma) <=TOL*(sigma)  are regarded
                                               i             1
          as negligible because relative perturbations of order TOL can
          make such singular values zero.

          9. Example

          To obtain a least-squares solution for r=b-Ax, where

                           (0.05  0.05 0.25 -0.25)      (1)
                           (0.25  0.25 0.05 -0.05)      (2)
                           (0.35  0.35 1.75 -1.75)      (3)
                         A=(1.75  1.75 0.35 -0.35),   B=(4)
                           (0.30 -0.30 0.30  0.30)      (5)
                           (0.40 -0.40 0.40  0.40)      (6)

                                                  -4
          and the value TOL is to be taken as 5*10  .

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf04maf}{nagf.ht}
{ Sparse symmetric positive-definite system linear equations}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf04maf}{NAG Documentation: f04maf}
\beginscroll
\begin{verbatim}



     F04MAF(3NAG)      Foundation Library (12/10/92)      F04MAF(3NAG)



          F04 -- Simultaneous Linear Equations                       F04MAF
                  F04MAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          To solve a sparse symmetric positive-definite system of linear
          equations, Ax=b, using a pre-conditioned conjugate gradient
          method, where A has been factorized by F01MAF.

          2. Specification

                 SUBROUTINE F04MAF (N, NZ, A, LICN, IRN, LIRN, ICN, B, ACC,
                1                   NOITS, WKEEP, WORK, IKEEP, INFORM,
                2                   IFAIL)
                 INTEGER          N, NZ, LICN, IRN(LIRN), LIRN, ICN(LICN),
                1                 NOITS(2), IKEEP(2*N), INFORM(4), IFAIL
                 DOUBLE PRECISION A(LICN), B(N), ACC(2), WKEEP(3*N), WORK
                1                 (3*N)

          3. Description

          F04MAF solves the n linear equations

                                     Ax=b,                              (1)

          where A is a sparse symmetric positive-definite matrix, following
          the incomplete Cholesky factorization by F01MAF, given by

                                      T T
                                C=PLDL P  , WAW=C+E,

          where P is a permutation matrix, L is a unit lower triangular
          matrix, D is a diagonal matrix with positive diagonal elements, E
          is an error matrix representing elements dropped during the
          factorization and diagonal elements that have been modified to
          ensure that C is positive-definite, and W is a diagonal matrix,
          chosen to make the diagonal elements of WAW unity.

          Equation (1) is solved by applying a pre-conditioned conjugate
          gradient method to the equations

                                       -1
                                (WAW)(W  x)=Wb,                         (2)

          using C as the pre-conditioning matrix. Details of the conjugate
          gradient method are given in Munksgaard [1].

          The iterative procedure is terminated if

                                ||Wr|| <=(eta),                         (3)
                                      2

          where r is the residual vector r=b-Ax, ||r||  denotes the
                                                      2
          Euclidean length of r, (eta) is a user-supplied tolerance and x
          is the current approximation to the solution. Notice that

                                               -1
                                  Wr=Wb-(WAW)(W  x)

          so that Wr is the residual of the normalised equations (2).

          F04MAF is based on the Harwell Library routine MA31B.

          4. References

          [1]   Munksgaard N (1980) Solving Sparse Symmetric Sets of Linear
                Equations by Pre-conditioned Conjugate Gradients. ACM Trans.
                Math. Softw. 6 206--219.

          5. Parameters

           1:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A. Constraint: N >= 1.

           2:  NZ -- INTEGER                                          Input
               On entry: the number of non-zero elements in the upper
               triangular part of the matrix A, including the number of
               elements on the leading diagonal. Constraint: NZ >= N.

           3:  A(LICN) -- DOUBLE PRECISION array                      Input
               On entry: the first LROW elements, where LROW is the value
               supplied in INFORM(1), must contain details of the
               factorization, as returned by F01MAF.

           4:  LICN -- INTEGER                                        Input
               On entry: the length of the array A, as declared in the
               (sub)program from which F04MAF is called. It need never be
               larger than the value of LICN supplied to F01MAF.
               Constraint: LICN >= INFORM(1).

           5:  IRN(LIRN) -- INTEGER array                             Input
               On entry: the first LCOL elements, where LCOL is the value
               supplied in INFORM(2), must contain details of the
               factorization, as returned by F01MAF.

           6:  LIRN -- INTEGER                                        Input
               On entry: the length of the array IRN, as declared in the
               (sub)program from which F04MAF is called. It need never be
               larger than the value of LIRN supplied to F01MAF.
               Constraint: LIRN >= INFORM(2).

           7:  ICN(LICN) -- INTEGER array                             Input
               On entry: the first LROW elements, where LROW is the value
               supplied in INFORM(1), must contain details of the
               factorization, as returned by F01MAF.

           8:  B(N) -- DOUBLE PRECISION array                  Input/Output
               On entry: the right-hand side vector b. On exit: B is
               overwritten by the solution vector x.

           9:  ACC(2) -- DOUBLE PRECISION array                Input/Output
               On entry: ACC(1) specifies the tolerance for convergence,
               (eta), in equation (3) of Section 3. If ACC(1) is outside
               the range [(epsilon),1], where (epsilon) is the machine
               precision, then the value (epsilon) is used in place of ACC
               (1). ACC(2) need not be set. On exit: ACC(2) contains the
               actual value of ||Wr||  at the final point. ACC(1) is
                                     2
               unchanged.

          10:  NOITS(2) -- INTEGER array                       Input/Output
               On entry: NOITS(1) specifies the maximum permitted number of
               iterations. If NOITS(1) < 1, then the value 100 is used in
               its place. NOITS(2) need not be set. On exit: NOITS(2)
               contains the number of iterations taken to converge. NOITS
               (1) is unchanged.

          11:  WKEEP(3*N) -- DOUBLE PRECISION array                   Input
               On entry: WKEEP must be unchanged from the previous call of
               F01MAF.

          12:  WORK(3*N) -- DOUBLE PRECISION array                   Output
               On exit: WORK(1) contains a lower bound for the condition
               number of A. The rest of the array is used for workspace.

          13:  IKEEP(2*N) -- INTEGER array                            Input
               On entry: IKEEP must be unchanged from the previous call of
               F01MAF.

          14:  INFORM(4) -- INTEGER array                             Input
               On entry: INFORM must be unchanged from the previous call of
               F01MAF.

          15:  IFAIL -- INTEGER                                Input/Output
               For this routine, the normal use of IFAIL is extended to
               control the printing of error and warning messages as well
               as specifying hard or soft failure (see the Essential
               Introduction).

               Before entry, IFAIL must be set to a value with the decimal
               expansion cba, where each of the decimal digits c, b and a
               must have a value of 0 or 1.
               a=0   specifies hard failure, otherwise soft failure;

               b=0   suppresses error messages, otherwise error messages
                     will be printed (see Section 6);

               c=0   suppresses warning messages, otherwise warning
                     messages will be printed (see Section 6).
               The recommended value for inexperienced users is 110 (i.e.,
               hard failure with all messages printed).

               Unless the routine detects an error (see Section 6), IFAIL
               contains 0 on exit.

          6. Error Indicators and Warnings

          Errors detected by the routine:

          For each error, an explanatory error message is output on the
          current error message unit (as defined by X04AAF), unless
          suppressed by the value of IFAIL on entry.

          IFAIL= 1
               On entry N < 1,

               or       NZ < N,

               or       LICN < INFORM(1),

               or       LIRN < INFORM(2).

          IFAIL= 2
               Convergence has not taken place within the requested NOITS
               (1) number of iterations. ACC(2) gives the value ||Wr|| ,
                                                                      2
               for the final point. Either too few iterations have been
               allowed, or the requested convergence criterion cannot be
               met.

          IFAIL= 3
               The matrix A is singular, or nearly singular. Singularity
               has been detected during the conjugate gradient iterations,
               so that the computations are not complete.

          IFAIL= 4
               The matrix A is singular, or nearly singular. The message
               output on the current error message channel will include an
               estimate of the condition number of A. In the case of soft
               failure an approximate solution is returned such that the
               value ||Wr||  is given by ACC(2) and the estimate (a lower
                           2
               bound) of the condition number is returned in WORK(1).

          7. Accuracy

          On successful return, or on return with IFAIL = 2 or IFAIL = 4
          the computed solution will satisfy equation (3) of Section 3,
          with (eta) = ACC(2).

          8. Further Comments

          The time taken by the routine will depend upon the sparsity of
          the factorization and the number of iterations required. The
          number of iterations will be affected by the nature of the
          factorization supplied by F01MAF. The more incomplete the
          factorization, the higher the number of iterations required by
          F04MAF.

          When the solution of several systems of equations, all with the
          same matrix of coefficients, A, is required, then F01MAF need be
          called only once to factorize A. This is illustrated in the
          context of an eigenvalue problem in the example program for
          F02FJF.

          9. Example

          The example program illustrates the use of F01MAF in conjunction
          with F04MAF to solve the 16 linear equations Ax=b, where

                           (1 a     a                      )
                           (a 1 a     a                    )
                           (  a 1 a     a                  )
                           (    a 1 0     a                )
                           (a     0 1 a     a              )
                           (  a     a 1 a     a            )
                           (    a     a 1 a     a          )
                           (      a     a 1 0     a        )
                         A=(        a     0 1 a     a      )
                           (          a     a 1 a     a    )
                           (            a     a 1 a     a  )
                           (              a     a 1 0     a)
                           (                a     0 1 a    )
                           (                  a     a 1 a  )
                           (                    a     a 1 a)
                           (                      a     a 1)

                    1
          where a=- -.
                    4

                   T (  1  1  1  1  1      1  1      1  1  1  1  1)
                  b =(  -  -  -  -  - 0 0  -  - 0 0  -  -  -  -  -)
                     (  2  4  4  2  4      4  4      4  2  4  4  2)

          The n by n matrix A arises in the solution of Laplace's equation
          in a unit-square, using a five-point formula with a 6 by 6
          discretisation, with unity on the boundaries.

          The drop tolerance, DROPTL, is taken as 0.1 and the density
          factor, DENSW, is taken as 0.8. The value IFAIL = 111 is used so
          that advisory and error messages will be printed, but soft
          failure would occur if IFAIL were returned as non-zero.

          A relative accuracy of about 0.0001 is requested in the solution
          from F04MAF, with a maximum of 50 iterations.

          The example program for F02FJF illustrates the use of routines
          F01MAF and F04MAF in solving an eigenvalue problem.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf04mbf}{nagf.ht}
{ Solves a system of real sparse symmetric linear equations}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf04mbf}{NAG Documentation: f04mbf}
\beginscroll
\begin{verbatim}



     F04MBF(3NAG)      Foundation Library (12/10/92)      F04MBF(3NAG)



          F04 -- Simultaneous Linear Equations                       F04MBF
                  F04MBF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F04MBF solves a system of real sparse symmetric linear equations
          using a Lanczos algorithm.

          2. Specification

                 SUBROUTINE F04MBF (N, B, X, APROD, MSOLVE, PRECON, SHIFT,
                1                   RTOL, ITNLIM, MSGLVL, ITN, ANORM,
                2                   ACOND, RNORM, XNORM, WORK, RWORK,
                3                   LRWORK, IWORK, LIWORK, INFORM, IFAIL)
                 INTEGER          N, ITNLIM, MSGLVL, ITN, LRWORK, IWORK
                1                 (LIWORK), LIWORK, INFORM, IFAIL
                 DOUBLE PRECISION B(N), X(N), SHIFT, RTOL, ANORM, ACOND,
                1                 RNORM, XNORM, WORK(N,5), RWORK(LRWORK)
                 LOGICAL          PRECON
                 EXTERNAL         APROD, MSOLVE

          3. Description

          F04MBF solves the system of linear equations

                               (A-(lambda)I)x=b                       (3.1)

          where A is an n by n sparse symmetric matrix and (lambda) is a
          scalar, which is of course zero if the solution of the equations

                                        Ax=b

          is required. It should be noted that neither A nor (A-(lambda)I)
          need be positive-definite.

          (lambda) is supplied as the parameter SHIFT, and allows F04MBF to
          be used for finding eigenvectors of A in methods such as Rayleigh
          quotient iteration (see for example Lewis [1]), in which case
          (lambda) will be an approximation to an eigenvalue of A and b an
          approximation to an eigenvector of A.

          The routine also provides an option to allow pre-conditioning and
          this will often reduce the number of iterations required by
          F04MBF.

          F04MBF is based upon algorithm SYMMLQ (see Paige and Saunders
          [2]) and solves the equations by an algorithm based upon the

          Lanczos process. Details of the method are given in Paige and
          Saunders [2]. The routine does not require A explicitly, but A is
          specified via a user-supplied routine APROD which, given an n
          element vector c, must return the vector z given by

                                        z=Ac.

          The pre-conditioning option is based on the following reasoning.
          If A can be expressed in the form

                                        A=I+B

          where B is of rank (rho), then the Lanczos process converges (in
          exact arithmetic) in at most (rho) iterations. If more generally
          A can be expressed in the form

                                        A=M+C

          where M is symmetric positive-definite and C has rank (rho), then

                           -(1/2)  -(1/2)    -(1/2)  -(1/2)
                          M      AM      =I+M      CM

               -(1/2)  -(1/2)
          and M      AM       also has rank (rho), and the Lanczos process
                      -(1/2)  -(1/2)
          applied to M      AM       would again converge in at most (rho)
          iterations. On a computer, the number of iterations may be
          greater than (rho), but the Lanczos process may still be expected
                                                        -(1/2)  -(1/2)
          to converge rapidly. F04MBF does not require M      AM       to
          be formed explicitly, but implicitly solves the equations

                -(1/2)              -(1/2)   -(1/2)       1/2
               M      (A-(lambda)I)M      y=M      b , y=M   x        (3.2)

          with the user being required to supply a routine MSOLVE to solve
          the equations

                                    Mz=c.                             (3.3)

          For the pre-conditioning option to be effective, it is desirable
          that equations (3.3) can be solved efficiently. The example
          program in Section 9 illustrates the use of this option.

          If we let r denote the residual vector

                                 r=b-(A-(lambda)I)x

          corresponding to an iterate x, then, when pre-conditioning has
          not been requested, the iterative procedure is terminated if it
          is estimated that

                      ||r||<=tol.||A-(lambda)I||.||x||,               (3.4)

          where tol is a user-supplied tolerance, ||r|| denotes the
          Euclidean length of the vector r and ||A|| denotes the Frobenius
          (Euclidean) norm of the matrix A. When pre-conditioning has been
          requested, the iterative procedure is terminated if it is
          estimated that

             -(1/2)            -(1/2)             -(1/2)      1/2
          ||M      r||<=tol.||M      (A-(lambda)I)M     ||.||M   x||. (3.5)

          Note that

                -(1/2)    -(1/2)    -(1/2)              -(1/2)  1/2
               M      r=(M      b)-M      (A-(lambda)I)M      (M   x)

                   -(1/2)
          so that M      r is the residual vector corresponding to equation
          (3.2). The routine will also terminate if it is estimated that

                   ||A-(lambda)I||.||x||>=||b||/(epsilon),            (3.6)

          where (epsilon) is the machine precision, when pre-conditioning
          has not been requested; or if it is estimated that


             -(1/2)              -(1/2)      1/2        -(1/2)
          ||M      (A-(lambda)I)M      ||.||M   x||>=||M      b||/(epsilon)

                                                                      (3.7)

          when pre-conditioning has been requested. If (3.6) is satisfied
          then x is almost certainly an eigenvector of A corresponding to
          the eigenvalue (lambda). If (lambda) was set to 0 (for the
          solution of Ax=b), then this condition simply means that A is
          effectively singular.

          4. References

          [1]   Lewis J G (1977) Algorithms for sparse matrix eigenvalue
                problems. Technical Report STAN-CS-77-595. Computer Science
                Department, Stanford University.

          [2]   Paige C C and Saunders M A (1975) Solution of Sparse
                Indefinite Systems of Linear Equations. SIAM J. Numer. Anal.
                12 617--629.

          5. Parameters

           1:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A. Constraint: N >= 1.

           2:  B(N) -- DOUBLE PRECISION array                         Input
               On entry: the right-hand side vector b.

           3:  X(N) -- DOUBLE PRECISION array                        Output
               On exit: the solution vector x.

           4:  APROD -- SUBROUTINE, supplied by the user.
                                                         External Procedure
               APROD must return the vector y=Ax for a given vector x.

               Its specification is:

                      SUBROUTINE APROD (IFLAG, N, X, Y, RWORK, LRWORK,
                     1                  IWORK,LIWORK)
                      INTEGER          IFLAG, N, LRWORK, LIWORK, IWORK
                     1                 (LIWORK)
                      DOUBLE PRECISION X(N), Y(N), RWORK(LRWORK)

                1:  IFLAG -- INTEGER                           Input/Output
                    On entry: IFLAG is always non-negative. On exit: IFLAG
                    may be used as a flag to indicate a failure in the
                    computation of  Ax.   If IFLAG is negative on exit from
                    APROD, F04MBF will exit immediately with IFAIL set to
                    IFLAG.

                2:  N -- INTEGER                                      Input
                    On entry: n, the order of the matrix A.

                3:  X(N) -- DOUBLE PRECISION array                    Input
                    On entry: the vector x for which Ax is required.

                4:  Y(N) -- DOUBLE PRECISION array                   Output
                    On exit: the vector y=Ax.

                5:  RWORK(LRWORK) -- DOUBLE PRECISION array  User Workspace

                6:  LRWORK -- INTEGER                                 Input

                7:  IWORK(LIWORK) -- INTEGER array           User Workspace

                8:  LIWORK -- INTEGER                                 Input
                    APROD is called from F04MBF with the parameters RWORK,
                    LRWORK, IWORK and LIWORK as supplied to F04MBF. The
                    user is free to use the arrays RWORK and IWORK to
                    supply information to APROD and MSOLVE as an
                    alternative to using COMMON.
               APROD must be declared as EXTERNAL in the (sub)program
               from which F04MBF is called. Parameters denoted as
               Input must not be changed by this procedure.

           5:  MSOLVE -- SUBROUTINE, supplied by the user.
                                                         External Procedure
               MSOLVE is only referenced when PRECON is supplied as .TRUE..
               When PRECON is supplied as .FALSE., then F04MBF may be
               called with APROD as the actual argument for MSOLVE. When
               PRECON is supplied as .TRUE., then MSOLVE must return the
               solution y of the equations My=x for a given vector x, where
               M must be symmetric positive-definite.

               Its specification is:

                      SUBROUTINE MSOLVE (IFLAG, N, X, Y, RWORK,
                     1                   LRWORK, IWORK,LIWORK)
                      INTEGER          IFLAG, N, LRWORK, LIWORK, IWORK
                     1                 (LIWORK)
                      DOUBLE PRECISION X(N), Y(N), RWORK(LRWORK)

                1:  IFLAG -- INTEGER                           Input/Output
                    On entry: IFLAG is always non-negative. On exit: IFLAG
                    may be used as a flag to indicate a failure in the
                    solution of My=x.

                    If IFLAG is negative on exit from MSOLVE, F04MBF will
                    exit immediately with IFAIL set to IFLAG.

                2:  N -- INTEGER                                      Input
                    On entry: n, the order of the matrix M.

                3:  X(N) -- DOUBLE PRECISION array                    Input
                    On entry: the vector x for which the equations My=x are
                    to be solved.

                4:  Y(N) -- DOUBLE PRECISION array                   Output
                    On exit: the solution to the equations My=x.

                5:  RWORK(LRWORK) -- DOUBLE PRECISION array  User Workspace

                6:  LRWORK -- INTEGER                                 Input

                7:  IWORK(LIWORK) -- INTEGER array           User Workspace

                8:  LIWORK -- INTEGER                                 Input
                    MSOLVE is called from F04MBF with the parameters RWORK,
                    LRWORK, IWORK and LIWORK as supplied to F04MBF. The
                    user is free to use the arrays RWORK and IWORK to
                    supply information to APROD and MSOLVE as an
                    alternative to using COMMON.
               MSOLVE must be declared as EXTERNAL in the (sub)program
               from which F04MBF is called. Parameters denoted as
               Input must not be changed by this procedure.

           6:  PRECON -- LOGICAL                                      Input
               On entry: PRECON specifies whether or not pre-conditioning
               is required. If PRECON = .TRUE., then pre-conditioning will
               be invoked and MSOLVE will be referenced by F04MBF; if
               PRECON = .FALSE., then MSOLVE is not referenced.

           7:  SHIFT -- DOUBLE PRECISION                              Input
               On entry: the value of (lambda). If the equations Ax=b are
               to be solved, then SHIFT must be supplied as zero.

           8:  RTOL -- DOUBLE PRECISION                               Input
               On entry: the tolerance for convergence, tol, of equation
               (3.4). RTOL should not normally be less than (epsilon),
               where (epsilon) is the machine precision.

           9:  ITNLIM -- INTEGER                                      Input
               On entry: an upper limit on the number of iterations. If
               ITNLIM <= 0, then the value N is used in place of ITNLIM.

          10:  MSGLVL -- INTEGER                                      Input
               On entry: the level of printing from F04MBF. If MSGLVL <= 0,
               then no printing occurs, but otherwise messages will be
               output on the advisory message channel (see X04ABF). A
               description of the printed output is given in Section 5.1
               below. The level of printing is determined as follows:
               MSGLVL <= 0
                     No printing.

               MSGLVL = 1
                     A brief summary is printed just prior to return from
                     F04MBF.

               MSGLVL >= 2
                     A summary line is printed periodically to monitor the
                     progress of F04MBF, together with a brief summary just
                     prior to return from F04MBF.

          11:  ITN -- INTEGER                                        Output
               On exit: the number of iterations performed.

          12:  ANORM -- DOUBLE PRECISION                             Output
               On exit: an estimate of ||A-(lambda)I|| when PRECON =
                              -(1/2)              -(1/2)
               .FALSE., and ||M      (A-(lambda)I)M      || when PRECON =
               .TRUE..

          13:  ACOND -- DOUBLE PRECISION                             Output
               On exit: an estimate of the condition number of (A-
               (lambda)I) when PRECON = .FALSE., and of
                -(1/2)              -(1/2)
               M      (A-(lambda)I)M       when PRECON = .TRUE.. This will
               usually be a substantial under-estimate.

          14:  RNORM -- DOUBLE PRECISION                             Output
               On exit: ||r||, where r=b-(A-(lambda)I)x and x is the
               solution returned in X.

          15:  XNORM -- DOUBLE PRECISION                             Output
               On exit: ||x||, where x is the solution returned in X.

          16:  WORK(5*N) -- DOUBLE PRECISION array                Workspace

          17:  RWORK(LRWORK) -- DOUBLE PRECISION array       User Workspace
               RWORK is not used by F04MBF, but is passed directly to
               routines APROD and MSOLVE and may be used to pass
               information to these routines.

          18:  LRWORK -- INTEGER                                      Input
               On entry: the length of the array RWORK as declared in the
               (sub)program from which F04MBF is called. Constraint: LRWORK
               >= 1.

          19:  IWORK(LIWORK) -- INTEGER array                User Workspace
               IWORK is not used by F04MBF, but is passed directly to
               routines APROD and MSOLVE and may be used to pass
               information to these routines.

          20:  LIWORK -- INTEGER                                      Input
               On entry: the length of the array IWORK as declared in the
               (sub)program from which F04MBF is called. Constraint: LIWORK
               >= 1.

          21:  INFORM -- INTEGER                                     Output
               On exit: the reason for termination of F04MBF as follows:
               INFORM = 0
                     The right-hand side vector b=0 so that the exact
                     solution is x=0. No iterations are performed in this
                     case.

               INFORM = 1
                     The termination criterion of equation (3.4) has been
                     satisfied with tol as the value supplied in RTOL.

               INFORM = 2
                     The termination criterion of equation (3.4) has been
                     satisfied with tol equal to (epsilon), where (epsilon)
                     is the machine precision. The value supplied in RTOL
                     must have been less than (epsilon) and was too small
                     for the machine.

               INFORM = 3
                     The termination criterion of equation (3.5) has been
                     satisfied so that X is almost certainly an eigenvector
                     of A corresponding to the eigenvalue SHIFT.
               The values INFORM = 4 and INFORM = 5 correspond to failure
               with IFAIL = 3 or IFAIL = 2 respectively (see Section 6) and
               when IFAIL is negative, INFORM will be set to the same
               negative value.

          22:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          5.1. Description of the Printed Output

          When MSGLVL > 0, then F04MBF will produce output (except in the
          case where the routine fails with IFAIL = 1) on the advisory
          message channel (see X04ABF ).

          The following notation is used in the output.

             Output     Meaning

                         -(1/2)                   
             RBAR       M      (b-(A-(lambda)I)x)=r

                         -(1/2)              -(1/2) 
             ABAR       M      (A-(lambda)I)M      =A

                         1/2
             Y          M   x

             R          b-(A-(lambda)I)x

             NORM(A)    ||A||

          Of course, when pre-conditioning has not been requested then the
          first three reduce to (b-(A-(lambda)I)x), (A-(lambda)I) and x
          respectively. When MSGLVL >= 2 then some initial information is
          printed and the following notation is used.

             Output     Meaning

                          T -1  1/2
             BETA1      (b M  b)   ==(beta)
                                           1

                                   2  -(1/2)  T  -(1/2)  -(1/2)   -(1/2)
             ALFA1      (1/(beta) ) (M      b) (M      AM      )(M      b)
                                 1
                        ==(alpha)
                                 1
          and a summary line is printed periodically giving the following
          information:

             Output     Meaning

             ITN        Iteration number, k.

                                                         L         L
             X1(LQ)     The first element of the vector x , where x  is the
                                                         k         k
                        current iterate. See Paige and Saunders [2] for
                        details.

                                                         C         C
             X1(CG)     The first element of the vector x , where x  is the
                                                         k         k
                        vector that would be obtained by conjugate
                        gradients. See Paige and Saunders [2] for details.

                                     

             NORM(RBAR) ||r||, where r is as defined above and x is either
                         L     C
                        x  or x  depending upon which is the best current
                         k     k
                        approximation to the solution. (See LQ/CG below).

             NORM(T)    The value ||T ||, where T  is the tridiagonal
                                     k           k
                        matrix of the Lanczos process. This increases
                                                                

                        monotonically and is a lower bound on ||A||.

             COND(L)    A monotonically increasing lower bound on the
                                                         -1
                        condition number of A, ||A||||(A)  ||.

                                         L
             LQ/CG      L is printed if x  is the best current
                                         k
                        approximation to the solution and C is printed
                        otherwise.

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL< 0
               A negative value of IFAIL indicates an exit from F04MBF
               because the user has set IFLAG negative in APROD or MSOLVE.
               The value of IFAIL will be the same as the user's setting of
               IFLAG.

          IFAIL= 1
               On entry N < 1,

               or       LRWORK < 1,

               or       LIWORK < 1.

          IFAIL= 2
               The pre-conditioning matrix M does not appear to be
               positive-definite. The user should check that MSOLVE is
               working correctly.

          IFAIL= 3
               The limit on the number of iterations has been reached. If
               IFAIL = 1 on entry then the latest approximation to the
               solution is returned in X and the values ANORM, ACOND, RNORM
               and XNORM are also returned.

          The value of INFORM contains additional information about the
          termination of the routine and users must examine INFORM to judge
          whether the routine has performed successfully for the problem in
          hand. In particular INFORM = 3 denotes that the matrix A-
          (lambda)I is effectively singular: if the purpose of calling
          F04MBF is to solve a system of equations Ax=b, then this
          condition must be regarded as a failure, but if the purpose is to
          compute an eigenvector, this result would be very satisfactory.

          7. Accuracy

          The computed solution x will satisfy the equation

                                 r=b-(A-(lambda)I)x

          where the value ||r|| is as returned in the parameter RNORM.

          8. Further Comments

          The time taken by the routine is likely to be principally
          determined by the time taken in APROD and, when pre-conditioning
          has been requested, in MSOLVE. Each of these routines is called
          once every iteration.

          The time taken by the remaining operations in F04MBF is
          approximately proportional to n.

          9. Example

          To solve the 10 equations Ax=b given by

                            (2 1 0 0 0 0 0 0 0 3)      (6)
                            (1 2 1 0 0 0 0 0 0 0)      (4)
                            (0 1 2 1 0 0 0 0 0 0)      (4)
                            (0 0 1 2 1 0 0 0 0 0)      (4)
                            (0 0 0 1 2 1 0 0 0 0)      (4)
                          A=(0 0 0 0 1 2 1 0 0 0),   b=(4).
                            (0 0 0 0 0 1 2 1 0 0)      (4)
                            (0 0 0 0 0 0 1 2 1 0)      (4)
                            (0 0 0 0 0 0 0 1 2 1)      (4)
                            (3 0 0 0 0 0 0 0 1 2)      (6)

          The tridiagonal part of A is positive-definite and such
          tridiagonal equations can be solved efficiently by F04FAF. The
          form of A suggests that this tridiagonal part is a good candidate
          for the pre-conditioning matrix M and so we illustrate the use of
          F04MBF by pre-conditioning with the 10 by 10 matrix

                                    (2 1 0 ... 0)
                                    (1 2 1 ... 0)
                                    (0 1 2 ... 0)
                                  M=(. . .   .  ).
                                    (. . .   .  )
                                    (. . .   .  )
                                    (0 0 0 ... 2)

          Since A-M has only 2 non-zero elements and is obviously of rank
          2, we can expect F04MBF to converge very quickly in this example.
          Of course, in practical problems we shall not usually be able to
          make such a good choice of M.

                                                  -5
          The example sets the tolerance RTOL = 10  .


          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf04mcf}{nagf.ht}
{ Solution of a system of real linear equations}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf04mcf}{NAG Documentation: f04mcf}
\beginscroll
\begin{verbatim}



     F04MCF(3NAG)      Foundation Library (12/10/92)      F04MCF(3NAG)



          F04 -- Simultaneous Linear Equations                       F04MCF
                  F04MCF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F04MCF computes the approximate solution of a system of real
          linear equations with multiple right-hand sides,  AX=B,  where A
          is a symmetric positive-definite variable-bandwidth matrix, which
          has previously been factorized by F01MCF. Related systems may
          also be solved.

          2. Specification

                 SUBROUTINE F04MCF (N, AL, LAL, D, NROW, IR, B, NRB,
                1                   ISELCT, X, NRX, IFAIL)
                 INTEGER          N, LAL, NROW(N), IR, NRB, ISELCT, NRX,
                1                 IFAIL
                 DOUBLE PRECISION AL(LAL), D(N), B(NRB,IR), X(NRX,IR)

          3. Description

          The normal use of this routine is the solution of the systems
          AX=B, following a call of F01MCF to determine the Cholesky
                             T
          factorization A=LDL  of the symmetric positive-definite variable-
          bandwidth matrix A.

          However, the routine may be used to solve any one of the
          following systems of linear algebraic equations:

                  T
          (1)  LDL X = B (usual system),

          (2)  LDX   = B (lower triangular system),

                 T
          (3)  DL X  = B (upper triangular system),

                 T
          (4)  LL X  = B

          (5)  LX    = B (unit lower triangular system),

                T
          (6)  L X   = B (unit upper triangular system).

          L denotes a unit lower triangular variable-bandwidth matrix of
          order n, D a diagonal matrix of order n, and B a set of right-
          hand sides.

          The matrix L is represented by the elements lying within its
          envelope i.e., between the first non-zero of each row and the
          diagonal (see Section 9 for an example). The width NROW(i) of the
          ith row is the number of elements between the first non-zero
          element and the element on the diagonal inclusive.

          4. References

          [1]   Wilkinson J H and Reinsch C (1971) Handbook for Automatic
                Computation II, Linear Algebra. Springer-Verlag.

          5. Parameters

           1:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix L. Constraint: N >= 1.

           2:  AL(LAL) -- DOUBLE PRECISION array                      Input
               On entry: the elements within the envelope of the lower
               triangular matrix L, taken in row by row order, as returned
               by F01MCF. The unit diagonal elements of L must be stored
               explicitly.

           3:  LAL -- INTEGER                                         Input
               On entry:
               the dimension of the array AL as declared in the
               (sub)program from which F04MCF is called.
               Constraint: LAL >= NROW(1) + NROW(2) +... + NROW(n).

           4:  D(N) -- DOUBLE PRECISION array                         Input
               On entry: the diagonal elements of the diagonal matrix D. D
               is not referenced if ISELCT >= 4.

           5:  NROW(N) -- INTEGER array                               Input
               On entry: NROW(i) must contain the width of row i of L,
               i.e.,the number of elements between the first (leftmost)
               non-zero element and the element on the diagonal, inclusive.
               Constraint: 1 <= NROW(i)<=i.

           6:  IR -- INTEGER                                          Input
               On entry: r, the number of right-hand sides. Constraint: IR
               >= 1.

           7:  B(NRB,IR) -- DOUBLE PRECISION array                    Input
               On entry: the n by r right-hand side matrix B. See also
               Section 8.

           8:  NRB -- INTEGER                                         Input
               On entry:
               the first dimension of the array B as declared in the
               (sub)program from which F04MCF is called.
               Constraint: NRB >= N.

           9:  ISELCT -- INTEGER                                      Input
               On entry: ISELCT must specify the type of system to be
               solved, as follows:

                                     T
               ISELCT = 1:  solve LDL X = B,

               ISELCT = 2:  solve LDX = B,

                                    T
               ISELCT = 3:  solve DL X = B,

                                    T
               ISELCT = 4:  solve LL X = B,

               ISELCT = 5:  solve LX = B,

                                   T
               ISELCT = 6:  solve L X = B.

          10:  X(NRX,IR) -- DOUBLE PRECISION array                   Output
               On exit: the n by r solution matrix X. See also Section 8.

          11:  NRX -- INTEGER                                         Input
               On entry:
               the first dimension of the array X as declared in the
               (sub)program from which F04MCF is called.
               Constraint: NRX >= N.

          12:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               On entry N < 1,

               or       for some i, NROW(i)<1 or NROW(i) > i,

               or       LAL < NROW(1) + NROW(2) +... + NROW(N).

          IFAIL= 2

               On entry IR < 1,

               or       NRB < N,

               or       NRX < N.

          IFAIL= 3
               On entry ISELCT < 1,

               or       ISELCT > 6.

          IFAIL= 4
               The diagonal matrix D is singular, i.e., at least one of the
               elements of D is zero. This can only occur if ISELCT <= 3.

          IFAIL= 5
               At least one of the diagonal elements of L is not equal to
               unity.

          7. Accuracy

          The usual backward error analysis of the solution of triangular
          system applies: each computed solution vector is exact for
          slightly perturbed matrices L and D, as appropriate (cf.
          Wilkinson and Reinsch [1] pp 25--27, 54--55).

          8. Further Comments

          The time taken by the routine is approximately proportional to
          pr, where

                           p=NROW(1)+NROW(2)+...+NROW(n).

          Unless otherwise stated in the Users' Note for your
          implementation, the routine may be called with the same actual
          array supplied for the parameters B and X, in which case the
          solution matrix will overwrite the right-hand side matrix.
          However this is not standard Fortran 77 and may not work in all
          implementations.

          9. Example

          To solve the system of equations AX=B, where

                                  (1  2  0  0  5  0)
                                  (2  5  3  0 14  0)
                                  (0  3 13  0 18  0)
                                A=(0  0  0 16  8 24)
                                  (5 14 18  8 55 17)
                                  (0  0  0 24 17 77)

          and

                                       ( 6 -10)
                                       (15 -21)
                                       (11  -3)
                                     B=( 0  24)
                                       (51 -39)
                                       (46  67)

          Here A is symmetric and positive-definite and must first be
          factorized by F01MCF.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf04qaf}{nagf.ht}{ Solves sparse unsymmetric equations}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf04qaf}{NAG Documentation: f04qaf}
\beginscroll
\begin{verbatim}



     F04QAF(3NAG)      Foundation Library (12/10/92)      F04QAF(3NAG)



          F04 -- Simultaneous Linear Equations                       F04QAF
                  F04QAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F04QAF solves sparse unsymmetric equations, sparse linear least-
          squares problems and sparse damped linear least-squares problems,
          using a Lanczos algorithm.

          2. Specification

                 SUBROUTINE F04QAF (M, N, B, X, SE, APROD, DAMP, ATOL,
                1                   BTOL, CONLIM, ITNLIM, MSGLVL, ITN,
                2                   ANORM, ACOND, RNORM, ARNORM, XNORM,
                3                   WORK, RWORK, LRWORK, IWORK, LIWORK,
                4                   INFORM, IFAIL)
                 INTEGER          M, N, ITNLIM, MSGLVL, ITN, LRWORK, IWORK
                1                 (LIWORK), LIWORK, INFORM, IFAIL
                 DOUBLE PRECISION B(M), X(N), SE(N), DAMP, ATOL, BTOL,
                1                 CONLIM, ANORM, ACOND, RNORM, ARNORM,
                2                 XNORM, WORK(N,2), RWORK(LRWORK)
                 EXTERNAL         APROD

          3. Description

          F04QAF can be used to solve a system of linear equations

                                     Ax=b                             (3.1)

          where A is an n by n sparse unsymmetric matrix, or can be used to
          solve linear least-squares problems, so that F04QAF minimizes the
          value (rho) given by

                             (rho)=||r||,  r=b-Ax                     (3.2)

          where A is an m by n sparse matrix and ||r|| denotes the
                                             2  T
          Euclidean length of r so that ||r|| =r r. A damping parameter,
          (lambda), may be included in the least-squares problem in which
          case F04QAF minimizes the value (rho) given by

                             2      2         2     2
                        (rho) =||r|| +(lambda) ||x||                  (3.3)

          (lambda) is supplied as the parameter DAMP and should of course
          be zero if the solution to problems (3.1) or (3.2) is required.
          Minimizing (rho) in (3.3) is often called ridge regression.

          F04QAF is based upon algorithm LSQR (see Paige and Saunders [1]
          and [2]) and solves the problems by an algorithm based upon the
          Lanczos process. Details of the method are given in [1]. The
          routine does not require A explicitly, but A is specified via a
          user-supplied routine APROD which must perform the operations (
                        T
          y+Ax) and (x+A y) for a given n element vector x and m element
          vector y. A parameter to APROD specifies which of the two
          operations is required on a given entry.

          The routine also returns estimates of the standard errors of the
          sample regression coefficients (x , for i=1,2,...,n) given by the
                                           i
          diagonal elements of the estimated variance-covariance matrix V.
          When problem (3.2) is being solved and A is of full rank, then V
          is given by

                            2  T  -1    2      2
                         V=s (A A)  ,  s =(rho) /(m-n),  m>n

          and when problem (3.3) is being solved then V is given by

                    2  T          2  -1    2      2
                 V=s (A A+(lambda) I)  ,  s =(rho) /m,  (lambda)/=0.

              

          Let A denote the matrix

                                    (A        )
               A=A,  (lambda)=0 ; A=((lambda)I),  (lambda)/=0,        (3.4)

              

          let r denote the residual vector

                                       (b) 
                  r=r,  (lambda)=0 ; r=(0)-Ax,  (lambda)/=0           (3.5)

                                                         

          corresponding to an iterate x, so that (rho)=||r|| is the
          function being minimized, and let ||A|| denote the Frobenius
          (Euclidean) norm of A. Then the routine accepts x as a solution
          if it is estimated that one of the following two conditions is
          satisfied:

                                    

                       (rho)<=tol ||A||.||x||+tol ||b||               (3.6)
                                 1               2

                              T           
                           ||A r||<=tol ||A||(rho)                    (3.7)
                                       1

          where tol  and tol  are user-supplied tolerances which estimate
                   1        2
          the relative errors in A and b respectively. Condition (3.6) is
          appropriate for compatible problems where, in theory, we expect
          the residual to be zero and will be satisfied by an acceptable
          solution x to a compatible problem. Condition (3.7) is
          appropriate for incompatible systems where we do not expect the
          residual to be zero and is based upon the observation that, in
          theory,

                                         T
                                        A r=0

          when x is a solution to the least-squares problem, and so (3.7)
          will be satisfied by an acceptable solution x to a linear least-
          squares problem.

          The routine also includes a test to prevent convergence to
          solutions, x, with unacceptably large elements. This can happen
          if A is nearly singular or is nearly rank deficient. If we let
                                 

          the singular values of A be

                        (sigma) >=(sigma) >=...>=(sigma) >=0
                               1         2              n

                                       

          then the condition number of A is defined as

                                   

                              cond(A)=(sigma) /(sigma)
                                             1        k

                                                                    

          where (sigma)  is the smallest non-zero singular value of A and
                       k
                                                   

          hence k is the rank of A. When k<n, then A is rank deficient, the
          least-squares solution is not unique and F04QAF will normally
                                                               

          converge to the minimal length solution. In practice A will not
          have exactly zero singular values, but may instead have small
          singular values that we wish to regard as zero.

          The routine provides for this possibility by terminating if

                                     

                                cond(A)>=c                            (3.8)
                                          lim

                                                                         

          where c    is a user-supplied limit on the condition number of A.
                 lim
          For problem (3.1) termination with this condition indicates that
          A is nearly singular and for problem (3.2) indicates that A is
          nearly rank deficient and so has near linear dependencies in its
                                                        T
          columns. In this case inspection of ||r||, ||A r|| and ||x||,
          which are all returned by the routine, will indicate whether or
          not an acceptable solution has been found. Condition (3.8),
          perhaps in conjunction with (lambda)/=0, can be used to try and '
          regularise' least-squares solutions. A full discussion of the
          stopping criteria is given in Section 6 of reference Paige and
          Saunders [1].

          Introduction of a non-zero damping parameter (lambda) tends to
          reduce the size of the computed solution and to make its
          components less sensitive to changes in the data, and F04QAF is
          applicable when a value of (lambda) is known a priori. To have an
                                                         

          effect, (lambda) should normally be at least \/(epsilon)||A||
          where (epsilon) is the machine precision. For further discussion
          see Paige and Saunders [2] and the references given there.

          Whenever possible the matrix A should be scaled so that the
          relative errors in the elements of A are all of comparable size.
          Such a scaling helps to prevent the least-squares problem from
          being unnecessarily sensitive to data errors and will normally
          reduce the number of iterations required. At the very least, in
          the absence of better information, the columns of A should be
          scaled to have roughly equal column length.

          4. References

          [1]   Paige C C and Saunders M A (1982) LSQR: An Algorithm for
                Sparse Linear Equations and Sparse Least-squares. ACM Trans.
                Math. Softw. 8 43--71.

          [2]   Paige C C and Saunders M A (1982) ALGORITHM 583 LSQR: Sparse
                Linear Equations and Least-squares Problems. ACM Trans.
                Math. Softw. 8 195--209.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: m, the number of rows of the matrix A.
               Constraint: M >= 1.

           2:  N -- INTEGER                                           Input
               On entry: n, the number of columns of the matrix A.
               Constraint: N >= 1.

           3:  B(M) -- DOUBLE PRECISION array                  Input/Output
               On entry: the right-hand side vector b. On exit: the array
               is overwritten.

           4:  X(N) -- DOUBLE PRECISION array                        Output
               On exit: the solution vector x.

           5:  SE(N) -- DOUBLE PRECISION array                       Output
               On exit: the estimates of the standard errors of the
               components of x. Thus SE(i) contains an estimate of the
               element v   of the estimated variance-covariance matrix V.
                        ii
               The estimates returned in SE will be the lower bounds on the
               actual estimated standard errors, but will usually have at
               least one correct figure.

           6:  APROD -- SUBROUTINE, supplied by the user.
                                                         External Procedure
                                                                   T
               APROD must perform the operations y:=y+Ax and x:=x+A y for
               given vectors x and y.

               Its specification is:

                      SUBROUTINE APROD (MODE, M, N, X, Y, RWORK,
                     1                  LRWORK, IWORK, LIWORK)
                      INTEGER          MODE, M, N, LRWORK, LIWORK,
                     1                 IWORK(LIWORK)
                      DOUBLE PRECISION X(N), Y(M), RWORK(LRWORK)

                1:  MODE -- INTEGER                            Input/Output
                    On entry: MODE specifies which operation is to be
                    performed:
                         If MODE = 1, then APROD must compute y+Ax.

                                                                 T
                         If MODE = 2, then APROD must compute x+A y.
                    On exit: MODE may be used as a flag to indicate a
                                                             T
                    failure in the computation of y+Ax or x+A y. If MODE is
                    negative on exit from APROD, F04QAF will exit
                    immediately with IFAIL set to MODE.

                2:  M -- INTEGER                                      Input
                    On entry: m, the number of rows of A.

                3:  N -- INTEGER                                      Input
                    On entry: n, the number of columns of A.

                4:  X(N) -- DOUBLE PRECISION array             Input/Output
                    On entry: the vector x. On exit: if MODE = 1, X must be
                    unchanged;

                                                   T
                    If MODE = 2, X must contain x+A y.

                5:  Y(M) -- DOUBLE PRECISION array             Input/Output
                    On entry: the vector y. On exit: if MODE = 1, Y must
                    contain y+Ax;

                    If MODE = 2, Y must be unchanged.

                6:  RWORK(LRWORK) -- DOUBLE PRECISION array  User Workspace

                7:  LRWORK -- INTEGER                                 Input

                8:  IWORK(LIWORK) -- INTEGER array           User Workspace

                9:  LIWORK -- INTEGER                                 Input
                    APROD is called from F04QAF with the parameters RWORK,
                    LRWORK, IWORK and LIWORK as supplied to F04QAF. The
                    user is free to use the arrays RWORK and IWORK to
                    supply information to APROD as an alternative to using
                    COMMON.
               APROD must be declared as EXTERNAL in the (sub)program
               from which F04QAF is called. Parameters denoted as
               Input must not be changed by this procedure.

           7:  DAMP -- DOUBLE PRECISION                               Input
               On entry: the value (lambda). If either problem (3.1) or
               problem (3.2) is to be solved, then DAMP must be supplied as
               zero.

           8:  ATOL -- DOUBLE PRECISION                               Input
               On entry: the tolerance, tol , of the convergence criteria
                                           1
               (3.6) and (3.7); it should be an estimate of the largest
               relative error in the elements of A. For example, if the
               elements of A are correct to about 4 significant figures,
                                                    -4
               then ATOL should be set to about 5*10  . If ATOL is supplied
               as less than (epsilon), where (epsilon) is the machine
               precision, then the value (epsilon) is used in place of
               ATOL.

           9:  BTOL -- DOUBLE PRECISION                               Input
               On entry: the tolerance, tol , of the convergence criterion
                                           2
               (3.6);  it should be an estimate of the largest relative
               error in the elements of B. For example, if the elements of
               B are correct to about 4 significant figures, then BTOL
                                          -4
               should be set to about 5*10  . If BTOL is supplied as less
               than (epsilon), where (epsilon) is the machine precision,
               then the value (epsilon) is used in place of BTOL.

          10:  CONLIM -- DOUBLE PRECISION                             Input
               On entry: the value c    of equation  (3.8); it should be an
                                    lim
                                                      

               upper limit on the condition number of A. CONLIM should not
               normally be chosen much larger than 1.0/ATOL. If CONLIM is
               supplied as zero then the value 1.0/(epsilon), where
               (epsilon) is the machine precision, is used in place of
               CONLIM.

          11:  ITNLIM -- INTEGER                                      Input
               On entry: an upper limit on the number of iterations. If
               ITNLIM <= 0, then the value N is used in place of ITNLIM,
               but for ill-conditioned problems a higher value of ITNLIM is
               likely to be necessary.

          12:  MSGLVL -- INTEGER                                      Input
               On entry: the level of printing from F04QAF. If MSGLVL <= 0,
               then no printing occurs, but otherwise messages will be
               output on the advisory message channel (see X04ABF). A
               description of the printed output is given in Section 5.2
               below. The level of printing is determined as follows:
               MSGLVL <= 0
                     No printing.

               MSGLVL = 1
                     A brief summary is printed just prior to return from
                     F04QAF.

               MSGLVL >= 2
                     A summary line is printed periodically to monitor the
                     progress of F04QAF, together with a brief summary just
                     prior to return from F04QAF.

          13:  ITN -- INTEGER                                        Output
               On exit: the number of iterations performed.

          14:  ANORM -- DOUBLE PRECISION                             Output
                                                            

               On exit: an estimate of ||A|| for the matrix A of equation
               (3.4).

          15:  ACOND -- DOUBLE PRECISION                             Output
                                            

               On exit: an estimate of cond(A) which is a lower bound.

          16:  RNORM -- DOUBLE PRECISION                             Output
                                                                

               On exit: an estimate of ||r|| for the residual,  r, of
               equation (3.5) corresponding to the solution x returned in
                              

               X. Note that ||r|| is the function being minimized.

          17:  ARNORM -- DOUBLE PRECISION                            Output
                                              T
               On exit: an estimate of the ||A r|| corresponding to the
               solution x returned in X.

          18:  XNORM -- DOUBLE PRECISION                             Output
               On exit: an estimate of ||x|| for the solution x returned in
               X.

          19:  WORK(2*N) -- DOUBLE PRECISION array                Workspace

          20:  RWORK(LRWORK) -- DOUBLE PRECISION array       User Workspace
               RWORK is not used by F04QAF, but is passed directly to
               routine APROD and may be used to pass information to that
               routine.

          21:  LRWORK -- INTEGER                                      Input
               On entry: the length of the array RWORK as declared in the
               (sub)program from which F04QAF is called. Constraint: LRWORK
               >= 1.

          22:  IWORK(LIWORK) -- INTEGER array                User Workspace
               IWORK is not used by F04QAF, but is passed directly to
               routine APROD and may be used to pass information to that
               routine.

          23:  LIWORK -- INTEGER                                      Input
               On entry: the length of the array IWORK as declared in the
               (sub)program from which F04QAF is called. Constraint: LIWORK
               >= 1.

          24:  INFORM -- INTEGER                                     Output
               On exit: the reason for termination of F04QAF as follows:
               INFORM = 0
                     The exact solution is x=0. No iterations are performed
                     in this case.

               INFORM = 1
                     The termination criterion of equation (3.6) has been
                     satisfied with tol  and tol  as the values supplied in
                                       1        2
                     ATOL and BTOL respectively.

               INFORM = 2
                     The termination criterion of equation (3.7) has been
                     satisfied with tol  as the value supplied in ATOL.
                                       1

               INFORM = 3
                     The termination criterion of equation (3.6) has been
                     satisfied with tol  and/or tol  as the value (epsilon)
                                       1           2
                     , where (epsilon) is the machine precision. One or
                     both of the values supplied in ATOL and BTOL must have
                     been less than (epsilon) and was too small for this
                     machine.

               INFORM = 4
                     The termination criterion of equation (3.7) has been
                     satisfied with tol  as the value (epsilon), where
                                       1
                     (epsilon) is the machine precision. The value supplied
                     in ATOL must have been less than (epsilon) and was too
                     small for this machine.
               The values INFORM = 5, INFORM = 6 and INFORM = 7 correspond
               to failure with IFAIL = 2, IFAIL = 3 and IFAIL = 4
               respectively (see Section 6) and when IFAIL is negative
               INFORM will be set to the same negative value.

          25:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          5.1. Description of the printed output

          When MSGLVL > 0, then F04QAF will produce output (except in the
          case where the routine fails with IFAIL = 1) on the advisory
          message channel (see X04ABF ).

          When MSGLVL >= 2 then a summary line is printed periodically
          giving the following information:

             Output       Meaning

             ITN          Iteration number, k.

             X(1)         The first element of the current iterate x .
                                                                    k

             FUNCTION     The current value of the function, (rho), being
                          minimized.

                                                             

             COMPAT       An estimate of ||r ||/||b||, where r  is the
                                            k                 k
                          residual corresponding to x . This value should
                                                     k
                          converge to zero (in theory) if and only if the
                          problem is compatible. COMPAT decreases
                          monotonically.

                                            T             
             INCOMPAT     An estimate of ||A r ||/(||A||||r ||) which
                                              k            k
                          should converge to zero if and only if at the
                          solution (rho) is non-zero. INCOMPAT is not
                          usually monotonic.

                                                                   

             NRM(ABAR)    A monotonically increasing estimate of ||A||.

             COND(ABAR)   A monotonically increasing estimate of the
                                                

                          condition number cond(A).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL< 0
               A negative value of IFAIL indicates an exit from F04QAF
               because the user has set MODE negative in APROD. The value
               of IFAIL will be the same as the user's setting of MODE.

          IFAIL= 1
               On entry M < 1,

               or       N < 1,

               or       LRWORK < 1,

               or       LIWORK < 1.

          IFAIL= 2
               The condition of equation (3.8) has been satisfied for the
               value of c    supplied in CONLIM. If this failure is
                         lim
               unexpected the user should check that APROD is working
               correctly. Although conditions (3.6) or (3.7) have not been
               satisfied, the values returned in RNORM, ARNORM and XNORM
               may nevertheless indicate that an acceptable solution has
               been reached.

          IFAIL= 3
               The conditions of equation (3.8) has been satisified for the
               value c   =1.0/(epsilon), where (epsilon) is the machine
                      lim
                                     

               precision. The matrix A is nearly singular or rank deficient
               and the problem is too ill-conditioned for this machine. If
               this failure is unexpected, the user should check that APROD
               is working correctly.

          IFAIL= 4
               The limit on the number of iterations has been reached. The
               number of iterations required by F04QAF and the condition of
                          

               the matrix A can depend strongly on the scaling of the
               problem. Poor scaling of the rows and columns of A should be
               avoided whenever possible.

          7. Accuracy

          When the problem is compatible, the computed solution x will
          satisfy the equation

                                       r=b-Ax,

          where an estimate of ||r|| is returned in the parameter RNORM.
          When the problem is incompatible, the computed solution x will
          satisfy the equation

                                        T
                                       A r=e,

          where an estimate of ||e|| is returned in the parameter ARNORM.
          See also Section 6.2 of Paige and Saunders [1].

          8. Further Comments

          The time taken by the routine is likely to be principally
          determined by the time taken in APROD, which is called twice on
          each iteration, once with MODE = 1 and once with MODE = 2. The
          time taken per iteration by the remaining operations in F04QAF is
          approximately proportional to max(m,n).

          The Lanczos process will usually converge more quickly if A is
          pre-conditioned by a non-singular matrix M that approximates A in
          some sense and is also chosen so that equations of the form My=c
          can efficiently be solved for y. Some discussion of pre-
          conditioning in the context of symmetric matrices is given in
          Section 3 of the document for F04MBF. In the context of F04QAF,
          problem (3.1) is equivalent to

                                     -1
                                  (AM  )y=b,  Mx=y

          and problem (3.2) is equivalent to minimizing

                                               -1
                          (rho)=||r||,  r=b-(AM  )y,  Mx=y.

                                         -1 T   -1   -T  T   -1
          Note that the normal matrix (AM  ) (AM  )=M  (A A)M   so that the
                             -1
          pre-conditioning AM   is equivalent to the pre-conditioning
           -T  T   -1                       T
          M  (A A)M   of the normal matrix A A.

          Pre-conditioning can be incorporated into F04QAF simply by coding
                                           -1         -T T
          the routine APROD to compute y+AM  x and x+M  A y in place of
                      T
          y+Ax and x+A y respectively, and then solving the equations Mx=y
                                           -1
          for x on return from F04QAF. y+AM  x should be computed by
                                                             -T T
          solving Mz=x for z and then computing y+Az, and x+M  A y should
                                  T   T
          be computed by solving M z=A y for z and then forming x+z.

          9. Example

          To solve the linear least-squares problem

                            minimize (rho)=||r||,  r=b-Ax

          where A is the 13 by 12 matrix and b is the 13 element vector
          given by

                        ( 1  0  0 -1  0  0  0  0  0  0  0  0)
                        ( 0  1  0  0 -1  0  0  0  0  0  0  0)
                        ( 0  0  1 -1  0  0  0  0  0  0  0  0)
                        (-1  0 -1  4 -1  0  0 -1  0  0  0  0)
                        ( 0 -1  0 -1  4 -1  0  0 -1  0  0  0)
                        ( 0  0  0  0 -1  1  0  0  0  0  0  0)
                      A=( 0  0  0  0  0  0  1 -1  0  0  0  0),
                        ( 0  0  0 -1  0  0 -1  4 -1  0 -1  0)
                        ( 0  0  0  0 -1  0  0 -1  4 -1  0 -1)
                        ( 0  0  0  0  0  0  0  0 -1  1  0  0)
                        ( 0  0  0  0  0  0  0 -1  0  0  1  0)
                        ( 0  0  0  0  0  0  0  0 -1  0  0  1)
                        ( 1  1  1  0  0  1  1  0  0  1  1  1)

                                          ( 0  )
                                          ( 0  )
                                          ( 0  )
                                          ( 1  )
                                          ( 1  )
                                         2( 0  )
                                     b=-h ( 0  )
                                          ( 1  )
                                          ( 1  )
                                          ( 0  )
                                          ( 0  )
                                          ( 0  )
                                          (  -3)
                                          (-h  )

          with h=0.1.

          Such a problem can arise by considering the Neumann problem on a
          rectangle

                              (delta)u
                              --------=0
                              (delta)n

               (delta)u            2           (delta)u      /
               --------=0   (nabla) u=g(x,y)   --------=0    |u=1
               (delta)n                        (delta)n      /
                                                             c

                              (delta)u
                              --------=0
                              (delta)n

          where C is the boundary of the rectangle, and discretising as
          illustrated below with the square mesh



                   Please see figure in printed Reference Manual

          The 12 by 12 symmetric part of A represents the difference
          equations and the final row comes from the normalising condition.
          The example program has g(x,y)=1 at all the internal mesh points,
          but apart from this is written in a general manner so that the
          number of rows (NROWS) and columns (NCOLS) in the grid can
          readily be altered.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf06}{nagf.ht}{ Linear Algebra Support Routines}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf06}{NAG Documentation: f06}
\beginscroll
\begin{verbatim}



     F06(3NAG)         Foundation Library (12/10/92)         F06(3NAG)



          F06 -- Linear Algebra Support Routines        Introduction -- F06
                                    Chapter F06
                          Linear Algebra Support Routines

          Contents of this Introduction:

          1.     Scope of the Chapter

          2.     Background to the Problems

          2.1.   The Use of BLAS Names

          2.2.   Background Information

          2.2.1. Real plane rotations

          2.3.   References

          3.     Recommendations on Choice and Use of Routines

          3.1.   The Level-0 Scalar Routines

          3.2.   The Level-1 Vector Routines

          3.3.   The Level-2 Matrix-vector Routines

          3.4.   The Level-3 Matrix-matrix Routines

          4.     Description of the F06 Routines

          4.1.   The Level-0 Scalar Routines

          4.2.   The Level-1 Vector Routines

          4.3.   The Level-2 Matrix-vector Routines

          4.4.   The Level-3 Matrix-matrix Routines



          1. Scope of the Chapter

          This Chapter is concerned with basic linear algebra routines
          which perform elementary algebraic operations involving scalars,
          vectors and matrices.

          2. Background to the Problems

          All the routines in this Chapter meet the specification of the
          Basic Linear Algebra Subprograms (BLAS) as described in Lawson
          et al [6], Dongarra et al [3] and [4]. The first reference
          describes a set of routines concerned with operations on scalars
          and vectors: these will be referred to here as the Level-0 and
          the Level-1 BLAS; the second reference describes a set of
          routines concerned with matrix-vector operations: these will be
          referred to here as the Level-2 BLAS; and the third reference
          describes a set of routines concerned with matrix-matrix
          operations: these will be referred to here as the Level-3 BLAS.
          The terminology reflects the number of operations involved. For
                                                 2
          example, a Level-2 routine involves 0(n ) operations for an n by
          n matrix.

          Table 1.1 indicates the naming scheme for the routines in this
          Chapter. The heading 'mixed type' is for routines where a mixture
          of data types is involved, such as a routine that returns the
          real Euclidean length of a complex vector.


                                       Level-0  Level-1  Level-2  Level-3
                'real'   BLAS routine  F06A F   F06E F   F06P F   F06Y F
             'complex'   BLAS routine  -        F06G F   F06S F   F06Z F

                                     Table 1.1



          The routines in this chapter do not have full routine documents,
          but instead are covered by some relevant background material, in
          Section 2.2, together with general descriptions, in Section 4,
          sufficient to enable their use. As this chapter is concerned only
          with basic linear algebra operations, the routines will not
          normally be required by the general user. The functionality of
          each routine is indicated in Section 3 so that those users
          requiring these routines to build specialist linear algebra
          modules can determine which routines are of interest.

          2.1. The Use of BLAS Names

          Many of the routines in other chapters of the Library call the
          BLAS in this chapter. These routines are usually called by the
          BLAS name and so, for correct operation of the Library, it is
          essential that users do not attempt to link their own versions of
          these routines. If users are in any doubt about how to avoid
          this, please consult your local support staff or the NAG Response
          Centre.

          The BLAS names are used in order to make use of efficient
          implementations of the routines when these exist. Such
          implementations are stringently tested before being used, to
          ensure that they correctly meet the specification of the BLAS,
          and that they return the desired accuracy (see, for example,
          Dongarra et al. [3] and [4]).

          2.2. Background Information

          Most of the routines in this chapter implement straightforward
          scalar, vector and matrix operations that need no further
          explanation beyond a statement of the purpose of the routine. In
          this section we give some additional background information for
          those few cases where additional explanation may be necessary.

          2.2.1.  Real plane rotations

          Two routines in the chapter are concerned with setting up and
          applying plane rotations. For further background information see
          Golub and Van Loan [5].

          A plane rotation matrix for the (i,j) plane, R  , is an
                                                        ij
          orthogonal matrix that is different from the unit matrix only in
          the elements r  , r  , r   and r  . If we put
                        ii   jj   ij      ji


                                      (r   r  )
                                      ( ii  ij)
                                    R=(r   r  ),
                                      ( ji  jj)

          then, in the real case, it is usual to choose R   so that
                                                         ij

                     ( c s)
                   R=(-s c),  c=cos(theta),  s=sin(theta).            (2.1)

          The application of plane rotations is straightforward and needs
          no further elaboration, so further comment is made only on the
          construction of plane rotations.

          The most common use of plane rotations is to choose c and s so
          that for given a and b,


                                ( c s)(a) (d)
                                (-s c)(b)=(0)                         (2.2)

          In such an application the matrix R is often termed a Givens
          rotation matrix.

          The BLAS routine F06AAF(*) (DROTG), see Lawson et al [6] and
          Dodson and Grimes [1, 2], computes c, s and d as


                                           2  2 1/2
                                d=(sigma)(a +b )   ,
                          {a/d, d/=0      {b/d, d/=0
                        c={1,   d=0 ,   s={0,   d=0                   (2.3)

                        {sign a,|a|>|b|
          where (sigma)={sign b,|a|<=|b|.

          The value z defined as

                               {s,   |s|<c or c=0
                             z={1/c, 0<|c|<=s                         (2.4)

          is also computed and this enables c and s to be reconstructed
          from the single value z as


                         {0,          z=1
                         {    2 1/2             {1,       z=1
                       c={(1-z )   , |z|<1    s={z,      |z|<1
                         {1/z,       |z|>1,     {    2
                                                {(1-c ), |z|>1.

          2.3. References

          [1]   Dodson D S and Grimes R G (1982) Remark on Algorithm 539.
                ACM Trans Math Softw. 8 403--404.

          [2]   Dodson D S and Grimes R G (1982) Remark on Algorithm 539.
                ACM Trans. Math. Softw. 9 140.

          [3]   Dongarra J J, Du Croz J J, Hammarling S and Hanson R J
                (1988) An Extended Set of FORTRAN Basic Linear Algebra
                Subprograms. ACM Trans. Math. Softw. 14 1--32.

          [4]   Dongarra J J, Du Croz J J, Duff I S and Hammarling S (1990)
                A Set of Level 3 Basic Linear Algebra Subprograms. ACM
                Trans. Math. Softw. 16 1--28.

          [5]   Golub G H and Van Loan C F (1989) Matrix Computations (2nd
                Edition). Johns Hopkins University Press, Baltimore,
                Maryland.

          [6]   Lawson C L, Hanson R J, Kincaid D R and Krogh F T (1979)
                Basic Linear Algebra Subprograms for Fortran Usage. ACM
                Trans. Math. Softw. 5 308--325.

          3. Recommendations on Choice and Use of Routines

          This section lists the routines in each of the categories Level-0
          (scalar), Level-1 (vector), Level-2 (matrix-vector and matrix)
          and Level-3 (matrix-matrix). The corresponding double precision
          BLAS name is indicated in brackets.

          Within each section routines are listed in alphabetic order of
          the fifth character in the routine name, so that corresponding
          real and complex routines may have adjacent entries.

          3.1. The Level-0 Scalar Routine

          The Level-0 routine performs the scalar operation of generating a
          plane rotation.

          F06AAF (DROTG)  generates a real plane rotation.

          3.2. The Level-1 Vector Routines

          The Level-1 routines perform operations on or between vectors,
          such as computing dot products and Euclidean lengths.

          F06EAF (DDOT)   computes the dot product of two real vectors

          F06GAF (ZDOTU)  computes the dot product of two complex vectors
                          (unconjugated)

          F06GBF (ZDOTC)  computes the dot product of two complex vectors
                          (conjugated)

          F06ECF (DAXPY)  adds a scalar times a vector to another real
                          vector

          F06GCF (ZAXPY)  adds a scalar times a vector to another complex
                          vector

          F06EDF (DSCAL)  multiplies a real vector by a scalar

          F06GDF (ZSCAL)  multiplies a complex vector by a scalar

          F06JDF (ZDSCAL) multiplies a complex vector by a real scalar

          F06EFF (DCOPY)  copies a real vector

          F06GFF (ZCOPY)  copies a complex vector

          F06EGF (DSWAP)  swaps two real vectors

          F06GGF (ZSWAP)  swaps two complex vectors

          F06EJF (DNRM2)  computes the Euclidean length of a real vector

          F06JJF (DZNRM2) computes the Euclidean length of a complex vector

          F06EKF (DASUM)  sums the absolute values of the elements of a
                          real vector

          F06JKF (DZASUM) sums the absolute values of the elements of a
                          complex vector

          F06JLF (IDAMAX) finds the index of the element of largest
                          absolute value of a real vector

          F06JMF (IZAMAX) finds the index of the element of largest
                          absolute value of a complex vector

          F06EPF (DROT)   applies a real plane rotation

          3.3. The Level-2 Matrix-vector Routines

          The Level-2 routines perform matrix-vector operations, such as
          forming the product between a matrix and a vector.

          F06PAF (DGEMV)  computes a matrix-vector product;
                          real general matrix

          F06SAF (ZGEMV)  computes a matrix-vector product;
                          complex general matrix

          F06PBF (DGBMV)  computes a matrix-vector product;
                          real general band matrix

          F06SBF (ZGBMV)  computes a matrix-vector product;
                          complex general band matrix

          F06PCF (DSYMV)  computes a matrix-vector product;
                          real symmetric matrix

          F06SCF (ZHEMV)  computes a matrix-vector product;
                          complex Hermitian matrix

          F06PDF (DSBMV)  computes a matrix-vector product;
                          real symmetric band matrix

          F06SDF (ZHBMV)  computes a matrix-vector product;
                          complex Hermitian band matrix

          F06PEF (DSPMV)  computes a matrix-vector product;
                          real symmetric packed matrix

          F06SEF (ZHPMV)  computes a matrix-vector product;
                          complex Hermitian packed matrix

          F06PFF (DTRMV)  computes a matrix-vector product;
                          real triangular matrix

          F06SFF (ZTRMV)  computes a matrix-vector product;
                          complex triangular matrix

          F06PGF (DTBMV)  computes a matrix-vector product;
                          real triangular band matrix

          F06SGF (ZTBMV)  computes a matrix-vector product;
                          complex triangular band matrix

          F06PHF (DTPMV)  computes a matrix-vector product;
                          real triangular packed matrix

          F06SHF (ZTPMV)  computes a matrix-vector product;
                          complex triangular packed matrix

          F06PJF (DTRSV)  solves a system of equations;
                          real triangular coefficient matrix

          F06SJF (ZTRSV)  solves a system of equations;
                          complex triangular coefficient matrix

          F06PKF (DTBSV)  solves a system of equations;
                          real triangular band coefficient matrix

          F06SKF (ZTBSV)  solves a system of equations;
                          complex triangular band coefficient matrix

          F06PLF (DTPSV)  solves a system of equations;
                          real triangular packed coefficient matrix

          F06SLF (ZTPSV)  solves a system of equations;
                          complex triangular packed coefficient matrix

          F06PMF (DGER)   performs a rank-one update;
                          real general matrix

          F06SMF (ZGERU)  performs a rank-one update;
                          complex general matrix (unconjugated vector)

          F06SNF (ZGERC)  performs a rank-one update;
                          complex general matrix (conjugated vector)

          F06PPF (DSYR)   performs a rank-one update;
                          real symmetric matrix

          F06SPF (ZHER)   performs a rank-one update;
                          complex Hermitian matrix

          F06PQF (DSPR)   performs a rank-one update;
                          real symmetric packed matrix

          F06SQF (ZHPR)   performs a rank-one update;
                          complex Hermitian packed matrix

          F06PRF (DSYR2)  performs a rank-two update;
                          real symmetric matrix

          F06SRF (ZHER2)  performs a rank-two update;
                          complex Hermitian matrix

          F06PSF (DSPR2)  performs a rank-two update;
                          real symmetric packed matrix

          F06SSF (ZHPR2)  performs a rank-two update;
                          complex Hermitian packed matrix

          3.4. The Level-3 Matrix-matrix Routines

          The Level-3 routines perform matrix-matrix operations, such as
          forming the product of two matrices.

          F06YAF (DGEMM)  computes a matrix-matrix product; two real
                          rectangular matrices

          F06ZAF (ZGEMM)  computes a matrix-matrix product; two complex
                          rectangular matrices

          F06YCF (DSYMM)  computes a matrix-matrix product; one real
                          symmetric matrix, one real rectangular matrix

          F06ZCF (ZHEMM)  computes a matrix-matrix product; one complex
                          Hermitian matrix, one complex rectangular matrix

          F06YFF (DTRMM)  computes a matrix-matrix product; one real
                          triangular matrix, one real rectangular matrix

          F06ZFF (ZTRMM)  computes a matrix-matrix product; one complex
                          triangular matrix, one complex rectangular matrix

          F06YJF (DTRSM)  solves a system of equations with multiple right-
                          hand sides, real triangular coefficient matrix

          F06ZJF (ZTRSM)  solves a system of equations with multiple right-
                          hand sides, complex triangular coefficient matrix

          F06YPF (DSYRK)  performs a rank-k update of a real symmetric
                          matrix

          F06ZPF (ZHERK)  performs a rank-k update of a complex hermitian
                          matrix

          F06YRF (DSYR2K) performs a rank-2k update of a real symmetric
                          matrix

          F06ZRF (ZHER2K) performs a rank-2k update of a complex Hermitian
                          matrix

          F06ZTF (ZSYMM)  computes a matrix-matrix product: one complex
                          symmetric matrix, one complex rectangular matrix

          F06ZUF (ZSYRK)  performs a rank-k update of a complex symmetric
                          matrix

          F06ZWF (ZSYR2K) performs a rank-2k update of a complex symmetric
                          matrix

          4. Description of the F06 Routines

          In this section we describe the purpose of each routine and give
          information on the parameter lists, where appropriate indicating
          their general nature. Usually the association between the routine
          arguments and the mathematical variables is obvious and in such
          cases a description of the argument is omitted.

          Within each section, the parameter lists for all routines are
          presented, followed by the purpose of the routines and
          information on the parameter lists. The double precision BLAS
          names are given in ENTRY statements.

          Within each section routines are listed in alphabetic order of
          the fifth character in the routine name, so that corresponding
          real and complex routines may have adjacent entries.

          4.1. The Level-0 Scalar Routines

          The scalar routines have no array arguments.


          SUBROUTINE   F06AAF( A,B,C,S )
          ENTRY        DROTG ( A,B,C,S )
          DOUBLE PRECISION     A,B,C,S

          F06AAF(*) generates the parameters c and s of a Givens rotation
          as defined by equations (2.3) and (2.4), from given a and b. On
          exit, A is overwritten by d and B is overwritten by z.

          4.2. The Level-1 Vector Routines

          The vector routines all have one or more one-dimensional arrays
          as arguments, each representing a vector.

          The length of each vector, n, is represented by the argument N,
          and the routines may be called with non-positive values of N, in
          which case the routine returns immediately except for the
          functions, which set the function value to zero before returning.

          In addition to the argument N, each array argument is also
          associated with an increment argument that immediately follows
          the array argument, and whose name consists of the three
          characters INC, followed by the name of the array. For example, a
          vector x will be represented by the two arguments X, INCX. The
          increment argument is the spacing (stride) in the array for which
          the elements of the vector occur. For instance, if INCX = 2, then
          the elements of x are in locations X(1),X(3),...,X(2*N-1) of the
          array X and the intermediate locations X(2),X(4),...,X(2*N-2) are
          not referenced.

          Thus when INCX > 0, the vector element x  is in the array element
                                                  i
          X(1+(i-1)*INCX). When INCX <= 0 the elements are stored in the
          reverse order so that the vector element x  is in the array
                                                    i
          element X(1-(n-i)*INCX) and hence, in particular, the element x
                                                                         n
          is in X(1). The declared length of the array X in the calling
          (sub)program must be at least (1+(N-1)*|INCX|).

          Non-positive increments are permitted only for those routines
          that have more than one array argument. While zero increments are
          formally permitted for such routines, their use in Chapter F06 is
          strongly discouraged since the effect may be implementation
          dependent.



          DOUBLE PRECISION FUNCTION F06EAF ( N,      X,INCX,Y,INCY )
          DOUBLE PRECISION          DDOT
          ENTRY                     DDOT   ( N,      X,INCX,Y,INCY )
          INTEGER                            N,        INCX,  INCY
          DOUBLE PRECISION                           X(*),  Y(*)

          COMPLEX(KIND(1.0D0)) FUNCTION F06GAF ( N,      X,INCX,Y,INCY )
          COMPLEX(KIND(1.0D0))          ZDOTU
          ENTRY                         ZDOTU  ( N,      X,INCX,Y,INCY )
          INTEGER                                N,        INCX,  INCY
          COMPLEX(KIND(1.0D0))                           X(*),  Y(*)

          COMPLEX(KIND(1.0D0)) FUNCTION F06GBF ( N,      X,INCX,Y,INCY )
          COMPLEX(KIND(1.0D0))          ZDOTC
          ENTRY                         ZDOTC  ( N,      X,INCX,Y,INCY )
          INTEGER                                N,        INCX,  INCY
          COMPLEX(KIND(1.0D0))                           X(*),  Y(*)

          SUBROUTINE                F06ECF ( N,ALPHA,X,INCX,Y,INCY )
          ENTRY                     DAXPY  ( N,ALPHA,X,INCX,Y,INCY )
          INTEGER                            N,        INCX,  INCY
          DOUBLE PRECISION                     ALPHA,X(*),  Y(*)

          SUBROUTINE                F06GCF ( N,ALPHA,X,INCX,Y,INCY )
          ENTRY                     ZAXPY  ( N,ALPHA,X,INCX,Y,INCY )
          INTEGER                            N,        INCX,  INCY
          COMPLEX(KIND(1.0D0))                 ALPHA,X(*),  Y(*)

          SUBROUTINE                F06EDF ( N,ALPHA,X,INCX )
          ENTRY                     DSCAL  ( N,ALPHA,X,INCX )
          INTEGER                            N,        INCX
          DOUBLE PRECISION                     ALPHA,X(*)

          SUBROUTINE                F06GDF ( N,ALPHA,X,INCX )
          ENTRY                     ZSCAL  ( N,ALPHA,X,INCX )
          INTEGER                            N,        INCX
          COMPLEX(KIND(1.0D0))                 ALPHA,X(*)

          SUBROUTINE                F06JDF ( N,ALPHA,X,INCX )
          ENTRY                     ZDSCAL ( N,ALPHA,X,INCX )
          INTEGER                            N,        INCX
          DOUBLE PRECISION          ALPHA
          COMPLEX(KIND(1.0D0))                       X(*)

          SUBROUTINE                F06EFF ( N,      X,INCX,Y,INCY )
          ENTRY                     DCOPY  ( N,      X,INCX,Y,INCY )
          INTEGER                            N,        INCX,  INCY
          DOUBLE PRECISION                           X(*),  Y(*)

          SUBROUTINE                F06GFF ( N,      X,INCX,Y,INCY )
          ENTRY                     ZCOPY  ( N,      X,INCX,Y,INCY )
          INTEGER                            N,        INCX,  INCY
          COMPLEX(KIND(1.0D0))                       X(*),  Y(*)

          SUBROUTINE                F06EGF ( N,      X,INCX,Y,INCY )
          ENTRY                     DSWAP  ( N,      X,INCX,Y,INCY )
          INTEGER                            N,        INCX,  INCY
          DOUBLE PRECISION                           X(*),  Y(*)

          SUBROUTINE                F06GGF ( N,      X,INCX,Y,INCY )
          ENTRY                     ZSWAP  ( N,      X,INCX,Y,INCY )
          INTEGER                            N,        INCX,  INCY
          COMPLEX(KIND(1.0D0))                       X(*),  Y(*)

          DOUBLE PRECISION FUNCTION F06EJF ( N,      X,INCX )
          DOUBLE PRECISION          DNRM2
          ENTRY                     DNRM2  ( N,      X,INCX )
          INTEGER                            N,        INCX
          DOUBLE PRECISION                           X(*)

          DOUBLE PRECISION FUNCTION F06JJF ( N,      X,INCX )
          DOUBLE PRECISION          DZNRM2
          ENTRY                     DZNRM2 ( N,      X,INCX )
          INTEGER                            N,        INCX
          COMPLEX(KIND(1.0D0))                       X(*)

          DOUBLE PRECISION FUNCTION F06EKF ( N,      X,INCX )
          DOUBLE PRECISION          DASUM
          ENTRY                     DASUM  ( N,      X,INCX )
          INTEGER                            N,        INCX
          DOUBLE PRECISION                           X(*)

          DOUBLE PRECISION FUNCTION F06JKF ( N,      X,INCX )
          DOUBLE PRECISION          DZASUM
          ENTRY                     DZASUM ( N,      X,INCX )
          INTEGER                            N,        INCX
          COMPLEX(KIND(1.0D0))                       X(*)

          INTEGER FUNCTION          F06JLF ( N,      X,INCX )
          INTEGER                   IDAMAX
          ENTRY                     IDAMAX ( N,      X,INCX )
          INTEGER                            N,        INCX
          DOUBLE PRECISION                            X(*)

          INTEGER FUNCTION          F06JMF ( N,      X,INCX )
          INTEGER                   IZAMAX
          ENTRY                     IZAMAX ( N,      X,INCX )
          INTEGER                            N,        INCX
          COMPLEX(KIND(1.0D0))                       X(*)

          SUBROUTINE                F06EPF ( N,      X,INCX,Y,INCY,C,S )
          ENTRY                     DROT   ( N,      X,INCX,Y,INCY,C,S )
          INTEGER                            N,        INCX,  INCY
          DOUBLE PRECISION                           X(*),  Y(*),  C,S

          F06EAF(*) and F06GAF(*)

                                  T
          return the dot product x y.

          F06GBF(*)

                                   H          H
          returns the dot product x y, where x  denotes the complex
                        T
          conjugate of x .

          F06ECF(*) and F06GCF(*)

          perform the operation y<-(alpha)x+y, often called an axpy
          operation.

          F06EDF(*), F06GDF(*) and F06JDF(*)

          perform the operation x<-(alpha)x.

          F06EFF(*) and F06GFF(*)

          perform the operation y<-x.

          F06EGF(*) and F06GGF(*)

          perform the operation x<=>y, that is x and y are swapped.

          F06EJF(*) and F06JJF(*)

                                                     ( n       )1/2
                                                     ( --     2)
          return the value ||x||  defined by ||x|| = ( >  |x | )   .
                                2                 2  ( --   i  )
                                                     ( i=1     )

          F06EKF(*)

                                                      n
                                                      --
          returns the value ||x||  defined by ||x|| = >  |x |.
                                 1                 1  --   i
                                                      i=1

          F06JKF(*)

                                                  n
                                                  --
          returns the value asum defined by asum= >  (|(Re(x )|+|Im(x )|).
                                                  --        i        i
                                                  i=1

          F06JLF(*)

          returns the first index j such that |x |=max |x |.
                                                j     i  i

          F06JMF(*)

          returns the first index j such that
          |Re(x )|+|Im(x )|=max (|(Re(x )|+|Im(x )|).
               j        j      i       i        i

          F06EPF(*)

                                      ( T)          ( T)
                                      (x )          (x )
                                      ( T)    ( c s)( T)
          performs the plane rotation (y ) <- (-s c)(y ).

          4.3. The Level-2 Matrix-vector Routines

          The matrix-vector routines all have one array argument
          representing a matrix; usually this is a two-dimensional array
          but in some cases the matrix is represented by a one-dimensional
          array.

          The size of the matrix is determined by the arguments M and N for
          an m by n rectangular matrix; and by the argument N for an n by n
          symmetric, Hermitian, or triangular matrix. Note that it is
          permissible to call the routines with M or N = 0, in which case
          the routines exit immediately without referencing their array
          arguments. For band matrices, the bandwidth is determined by the
          arguments KL and KU for a rectangular matrix with kl sub-
          diagonals and ku super-diagonals; and by the argument K for a
          symmetric, Hermitian, or triangular matrix with k sub-diagonals
          and/or super-diagonals.

          The description of the matrix consists either of the array name
          (A) followed by the first dimension of the array as declared in
          the calling (sub)program (LDA), when the matrix is being stored
          in a two-dimensional array; or the array name (AP) alone when the
          matrix is being stored as a (packed) vector. In the former case
          the actual array must contain at least ((n-1)d+l) elements, where
          d is the first dimension of the array, d>=l , and l=m for arrays
          representing general matrices, l=n for arrays representing
          symmetric, Hermitian and triangular matrices, l=kl+ku+1 for
          arrays representing general band matrices and l=k+1 for
          symmetric, Hermitian and triangular band matrices. For one-
          dimensional arrays representing matrices (packed storage) the
                                             1
          actual array must contain at least -n(n+1) elements.
                                             2

          As with the vector routines, vectors are represented by one-
          dimensional arrays together with a corresponding increment
          argument (see Section 4.2). The only difference is that for these
          routines a zero increment is not permitted.

          When the vector x consists of k elements then the declared length
          of the array X in the calling (sub)program must be at least
          (1+(k-1)|INCX|).

          The arguments that specify options are character arguments with
          the names TRANS, UPLO and DIAG. TRANS is used by the matrix-
          vector product routines as follows:

              Value      Meaning

              'N' or 'n' Operate with the matrix

              'T' or 't' Operate with the transpose of the matrix

              'C' or 'c' Operate with the conjugate transpose of the matrix

          In the real case the values 'T', 't', 'C' and 'c' have the same
          meaning.

          UPLO is used by the Hermitian, symmetric, and triangular matrix
          routines to specify whether the upper or lower triangle is being
          referenced as follows:


              Value      Meaning

              'U' or 'u' Upper triangle

              'L' or 'l' Lower triangle

          DIAG is used by the triangular matrix routines to specify whether
          or not the matrix is unit triangular, as follows:

              Value      Meaning

              'U' or 'u' Unit triangular

              'N' or 'n' Non-unit triangular

          When DIAG is supplied as 'U' or 'u' the diagonal elements are not
          referenced.

          It is worth noting that actual character arguments in Fortran may
          be longer than the corresponding dummy arguments. So that, for
          example, the value 'T' for TRANS may be passed as 'TRANSPOSE'.

          The routines for real symmetric and complex Hermitian matrices
          allow for the matrix to be stored in either the upper (UPLO = 'U
          to be packed in a one-dimensional array. In the latter case the
          upper triangle may be packed sequentially column by column (UPLO
          = 'U'), or the lower triangle may be packed sequentially column
          by column (UPLO = 'L'). Note that for real symmetric matrices
          packing the upper triangle by column is equivalent to packing the
          lower triangle by rows, and packing the lower triangle by columns
          is equivalent to packing the upper triangle by rows. (For complex
          Hermitian matrices the only difference is that the off-diagonal
          elements are conjugated.)

          For triangular matrices the argument UPLO serves to define
          whether the matrix is upper (UPLO = 'U') or lower (UPLO = 'L')
          triangular. In packed storage the triangle has to be packed by
          column.

          The band matrix routines allow storage so that the jth column of
          the matrix is stored in the jth column of the Fortran array. For
          a general band matrix the diagonal of the matrix is stored in the
          (ku+1)th row of the array. For a Hermitian or symmetric matrix
          either the upper triangle (UPLO = 'U') may be stored in which
          case the leading diagonal is in the (k+1)th row of the array, or
          the lower triangle (UPLO = 'L') may be stored in which case the
          leading diagonal is in the first row of the array. For an upper
          triangular band matrix (UPLO = 'U') the leading diagonal is in
          the (k+1)th row of the array and for a lower triangular band
          matrix (UPLO = 'L') the leading diagonal is in the first row.

          For a Hermitian matrix the imaginary parts of the diagonal
          elements are of course zero and thus the imaginary parts of the
          corresponding Fortran array elements need not be set, but are
          assumed to be zero.

          For packed triangular matrices the same storage layout is used
          whether or not DIAG = 'U', i.e., space is left for the diagonal
          elements even if those array elements are not referenced.

                                             H
          Throughout the following sections A  denotes the complex
                        T
          conjugate of A .


          SUBROUTINE F06PAF( TRANS,M,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY )
          ENTRY DGEMV      ( TRANS,M,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY )
          CHARACTER*1        TRANS
          INTEGER            M,N,LDA,INCX,INCY
          DOUBLE PRECISION   ALPHA,A(LDA,*),X(*),BETA,Y(*)

          SUBROUTINE F06SAF( TRANS,M,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY )
          ENTRY ZGEMV      ( TRANS,M,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY )
          CHARACTER*1          TRANS
          INTEGER              M,N,LDA,INCX,INCY
          COMPLEX(KIND(1.0D0)) ALPHA,A(LDA,*),X(*),BETA,Y(*)

          SUBROUTINE F06PBF( TRANS,M,N,KL,KU,ALPHA,A,LDA,X,INCX,BETA,Y,INCY )
          ENTRY DGBMV      ( TRANS,M,N,KL,KU,ALPHA,A,LDA,X,INCX,BETA,Y,INCY )
          CHARACTER*1        TRANS
          INTEGER            M,N,KL,KU,LDA,INCX,INCY
          DOUBLE PRECISION   ALPHA,A(LDA,*),X(*),BETA,Y(*)

          SUBROUTINE F06SBF( TRANS,M,N,KL,KU,ALPHA,A,LDA,X,INCX,BETA,Y,INCY )
          ENTRY ZGBMV      ( TRANS,M,N,KL,KU,ALPHA,A,LDA,X,INCX,BETA,Y,INCY )
          CHARACTER*1          TRANS
          INTEGER              M,N,KL,KU,LDA,INCX,INCY
          COMPLEX(KIND(1.0D0)) ALPHA,A(LDA,*),X(*),BETA,Y(*)

          SUBROUTINE F06PCF( UPLO,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY )
          ENTRY DSYMV      ( UPLO,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY )
          CHARACTER*1        UPLO
          INTEGER            N,LDA,INCX,INCY
          DOUBLE PRECISION   ALPHA,A(LDA,*),X(*),BETA,Y(*)

          SUBROUTINE F06SCF( UPLO,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY )
          ENTRY ZHEMV      ( UPLO,N,ALPHA,A,LDA,X,INCX,BETA,Y,INCY )
          CHARACTER*1          UPLO
          INTEGER              N,LDA,INCX,INCY
          COMPLEX(KIND(1.0D0)) ALPHA,A(LDA,*),X(*),BETA,Y(*)

          SUBROUTINE F06PDF( UPLO,N,K,ALPHA,A,LDA,X,INCX,BETA,Y,INCY )
          ENTRY DSBMV      ( UPLO,N,K,ALPHA,A,LDA,X,INCX,BETA,Y,INCY )
          CHARACTER*1        UPLO
          INTEGER            N,K,LDA,INCX,INCY
          DOUBLE PRECISION   ALPHA,A(LDA,*),X(*),BETA,Y(*)

          SUBROUTINE F06SDF( UPLO,N,K,ALPHA,A,LDA,X,INCX,BETA,Y,INCY )
          ENTRY ZHBMV      ( UPLO,N,K,ALPHA,A,LDA,X,INCX,BETA,Y,INCY )
          CHARACTER*1          UPLO
          INTEGER              N,K,LDA,INCX,INCY
          COMPLEX(KIND(1.0D0)) ALPHA,A(LDA,*),X(*),BETA,Y(*)

          SUBROUTINE F06PEF( UPLO,N,ALPHA,AP,X,INCX,BETA,Y,INCY )
          ENTRY DSPMV      ( UPLO,N,ALPHA,AP,X,INCX,BETA,Y,INCY )
          CHARACTER*1        UPLO
          INTEGER            N,INCX,INCY
          DOUBLE PRECISION   ALPHA,AP(*),X(*),BETA,Y(*)

          SUBROUTINE F06SEF( UPLO,N,ALPHA,AP,X,INCX,BETA,Y,INCY )
          ENTRY ZHPMV      ( UPLO,N,ALPHA,AP,X,INCX,BETA,Y,INCY )
          CHARACTER*1          UPLO
          INTEGER              N,INCX,INCY
          COMPLEX(KIND(1.0D0)) ALPHA,AP(*),X(*),BETA,Y(*)

          SUBROUTINE F06PFF( UPLO,TRANS,DIAG,N,A,LDA,X,INCX )
          ENTRY DTRMV      ( UPLO,TRANS,DIAG,N,A,LDA,X,INCX )
          CHARACTER*1        UPLO,TRANS,DIAG
          INTEGER            N,LDA,INCX
          DOUBLE PRECISION   A(LDA,*),X(*)

          SUBROUTINE F06SFF( UPLO,TRANS,DIAG,N,A,LDA,X,INCX )
          ENTRY ZTRMV      ( UPLO,TRANS,DIAG,N,A,LDA,X,INCX )
          CHARACTER*1          UPLO,TRANS,DIAG
          INTEGER              N,LDA,INCX
          COMPLEX(KIND(1.0D0)) A(LDA,*),X(*)

          SUBROUTINE F06PGF( UPLO,TRANS,DIAG,N,K,A,LDA,X,INCX )
          ENTRY DTBMV      ( UPLO,TRANS,DIAG,N,K,A,LDA,X,INCX )
          CHARACTER*1        UPLO,TRANS,DIAG
          INTEGER            N,K,LDA,INCX
          DOUBLE PRECISION   A(LDA,*),X(*)

          SUBROUTINE F06SGF( UPLO,TRANS,DIAG,N,K,A,LDA,X,INCX )
          ENTRY ZTBMV      ( UPLO,TRANS,DIAG,N,K,A,LDA,X,INCX )
          CHARACTER*1          UPLO,TRANS,DIAG
          INTEGER              N,K,LDA,INCX
          COMPLEX(KIND(1.0D0)) A(LDA,*),X(*)

          SUBROUTINE F06PHF( UPLO,TRANS,DIAG,N,AP,X,INCX )
          ENTRY DTPMV      ( UPLO,TRANS,DIAG,N,AP,X,INCX )
          CHARACTER*1        UPLO,TRANS,DIAG
          INTEGER            N,INCX
          DOUBLE PRECISION   AP(*),X(*)

          SUBROUTINE F06SHF( UPLO,TRANS,DIAG,N,AP,X,INCX )
          ENTRY ZTPMV      ( UPLO,TRANS,DIAG,N,AP,X,INCX )
          CHARACTER*1          UPLO,TRANS,DIAG
          INTEGER              N,INCX
          COMPLEX(KIND(1.0D0)) AP(*),X(*)

          SUBROUTINE F06PJF( UPLO,TRANS,DIAG,N,A,LDA,X,INCX )
          ENTRY DTRSV      ( UPLO,TRANS,DIAG,N,A,LDA,X,INCX )
          CHARACTER*1        UPLO,TRANS,DIAG
          INTEGER            N,LDA,INCX
          DOUBLE PRECISION   A(LDA,*),X(*)

          SUBROUTINE F06SJF( UPLO,TRANS,DIAG,N,A,LDA,X,INCX )
          ENTRY ZTRSV      ( UPLO,TRANS,DIAG,N,A,LDA,X,INCX )
          CHARACTER*1          UPLO,TRANS,DIAG
          INTEGER              N,LDA,INCX
          COMPLEX(KIND(1.0D0)) A(LDA,*),X(*)

          SUBROUTINE F06PKF( UPLO,TRANS,DIAG,N,K,A,LDA,X,INCX )
          ENTRY DTBSV      ( UPLO,TRANS,DIAG,N,K,A,LDA,X,INCX )
          CHARACTER*1        UPLO,TRANS,DIAG
          INTEGER            N,K,LDA,INCX
          DOUBLE PRECISION   A(LDA,*),X(*)

          SUBROUTINE F06SKF( UPLO,TRANS,DIAG,N,K,A,LDA,X,INCX )
          ENTRY ZTBSV      ( UPLO,TRANS,DIAG,N,K,A,LDA,X,INCX )
          CHARACTER*1          UPLO,TRANS,DIAG
          INTEGER              N,K,LDA,INCX
          COMPLEX(KIND(1.0D0)) A(LDA,*),X(*)

          SUBROUTINE F06PLF( UPLO,TRANS,DIAG,N,AP,X,INCX )
          ENTRY DTPSV      ( UPLO,TRANS,DIAG,N,AP,X,INCX )
          CHARACTER*1        UPLO,TRANS,DIAG
          INTEGER            N,INCX
          DOUBLE PRECISION   AP(*),X(*)

          SUBROUTINE F06SLF( UPLO,TRANS,DIAG,N,AP,X,INCX )
          ENTRY ZTPSV      ( UPLO,TRANS,DIAG,N,AP,X,INCX )
          CHARACTER*1          UPLO,TRANS,DIAG
          INTEGER              N,INCX
          COMPLEX(KIND(1.0D0)) AP(*),X(*)

          SUBROUTINE F06PMF( M,N,ALPHA,X,INCX,Y,INCY,A,LDA )
          ENTRY DGER       ( M,N,ALPHA,X,INCX,Y,INCY,A,LDA )
          INTEGER            M,N,INCX,INCY,LDA
          DOUBLE PRECISION   ALPHA,X(*),Y(*),A(LDA,*)

          SUBROUTINE F06SMF( M,N,ALPHA,X,INCX,Y,INCY,A,LDA )
          ENTRY ZGERU      ( M,N,ALPHA,X,INCX,Y,INCY,A,LDA )
          INTEGER              M,N,INCX,INCY,LDA
          COMPLEX(KIND(1.0D0)) ALPHA,X(*),Y(*),A(LDA,*)

          SUBROUTINE F06SNF( M,N,ALPHA,X,INCX,Y,INCY,A,LDA )
          ENTRY ZGERC      ( M,N,ALPHA,X,INCX,Y,INCY,A,LDA )
          INTEGER              M,N,INCX,INCY,LDA
          COMPLEX(KIND(1.0D0)) ALPHA,X(*),Y(*),A(LDA,*)

          SUBROUTINE F06PPF( UPLO,N,ALPHA,X,INCX,A,LDA )
          ENTRY DSYR       ( UPLO,N,ALPHA,X,INCX,A,LDA )
          CHARACTER*1        UPLO
          INTEGER            N,INCX,LDA
          DOUBLE PRECISION   ALPHA,X(*),A(LDA,*)

          SUBROUTINE F06SPF( UPLO,N,ALPHA,X,INCX,A,LDA )
          ENTRY ZHER       ( UPLO,N,ALPHA,X,INCX,A,LDA )
          CHARACTER*1          UPLO
          INTEGER              N,INCX,LDA
          DOUBLE PRECISION     ALPHA
          COMPLEX(KIND(1.0D0)) X(*),A(LDA,*)

          SUBROUTINE F06PQF( UPLO,N,ALPHA,X,INCX,AP )
          ENTRY DSPR       ( UPLO,N,ALPHA,X,INCX,AP )
          CHARACTER*1        UPLO
          INTEGER                   N,INCX
          DOUBLE PRECISION            ALPHA,X(*),AP(*)

          SUBROUTINE F06SQF( UPLO,N,ALPHA,X,INCX,AP )
          ENTRY ZHPR       ( UPLO,N,ALPHA,X,INCX,AP )
          CHARACTER*1          UPLO
          INTEGER              N,INCX
          DOUBLE PRECISION     ALPHA
          COMPLEX(KIND(1.0D0)) X(*),AP(*)

          SUBROUTINE F06PRF( UPLO,N,ALPHA,X,INCX,Y,INCY,A,LDA )
          ENTRY DSYR2      ( UPLO,N,ALPHA,X,INCX,Y,INCY,A,LDA )
          CHARACTER*1        UPLO
          INTEGER            N,INCX,INCY,LDA
          DOUBLE PRECISION   ALPHA,X(*),Y(*),A(LDA,*)

          SUBROUTINE F06SRF( UPLO,N,ALPHA,X,INCX,Y,INCY,A,LDA )
          ENTRY ZHER2      ( UPLO,N,ALPHA,X,INCX,Y,INCY,A,LDA )
          CHARACTER*1          UPLO
          INTEGER              N,INCX,INCY,LDA
          COMPLEX(KIND(1.0D0)) ALPHA,X(*),Y(*),A(LDA,*)

          SUBROUTINE F06PSF( UPLO,N,ALPHA,X,INCX,Y,INCY,AP )
          ENTRY DSPR2      ( UPLO,N,ALPHA,X,INCX,Y,INCY,AP )
          CHARACTER*1        UPLO
          INTEGER            N,INCX,INCY
          DOUBLE PRECISION  ALPHA,X(*),Y(*),AP(*)

          SUBROUTINE F06SSF( UPLO,N,ALPHA,X,INCX,Y,INCY,AP )
          ENTRY ZHPR2      ( UPLO,N,ALPHA,X,INCX,Y,INCY,AP )
          CHARACTER*1          UPLO
          INTEGER              N,INCX,INCY
          COMPLEX(KIND(1.0D0)) ALPHA,X(*),Y(*),AP(*)

          F06PAF(*), F06SAF(*), F06PBF(*) and F06SBF(*)

          perform the operation

              y<-(alpha)Ax+(beta)y, when TRANS = 'N',

                         T
              y<-(alpha)A x+(beta)y, when TRANS = 'T',

                         H
              y<-(alpha)A x+(beta)y, when TRANS = 'C',

          where A is a general matrix for F06PAF(*) and F06SAF(*), and is a
          general band matrix for F06PBF(*) and F06SBF(*).

          F06PCF(*), F06SCF(*), F06PEF(*), F06SEF(*), F06PDF(*) and
          F06SDF(*)

          perform the operation

          y<-(alpha)Ax+(beta)y

          where A is symmetric and Hermitian for F06PCF(*) and F06SCF(*)
          respectively, is symmetric and Hermitian stored in packed form
          for F06PEF(*) and F06SEF(*) respectively, and is symmetric and
          Hermitian band for F06PDF(*) and F06SDF(*).

          F06PFF(*), F06SFF(*), F06PHF(*), F06SHF(*), F06PGF(*) and
          F06SGF(*)

          perform the operation

              x<-Ax,       when TRANS = 'N',

                  T
              x<-A x,      when TRANS = 'T',

                  H
              x<-A x,      when TRANS = 'C',

          where A is a triangular matrix for F06PFF(*) and F06SFF(*), is a
          triangular matrix stored in packed form for F06PHF(*) and
          F06SHF(*), and is a triangular band matrix for F06PGF(*) and
          F06SGF(*).

          F06PJF(*), F06SJF(*), F06PLF(*), F06SLF(*), F06PKF(*) and
          F06SKF(*)

          solve the equations

              Ax=b,        when TRANS = 'N',

               T
              A x=b,       when TRANS = 'T',

               H
              A x=b,       when TRANS = 'C',

          where A is a triangular matrix for F06PJF(*) and F06SJF(*), is a
          triangular matrix stored in packed form for F06PLF(*) and
          F06SLF(*), and is a triangular band matrix for F06PKF(*) and
          F06SKF(*). The vector b must be supplied in the array X and is
          overwritten by the solution. It is important to note that no test
          for singularity is included in these routines.

          F06PMF(*) and F06SMF(*)

                                            T
          perform the operation A<-(alpha)xy +A, where A is a general
          matrix.

          F06SNF(*)

                                             H
          performs the operation A<-(alpha)xy +A, where A is a general
          complex matrix.

          F06PPF(*) and F06PQF(*)

                                            T
          perform the operation A<-(alpha)xx +A, where A is a symmetric
          matrix for F06PPF(*) and is a symmetric matrix stored in packed
          form for F06PQF(*).

          F06SPF(*) and F06SQF(*)

                                            H
          perform the operation A<-(alpha)xx +A, where A is an Hermitian
          matrix for F06SPF(*) and is an Hermitian matrix stored in packed
          form for F06SQF(*).

          F06PRF(*) and F06PSF(*)

                                            T          T
          perform the operation A<-(alpha)xy +(alpha)yx +A, where A is a
          symmetric matrix for F06PRF(*) and is a symmetric matrix stored
          in packed form for F06PSF(*).

          F06SRF(*) and F06SSF(*)

                                            H          H
          perform the operation A<-(alpha)xy +(alpha)yx +A, where A is an
          Hermitian matrix for F06SRF(*) and is an Hermitian matrix stored
          in packed form for F06SSF(*).

          The following argument values are invalid:

               Any value of the character arguments DIAG, TRANS, or UPLO
               whose meaning is not specified.

               M < 0

               N < 0

               KL < 0

               KU < 0

               K < 0

               LDA < M

               LDA < KL + KU + 1

               LDA < N for the routines involving full Hermitian,
               symmetric or triangular matrices

               LDA < K + 1 for the routines involving band Hermitian,
               symmetric or triangular matrices

               INCX = 0

               INCY = 0

          If a routine is called with an invalid value then an error
          message is output, on the error message unit (see X04AAF), giving
          the name of the routine and the number of the first invalid
          argument, and execution is terminated.

          4.4. The Level-3 Matrix-matrix Routines

          The matrix-matrix routines all have either two or three arguments
          representing a matrix, one of which is an input-output argument,
          and in each case the arguments are two-dimensional arrays.

          The sizes of the matrices are determined by one or more of the
          arguments M, N and K. The size of the input-output array is
          always determined by the arguments M and N for a rectangular m by
          n matrix, and by the argument N for a square n by n matrix. It is
          permissible to call the routines with M or N = 0, in which case
          the routines exit immediately without referencing their array
          arguments.

          Many of the routines perform an operation of the form

                                    C<-P+(beta)C,

          where P is the product of two matrices, or the sum of two such
          products. When the inner dimension of the matrix product is
          different from m or n it is denoted by K. Again it is permissible
          to call the routines with K = 0 and if M > 0, but K = 0, then the
          routines perform the operation


                                     C<-(beta)C.

          As with the Level-2 routines (see Section 4.3) the description of
          the matrix consists of the array name (A or B or C) followed by
          the first dimension (LDA or LDB or LDC).

          The arguments that specify options are character arguments with
          the names SIDE, TRANSA, TRANSB, TRANS, UPLO and DIAG. UPLO and
          DIAG have the same values and meanings as for the Level-2
          routines (see Section 4.3); TRANSA, TRANSB and TRANS have the
          same values and meanings as TRANS in the Level-2 routines, where
          TRANSA and TRANSB apply to the matrices A and B respectively.
          SIDE is used by the routines as follows:

              Value   Meaning

              'L'     Multiply general matrix by symmetric, Hermitian or
                      triangular matrix on the left

              'R'     Multiply general matrix by symmetric, Hermitian or
                      triangular matrix on the right

          The storage conventions for matrices are as for the Level-2
          routines (see Section 4.3).

          SUBROUTINE F06YAF( TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC )
          ENTRY      DGEMM ( TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC )
          CHARACTER          TRANSA,TRANSB
          INTEGER            M,N,K,LDA,LDB,LDC
          DOUBLE PRECISION   ALPHA,A(LDA,*),B(LDB,*),BETA,C(LDC,*)

          SUBROUTINE F06ZAF( TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC )
          ENTRY      ZGEMM ( TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC )
          CHARACTER            TRANSA,TRANSB
          INTEGER              M,N,K,LDA,LDB,LDC
          COMPLEX(KIND(1.0D0)) ALPHA,A(LDA,*),B(LDB,*),BETA,C(LDC,*)

          SUBROUTINE F06YCF( SIDE,UPLO,M,N,ALPHA,A,LDA,B,LDB,BETA,C,LDC )
          ENTRY      DSYMM ( SIDE,UPLO,M,N,ALPHA,A,LDA,B,LDB,BETA,C,LDC )
          CHARACTER          SIDE,UPLO
          INTEGER            M,N,LDA,LDB,LDC
          DOUBLE PRECISION   ALPHA,A(LDA,*),B(LDB,*),BETA,C(LDC,*)

          SUBROUTINE F06ZCF( SIDE,UPLO,M,N,ALPHA,A,LDA,B,LDB,BETA,C,LDC )
          ENTRY      ZHEMM ( SIDE,UPLO,M,N,ALPHA,A,LDA,B,LDB,BETA,C,LDC )
          CHARACTER            SIDE,UPLO
          INTEGER              M,N,LDA,LDB,LDC
          COMPLEX(KIND(1.0D0)) ALPHA,A(LDA,*),B(LDB,*),BETA,C(LDC,*)

          SUBROUTINE F06ZTF( SIDE,UPLO,M,N,ALPHA,A,LDA,B,LDB,BETA,C,LDC )
          ENTRY      ZSYMM ( SIDE,UPLO,M,N,ALPHA,A,LDA,B,LDB,BETA,C,LDC )
          CHARACTER            SIDE,UPLO
          INTEGER              M,N,LDA,LDB,LDC
          COMPLEX(KIND(1.0D0)) ALPHA,A(LDA,*),B(LDB,*),BETA,C(LDC,*)

          SUBROUTINE F06YFF( SIDE,UPLO,TRANSA,DIAG,M,N,ALPHA,A,LDA,B,LDB )
          ENTRY      DTRMM ( SIDE,UPLO,TRANSA,DIAG,M,N,ALPHA,A,LDA,B,LDB )
          CHARACTER          SIDE,UPLO,TRANSA,DIAG
          INTEGER            M,N,LDA,LDB
          DOUBLE PRECISION   ALPHA,A(LDA,*),B(LDB,*)

          SUBROUTINE F06ZFF( SIDE,UPLO,TRANSA,DIAG,M,N,ALPHA,A,LDA,B,LDB )
          ENTRY      ZTRMM ( SIDE,UPLO,TRANSA,DIAG,M,N,ALPHA,A,LDA,B,LDB )
          CHARACTER            SIDE,UPLO,TRANSA,DIAG
          INTEGER              M,N,LDA,LDB
          COMPLEX(KIND(1.0D0)) ALPHA,A(LDA,*),B(LDB,*)

          SUBROUTINE F06YJF( SIDE,UPLO,TRANSA,DIAG,M,N,ALPHA,A,LDA,B,LDB )
          ENTRY      DTRSM ( SIDE,UPLO,TRANSA,DIAG,M,N,ALPHA,A,LDA,B,LDB )
          CHARACTER          SIDE,UPLO,TRANSA,DIAG
          INTEGER            M,N,LDA,LDB
          DOUBLE PRECISION   ALPHA,A(LDA,*),B(LDB,*)

          SUBROUTINE F06ZJF( SIDE,UPLO,TRANSA,DIAG,M,N,ALPHA,A,LDA,B,LDB )
          ENTRY      ZTRSM ( SIDE,UPLO,TRANSA,DIAG,M,N,ALPHA,A,LDA,B,LDB )
          CHARACTER            SIDE,UPLO,TRANSA,DIAG
          INTEGER              M,N,LDA,LDB
          COMPLEX(KIND(1.0D0)) ALPHA,A(LDA,*),B(LDB,*)

          SUBROUTINE F06YPF( UPLO,TRANS,N,K,ALPHA,A,LDA,BETA,C,LDC )
          ENTRY      DSYRK ( UPLO,TRANS,N,K,ALPHA,A,LDA,BETA,C,LDC )
          CHARACTER          UPLO,TRANS
          INTEGER            N,K,LDA,LDC
          DOUBLE PRECISION   ALPHA,A(LDA,*),BETA,C(LDC,*)

          SUBROUTINE F06ZPF( UPLO,TRANS,N,K,ALPHA,A,LDA,BETA,C,LDC )
          ENTRY      ZHERK ( UPLO,TRANS,N,K,ALPHA,A,LDA,BETA,C,LDC )
          CHARACTER            UPLO,TRANS
          INTEGER              N,K,LDA,LDC
          DOUBLE PRECISION     ALPHA,BETA
          COMPLEX(KIND(1.0D0)) A(LDA,*),C(LDC,*)

          SUBROUTINE F06ZUF( UPLO,TRANS,N,K,ALPHA,A,LDA,BETA,C,LDC )
          ENTRY      ZSYRK ( UPLO,TRANS,N,K,ALPHA,A,LDA,BETA,C,LDC )
          CHARACTER            UPLO,TRANS
          INTEGER              N,K,LDA,LDC
          COMPLEX(KIND(1.0D0)) ALPHA,A(LDA,*),BETA,C(LDC,*)

          SUBROUTINE F06YRF( UPLO,TRANS,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC )
          ENTRY      DSYR2K( UPLO,TRANS,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC )
          CHARACTER          UPLO,TRANS
          INTEGER            N,K,LDA,LDB,LDC
          DOUBLE PRECISION   ALPHA,A(LDA,*),B(LDB,*),BETA,C(LDC,*)

          SUBROUTINE F06ZRF( UPLO,TRANS,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC )
          ENTRY      ZHER2K( UPLO,TRANS,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC )
          CHARACTER            UPLO,TRANS
          INTEGER              N,K,LDA,LDB,LDC
          DOUBLE PRECISION     BETA
          COMPLEX(KIND(1.0D0)) ALPHA,A(LDA,*),B(LDB,*),C(LDC,*)

          SUBROUTINE F06ZWF( UPLO,TRANS,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC )
          ENTRY      ZSYR2K( UPLO,TRANS,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC )
          CHARACTER            UPLO,TRANS
          INTEGER              N,K,LDA,LDB,LDC
          COMPLEX(KIND(1.0D0)) ALPHA,A(LDA,*),B(LDB,*),BETA,C(LDC,*)


          F06YAF(*) and F06ZAF(*)

          perform the operation indicated in the following table:

                        TRANSA = 'N'    TRANSA = 'T'      TRANSA = 'C'

                                                     T               H
          TRANSB='N'   C <- (alpha)AB   C <- (alpha)A B   C <- (alpha)A B
                            +(beta)C        +(beta)C          +(beta)C
                       A is m*k,        A is k*m,         A is k*m,
                       B is k*n         B is k*n          B is k*n

                                     T               T T               H T
          TRANSB='T'   C <- (alpha)AB   C <- (alpha)A B   C <- (alpha)A B
                           +(beta)C         +(beta)C          +(beta)C
                       A is m*k,        A is k*m,         A is k*m,
                       B is n*k         B is n*k          B is n*k

                                     H               T H               H H
          TRANSB='C'   C <- (alpha)AB   C <- (alpha)A B   C <- (alpha)A B
                           +(beta)C         +(beta)C          +(beta)C
                       A is m*k,        A is k*m,         A is k*m,
                       B is n*k         B is n*k          B is n*k


          where A and B are general matrices and C is a general m by n
          matrix.

          F06YCF(*), F06ZCF(*) and F06ZTF(*) perform the operation

          indicated in the following table:

              SIDE = 'L'               SIDE = 'R'

              C<-(alpha)AB+(beta)C     C<-(alpha)BA+(beta)C

              A is m*m                 B is m*n

              B is m*n                 A is n*n

          where A is symmetric for F06YCF(*) and F06ZTF(*) and is Hermitian
          for F06ZCF(*), B is a general matrix and C is a general m by n
          matrix.

          F06YFF(*) and F06ZFF(*) perform the operation indicated in the
          following table:

                    TRANSA = 'N'       TRANSA = 'T'        TRANSA = 'C'

                                                    T                   H
          SIDE='L'  B <- (alpha)AB     B <- (alpha)A B     B <- (alpha)A B

                    A is               A is                A is
                    triangular         triangular          triangular
                    m*m                m*m                 m*m

                                                     T                   H
          SIDE='R'  B <- (alpha)BA     B <- (alpha)BA      B <- (alpha)BA

                    A is               A is                A is
                    triangular         triangular          triangular
                    n*n                n*n                 n*n

          where B is a general m by n matrix.

          F06YJF(*) and F06ZJF(*) solve the equations, indicated in the
          following table, for X:

                    TRANSA = 'N'       TRANSA = 'T'       TRANSA = 'C'

                                        T                  H
          SIDE='L'  AX=(alpha)B        A X=(alpha)B       A X=(alpha)B

                    A is               A is               A is
                    triangular         triangular         triangular
                    m*m                m*m                m*m

                                         T                  H
          SIDE='R'  XA=(alpha)B        XA =(alpha)B       XA =(alpha)B

                    A is               A is               A is
                    triangular         triangular         triangular
                    n*n                n*n                n*n

          where B is a general m by n matrix. The m by n solution matrix X
          is overwritten on the array B. It is important to note that no
          test for singularity is included in these routines.

          F06YPF(*), F06ZPF(*) and F06ZUF(*) perform the operation
          indicated in the following table:

                    TRANS = 'N'        TRANS = 'T'        TRANS = 'C'

                                  T                 T                  T
          F06YPF    C <- (alpha)AA     C <- (alpha)A A    C <- (alpha)A A
                        +(beta)C           +(beta)C           +(beta)C
                                  T                 T
          F06ZUF    C <- (alpha)AA     C <- (alpha)A A         --
                        +(beta)C           +(beta)C
                                  H                                    H
          F06ZPF    C <- (alpha)AA          --            C <- (alpha)A A
                        +(beta)C                              +(beta)C

                    A is n*k           A is k*n           A is k*n

          where A is a general matrix and C is an n by n symmetric matrix
          for F06YPF(*) and F06ZUF(*), and is an n by n Hermitian matrix
          for F06ZPF(*).

          F06YRF(*), F06ZRF(*) and F06ZWF(*) perform the operation
          indicated in the following table:


                    TRANS = 'N'        TRANS = 'T'        TRANS = 'C'

                                  T                 T                  T
          F06YRF    C <- (alpha)AB     C <- (alpha)A B    C <- (alpha)A B
                                  T                 T                  T
                        +(alpha)BA         +(alpha)B A        +(alpha)B A
                        +(beta)C           +(beta)C           +(beta)C
                                  T                 T
          F06ZWF    C <- (alpha)AB     C <- (alpha)A B           --
                                  T                 T
                        +(alpha)BA         +(alpha)B A
                        +(beta)C           +(beta)C
                                  H                                    H
          F06ZRF    C <- (alpha)AB           --           C <- (alpha)A B
                                  H                                    H
                        +(alpha)BA                            +(alpha)B A
                        +(beta)C                              +(beta)C

                    A and B are n*k    A and B are k*n    A and B are k*n

          where A and B are general matrices and C is an n by n symmetric
          matrix for F06YRF(*) and F06ZWF(*), and is an n by n Hermitian
          matrix for F06ZPF(*).

          The following values of arguments are invalid:

               Any value of the character arguments SIDE, TRANSA, TRANSB,
               TRANS, UPLO or DIAG, whose meaning is not specified.

               M < 0

               N < 0

               K < 0

               LDA < the number of rows in the matrix A.

               LDB < the number of rows in the matrix B.

               LDC < the number of rows in the matrix C.

          If a routine is called with an invalid value then an error
          message is output, on the error message unit (see X04AAF), giving
          the name of the routine and the number of the first invalid
          argument, and execution is terminated.


          F06 -- Linear Algebra Support Routines            Contents -- F06
          Chapter F06

          Linear Algebra Support Routines

          F06AAF  (DROTG) Generate real plane rotation

          F06EAF  (DDOT) Dot product of two real vectors

          F06ECF  (DAXPY) Add scalar times real vector to real vector

          F06EDF  (DSCAL) Multiply real vector by scalar

          F06EFF  (DCOPY) Copy real vector

          F06EGF  (DSWAP) Swap two real vectors

          F06EJF  (DNRM2) Compute Euclidean norm of real vector

          F06EKF  (DASUM) Sum the absolute values of real vector elements

          F06EPF  (DROT) Apply real plane rotation

          F06GAF  (ZDOTU) Dot product of two complex vectors, unconjugated

          F06GBF  (ZDOTC) Dot product of two complex vectors, conjugated

          F06GCF  (ZAXPY) Add scalar times complex vector to complex vector

          F06GDF  (ZSCAL) Multiply complex vector by complex scalar

          F06GFF  (ZCOPY) Copy complex vector

          F06GGF  (ZSWAP) Swap two complex vectors

          F06JDF  (ZDSCAL) Multiply complex vector by real scalar

          F06JJF  (DZNRM2) Compute Euclidean norm of complex vector

          F06JKF  (DZASUM) Sum the absolute values of complex vector
                  elements

          F06JLF  (IDAMAX) Index, real vector element with largest absolute
                  value

          F06JMF  (IZAMAX) Index, complex vector element with largest
                  absolute value

          F06PAF  (DGEMV) Matrix-vector product, real rectangular matrix

          F06PBF  (DGBMV) Matrix-vector product, real rectangular band
                  matrix

          F06PCF  (DSYMV) Matrix-vector product, real symmetric matrix

          F06PDF  (DSBMV) Matrix-vector product, real symmetric band matrix

          F06PEF  (DSPMV) Matrix-vector product, real symmetric packed
                  matrix

          F06PFF  (DTRMV) Matrix-vector product, real triangular matrix

          F06PGF  (DTBMV) Matrix-vector product, real triangular band
                  matrix

          F06PHF  (DTPMV) Matrix-vector product, real triangular packed
                  matrix

          F06PJF  (DTRSV) System of equations, real triangular matrix

          F06PKF  (DTBSV) System of equations, real triangular band matrix

          F06PLF  (DTPSV) System of equations, real triangular packed
                  matrix

          F06PMF  (DGER) Rank-1 update, real rectangular matrix

          F06PPF  (DSYR) Rank-1 update, real symmetric matrix

          F06PQF  (DSPR) Rank-1 update, real symmetric packed matrix

          F06PRF  (DSYR2) Rank-2 update, real symmetric matrix

          F06PSF  (DSPR2) Rank-2 update, real symmetric packed matrix

          F06SAF  (ZGEMV) Matrix-vector product, complex rectangular matrix

          F06SBF  (ZGBMV) Matrix-vector product, complex rectangular band
                  matrix

          F06SCF  (ZHEMV) Matrix-vector product, complex Hermitian matrix

          F06SDF  (ZHBMV) Matrix-vector product, complex Hermitian band
                  matrix

          F06SEF  (ZHPMV) Matrix-vector product, complex Hermitian packed
                  matrix

          F06SFF  (ZTRMV) Matrix-vector product, complex triangular matrix

          F06SGF  (ZTBMV) Matrix-vector product, complex triangular band
                  matrix

          F06SHF  (ZTPMV) Matrix-vector product, complex triangular packed
                  matrix

          F06SJF  (ZTRSV) System of equations, complex triangular matrix

          F06SKF  (ZTBSV) System of equations, complex triangular band
                  matrix

          F06SLF  (ZTPSV) System of equations, complex triangular packed
                  matrix

          F06SMF  (ZGERU) Rank-1 update, complex rectangular matrix,
                  unconjugated vector

          F06SNF  (ZGERC) Rank-1 update, complex rectangular matrix,
                  conjugated vector

          F06SPF  (ZHER) Rank-1 update, complex Hermitian matrix

          F06SQF  (ZHPR) Rank-1 update, complex Hermitian packed matrix

          F06SRF  (ZHER2) Rank-2 update, complex Hermitian matrix

          F06SSF  (ZHPR2) Rank-2 update, complex Hermitian packed matrix

          F06YAF  (DGEMM) Matrix-matrix product, two real rectangular
                  matrices

          F06YCF  (DSYMM) Matrix-matrix product, one real symmetric matrix,
                  one real rectangular matrix

          F06YFF  (DTRMM) Matrix-matrix product, one real triangular
                  matrix, one real rectangular matrix

          F06YJF  (DTRSM) Solves a system of equations with multiple right-
                  hand sides, real triangular coefficient matrix

          F06YPF  (DSYRK) Rank-k update of a real symmetric matrix

          F06YRF  (DSYR2K) Rank-2k update of a real symmetric matrix

          F06ZAF  (ZGEMM) Matrix-matrix product, two complex rectangular
                  matrices

          F06ZCF  (ZHEMM) Matrix-matrix product, one complex Hermitian
                  matrix, one complex rectangular matrix

          F06ZFF  (ZTRMM) Matrix-matrix product, one complex triangular
                  matrix, one complex rectangular matrix

          F06ZJF  (ZTRSM) Solves system of equations with multiple right-
                  hand sides, complex triangular coefficient matrix

          F06ZPF  (ZHERK) Rank-k update of a complex Hermitian matrix

          F06ZRF  (ZHER2K) Rank-2k update of a complex Hermitian matrix

          F06ZTF  (ZSYMM) Matrix-matrix product, one complex symmetric
                  matrix, one complex rectangular matrix

          F06ZUF  (ZSYRK) Rank-k update of a complex symmetric matrix

          F06ZWF  (ZSYR2K) Rank-2k update of a complex symmetric matrix

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf07}{nagf.ht}{ Linear Equations (LAPACK)}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf07}{NAG Documentation: f07}
\beginscroll
\begin{verbatim}



     F07(3NAG)         Foundation Library (12/10/92)         F07(3NAG)



          F07 -- Linear Equations (LAPACK)              Introduction -- F07
                                    Chapter F07
                             Linear Equations (LAPACK)

          1. Scope of the Chapter

          This chapter provides four routines concerned with matrix
          factorization, and the solution of systems of linear equations
          following the matrix factorizations.

          2. Background to the Problems

          Background material, together with pointers to the routines in
          this chapter, are to be found in the F01 and F04 Chapter
          Introductions.

          3. Recommendations on Choice and Use of Routines

          The routines in this chapter are derived from the LAPACK project
          and may also be called using the LAPACK name, which is given in
          brackets following the F07 name in the following descriptions.

          Routine F07ADF (DGETRF) performs an LU factorization of a real m
          by n matrix A. Following the use of this routine, F07AEF (DGETRS)
          may be used to solve a system of n non-singular linear equations,
          with one or more right-hand sides.

          Routine F07FDF (DPOTRF) performs the Cholesky factorization of a
          real symmetric positive-definite matrix A. Following the use of
          this routine, F07FEF (DPOTRS) may be used to solve a system of
          symmetric positive-definite linear equations, with one or more
          right-hand sides.


          F07 -- Linear Equations (LAPACK)                  Contents -- F07
          Chapter F07

          Linear Equations (LAPACK)

          F07ADF  (DGETRF) LU factorization of real m by n matrix

          F07AEF  (DGETRS) Solution of real system of linear equations,
                  multiple right-hand sides, matrix already factorized by
                  F07ADF

          F07FDF  (DPOTRF) Cholesky factorization of real symmetric
                  positive-definite matrix

          F07FEF  (DPOTRS) Solution of real symmetric positive-definite
                  system of linear equations, multiple right-hand sides,
                  matrix already factorized by F07FDF

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf07adf}{nagf.ht}
{ Computes the LU factorization of a real m by n matrix}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf07adf}{NAG Documentation: f07adf}
\beginscroll
\begin{verbatim}



     F07ADF(3NAG)      Foundation Library (12/10/92)      F07ADF(3NAG)



          F07 -- Linear Equations (LAPACK)                           F07ADF
                  F07ADF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F07ADF (DGETRF) computes the LU factorization of a real m by n
          matrix.

          2. Specification

                 SUBROUTINE F07ADF (M, N, A, LDA, IPIV, INFO)
                 ENTRY            M, N, A, LDA, IPIV, INFO
                 INTEGER          M, N, LDA, IPIV(*), INFO
                 DOUBLE PRECISION A(LDA,*)

          The ENTRY statement enables the routine to be called by its
          LAPACK name.

          3. Description

          This routine forms the LU factorization of a real m by n matrix A
          as A=PLU, where P is a permutation matrix, L is lower triangular
          with unit diagonal elements (lower trapezoidal if m>n) and U is
          upper triangular (upper trapezoidal if m<n). Usually A is square
          (m=n), and both L and U are triangular. The routine uses partial
          pivoting, with row interchanges.

          4. References

          [1]   Golub G H and Van Loan C F (1989) Matrix Computations (2nd
                Edition). Johns Hopkins University Press, Baltimore,
                Maryland.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: m, the number of rows of the matrix A.
               Constraint: M >= 0.

           2:  N -- INTEGER                                           Input
               On entry: n, the number of columns of the matrix A.
               Constraint: N >= 0.

           3:  A(LDA,*) -- DOUBLE PRECISION array              Input/Output
               Note: the second dimension of the array A must be at least
               max(1,N).
               On entry: the m by n matrix A. On exit: A is overwritten by
               the factors L and U; the unit diagonal elements of L are not
               stored.

           4:  LDA -- INTEGER                                         Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F07ADF is called.
               Constraint: LDA >= max(1,M).

           5:  IPIV(*) -- INTEGER array                              Output
               Note: the dimension of the array IPIV must be at least
               max(1,min(M,N)).
               On exit: the pivot indices. Row i of the matrix A was
               interchanged with row IPIV(i) for i=1,2,...,min(m,n).

           6:  INFO -- INTEGER                                       Output
               On exit: INFO = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          INFO < 0
               If INFO = -i, the ith parameter has an illegal value. An
               explanatory message is output, and execution of the program
               is terminated.

          INFO > 0
               If INFO = i, u   is exactly zero. The factorization has been
                             ii
               completed but the factor U is exactly singular, and division
               by zero will occur if it is subsequently used to solve a
                                                         -1
               system of linear equations or to compute A  .

          7. Accuracy

          The computed factors L and U are the exact factors of a perturbed
          matrix A+E, where

                          |E|<=c(min(m,n))(epsilon)P|L||U|,

          c(n) is a modest linear function of n, and (epsilon) is the
          machine precision.

          8. Further Comments

          The total number of floating-point operations is approximately
           2 3                           1 2                   1 2
           -n  if m=n (the usual case),  -n (3m-n) if m>n and  -m (3n-m) if
           3                             3                     3
          m<n.

          A call to this routine with m=n may be followed by calls to the
          routines:

                                                 T
               F07AEF (DGETRS) to solve AX=B or A X=B;

               F07AGF (DGECON)(*) to estimate the condition number of A;

               F07AJF (DGETRI)(*) to compute the inverse of A.

          The complex analogue of this routine is F07ARF (ZGETRF)(*).

          9. Example

          To compute the LU factorization of the matrix A, where

                              ( 1.80  2.88  2.05 -0.89)
                              ( 5.25 -2.95 -0.95 -3.80)
                            A=( 1.58 -2.69 -2.90 -1.04).
                              (-1.11 -0.66 -0.59  0.80)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf07aef}{nagf.ht}{ Solves a real system of linear equations}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf07aef}{NAG Documentation: f07aef}
\beginscroll
\begin{verbatim}



     F07AEF(3NAG)      Foundation Library (12/10/92)      F07AEF(3NAG)



          F07 -- Linear Equations (LAPACK)                           F07AEF
                  F07AEF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F07AEF (DGETRS) solves a real system of linear equations with
                                              T
          multiple right-hand sides, AX=B or A X=B, where A has been
          factorized by F07ADF (DGETRF).

          2. Specification

                 SUBROUTINE F07AEF (TRANS, N, NRHS, A, LDA, IPIV, B, LDB,
                1                   INFO)
                 ENTRY            TRANS, N, NRHS, A, LDA, IPIV, B, LDB, INFO
                 INTEGER          N, NRHS, LDA, IPIV(*), LDB, INFO
                 DOUBLE PRECISION A(LDA,*), B(LDB,*)
                 CHARACTER*1      TRANS

          The ENTRY statement enables the routine to be called by its
          LAPACK name.

          3. Description

                                                              T
          To solve a real system of linear equations AX=B or A X=B, this
          routine must be preceded by a call to F07ADF (DGETRF)which
          computes the LU factorization of A as A=PLU. The solution is
          computed by forward and backward substitution.

          If TRANS = 'N', the solution is computed by solving PLY=B and
          then UX=Y.

                                                                      T
          If TRANS = 'T' or 'C', the solution is computed by solving U Y=B
                    T T
          and then L P X=Y.

          4. References

          [1]   Golub G H and Van Loan C F (1989) Matrix Computations (2nd
                Edition). Johns Hopkins University Press, Baltimore,
                Maryland.

          5. Parameters

           1:  TRANS -- CHARACTER*1                                   Input
               On entry: indicates the form of the equations as follows:
                    if TRANS = 'N', then AX=B is solved for X;

                                                 T
                    if TRANS = 'T' or 'C', then A X=B is solved for X.
                Constraint: TRANS = 'N', 'T' or 'C'.

           2:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A. Constraint: N >= 0.

           3:  NRHS -- INTEGER                                        Input
               On entry: r, the number of right-hand sides. Constraint:
               NRHS >= 0.

           4:  A(LDA,*) -- DOUBLE PRECISION array                     Input
               Note: the second dimension of the array A must be at least
               max(1,N).
               On entry: the LU factorization of A, as returned by F07ADF
               (DGETRF).

           5:  LDA -- INTEGER                                         Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F07AEF is called.
               Constraint: LDA >= max(1,N).

           6:  IPIV(*) -- INTEGER array                               Input
               Note: the dimension of the array IPIV must be at least
               max(1,N).
               On entry: the pivot indices, as returned by F07ADF (DGETRF).

           7:  B(LDB,*) -- DOUBLE PRECISION array              Input/Output
               Note: the second dimension of the array B must be at least
               max(1,NRHS).
               On entry: the n by r right-hand side matrix B. On exit: the
               n by r solution matrix X.

           8:  LDB -- INTEGER                                         Input
               On entry:
               the first dimension of the array B as declared in the
               (sub)program from which F07AEF is called.
               Constraint: LDB >= max(1,N).

           9:  INFO -- INTEGER                                       Output
               On exit: INFO = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          INFO < 0
               If INFO = -i, the ith parameter has an illegal value. An
               explanatory message is output, and execution of the program
               is terminated.

          7. Accuracy

          For each right-hand side vector b, the computed solution x is the
          exact solution of a perturbed system of equations (A+E)x=b, where

                             |E|<=c(n)(epsilon)P|L||U|,

          c(n) is a modest linear function of n, and (epsilon) is the
          machine precision.

             ^
          If x is the true solution, then the computed solution x satisfies
          a forward error bound of the form

                             ^
                        ||x-x||
                               infty
                        ------------ <= c(n)cond(A,x)(epsilon)
                         ||x||
                              infty

                              -1
          where cond(A,x)=|||A  ||A||x|||     /||x||      <=
                                         infty      infty
                      -1
          cond(A)=|||A  ||A|||     <=(kappa)     (A). Note that cond(A,x)
                              infty         infty
                                                      T
          can be much smaller than cond(A), and cond(A ) can be much larger
          (or smaller) than cond(A).

          Forward and backward error bounds can be computed by calling
          F07AHF (DGERFS)(*), and an estimate for (kappa)     (A) can be
                                                         infty
          obtained by calling F07AGF (DGECON)(*) with NORM ='I'.

          8. Further Comments

          The total number of floating-point operations is approximately
            2
          2n r.

          This routine may be followed by a call to F07AHF (DGERFS)(*) to
          refine the solution and return an error estimate.

          The complex analogue of this routine is F07ASF (ZGETRS)(*).

          9. Example

          To solve the system of equations AX=B, where

                               ( 1.80  2.88  2.05 -0.89)
                               ( 5.25 -2.95 -0.95 -3.80)
                             A=( 1.58 -2.69 -2.90 -1.04)
                               (-1.11 -0.66 -0.59  0.80)

          and


                                    ( 9.52  18.47)
                                    (24.35   2.25)
                                  B=( 0.77 -13.28).
                                    (-6.22  -6.21)

          Here A is unsymmetric and must first be factorized by F07ADF
          (DGETRF)).

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf07fdf}{nagf.ht}
{ Factorization of a real symmetric positive-definite matrix}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf07fdf}{NAG Documentation: f07fdf}
\beginscroll
\begin{verbatim}



     F07FDF(3NAG)      Foundation Library (12/10/92)      F07FDF(3NAG)



          F07 -- Linear Equations (LAPACK)                           F07FDF
                  F07FDF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F07FDF (DPOTRF) computes the Cholesky factorization of a real
          symmetric positive-definite matrix.

          2. Specification

                 SUBROUTINE F07FDF (UPLO, N, A, LDA, INFO)
                 ENTRY            UPLO, N, A, LDA, INFO
                 INTEGER          N, LDA, INFO
                 DOUBLE PRECISION A(LDA,*)
                 CHARACTER*1      UPLO

          The ENTRY statement enables the routine to be called by its
          LAPACK name.

          3. Description

          This routine forms the Cholesky factorization of a real symmetric
                                                  T                       T
          positive-definite matrix A either as A=U U if UPLO = 'U' or A=LL
          if UPLO = 'L', where U is an upper triangular matrix and L is
          lower triangular.

          4. References

          [1]   Demmel J W (1989) On Floating-point Errors in Cholesky.
                LAPACK Working Note No. 14. University of Tennessee,
                Knoxville.

          [2]   Golub G H and Van Loan C F (1989) Matrix Computations (2nd
                Edition). Johns Hopkins University Press, Baltimore,
                Maryland.

          5. Parameters

           1:  UPLO -- CHARACTER*1                                    Input
               On entry: indicates whether the upper or lower triangular
               part of A is stored and how A is factorized, as follows:
                    if UPLO = 'U', then the upper triangular part of A is
                                                   T
                    stored and A is factorized as U U, where U is upper
                    triangular;

                    if UPLO = 'L', then the lower triangular part of A is
                                                    T
                    stored and A is factorized as LL , where L is lower
                    triangular.
                Constraint: UPLO = 'U' or 'L'.

           2:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A. Constraint: N >= 0.

           3:  A(LDA,*) -- DOUBLE PRECISION array              Input/Output
               Note: the second dimension of the array A must be at least
               max(1,N).
               On entry: the n by n symmetric positive-definite matrix A.
               If UPLO = 'U', the upper triangle of A must be stored and
               the elements of the array below the diagonal are not
               referenced; if UPLO = 'L', the lower triangle of A must be
               stored and the elements of the array above the diagonal are
               not referenced. On exit: the upper or lower triangle of A is
               overwritten by the Cholesky factor U or L as specified by
               UPLO.

           4:  LDA -- INTEGER                                         Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F07FDF is called.
               Constraint: LDA >= max(1,N).

           5:  INFO -- INTEGER                                       Output
               On exit: INFO = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          INFO < 0
               If INFO = -i, the ith parameter has an illegal value. An
               explanatory message is output, and execution of the program
               is terminated.

          INFO > 0
               If INFO = i, the leading minor of order i is not positive-
               definite and the factorization could not be completed. Hence
               A itself is not positive-definite. This may indicate an
               error in forming the matrix A. To factorize a symmetric
               matrix which is not positive-definite, call F07MDF
               (DSYTRF)(*) instead.

          7. Accuracy

          If UPLO = 'U', the computed factor U is the exact factor of a
          perturbed matrix A+E, where

                                                 T
                             |E|<=c(n)(epsilon)|U ||U|,

          c(n) is a modest linear function of n, and (epsilon) is the
          machine precision. If UPLO = 'L', a similar statement holds for
          the computed factor L. It follows that
                                 

          |e  |<=c(n)(epsilon)  /a  a  .
            ij                \/  ii jj

          8. Further Comments

          The total number of floating-point operations is approximately
           1 3
           -n .
           3

          A call to this routine may be followed by calls to the routines:

               F07FEF (DPOTRS) to solve AX=B;

               F07FGF (DPOCON)(*) to estimate the condition number of A;

               F07FJF (DPOTRI)(*) to compute the inverse of A.

          The complex analogue of this routine is F07FRF (ZPOTRF)(*).

          9. Example

          To compute the Cholesky factorization of the matrix A, where

                              ( 4.16 -3.12  0.56 -0.10)
                              (-3.12  5.03 -0.83  1.18)
                            A=( 0.56 -0.83  0.76  0.34).
                              (-0.10  1.18  0.34  1.18)

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXf07fef}{nagf.ht}
{ Real symmetric positive-definite system of linear equations}
\begin{chunk}{nagf.ht}
\begin{page}{manpageXXf07fef}{NAG Documentation: f07fef}
\beginscroll
\begin{verbatim}



     F07FEF(3NAG)      Foundation Library (12/10/92)      F07FEF(3NAG)



          F07 -- Linear Equations (LAPACK)                           F07FEF
                  F07FEF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          F07FEF (DPOTRS) solves a real symmetric positive-definite system
          of linear equations with multiple right-hand sides, AX=B, where A
          has been factorized by F07FDF (DPOTRF).

          2. Specification

                 SUBROUTINE F07FEF (UPLO, N, NRHS, A, LDA, B, LDB, INFO)
                 ENTRY            UPLO, N, NRHS, A, LDA, B, LDB, INFO
                 INTEGER          N, NRHS, LDA, LDB, INFO
                 DOUBLE PRECISION A(LDA,*), B(LDB,*)
                 CHARACTER*1      UPLO

          The ENTRY statement enables the routine to be called by its
          LAPACK name.

          3. Description

          To solve a real symmetric positive-definite system of linear
          equations AX=B, this routine must be preceded by a call to
          F07FDF (DPOTRF) which computes the Cholesky factorization of A.
          The solution X is computed by forward and backward substitution.

                            T
          If UPLO = 'U', A=U U, where U is upper triangular; the solution X
                                  T
          is computed by solving U Y=B and then UX=Y.

                             T
          If UPLO = 'L', A=LL , where L is lower triangular; the solution X
                                                T
          is computed by solving LY=B and then L X=Y.

          4. References

          [1]   Golub G H and Van Loan C F (1989) Matrix Computations (2nd
                Edition). Johns Hopkins University Press, Baltimore,
                Maryland.

          5. Parameters

           1:  UPLO -- CHARACTER*1                                    Input
               On entry: indicates whether the upper or lower triangular
               part of A is stored and how A is factorized, as follows:
                                           T
                    if UPLO = 'U', then A=U U where U is upper triangular;

                                            T
                    if UPLO = 'L', then A=LL  where L is lower triangular.
                Constraint: UPLO = 'U' or 'L'.

           2:  N -- INTEGER                                           Input
               On entry: n, the order of the matrix A. Constraint: N >= 0.

           3:  NRHS -- INTEGER                                        Input
               On entry: r, the number of right-hand sides. Constraint:
               NRHS >= 0.

           4:  A(LDA,*) -- DOUBLE PRECISION array                     Input
               Note: the second dimension of the array A must be at least
               max(1,N).
               On entry: the Cholesky factor of A, as returned by F07FDF
               (DPOTRF).

           5:  LDA -- INTEGER                                         Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which F07FEF is called.
               Constraint: LDA >=max(1,N).

           6:  B(LDB,*) -- DOUBLE PRECISION array              Input/Output
               Note: the second dimension of the array B must be at least
               max(1,NRHS).
               On entry: the n by r right-hand side matrix B.

           7:  LDB -- INTEGER                                         Input
               On entry:
               the first dimension of the array B as declared in the
               (sub)program from which F07FEF is called.
               Constraint: LDB >=max(1,N).

           8:  INFO -- INTEGER                                       Output
               On exit: INFO = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          INFO < 0
               If INFO = -i, the ith parameter has an illegal value. An
               explanatory message is output, and execution of the program
               is terminated.

          7. Accuracy

          For each right-hand side vector b, the computed solution x is the
          exact solution of a perturbed system of equations (A+E)x=b, where

                                   T
               |E|<=c(n)(epsilon)|U ||U| if UPLO = 'U',

                                      T
               |E|<=c(n)(epsilon)|L||L | if UPLO = 'L',

          c(n) is a modest linear function of n, and (epsilon) is the
          machine precision.

             ^
          If x is the true solution, then the computed solution x satisfies
          a forward bound of the form

                             ^
                        ||x-x||
                               infty
                        ------------<=c(n)cond(A,x)(epsilon)
                         ||x||
                              infty

                              -1
          where cond(A,x)=|||A  ||A||x|||     /||x||      <=
                                         infty      infty
                      -1
          cond(A)=|||A  ||A|||     <=(kappa)     (A). Note that cond(A,x)
                              infty         infty
          can be much smaller than cond(A).

          Forward and backward error bounds can be computed by calling
          F07FHF (DPORFS)(*), and an estimate for (kappa)     (A) (
                                                         infty
          =(kappa) (A)) can be obtained by calling F07FGF (DPOCON)(*).
                  1

          8. Further Comments

          The total number of floating-point operations is approximately
            2
          2n r.

          This routine may be followed by a call to F07FHF (DPORFS)(*) to
          refine the solution and return an error estimate.

          The complex analogue of this routine is F07FSF (ZPOTRS)(*).

          9. Example

          To compute the Cholesky factorization of the matrix A, where

                              ( 4.16 -3.12  0.56 -0.10)
                              (-3.12  5.03 -0.83  1.18)
                            A=( 0.56 -0.83  0.76  0.34).
                              (-0.10  1.18  0.34  1.18)

          and

                                    (  8.70 8.30)
                                    (-13.35 2.13)
                                  B=(  1.89 1.61).
                                    ( -4.14 5.00)

          Here A is symmetric positive-definite and must first be
          factorized by F07FDF (DPOTRF).

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\section{nagm.ht}
\pagetitle{manpageXXm01}{nagm.ht}{ Sorting}
\begin{chunk}{nagm.ht}
\begin{page}{manpageXXm01}{NAG Documentation: m01}
\beginscroll
\begin{verbatim}



     M01(3NAG)         Foundation Library (12/10/92)         M01(3NAG)



          M01 -- Sorting                                Introduction -- M01
                                    Chapter M01
                                      Sorting

          1. Scope of the Chapter

          This chapter is concerned with sorting numeric data. It handles
          only the simplest types of data structure and it is concerned
          only with internal sorting -- that is, sorting a set of data
          which can all be stored within the program.

          Users with large files of data or complex data structures to be
          sorted should use a comprehensive sorting program or package.

          2. Background to the Problems

          The usefulness of sorting is obvious (perhaps a little too
          obvious, since sorting can be expensive and is sometimes done
          when not strictly necessary). Sorting may traditionally be
          associated with data-processing and non-numerical programming,
          but it has many uses within the realm of numerical analysis, for
          example, to arrange eigenvalues in ascending order of absolute
          value and in the ranking of observations for nonparametric
          statistics.

          The general problem may be defined as follows. We are given N
          items of data


                                    R ,R ,...,R .
                                     1  2      N

          Each item R  contains a key K  which can be ordered relative to
                     i                 i
          any other key according to some specified criterion (for example,
          ascending numeric value). The problem is to determine a
          permutation


                                 p(1),p(2),...,p(N)

          which puts the keys in order:

                              K    <=K    <=...<=K
                               p(1)   p(2)        p(N)

          Sometimes we may wish actually to rearrange the items so that
          their keys are in order; for other purposes we may simply require
          a table of indices so that the items can be referred to in sorted
          order; or yet again we may require a table of ranks, that is, the
          positions of each item in the sorted order.

          For example, given the single-character items, to be sorted into
          alphabetic order:

               E    B    A    D    C

          the indices of the items in sorted order are

               3    2    5    4    1

          and the ranks of the items are

               5    2    1    4    3

          Indices may be converted to ranks, and vice versa, by simply
          computing the inverse permutation.

          The items may consist solely of the key (each item may simply be
          a number). On the other hand, the items may contain additional
          information (for example, each item may be an eigenvalue of a
          matrix and its associated eigenvector, the eigenvalue being the
          key). In the latter case there may be many distinct items with
          equal keys, and it may be important to preserve the original
          order among them (if this is achieved, the sorting is called '
          stable').

          There are a number of ingenious algorithms for sorting. For a
          fascinating discussion of them, and of the whole subject, see
          Knuth [1].

          2.1. References

          [1]   Knuth D E (1973) The Art of Computer Programming, Vol 3.
                Addison-Wesley.

          3. Recommendations on Choice and Use of Routines

          Four categories of routines are provided:

          - routines which rearrange the data into sorted order (M01C-);

          - routines which determine the ranks of the data, leaving the
          data unchanged (M01D-);

          - routines which rearrange the data according to pre-determined
          ranks (M01E-);

          - service routines (M01Z-).

          Routines are provided for sorting double precision data only.

          If the task is simply to rearrange a one-dimensional array of
          data into sorted order, then M01CAF should be used, since this
          requires no extra workspace and is faster than any other method.

          For many applications it is in fact preferable to separate the
          task of determining the sorted order (ranking) from the task of
          rearranging data into a pre-determined order; the latter task may
          not need to be performed at all. Frequently it may be sufficient
          to refer to the data in sorted order via an index vector, without
          rearranging it. Frequently also one set of data (e.g. a column of
          a matrix) is used for determining a set of ranks, which are then
          applied to other data (e.g. the remaining columns of the matrix).

          To determine the ranks of a set of data, use an M01D- routine.
          Routines are provided for ranking one-dimensional arrays, and for
          ranking rows or columns of two-dimensional arrays.

          To create an index vector so that data can be referred to in
          sorted order, first call an M01D- routine to determine the ranks,
          and then call M01ZAF to convert the vector of ranks into an index
          vector.

          To rearrange data according to pre-determined ranks: use M01EAF
          if the data is stored in a one-dimensional array; or if the data
          is stored in a more complicated structure, use an index vector to
          generate a new copy of the data in the desired order.

          Examples of these operations can be found in the routine
          documents of the relevant routines.

          4. Index

           Ranking:
               columns of a matrix, double precision numbers         M01DJF
               rows of a matrix, double precision numbers            M01DEF
               vector, double precision numbers                      M01DAF
          Rearranging (according to pre-determined ranks):
               vector, double precision numbers                      M01EAF
          Service routines:
               invert a permutation (ranks to indices or vice        M01ZAF
               versa)
          Sorting (i.e., rearranging into sorted order):
               vector, double precision numbers                      M01CAF


          M01 -- Sorting                                    Contents -- M01
          Chapter M01

          Sorting

          M01CAF  Sort a vector, double precision numbers

          M01DAF  Rank a vector, double precision numbers

          M01DEF  Rank rows of a matrix, double precision numbers

          M01DJF  Rank columns of a matrix, double precision numbers

          M01EAF  Rearrange a vector according to given ranks, double
                  precision numbers

          M01ZAF  Invert a permutation

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXm01caf}{nagm.ht}{ Sort vector of double precision numbers}
\begin{chunk}{nagm.ht}
\begin{page}{manpageXXm01caf}{NAG Documentation: m01caf}
\beginscroll
\begin{verbatim}



     M01CAF(3NAG)      Foundation Library (12/10/92)      M01CAF(3NAG)



          M01 -- Sorting                                             M01CAF
                  M01CAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          M01CAF rearranges a vector of double precision numbers into
          ascending or descending order.

          2. Specification

                 SUBROUTINE M01CAF (RV, M1, M2, ORDER, IFAIL)
                 INTEGER          M1, M2, IFAIL
                 DOUBLE PRECISION RV(M2)
                 CHARACTER*1      ORDER

          3. Description

          M01CAF is based on Singleton's implementation of the 'median-of-
          three' Quicksort algorithm [2], but with two additional
          modifications. First, small subfiles are sorted by an insertion
          sort on a separate final pass (Sedgewick [1]). Second, if a
          subfile is partitioned into two very unbalanced subfiles, the
          larger of them is flagged for special treatment: before it is
          partitioned, its end-points are swapped with two random points
          within it; this makes the worst case behaviour extremely
          unlikely.

          4. References

          [1]   Sedgewick R (1978) Implementing Quicksort Programs. Comm.
                ACM. 21 847--857.

          [2]   Singleton R C (1969) An Efficient Algorithm for Sorting with
                Minimal Storage: Algorithm 347. Comm. ACM. 12 185--187.

          5. Parameters

           1:  RV(M2) -- DOUBLE PRECISION array                Input/Output
               On entry: elements M1 to M2 of RV must contain double
               precision values to be sorted. On exit: these values are
               rearranged into sorted order.

           2:  M1 -- INTEGER                                          Input
               On entry: the index of the first element of RV to be sorted.
               Constraint: M1 > 0.

           3:  M2 -- INTEGER                                          Input

               On entry: the index of the last element of RV to be sorted.
               Constraint: M2 >= M1.

           4:  ORDER -- CHARACTER*1                                   Input
               On entry: if ORDER is 'A', the values will be sorted into
               ascending (i.e., non-decreasing) order; if ORDER is 'D',
               into descending order. Constraint: ORDER = 'A' or 'D'.

           5:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry M2 < 1,

               or       M1 < 1,

               or       M1 > M2.

          IFAIL= 2
               On entry ORDER is not 'A' or 'D'.

          7. Accuracy

          Not applicable.

          8. Further Comments

          The average time taken by the routine is approximately
          proportional to n*logn, where n = M2 - M1 + 1. The worst case
                                   2
          time is proportional to n  but this is extremely unlikely to
          occur.

          9. Example

          The example program reads a list of double precision numbers and
          sorts them into ascending order.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXm01daf}{nagm.ht}
{ Ranks a vector of double precision numbers}
\begin{chunk}{nagm.ht}
\begin{page}{manpageXXm01daf}{NAG Documentation: m01daf}
\beginscroll
\begin{verbatim}



     M01DAF(3NAG)      Foundation Library (12/10/92)      M01DAF(3NAG)



          M01 -- Sorting                                             M01DAF
                  M01DAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          M01DAF ranks a vector of double precision numbers in ascending or
          descending order.

          2. Specification

                 SUBROUTINE M01DAF (RV, M1, M2, ORDER, IRANK, IFAIL)
                 INTEGER          M1, M2, IRANK(M2), IFAIL
                 DOUBLE PRECISION RV(M2)
                 CHARACTER*1      ORDER

          3. Description

          M01DAF uses a variant of list-merging, as described by Knuth [1]
          pp 165-166. The routine takes advantage of natural ordering in
          the data, and uses a simple list insertion in a preparatory pass
          to generate ordered lists of length at least 10. The ranking is
          stable: equal elements preserve their ordering in the input data.

          4. References

          [1]   Knuth D E (1973) The Art of Computer Programming, Vol 3.
                Addison-Wesley.

          5. Parameters

           1:  RV(M2) -- DOUBLE PRECISION array                       Input
               On entry: elements M1 to M2 of RV must contain double
               precision values to be ranked.

           2:  M1 -- INTEGER                                          Input
               On entry: the index of the first element of RV to be ranked.
               Constraint: M1 > 0.

           3:  M2 -- INTEGER                                          Input
               On entry: the index of the last element of RV to be ranked.
               Constraint: M2 >= M1.

           4:  ORDER -- CHARACTER*1                                   Input
               On entry: if ORDER is 'A', the values will be ranked in
               ascending (i.e., non-decreasing) order; if ORDER is 'D',
               into descending order. Constraint: ORDER = 'A' or 'D'.

           5:  IRANK(M2) -- INTEGER array                            Output
               On exit: elements M1 to M2 of IRANK contain the ranks of the
               corresponding elements of RV. Note that the ranks are in the
               range M1 to M2: thus, if RV(i) is the first element in the
               rank order, IRANK(i) is set to M1.

           6:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry M2 < 1,

               or       M1 < 1,

               or       M1 > M2.

          IFAIL= 2
               On entry ORDER is not 'A' or 'D'.

          7. Accuracy

          Not applicable.

          8. Further Comments

          The average time taken by the routine is approximately
          proportional to n*logn, where n = M2 - M1 + 1.

          9. Example

          The example program reads a list of double precision numbers and
          ranks them in ascending order.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXm01def}{nagm.ht}
{ Ranks the rows of a matrix of double precision numbers}
\begin{chunk}{nagm.ht}
\begin{page}{manpageXXm01def}{NAG Documentation: m01def}
\beginscroll
\begin{verbatim}



     M01DEF(3NAG)      Foundation Library (12/10/92)      M01DEF(3NAG)



          M01 -- Sorting                                             M01DEF
                  M01DEF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          M01DEF ranks the rows of a matrix of double precision numbers in
          ascending or descending order.

          2. Specification

                 SUBROUTINE M01DEF (RM, LDM, M1, M2, N1, N2, ORDER, IRANK,
                1                   IFAIL)
                 INTEGER          LDM, M1, M2, N1, N2, IRANK(M2), IFAIL
                 DOUBLE PRECISION RM(LDM,N2)
                 CHARACTER*1      ORDER

          3. Description

          M01DEF ranks rows M1 to M2 of a matrix, using the data in columns
          N1 to N2 of those rows. The ordering is determined by first
          ranking the data in column N1, then ranking any tied rows
          according to the data in column N1 + 1, and so on up to column
          N2.

          M01DEF uses a variant of list-merging, as described by Knuth [1]
          pp 165-166. The routine takes advantage of natural ordering in
          the data, and uses a simple list insertion in a preparatory pass
          to generate ordered lists of length at least 10. The ranking is
          stable: equal rows preserve their ordering in the input data.

          4. References

          [1]   Knuth D E (1973) The Art of Computer Programming, Vol 3.
                Addison-Wesley.

          5. Parameters

           1:  RM(LDM,N2) -- DOUBLE PRECISION array                   Input
               On entry: columns N1 to N2 of rows M1 to M2 of RM must
               contain double precision data to be ranked.

           2:  LDM -- INTEGER                                         Input
               On entry:
               the first dimension of the array RM as declared in the
               (sub)program from which M01DEF is called.
               Constraint: LDM >= M2.

           3:  M1 -- INTEGER                                          Input
               On entry: the index of the first row of RM to be ranked.
               Constraint: M1 > 0.

           4:  M2 -- INTEGER                                          Input
               On entry: the index of the last row of RM to be ranked.
               Constraint: M2 >= M1.

           5:  N1 -- INTEGER                                          Input
               On entry: the index of the first column of RM to be used.
               Constraint: N1 > 0.

           6:  N2 -- INTEGER                                          Input
               On entry: the index of the last column of RM to be used.
               Constraint: N2 >= N1.

           7:  ORDER -- CHARACTER*1                                   Input
               On entry: if ORDER is 'A', the rows will be ranked in
               ascending (i.e., non-decreasing) order; if ORDER is 'D',
               into descending order. Constraint: ORDER = 'A' or 'D'.

           8:  IRANK(M2) -- INTEGER array                            Output
               On exit: elements M1 to M2 of IRANK contain the ranks of the
               corresponding rows of RM. Note that the ranks are in the
               range M1 to M2: thus, if the ith row of RM is the first in
               the rank order, IRANK(i) is set to M1.

           9:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry M2 < 1,

               or       N2 < 1,

               or       M1 < 1,

               or       M1 > M2,

               or       N1 < 1,

               or       N1 > N2,

               or       LDM < M2.

          IFAIL= 2
               On entry ORDER is not 'A' or 'D'.

          7. Accuracy

          Not applicable.

          8. Further Comments

          The average time taken by the routine is approximately
          proportional to n*logn, where n = M2 - M1 + 1.

          9. Example

          The example program reads a matrix of double precision numbers
          and ranks the rows in ascending order.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXm01djf}{nagm.ht}
{ Ranks the columns of a matrix of double precision numbers}
\begin{chunk}{nagm.ht}
\begin{page}{manpageXXm01djf}{NAG Documentation: m01djf}
\beginscroll
\begin{verbatim}



     M01DJF(3NAG)      Foundation Library (12/10/92)      M01DJF(3NAG)



          M01 -- Sorting                                             M01DJF
                  M01DJF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          M01DJF ranks the columns of a matrix of double precision numbers
          in ascending or descending order.

          2. Specification

                 SUBROUTINE M01DJF (RM, LDM, M1, M2, N1, N2, ORDER, IRANK,
                1                   IFAIL)
                 INTEGER          LDM, M1, M2, N1, N2, IRANK(N2), IFAIL
                 DOUBLE PRECISION RM(LDM,N2)
                 CHARACTER*1      ORDER

          3. Description

          M01DJF ranks columns N1 to N2 of a matrix, using the data in rows
          M1 to M2 of those columns. The ordering is determined by first
          ranking the data in row M1, then ranking any tied columns
          according to the data in row M1 + 1, and so on up to row M2.

          M01DJF uses a variant of list-merging, as described by Knuth [1]
          pp 165-166. The routine takes advantage of natural ordering in
          the data, and uses a simple list insertion in a preparatory pass
          to generate ordered lists of length at least 10. The ranking is
          stable: equal columns preserve their ordering in the input data.

          4. References

          [1]   Knuth D E (1973) The Art of Computer Programming, Vol 3.
                Addison-Wesley.

          5. Parameters

           1:  RM(LDM,N2) -- DOUBLE PRECISION array                   Input
               On entry: rows M1 to M2 of columns N1 to N2 of RM must
               contain double precision data to be ranked.

           2:  LDM -- INTEGER                                         Input
               On entry:
               the first dimension of the array RM as declared in the
               (sub)program from which M01DJF is called.
               Constraint: LDM >= M2.

           3:  M1 -- INTEGER                                          Input
               On entry: the index of the first row of RM to be used.
               Constraint: M1 > 0.

           4:  M2 -- INTEGER                                          Input
               On entry: the index of the last row of RM to be used.
               Constraint: M2 >= M1.

           5:  N1 -- INTEGER                                          Input
               On entry: the index of the first column of RM to be ranked.
               Constraint: N1 > 0.

           6:  N2 -- INTEGER                                          Input
               On entry: the index of the last column of RM to be ranked.
               Constraint: N2 >= N1.

           7:  ORDER -- CHARACTER*1                                   Input
               On entry: if ORDER is 'A', the columns will be ranked in
               ascending (i.e., non-decreasing) order; if ORDER is 'D',
               into descending order. Constraint: ORDER = 'A' or 'D'.

           8:  IRANK(N2) -- INTEGER array                            Output
               On exit: elements N1 to N2 of IRANK contain the ranks of the
               corresponding columns of RM. Note that the ranks are in the
               range N1 to N2: thus, if the ith column of RM is the first
               in the rank order, IRANK(i) is set to N1.

           9:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry M2 < 1,

               or       N2 < 1,

               or       M1 < 1,

               or       M1 > M2,

               or       N1 < 1,

               or       N1 > N2,

               or       LDM < M2.

          IFAIL= 2
               On entry ORDER is not 'A' or 'D'.

          7. Accuracy

          Not applicable.

          8. Further Comments

          The average time taken by the routine is approximately
          proportional to n*logn, where n = N2 - N1 + 1.

          9. Example

          The example program reads a matrix of double precision numbers
          and ranks the columns in ascending order.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXm01eaf}{nagm.ht}
{ Rearranges a vector of double precision numbers}
\begin{chunk}{nagm.ht}
\begin{page}{manpageXXm01eaf}{NAG Documentation: m01eaf}
\beginscroll
\begin{verbatim}



     M01EAF(3NAG)      Foundation Library (12/10/92)      M01EAF(3NAG)



          M01 -- Sorting                                             M01EAF
                  M01EAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          M01EAF rearranges a vector of double precision numbers into the
          order specified by a vector of ranks.

          2. Specification

                 SUBROUTINE M01EAF (RV, M1, M2, IRANK, IFAIL)
                 INTEGER          M1, M2, IRANK(M2), IFAIL
                 DOUBLE PRECISION RV(M2)

          3. Description

          M01EAF is designed to be used typically in conjunction with the
          M01D- ranking routines. After one of the M01D- routines has been
          called to determine a vector of ranks, M01EAF can be called to
          rearrange a vector of real numbers into the rank order. If the
          vector of ranks has been generated in some other way, then
          M01ZBF(*) should be called to check its validity before M01EAF is
          called.

          4. References

          None.

          5. Parameters

           1:  RV(M2) -- DOUBLE PRECISION array                Input/Output
               On entry: elements M1 to M2 of RV must contain double
               precision values to be rearranged. On exit: these values are
               rearranged into rank order. For example, if IRANK(i) = M1,
               then the initial value of RV(i) is moved to RV(M1).

           2:  M1 -- INTEGER                                          Input

           3:  M2 -- INTEGER                                          Input
               On entry: M1 and M2 must specify the range of the ranks
               supplied in IRANK and the elements of RV to be rearranged.
               Constraint: 0 < M1 <= M2.

           4:  IRANK(M2) -- INTEGER array                             Input
               On entry: elements M1 to M2 of IRANK must contain a
               permutation of the integers M1 to M2, which are interpreted
               as a vector of ranks.

           5:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry M2 < 1,

               or       M1 < 1,

               or       M1 > M2.

          IFAIL= 2
               Elements M1 to M2 of IRANK contain a value outside the range
               M1 to M2.

          IFAIL= 3
               Elements M1 to M2 of IRANK contain a repeated value.

          If IFAIL = 2 or 3, elements M1 to M2 of IRANK do not contain a
          permutation of the integers M1 to M2. On exit, the contents of RV
          may be corrupted. To check the validity of IRANK without the risk
          of corrupting RV, use M01ZBF(*).

          7. Accuracy

          Not applicable.

          8. Further Comments

          The average time taken by the routine is approximately
          proportional to n, where n = M2 - M1 + 1.

          9. Example

          The example program reads a matrix of double precision numbers
          and rearranges its rows so that the elements of the kth column
          are in ascending order. To do this, the program first calls
          M01DAF to rank the elements of the kth column, and then calls
          M01EAF to rearrange each column into the order specified by the
          ranks. The value of k is read from the data-file.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXm01zaf}{nagm.ht}{ Inverts a permutation}
\begin{chunk}{nagm.ht}
\begin{page}{manpageXXm01zaf}{NAG Documentation: m01zaf}
\beginscroll
\begin{verbatim}



     M01ZAF(3NAG)      Foundation Library (12/10/92)      M01ZAF(3NAG)



          M01 -- Sorting                                             M01ZAF
                  M01ZAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          M01ZAF inverts a permutation, and hence converts a rank vector to
          an index vector, or vice versa.

          2. Specification

                 SUBROUTINE M01ZAF (IPERM, M1, M2, IFAIL)
                 INTEGER          IPERM(M2), M1, M2, IFAIL

          3. Description

          There are two common ways of describing a permutation using an
          integer vector IPERM. The first uses ranks: IPERM(i) holds the
          position to which the ith data element should be moved in order
          to sort the data; in other words its rank in the sorted order.
          The second uses indices: IPERM(i) holds the current position of
          the data element which would occur in ith position in sorted
          order. For example, given the values

                 3.5    5.9    2.9    0.5

          to be sorted in ascending order, the ranks would be

                 3      4      2      1

          and the indices would be

                 4      3      1      2

          The M01D- routines generate ranks, and the M01E- routines require
          ranks to be supplied to specify the re-ordering. However if it is
          desired simply to refer to the data in sorted order without
          actually re-ordering them, indices are more convenient than ranks
          (see the example in Section 9).

          M01ZAF can be used to convert ranks to indices, or indices to
          ranks, as the two permutations are inverses of one another.

          4. References

          None.

          5. Parameters

           1:  IPERM(M2) -- INTEGER array                      Input/Output
               On entry: elements M1 to M2 of IPERM must contain a
               permutation of the integers M1 to M2. On exit: these
               elements contain the inverse permutation of the integers M1
               to M2.

           2:  M1 -- INTEGER                                          Input

           3:  M2 -- INTEGER                                          Input
               On entry: M1 and M2 must specify the range of elements used
               in the array IPERM and the range of values in the
               permutation, as specified under IPERM. Constraint: 0 < M1 <=
               M2.

           4:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry M2 < 1,

               or       M1 < 1,
               or       M1 > M2.
          IFAIL= 2
               Elements M1 to M2 of IPERM contain a value outside the range
               M1 to M2.

          IFAIL= 3
               Elements M1 to M2 of IPERM contain a repeated value.

          If IFAIL = 2 or 3, elements M1 to M2 of IPERM do not contain a
          permutation of the integers M1 to M2; on exit these elements are
          usually corrupted. To check the validity of a permutation without
          the risk of corrupting it, use M01ZBF(*).

          7. Accuracy

          Not applicable.

          8. Further Comments

          None.

          9. Example

          The example program reads a matrix of double precision numbers
          and prints its rows in ascending order as ranked by M01DEF. The
          program first calls M01DEF to rank the rows, and then calls
          M01ZAF to convert the rank vector to an index vector, which is
          used to refer to the rows in sorted order.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\section{nags.ht}
\pagetitle{manpageXXs}{nags.ht}{ Approximations of Special Functions}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs}{NAG Documentation: s}
\beginscroll
\begin{verbatim}



     S(3NAG)           Foundation Library (12/10/92)           S(3NAG)



          S -- Approximations of Special Functions        Introduction -- S
                                     Chapter S
                        Approximations of Special Functions

          1. Scope of the Chapter

          This chapter is concerned with the provision of some commonly
          occurring physical and mathematical functions.

          2. Background to the Problems

          The majority of the routines in this chapter approximate real-
          valued functions of a single real argument, and the techniques
          involved are described in Section 2.1. In addition the chapter
          contains routines for elliptic integrals (see Section 2.2),
          Bessel and Airy functions of a complex argument (see Section 2.3)
          , and exponential of a complex argument.

          2.1. Functions of a Single Real Argument

          Most of the routines for functions of a single real argument have
          been based on truncated Chebyshev expansions. This method of
          approximation was adopted as a compromise between the conflicting
          requirements of efficiency and ease of implementation on many
          different machine ranges. For details of the reasons behind this
          choice and the production and testing procedures followed in
          constructing this chapter see Schonfelder [7].

          Basically if the function to be approximated is f(x), then for
          xis in  [a,b] an approximation of the form


                                          --'
                                f(x)=g(x) >  C T (t)
                                          --  r r
                                          r=0

                     --'
          is used, ( >  denotes, according to the usual convention, a
                     --
          summation in which the first term is halved), where g(x) is some
          suitable auxiliary function which extracts any singularities,
          asymptotes and, if possible, zeros of the function in the range
          in question and t=t(x) is a mapping of the general range [a,b] to
          the specific range [-1,+1] required by the Chebyshev polynomials,
          T (t). For a detailed description of the properties of the
           r
          Chebyshev polynomials see Clenshaw [5] and Fox and Parker [6].

          The essential property of these polynomials for the purposes of
          function approximation is that T (t) oscillates between +-1 and
                                          n
          it takes its extreme values n+1 times in the interval [-1,+1].
          Therefore, provided the coefficients C  decrease in magnitude
                                                r
          sufficiently rapidly the error made by truncating the Chebyshev
          expansion after n terms is approximately given by


                                    E(t)~=C T (t)
                                           n n

          That is the error oscillates between +-C  and takes its extreme
                                                  n
          value n+1 times in the interval in question. Now this is just the
          condition that the approximation be a mini-max representation,
          one which minimizes the maximum error. By suitable choice of the
          interval, [a,b], the auxiliary function, g(x), and the mapping of
          the independent variable, t(x), it is almost always possible to
          obtain a Chebyshev expansion with rapid convergence and hence
          truncations that provide near mini-max polynomial approximations
          to the required function. The difference between the true mini-
          max polynomial and the truncated Chebyshev expansion is seldom
          sufficiently great to be of significance.

          The evaluation of the Chebyshev expansions follows one of two
          methods. The first and most efficient, and hence most commonly
          used, works with the equivalent simple polynomial. The second
          method, which is used on the few occasions when the first method
          proves to be unstable, is based directly on the truncated
          Chebyshev series and uses backward recursion to evaluate the sum.
          For the first method, a suitably truncated Chebyshev expansion
          (truncation is chosen so that the error is less than the machine
          precision) is converted to the equivalent simple polynomial. That
          is we evaluate the set of coefficients b  such that
                                                  r

                                   n-1      n-1
                                   --    r  --'
                             y(t)= >  b t = >  C T (t).
                                   --  r    --  r r
                                   r=0      r=0

          The polynomial can then be evaluated by the efficient Horner's
          method of nested multiplications,

                     y(t)=(b +t(b +t(b +...t(b   +tb   )))...).
                            0    1    2       n-2   n-1

          This method of evaluation results in efficient routines but for
          some expansions there is considerable loss of accuracy due to
          cancellation effects. In these cases the second method is used.
          It is well known that if

                        b    =C
                         n-1   n-1

                        b    =2tb   +C
                         n-2     n-1  n-2

                        b  =2tb   -b   +C ,  j=n-3,n-4,...,0
                         j     j+1  j+2  j

          then

                                --'         1
                                >  C T (t)= -(b -b )
                                --  r r     2  0  2
                                r=0

          and this is always stable. This method is most efficiently
          implemented by using three variables cyclically and explicitly
          constructing the recursion.

          That is,

                        (alpha) = C
                                   n-1
                        (beta) = 2t(alpha)+C
                                            n-2
                        (gamma) = 2t(beta)-(alpha)+C
                                                    n-3
                        (alpha) = 2t(gamma)-(beta)+C
                                                    n-4
                        (beta) = 2t(alpha)-(gamma)+C
                                                    n-5
                          ...
                          ...
                        (alpha) = 2t(gamma)-(beta)+C   (say)
                                                    2
                        (beta) = 2t(alpha)-(gamma)+C
                                                    1
                                                1
                        y(t) = t(beta)-(alpha)+ -C
                                                2 0

          The auxiliary functions used are normally functions compounded of
          simple polynomial (usually linear) factors extracting zeros, and
          the primary compiler-provided functions, sin, cos, ln, exp, sqrt,
          which extract singularities and/or asymptotes or in some cases
          basic oscillatory behaviour, leaving a smooth well-behaved
          function to be approximated by the Chebyshev expansion which can
          therefore be rapidly convergent.

          The mappings of [a,b] to [-1,+1] used, range from simple linear
          mappings to the case when b is infinite and considerable
          improvement in convergence can be obtained by use of a bilinear
          form of mapping. Another common form of mapping is used when the
          function is even, that is it involves only even powers in its
          expansion. In this case an approximation over the whole interval
                                                    (x)2
          [-a,a] can be provided using a mapping t=2(-) -1. This embodies
                                                    (a)
          the evenness property but the expansion in t involves all powers
          and hence removes the necessity of working with an expansion with
          half its coefficients zero.

          For many of the routines an analysis of the error in principle is
          given, viz, if E and (nabla) are the absolute errors in function
          and argument and (epsilon) and (delta) are the corresponding
          relative errors, then

                                  E~=|f'(x)|(nabla)

                                 E~=|xf'(x)|(delta)

                                        | xf'(x)|
                             (epsilon)~=| ------|(delta)
                                        |  f(x) |

          If we ignore errors that arise in the argument of the function by
          propagation of data errors etc and consider only those errors
          that result from the fact that a real number is being represented
          in the computer in floating-point form with finite precision,
          then (delta) is bounded and this bound is independent of the
          magnitude of x; e.g. on an 11-digit machine

                                               -11
                                  |(delta)|<=10   .

          (This of course implies that the absolute error (nabla)=x(delta)
          is also bounded but the bound is now dependent on x). However
          because of this the last two relations above are probably of more
          interest. If possible the relative error propagation is
          discussed; that is the behaviour of the error amplification
          factor |xf'(x)/f(x)| is described, but in some cases, such as
          near zeros of the function which cannot be extracted explicitly,
          absolute error in the result is the quantity of significance and
          here the factor |xf'(x)| is described. In general, testing of the
          functions has shown that their error behaviour follows fairly
          well these theoretical error behaviours. In regions, where the
          error amplification factors are less than or of the order of one,
          the errors are slightly larger than the above predictions. The
          errors are here limited largely by the finite precision of
          arithmetic in the machine but (epsilon) is normally no more than
          a few times greater than the bound on (delta). In regions where
          the amplification factors are large, order of ten or greater, the
          theoretical analysis gives a good measure of the accuracy
          obtainable.

          It should be noted that the definitions and notations used for
          the functions in this chapter are all taken from Abramowitz and
          Stegun [1]. Users are strongly recommended to consult this book
          for details before using the routines in this chapter.

          2.2. Approximations to Elliptic Integrals

          The functions provided here are symmetrised variants of the
          classic elliptic integrals. These alternative definitions have
          been suggested by Carlson (see [2], [3] and [4]) and he also
          developed the basic algorithms used in this chapter.

          The standard integral of the first kind is represented by


                                     infty
                                   1 /            dt
                        R (x,y,z)= - |     -----------------
                         F         2 /       
                                     0     \/(t+x)(t+y)(t+z)

          where x,y,z>=0 and at most one may be equal to zero.

                                     1
          The normalisation factor,  -, is chosen so as to make
                                     2

                                                

                                  R (x,x,x)=1/\/x.
                                   F

          If any two of the variables are equal, R  degenerates into the
                                                  F
          second function


                                             infty
                                           1 /         dt
                        R (x,y)=R (x,y,y)= - |     ----------
                         C       F         2 /       
                                             0     \/t+x(t+y)

          where the argument restrictions are now x>=0 and y/=0.

          This function is related to the logarithm or inverse hyperbolic
          functions if 0<y<x, and to the inverse circular functions if
          0<=x<=y.

          The integrals of the second kind are defined by

                                    infty
                                  3 /             dt
                       R (x,y,z)= - |     -------------------
                        D         2 /        
                                    0       /               3
                                          \/ (t+x)(t+y)(t+z)

          with z>0, x>=0 and y>=0 but only one of x or y may be zero.

          The function is a degenerate special case of the integral of the
          third kind

                                   infty
                                 3 /                  dt
                R (x,y,z,(rho))= - |     ----------------------------
                 J               2 /     (                 )
                                   0     (\/(t+x)(t+y)(t+z))(t+(rho))

          with (rho)/=0, x,y,z>=0 with at most one equality holding. Thus
          R (x,y,z)=R (x,y,z,z). The normalisation of both these functions
           D         J
          is chosen so that

                                                       

                           R (x,x,x)=R (x,x,x,x)=1/(x\/x)
                            D         J

          The algorithms used for all these functions are based on
          duplication theorems. These allow a recursion system to be
          established which constructs a new set of arguments from the old
          using a combination of arithmetic and geometric means. The value
          of the function at the original arguments can then be simply
          related to the value at the new arguments. These recursive
          reductions are used until the arguments differ from the mean by
          an amount small enough for a Taylor series about the mean to give
          sufficient accuracy when retaining terms of order less than six.
          Each step of the recurrences reduces the difference from the mean
          by a factor of four, and as the truncation error is of order six,
                                               -n
          the truncation error goes like (4096)  , where n is the number of
          iterations.

          The above forms can be related to the more traditional canonical
          forms (see Abramowitz and Stegun [1], 17.2).

                           2               2               2
          If we write q=cos (phi),r=1-m.sin (phi),s=1+n.sin (phi), where
                    1
          0<(phi)<= -(pi), we have: the elliptic integral of the first
                    2
          kind:

                        sin(phi)      -1/2      1-/2
                        /           2         2
            F((phi)|m)= |       (1-t )   (1-mt )   dt=sin(phi).R (q,r,1);
                        /                                       F
                        0

          the elliptic integral of the second kind:

                                 sin(phi)      -1/2      -1/2
                                 /           2         2
                   E((phi)|m) =  |       (1-t )   (1-mt )  dt
                                 /
                                 0
                                                    1     3
                              = sin(phi).R (q,r,1)- -m.sin (phi).R (q,r,1)
                                          F         3             D

          the elliptic integral of the third kind:

                                 sin(phi)      -1/2      -1/2
                                 /           2         2         2 -1
              (Pi)(n;(phi)|m) =  |       (1-t )   (1-mt )   (1+nt )  dt
                                 /
                                 0
                                                    1     3
                              =sin(phi).R (q,r,1)- -n.sin (phi).R (q,r,1,s)
                                         F         3             J

          Also the complete elliptic integral of the first kind:

                      (pi)/2
                      /             2       -1/2
                K(m)= |     (1-m.sin (theta))   d(theta)=R (0,1-m,1);
                      /                                   F
                      0

          the complete elliptic integral of the second kind:


                (pi)/2
                /         2        1/2                     1
          E(m)= | (1-m.sin (theta))  d(theta)=R (0,1-m,1)- -mR (0,1-m,1).
                /                              F           3  D
                0


          2.3. Bessel and Airy Functions of a Complex Argument

          The routines for Bessel and Airy functions of a real argument are
          based on Chebyshev expansions, as described in Section 2.1. The
          routines for functions of a complex argument, however, use
          different methods. These routines relate all functions to the
          modified Bessel functions I    (z) and K    (z) computed in the
                                     (nu)         (nu)
          right-half complex plane, including their analytic continuations.
          I     and K     are computed by different methods according to
           (nu)      (nu)
          the values of zand (nu). The methods include power series,
          asymptotic expansions and Wronskian evaluations. The relations
          between functions are based on well known formulae (see
          Abramowitz and Stegun [1]).

          2.4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          [2]   Carlson B C (1977) Special Functions of Applied Mathematics.
                Academic Press.

          [3]   Carlson B C (1965) On Computing Elliptic Integrals and
                Functions. J Math Phys. 44 36--51.

          [4]   Carlson B C (1977) Elliptic Integrals of the First Kind.
                SIAM J Math Anal. 8 231--242.

          [5]   Clenshaw C W (1962) Mathematical Tables. Chebyshev Series
                for Mathematical Functions. HMSO.

          [6]   Fox L and Parker I B (1968) Chebyshev Polynomials in
                Numerical Analysis. Oxford University Press.

          [7]   Schonfelder J L (1976 ) The Production of Special Function
                Routines for a Multi-Machine Library. Software Practice and
                Experience. 6(1)

          3. Recommendations on Choice and Use of Routines

          3.1. Elliptic Integrals

          IMPORTANT ADVICE: users who encounter elliptic integrals in the
          course of their work are strongly recommended to look at
          transforming their analysis directly to one of the Carlson forms,
          rather than the traditional canonical Legendre forms. In general,
          the extra symmetry of the Carlson forms is likely to simplify the
          analysis, and these symmetric forms are much more stable to
          calculate.

          The routine S21BAF for R  is largely included as an auxiliary to
                                  C
          the other routines for elliptic integrals. This integral
          essentially calculates elementary functions, e.g.


                                        (( 1+x)2  )
                            lnx=(x-1).R (( ---) ,x),x>0;
                                       C((  2 )   )

                                            2
                            arcsinx=x.R (1-x ,1),|x|<=1;
                                       C

                                              2
                             arcsinhx=x.R (1+x ,1),  etc
                                         C

          In general this method of calculating these elementary functions
          is not recommended as there are usually much more efficient
          specific routines available in the Library. However, S21BAF may
          be used, for example, to compute lnx/(x-1) when x is close to 1,
          without the loss of significant figures that occurs when lnx and
          x-1 are computed separately.

          3.2. Bessel and Airy Functions

          For computing the Bessel functions J    (x), Y    (x), I    (x)
                                              (nu)      (nu)      (nu)
          and K    (x) where x is real and (nu)=0 or 1, special routines
               (nu)
          are provided, which are much faster than the more general
          routines that allow a complex argument and arbitrary real (nu)>=0
          functions and their derivatives Ai(x), Bi(x), Ai'(x), Bi'(x) for
          a real argument which are much faster than the routines for
          complex arguments.

          3.3. Index

          Airy function, Ai, real argument                           S17AGF
          Airy function, Ai', real argument                          S17AJF
          Airy function, Ai or Ai', complex argument, optionally     S17DGF
          scaled
          Airy function, Bi, real argument                           S17AHF
          Airy function, Bi', real argument                          S17AKF
          Airy function, Bi or Bi', complex argument, optionally     S17DHF
          scaled
          Bessel function, J , real argument                         S17AEF
                            0
          Bessel function, J , real argument                         S17AFF
                            1
          Bessel function, J    , complex argument, optionally       S17DEF
                            (nu)
          scaled
          Bessel function, Y , real argument                         S17ACF
                            0
          Bessel function, Y , real argument                         S17ADF
                            1
          Bessel function, Y    , complex argument, optionally       S17DCF
                            (nu)
          scaled
          Complement of the Error function                           S15ADF
          Cosine Integral                                            S13ACF
          Elliptic integral, symmetrised, degenerate of 1st kind,    S21BAF
          R
           C
          Elliptic integral, symmetrised, of 1st kind, R             S21BBF
                                                        F
          Elliptic integral, symmetrised, of 2nd kind, R             S21BCF
                                                        D
          Elliptic integral, symmetrised, of 3rd kind, R             S21BDF
                                                        J
          Erf, real argument                                         S15AEF
          Erfc, real argument                                        S15ADF
          Error function                                             S15AEF
          Exponential, complex                                       S01EAF
          Exponential Integral                                       S13AAF
          Fresnel Integral, C                                        S20ADF
          Fresnel Integral, S                                        S20ACF
          Gamma function                                             S14AAF
          Gamma function, incomplete                                 S14BAF
          Generalized Factorial function                             S14AAF
                           (1)      (2)
          Hankel function H     or H    , complex argument,          S17DLF
                           (nu)     (nu)
          optionally scaled
          Incomplete Gamma function                                  S14BAF
          Jacobian elliptic functions, sn, cn, dn                    S21CAF
          Kelvin function, bei x                                     S19ABF
          Kelvin function, ber x                                     S19AAF
          Kelvin function, kei x                                     S19ADF
          Kelvin function, ker x                                     S19ACF
          Logarithm of Gamma function                                S14ABF
          Modified Bessel function, I , real argument                S18AEF
                                     0
          Modified Bessel function, I , real argument                S18AFF
                                     1
          Modified Bessel function, I    , complex argument,         S18DEF
                                     (nu)
          optionally scaled
          Modified Bessel function, K , real argument                S18ACF
                                     0
          Modified Bessel function, K , real argument                S18ADF
                                     1
          Modified Bessel function, K    , complex argument,         S18DCF
                                     (nu)
          optionally scaled
          Sine integral                                              S13ADF


          S -- Approximations of Special Functions            Contents -- S
          Chapter S

          Approximations of Special Functions

                                        z
          S01EAF  Complex exponential, e

          S13AAF  Exponential integral E (x)
                                        1

          S13ACF  Cosine integral Ci(x)

          S13ADF  Sine integral Si(x)

          S14AAF  Gamma function

          S14ABF  Log Gamma function

          S14BAF  Incomplete gamma functions P(a,x) and Q(a,x)

          S15ADF  Complement of error function erfc x

          S15AEF  Error function erf x

          S17ACF  Bessel function Y (x)
                                   0

          S17ADF  Bessel function Y (x)
                                   1

          S17AEF  Bessel function J (x)
                                   0

          S17AFF  Bessel function J (x)
                                   1

          S17AGF  Airy function Ai(x)

          S17AHF  Airy function Bi(x)

          S17AJF  Airy function Ai'(x)

          S17AKF  Airy function Bi'(x)

          S17DCF  Bessel functions Y      (z), real a>=0, complex z,
                                    (nu)+a
                  (nu)=0,1,2,...

          S17DEF  Bessel functions J      (z), real a>=0, complex z,
                                    (nu)+a
                  (nu)=0,1,2,...

          S17DGF  Airy functions Ai(z) and Ai'(z), complex z

          S17DHF  Airy functions Bi(z) and Bi'(z), complex z

                                    (j)
          S17DLF  Hankel functions H      (z), j=1,2, real a>=0, complex z,
                                    (nu)+a
                  (nu)=0,1,2,...

          S18ACF  Modified Bessel function K (x)
                                            0

          S18ADF  Modified Bessel function K (x)
                                            1

          S18AEF  Modified Bessel function I (x)
                                            0

          S18AFF  Modified Bessel function I (x)
                                            1

          S18DCF  Modified Bessel functions K      (z), real a>=0, complex
                                             (nu)+a
                  z, (nu)=0,1,2,...

          S18DEF  Modified Bessel functions I      (z), real a>=0, complex
                                             (nu)+a
                  z, (nu)=0,1,2,...

          S19AAF  Kelvin function ber x

          S19ABF  Kelvin function bei x

          S19ACF  Kelvin function ker x

          S19ADF  Kelvin function kei x

          S20ACF  Fresnel integral S(x)

          S20ADF  Fresnel integral C(x)

          S21BAF  Degenerate symmetrised elliptic integral of 1st kind
                  R (x,y)
                   C

          S21BBF  Symmetrised elliptic integral of 1st kind R (x,y,z)
                                                             F

          S21BCF  Symmetrised elliptic integral of 2nd kind R (x,y,z)
                                                             D

          S21BDF  Symmetrised elliptic integral of 3rd kind R (x,y,z,r)
                                                             J

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs01eaf}{nags.ht}
{ Exponential function $e^z$ , for complex $z$}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs01eaf}{NAG Documentation: s01eaf}
\beginscroll
\begin{verbatim}



     S01EAF(3NAG)      Foundation Library (12/10/92)      S01EAF(3NAG)



          S01 -- Approximations of Special Functions                 S01EAF
                  S01EAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

                                                     z
          S01EAF evaluates the exponential function e , for complex z.

          2. Specification

                 COMPLEX(KIND(1.0D0)) FUNCTION S01EAF (Z, IFAIL)
                 INTEGER                               IFAIL
                 COMPLEX(KIND(1.0D0))                  Z

          3. Description

                                                           z
          This routine evaluates the exponential function e , taking care
          to avoid machine overflow, and giving a warning if the result
          cannot be computed to more than half precision. The function is
                        z  x
          evaluated as e =e (cosy+isiny), where x and y are the real and
          imaginary parts respectively of z.

          Since cosy and siny are less than or equal to 1 in magnitude, it
                            x                        x         x
          is possible that e  may overflow although e cosy or e siny does
                                                               x+ln|cosy|
          not. In this case the alternative formula sign(cosy)e
          is used for the real part of the result, and
                     x+ln|siny|
          sign(siny)e           for the imaginary part. If either part of
          the result still overflows, a warning is returned through
          parameter IFAIL.

          If Im z is too large, precision may be lost in the evaluation of
          siny and cosy. Again, a warning is returned through IFAIL.

          4. References

          None.

          5. Parameters

           1:  Z -- COMPLEX(KIND(1.0D0))                              Input
               On entry: the argument z of the function.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               The real part of the result overflows, and is set to the
               largest safe number with the correct sign. The imaginary
               part of the result is meaningful.

          IFAIL= 2
               The imaginary part of the result overflows, and is set to
               the largest safe number with the correct sign. The real part
               of the result is meaningful.

          IFAIL= 3
               Both real and imaginary parts of the result overflow, and
               are set to the largest safe number with the correct signs.

          IFAIL= 4
               The computed result is accurate to less than half precision,
               due to the size of Im z.

          IFAIL= 5
               The computed result has no precision, due to the size of Im
               z, and is set to zero.

          7. Accuracy

          Accuracy is limited in general only by the accuracy of the
          Fortran intrinsic functions in the computation of siny, cosy and
           x
          e , where x=Re z, y=Im z. As y gets larger, precision will
          probably be lost due to argument reduction in the evaluation of
          the sine and cosine functions, until the warning error IFAIL = 4
                                           

          occurs when y gets larger than \/1/(epsilon), where (epsilon) is
          the machine precision. Note that on some machines, the intrinsic
          functions SIN and COS will not operate on arguments larger than
                  

          about \/1/(epsilon), and so IFAIL can never return as 4.

          In the comparatively rare event that the result is computed by
                                  x+ln|cosy|                x+ln|siny|
          the formulae sign(cosy)e           and sign(siny)e          , a
          further small loss of accuracy may be expected due to rounding
          errors in the logarithmic function.

          8. Further Comments

          None.

          9. Example

          The example program reads values of the argument z from a file,
          evaluates the function at each value of z and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs13aaf}{nags.ht}
{ Returns the value of the exponential integral $E(x)$}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs13aaf}{NAG Documentation: s13aaf}
\beginscroll
\begin{verbatim}



     S13AAF(3NAG)      Foundation Library (12/10/92)      S13AAF(3NAG)



          S13 -- Approximations of Special Functions                 S13AAF
                  S13AAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S13AAF returns the value of the exponential integral E (x), via
                                                                1
          the routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S13AAF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          The routine calculates an approximate value for

                                     infty
                                     /     e-u
                              E (x)= |     -  du , x>0.
                               1     /     u
                                     x

          For 0<x<=4, the approximation is based on the Chebyshev expansion

                                   --                        1
                   E (x)=y(t)-lnx= > 'a T (t)-lnx , where t= -x-1.
                    1              --  r r                   2
                                   r

          For x>4,

                                   -x       -x
                                  e        e   --'
                           E (x)= ---y(t)= --- >  a T (t),
                            1      x        x  --  r r
                                               r

                                                     11.25-x
                        where  t=-1.0+14.5/(x+3.25)= -------.
                                                     3.25+x

          In both cases, -1<=t<=+1.

          To guard against producing underflows, if x>x   the result is set
                                                       hi
          directly to zero. For the value x   see the Users' Note for your
                                           hi
          implementation.

          4. References

          [1]   Abramowitz M and Stegun I A (1965) Handbook of Mathematical
                Functions. Dover Publications. Ch. 26.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function. Constraint: X > 0.
               0.

           2:  IFAIL -- INTEGER                                Input/Output
               Before entry, IFAIL must be assigned a value. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               Unless the routine detects an error (see Section 6), IFAIL
               contains 0 on exit.

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               The routine has been called with an argument less than or
               equal to zero for which the function is not defined. The
               result returned is zero.

          7. Accuracy

          If (delta) and (epsilon) are the relative errors in argument and
          result respectively, then in principle,

                                         |   -x         |
                                         |  e           |
                            |(epsilon)|~=| -----*(delta)|
                                         | E (x)        |
                                         |  1           |

          so the relative error in the argument is amplified in the result
                                -x
          by at least a factor e  /E (x). The equality should hold if
                                    1
          (delta) is greater than the machine precision ((delta) due to
          data errors etc) but if (delta) is simply a result of round-off
          in the machine representation, it is possible that an extra
          figure may be lost in internal calculation and round-off.

          The behaviour of this amplification factor is shown in Figure 1.


                                     Figure 1
                   Please see figure in printed Reference Manual

          It should be noted that, for small x, the amplification factor
          tends to zero and eventually the error in the result will be
          limited by machine precision.

          For large x,

                             (epsilon)~x(delta)=(Delta),

          the absolute error in the argument.

          8. Further Comments

          None.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs13acf}{nags.ht}{ Returns the value of the cosine integral}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs13acf}{NAG Documentation: s13acf}
\beginscroll
\begin{verbatim}



     S13ACF(3NAG)      Foundation Library (12/10/92)      S13ACF(3NAG)



          S13 -- Approximations of Special Functions                 S13ACF
                  S13ACF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S13ACF returns the value of the cosine integral

                                            x
                                            / cosu-1
                         Ci(x)=(gamma)+lnx+ | ------du,  x>0
                                            /   u
                                            0

          via the routine name, where (gamma) denotes Euler's constant.

          2. Specification

                 DOUBLE PRECISION FUNCTION S13ACF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          The routine calculates an approximate value for Ci(x).

          For 0<x<=16 it is based on the Chebyshev expansion

                                   --'              ( x )2
                        Ci(x)=lnx+ >   a T (t) , t=2( --) -1.
                                   --   r r         ( 16)
                                   r=0

          For 16<x<x   where the value of x   is given in the Users' Note
                    hi                     hi
          for your implementation,

                                     f(x)sinx  g(x)cosx
                              Ci(x)= --------- --------
                                        x          2
                                                  x

                      --'                   --'             ( 16)2
          where f(x)= >   f T (t) and g(x)= >   g T (t), t=2( --) -1.
                      --   r r              --   r r        ( x )
                      r=0                   r=0

          For x>=x  , Ci(x)=0 to within the accuracy possible (see Section
                  hi
          7).

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function. Constraint: X > 0.
               0.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               The routine has been called with an argument less than or
               equal to zero for which the function is not defined. The
               result returned is zero.

          7. Accuracy

          If E and (epsilon) are the absolute and relative errors in the
          result and (delta) is the relative error in the argument then in
          principle these are related by

                                                     | (delta)cosx|
                 |E|~=|(delta)cosx| and |(epsilon)|~=| -----------|.
                                                     |    Ci(x)   |

          That is accuracy will be limited by machine precision near the
          origin and near the zeros of cosx, but near the zeros of Ci(x)
          only absolute accuracy can be maintained.

          The behaviour of this amplification is shown in Figure 1.


                                     Figure 1
                   Please see figure in printed Reference Manual

                                        sinx
          For large values of x, Ci(x)~ ---- therefore
                                         x
          (epsilon)~(delta)xcotx and since (delta) is limited by the finite
          precision of the machine it becomes impossible to return results
          which have any relative accuracy. That is, when x>=1/(delta) we
          have that |Ci(x)|<=1/x~E and hence is not significantly different
          from zero.

          Hence x   is chosen such that for values of x>=x  , Ci(x) in
                 hi                                       hi
          principle would have values less than the machine precision and
          so is essentially zero.

          8. Further Comments

          For details of the time taken by the routine see the Users' Note
          for your implementation.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs13adf}{nags.ht}{ Returns the value of the sine integral}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs13adf}{NAG Documentation: s13adf}
\beginscroll
\begin{verbatim}



     S13ADF(3NAG)      Foundation Library (12/10/92)      S13ADF(3NAG)



          S13 -- Approximations of Special Functions                 S13ADF
                  S13ADF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S13ADF returns the value of the sine integral

                                         x
                                         / sinu
                                  Si(x)= | ----du,
                                         /  u
                                         0

          via the routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S13ADF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          The routine calculates an approximate value for Si(x).

          For |x|<=16.0 it is based on the Chebyshev expansion

                                 --'              ( x )2
                         Si(x)=x >   a T (t) , t=2( --) -1.
                                 --   r r         ( 16)
                                 r=0

          For 16<|x|<x  , where x   is an implementation dependent number,
                      hi         hi

                                   { (pi)  f(x)cosx  g(x)sinx}
                      Si(x)=sign(x){ ----- --------- --------}
                                   {  2       x          2   }
                                   {                    x    }

                      --'                   --'             ( 16)2
          where f(x)= >   f T (t) and g(x)= >   g T (t), t=2( --) -1.
                      --   r r              --   r r        ( x )
                      r=0                   r=0

                               1
          For |x|>=x  , Si(x)= -(pi)signx to within machine precision.
                    hi         2

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          There are no failure exits from this routine. The parameter IFAIL
          has been included for consistency with other routines in this
          chapter.

          7. Accuracy

          If (delta) and (epsilon) are the relative errors in the argument
          and result, respectively, then in principle

                                         | (delta)sinx|
                            |(epsilon)|~=| -----------|.
                                         |    Si(x)   |

          The equality may hold if (delta) is greater than the machine
          precision ((delta) due to data errors etc) but if (delta) is
          simply due to round-off in the machine representation, then since
          the factor relating (delta) to (epsilon) is always less than one,
          the accuracy will be limited by machine precision.

          8. Further Comments

          For details of the time taken by the routine see the Users' Note
          for your implementation.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs14aaf}{nags.ht}{ Returns the value of the Gamma function}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs14aaf}{NAG Documentation: s14aaf}
\beginscroll
\begin{verbatim}



     S14AAF(3NAG)      Foundation Library (12/10/92)      S14AAF(3NAG)



          S14 -- Approximations of Special Functions                 S14AAF
                  S14AAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S14AAF returns the value of the Gamma function (Gamma)(x), via
          the routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S14AAF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          This routine evaluates an approximation to the Gamma function
          (Gamma)(x). The routine is based on the Chebyshev expansion:

                               --'
                 (Gamma)(1+u)= >   a T (t) , where 0<=u<1 , t=2u-1,
                               --   r r
                               r=0

          and uses the property (Gamma)(1+x)=x(Gamma)(x). If x=N+1+u where
          N is integral and 0<=u<1 then it follows that:

               for N>0  (Gamma)(x)=(x-1)(x-2)...(x-N)(Gamma)(1+u),

               for N=0  (Gamma)(x)=(Gamma)(1+u),

                                        (Gamma)(1+u)
               for N<0  (Gamma)(x)= ---------------------.
                                    x(x+1)(x+2)...(x-N-1)

          There are four possible failures for this routine:

               (i) if x is too large, there is a danger of overflow since
               (Gamma)(x) could become too large to be represented in the
               machine;

               (ii) if x is too large and negative, there is a danger of
               underflow;

               (iii) if x is equal to a negative integer, (Gamma)(x) would
               overflow since it has poles at such points;

               (iv) if x is too near zero, there is again the danger of
                                                                    1
               overflow on some machines. For small x, (Gamma)(x)~= -, and
                                                                    x
               on some machines there exists a range of non-zero but small
               values of x for which 1/x is larger than the greatest
               representable value.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function. Constraint: X must
               not be a negative integer.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               The argument is too large. On soft failure the routine
               returns the approximate value of (Gamma)(x) at the nearest
               valid argument.

          IFAIL= 2
               The argument is too large and negative. On soft failure the
               routine returns zero.

          IFAIL= 3
               The argument is too close to zero. On soft failure the
               routine returns the approximate value of (Gamma)(x) at the
               nearest valid argument.

          IFAIL= 4
               The argument is a negative integer, at which value
               (Gamma)(x) is infinite. On soft failure the routine returns
               a large positive value.

          7. Accuracy

          Let (delta) and (epsilon) be the relative errors in the argument
          and the result respectively. If (delta) is somewhat larger than
          the machine precision (i.e., is due to data errors etc), then
          (epsilon) and (delta) are approximately related by:

                            (epsilon)~=|x(Psi)(x)|(delta)

          (provided (epsilon) is also greater than the representation
                                                         (Gamma)'(x)
          error). Here (Psi)(x) is the digamma function  -----------.
                                                         (Gamma)(x)
          Figure 1 shows the behaviour of the error amplification factor
          |x(Psi)(x)|.


                                     Figure 1
                   Please see figure in printed Reference Manual

          If (delta) is of the same order as machine precision, then
          rounding errors could make (epsilon) slightly larger than the
          above relation predicts.

          There is clearly a severe, but unavoidable, loss of accuracy for
          arguments close to the poles of (Gamma)(x) at negative integers.
          However relative accuracy is preserved near the pole at x=0 right
          up to the point of failure arising from the danger of overflow.

          Also accuracy will necessarily be lost as x becomes large since
          in this region

                               (epsilon)~=(delta)xlnx.

          However since (Gamma)(x) increases rapidly with x, the routine
          must fail due to the danger of overflow before this loss of
          accuracy is too great. (e.g. for x=20, the amplification factor
          ~= 60.)

          8. Further Comments

          For details of the time taken by the routine see the Users' Note
          for your implementation.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs14abf}{nags.ht}
{ Returns a value for the logarithm of the Gamma function}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs14abf}{NAG Documentation: s14abf}
\beginscroll
\begin{verbatim}



     S14ABF(3NAG)      Foundation Library (12/10/92)      S14ABF(3NAG)



          S14 -- Approximations of Special Functions                 S14ABF
                  S14ABF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S14ABF returns a value for the logarithm of the Gamma function,
          ln(Gamma)(x), via the routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S14ABF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          This routine evaluates an approximation to ln(Gamma)(x). It is
          based on two Chebyshev expansions.

          For 0<x<=x     , ln(Gamma)(x)=-lnx to within machine accuracy.
                    small

          For x     <x<=15.0, the recursive relation
               small
          (Gamma)(1+x)=x(Gamma)(x) is used to reduce the calculation to one
          involving (Gamma)(1+u), 0<=u<1 which is evaluated as:

                                       --'
                         (Gamma)(1+u)= >   a T (t),  t=2u-1.
                                       --   r r
                                       r=0

          Once (Gamma)(x) has been calculated, the required result is
          produced by taking the logarithm.

          For 15.0<x<=x   ,
                       big

                                       1        1
                      ln(Gamma)(x)=(x- -)lnx-x+ -ln2(pi)+y(x)/x
                                       2        2
                                           2
                      --'             ( 15)
          where y(x)= >   b T (t), t=2( --) -1.
                      --   r r        ( x )
                      r=0

          For x   <x<=x     the term y(x)/x is negligible and so its
               big     vbig
          calculation is omitted.

          For x>x     there is a danger of setting overflow so the routine
                 vbig
          must fail.

          For x<=0.0 the function is not defined and the routine fails.

          Note: x      is calculated so that if x<x     , (Gamma)(x)=1/x to
                 small                             small
          within machine accuracy. x    is calculated so that if x>x   ,
                                    big                             big

                                          1        1
                         ln(Gamma)(x)=(x- -)lnx-x+ -ln2(pi)
                                          2        2

          to within machine accuracy. x     is calculated so that
                                       vbig
          ln(Gamma)(x    ) is close to the value returned by X02ALF(*).
                     vbig

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function. Constraint: X > 0.
               0.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               X <= 0.0, the function is undefined. On soft failure, the
               routine returns zero.

          IFAIL= 2
               X is too large, the function would overflow. On soft
               failure, the routine returns the value of the function at
               the largest permissible argument.

          7. Accuracy

          Let (delta) and (epsilon) be the relative errors in the argument
          and result respectively, and E be the absolute error in the
          result.

          If (delta) is somewhat larger than the relative machine
          precision, then

                                                  |  x*(Psi)(x) |
            E~=|x*(Psi)(x)|(delta) and (epsilon)~=| ------------|(delta)
                                                  | ln(Gamma)(x)|

                                                  (Gamma)'(x)
          where (Psi)(x) is the digamma function  -----------. Figure 1 and
                                                  (Gamma)(x)
          Figure 2 show the behaviour of these error amplification factors.


                                     Figure 1
                   Please see figure in printed Reference Manual

                                     Figure 2
                   Please see figure in printed Reference Manual

          These show that relative error can be controlled, since except
          near x=1 or 2 relative error is attenuated by the function or at
          least is not greatly amplified.

                                  (    1 )
          For large x, (epsilon)~=(1+ ---)(delta) and for small x,
                                  (   lnx)
                       1
          (epsilon)~= ---(delta).
                      lnx

          The function ln(Gamma)(x) has zeros at x=1 and 2 and hence
          relative accuracy is not maintainable near those points. However
          absolute accuracy can still be provided near those zeros as is
          shown above.

          If however, (delta) is of the order of the machine precision,
          then rounding errors in the routine's internal arithmetic may
          result in errors which are slightly larger than those predicted
          by the equalities. It should be noted that even in areas where
          strong attenuation of errors is predicted the relative precision
          is bounded by the effective machine precision.

          8. Further Comments

          For details of the time taken by the routine see the Users' Note
          for your implementation.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs14baf}{nags.ht}
{ Incomplete gamma functions P(a,x) and Q(a,x)}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs14baf}{NAG Documentation: s14baf}
\beginscroll
\begin{verbatim}



     S14BAF(3NAG)      Foundation Library (12/10/92)      S14BAF(3NAG)



          S14 -- Approximations of Special Functions                 S14BAF
                  S14BAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S14BAF computes values for the incomplete gamma functions P(a,x)
          and Q(a,x).

          2. Specification

                 SUBROUTINE S14BAF (A, X, TOL, P, Q, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION A, X, TOL, P, Q

          3. Description

          This subroutine evaluates the incomplete gamma functions in the
          normalised form

                                              x
                                       1      / a-1 -t
                           P(a,x)= ---------- |t   e  dt,
                                   (Gamma)(a) /
                                              0

                                            infty
                                     1      /     a-1 -t
                         Q(a,x)= ---------- |    t   e  dt,
                                 (Gamma)(a) /
                                            x

          with x>=0 and a>0, to a user-specified accuracy. With this
          normalisation, P(a,x)+Q(a,x)=1.

          Several methods are used to evaluate the functions depending on
          the arguments a and x, the methods including Taylor expansion for
          P(a,x), Legendre's continued fraction for Q(a,x), and power
          series for Q(a,x). When both a and x are large, and a~=x, the
          uniform asymptotic expansion of Temme [3] is employed for greater
          efficiency - specifically, this expansion is used when a>=20 and
          0.7a<=x<=1.4a.

          Once either of P or Q is computed, the other is obtained by
          subtraction from 1. In order to avoid loss of relative precision
          in this subtraction, the smaller of P and Q is computed first.

          This routine is derived from subroutine GAM in Gautschi [2].

          4. References

          [1]   Gautschi W (1979) A Computational Procedure for Incomplete
                Gamma Functions. ACM Trans. Math. Softw. 5 466--481.

          [2]   Gautschi W (1979) Algorithm 542: Incomplete Gamma Functions.
                ACM Trans. Math. Softw. 5 482--489.

          [3]   Temme N M (1987) On the Computation of the Incomplete Gamma
                Functions for Large Values of the Parameters. Algorithms for
                Approximation. (ed J C Mason and M G Cox) Oxford University
                Press.

          5. Parameters

           1:  A -- DOUBLE PRECISION                                  Input
               On entry: the argument a of the functions. Constraint: A >
               0.0.

           2:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the functions. Constraint: X >=
               0.0.

           3:  TOL -- DOUBLE PRECISION                                Input
               On entry: the relative accuracy required by the user in the
               results. If S14BAF is entered with TOL greater than 1.0 or
               less than machine precision, then the value of machine
               precision is used instead.

           4:  P -- DOUBLE PRECISION                                 Output

           5:  Q -- DOUBLE PRECISION                                 Output
               On exit: the values of the functions P(a,x) and Q(a,x)
               respectively.

           6:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               On entry A <= 0.0.

          IFAIL= 2
               On entry X < 0.0.

          IFAIL= 3
               Convergence of the Taylor series or Legendre continued
               fraction fails within 600 iterations. This error is
               extremely unlikely to occur; if it does, contact NAG.

          7. Accuracy

          There are rare occasions when the relative accuracy attained is
          somewhat less than that specified by parameter TOL. However, the
          error should never exceed more than one or two decimal places.
          Note also that there is a limit of 18 decimal places on the
          achievable accuracy, because constants in the routine are given
          to this precision.

          8. Further Comments

          The time taken for a call of S14BAF depends on the precision
          requested through TOL, and also varies slightly with the input
          arguments a and x.

          9. Example

          The example program reads values of the argument a and x from a
          file, evaluates the function and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs15adf}{nags.ht}
{ Returns the value of the complementary error function}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs15adf}{NAG Documentation: s15adf}
\beginscroll
\begin{verbatim}



     S15ADF(3NAG)      Foundation Library (12/10/92)      S15ADF(3NAG)



          S15 -- Approximations of Special Functions                 S15ADF
                  S15ADF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S15ADF returns the value of the complementary error function,
          erfcx, via the routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S15ADF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          The routine calculates an approximate value for the complement of
          the error function

                                                2
                                        infty -u
                                   2    /
                         erfc x= ------ |    e   du=1-erf x.
                                        /
                                 \/(pi) x

          For x>=0, it is based on the Chebyshev expansion

                                            2
                                          -x
                                  erfc x=e   y(x),

                      --'
          where y(x)= >   a T (t) and t=(x-3.75)/(x+3.75), -1<=t<=+1.
                      --   r r
                      r=0

          For x>=x  , where there is a danger of setting underflow, the
                  hi
          result is returned as zero.

                               2
                             -x
          For x<0, erfc x=2-e   y(|x|).

          For x<x   <0, the result is returned as 2.0 which is correct to
                 low
          within machine precision. The values of x   and x    are given in
                                                   hi      low
          the Users' Note for your implementation.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          There are no failure exits from this routine. The parameter IFAIL
          has been included for consistency with other routines in this
          chapter.

          7. Accuracy

          If (delta) and (epsilon) are relative errors in the argument and
          result, respectively, then in principle

                                     |         2          |
                                     |       -x           |
                                     |    2xe             |
                        |(epsilon)|~=| ------------(delta)|.
                                     |                    |

                                     | \/(pi)erfc x       |

          That is, the relative error in the argument, x, is amplified by a
                          2
                        -x
                     2xe
          factor  ------------ in the result.
                    

                  \/(pi)erfc x

          The behaviour of this factor is shown in Figure 1.


                                     Figure 1

                   Please see figure in printed Reference Manual

                                                                     2x
          It should be noted that near x=0 this factor behaves as  ------
                                                                     

                                                                   \/(pi)
          and hence the accuracy is largely determined by the machine
          precision. Also for large negative x, where the factor is
                2
              -x
            xe
          ~ ------, accuracy is mainly limited by machine precision.
              

            \/(pi)
                                                               2
          However, for large positive x, the factor becomes ~2x  and to an
          extent relative accuracy is necessarily lost. The absolute
          accuracy E is given by

                                           2
                                         -x
                                      2xe
                                  E~= ------(delta)
                                        

                                      \/(pi)

          so absolute accuracy is guaranteed for all x.

          8. Further Comments

          For details of the time taken by the routine see the Users' Note
          for your implementation.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs15aef}{nags.ht}
{ Returns the value of the error function erfx}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs15aef}{NAG Documentation: s15aef}
\beginscroll
\begin{verbatim}



     S15AEF(3NAG)      Foundation Library (12/10/92)      S15AEF(3NAG)



          S15 -- Approximations of Special Functions                 S15AEF
                  S15AEF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S15AEF returns the value of the error function erfx, via the
          routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S15AEF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          Evaluates the error function,

                                   2
                               x -t
                          2    /
               erf x =  ------ |e   dt.
                               /
                        \/(pi) 0

          For |x|<=2,
                          --'                   1 2
                erf x = x >   a T (t), where t= -x -1.
                          --   r r              2
                          r=0

          For 2<|x|<x  ,
                     hi
                             {        2               }
                             {      -x                }
                             {     e       --         }           x-7
                erf x = signx{1- --------- >  'b T (t)}, where t= ---.
                             {             --   r r   }           x+3
                             {   |x|\/(pi) r=0        }

          For |x|>=x  ,
                    hi
                erf x =  signx.

          x   is the value above which erf x=+-1 within machine precision.
           hi
          Its value is given in the Users' Note for your implementation.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          There are no failure exits from this routine. The parameter IFAIL
          has been included for consistency with other routines in this
          chapter.

          7. Accuracy

          On a machine with approximately 11 significant figures the
          routine agrees with available tables to 10 figures and
          consistency checking with S15ADF of the relation

                                  erf x+erfc x=1.0

          shows errors in at worst the 11th figure.

          8. Further Comments

          None.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs17acf}{nags.ht}
{ Returns the value of the Bessel Function $Y_0(x)$}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs17acf}{NAG Documentation: s17acf}
\beginscroll
\begin{verbatim}



     S17ACF(3NAG)      Foundation Library (12/10/92)      S17ACF(3NAG)



          S17 -- Approximations of Special Functions                 S17ACF
                  S17ACF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S17ACF returns the value of the Bessel Function Y (x), via the
                                                           0
          routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S17ACF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          This routine evaluates an approximation to the Bessel Function of
          the second kind Y (x).
                           0

          Note: Y (x) is undefined for x<=0 and the routine will fail for
                 0
          such arguments.

          The routine is based on four Chebyshev expansions:

          For 0<x<=8,
                                                                   2
                      2      --'          --'                  ( x)
              Y (x)= ----lnx >   a T (t)+ >   b T (t), with t=2( -) -1,
               0     (pi)    --   r r     --   r r             ( 8)
                             r=0          r=0

          For x>8,

                          

                         /   2  {        (   (pi))         (   (pi))}
                Y (x)=  /  -----{P (x)sin(x- ----)+Q (x)cos(x- ----)}
                 0    \/   (pi)x{ 0      (    4  )  0      (    4  )}

                       --'
          where P (x)= >   c T (t),
                 0     --   r r
                       r=0
                                                2
                     8 --'                  ( 8)
          and Q (x)= - >   d T (t), with t=2( -) -1.
               0     x --   r r             ( x)
                       r=0

                                    2  (  ( x)        )
          For x near zero, Y (x)~= ----(ln( -)+(gamma)), where (gamma)
                            0      (pi)(  ( 2)        )
          denotes Euler's constant. This approximation is used when x is
          sufficiently small for the result to be correct to machine
          precision.

          For very large x, it becomes impossible to provide results with
          any reasonable accuracy (see Section 7), hence the routine fails.
          Such arguments contain insufficient information to determine the
                                                                 

                                                                / 2
          phase of oscillation of Y (x); only the amplitude,   /  -, can be
                                   0                         \/   x
          determined and this is returned on soft failure. The range for
          which this occurs is roughly related to the machine precision:
          the routine will fail if x>~1/machine precision (see the Users'
          Note for your implementation for details).

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          [2]   Clenshaw C W (1962) Mathematical Tables. Chebyshev Series
                for Mathematical Functions. HMSO.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function. Constraint: X > 0.
               0.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               X is too large. On soft failure the routine returns the
               amplitude of the Y  oscillation, \/2/(pi)x.
                                 0

          IFAIL= 2
               X <= 0.0, Y  is undefined. On soft failure the routine
                          0
               returns zero.

          7. Accuracy

          Let (delta) be the relative error in the argument and E be the
          absolute error in the result. (Since Y (x) oscillates about zero,
                                                0
          absolute error and not relative error is significant, except for
          very small x.)

          If (delta) is somewhat larger than the machine representation
          error (e.g. if (delta) is due to data errors etc), then E and
          (delta) are approximately related by

                                 E~=|xY (x)|(delta)
                                       1

          (provided E is also within machine bounds). Figure 1 displays the
          behaviour of the amplification factor |xY (x)|.
                                                   1


                                     Figure 1
                   Please see figure in printed Reference Manual

          However, if (delta) is of the same order as the machine
          representation errors, then rounding errors could make E slightly
          larger than the above relation predicts.

          For very small x, the errors are essentially independent of
          (delta) and the routine should provide relative accuracy bounded
          by the machine precision.

          For very large x, the above relation ceases to apply. In this
                                                                   

                            /   2     (   (pi))                   /   2
          region, Y (x)~=  /  -----sin(x- ----). The amplitude   /  -----
                   0     \/   (pi)x   (    4  )                /   (pi)x
          can be calculated with reasonable accuracy for all x, but
             (   (pi))               (pi)
          sin(x- ----) cannot. If x- ---- is written as 2N(pi)+(theta)
             (    4  )                4
                                                              (   (pi))
          where N is an integer and 0<=(theta)<2(pi), then sin(x- ----) is
                                                              (    4  )
                                                   -1
          determined by (theta) only. If x>~(delta)  , (theta) cannot be
          determined with any accuracy at all. Thus if x is greater than,
          or of the order of the inverse of machine precision, it is
          impossible to calculate the phase of Y (x) and the routine must
                                                0
          fail.

          8. Further Comments

          For details of the time taken by the routine see the Users' Note
          for your implementation.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs17adf}{nags.ht}
{ Returns the value of the Bessel Function $Y_1(x)$}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs17adf}{NAG Documentation: s17adf}
\beginscroll
\begin{verbatim}



     S17ADF(3NAG)      Foundation Library (12/10/92)      S17ADF(3NAG)



          S17 -- Approximations of Special Functions                 S17ADF
                  S17ADF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S17ADF returns the value of the Bessel Function Y (x), via the
                                                           1
          routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S17ADF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          This routine evaluates an approximation to the Bessel Function of
          the second kind Y (x).
                           1

          Note: Y (x) is undefined for x<=0 and the routine will fail for
                 1
          such arguments.

          The routine is based on four Chebyshev expansions:

          For 0<x<=8,

                        2      x --'           2     x --'
                Y (x)= ----lnx - >   a T (t)- ----x+ - >   b T (t) , with t
                 1     (pi)    8 --   r r     (pi)   8 --   r r
                                 r=0                   r=0
                           2
                       ( x)
                     =2( -) -1;
                       ( 8)


          For x>8,
                            

                           /   2  {        (    (pi))         (    (pi))}
                  Y (x)=  /  -----{P (x)sin(x-3 ----)+Q (x)cos(x-3 ----)}
                   1    \/   (pi)x{ 1      (     4  )  1      (     4  )}

                             --'
                where P (x)= >   c T (t),
                       1     --   r r
                             r=0
                                                      2
                           8 --'                  ( 8)
                and Q (x)= - >   d T (t), with t=2( -) -1.
                     1     x --   r r             ( x)
                             r=0

                                      2
          For x near zero, Y (x)~=- -----. This approximation is used when
                            1       (pi)x
          x is sufficiently small for the result to be correct to machine
          precision. For extremely small x, there is a danger of overflow
                             2
          in calculating - ----- and for such arguments the routine will
                           (pi)x
          fail.

          For very large x, it becomes impossible to provide results with
          any reasonable accuracy (see Section 7), hence the routine fails.
          Such arguments contain insufficient information to determine the
                                                                 

                                                                /   2
          phase of oscillation of Y (x), only the amplitude,   /  -----,
                                   1                         \/   (pi)x
          can be determined and this is returned on soft failure. The range
          for which this occurs is roughly related to machine precision;
          the routine will fail if x>~1/machine precision (see the Users'
          Note for your implementation for details).

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          [2]   Clenshaw C W (1962) Mathematical Tables. Chebyshev Series
                for Mathematical Functions. HMSO.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function. Constraint: X > 0.
               0.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               X is too large. On soft failure the routine returns the
                                                   

                                                  /   2
               amplitude of the Y  oscillation,  /  -----.
                                 1             \/   (pi)x

          IFAIL= 2
               X <= 0.0, Y  is undefined. On soft failure the routine
                          1
               returns zero.

          IFAIL= 3
               X is too close to zero, there is a danger of overflow. On
               soft failure, the routine returns the value of Y (x) at the
                                                               1
               smallest valid argument.

          7. Accuracy

          Let (delta) be the relative error in the argument and E be the
          absolute error in the result. (Since Y (x) oscillates about zero,
                                                1
          absolute error and not relative error is significant, except for
          very small x.)

          If (delta) is somewhat larger than the machine precision (e.g. if
          (delta) is due to data errors etc), then E and (delta) are
          approximately related by:

                              E~=|xY (x)-Y (x)|(delta)
                                    0     1

          (provided E is also within machine bounds). Figure 1 displays the
          behaviour of the amplification factor |xY (x)-Y (x)|.
                                                   0     1


                                     Figure 1
                   Please see figure in printed Reference Manual

          However, if (delta) is of the same order as machine precision,
          then rounding errors could make E slightly larger than the above
          relation predicts.

          For very small x, absolute error becomes large, but the relative
          error in the result is of the same order as (delta).

          For very large x, the above relation ceases to apply. In this
                          2(pi)   (   3(pi))                 2(pi)
          region, Y (x)~= -----sin(x- -----). The amplitude  ----- can be
                   1        x     (     4  )                   x
                                                                (   3(pi))
          calculated with reasonable accuracy for all x, but sin(x- -----)
                                                                (     4  )
                        3(pi)
          cannot. If x- ----- is written as 2N(pi)+(theta) where N is an
                          4
                                                (   3(pi))
          integer and 0<=(theta)<2(pi), then sin(x- -----) is determined by
                                                (     4  )
                                    -1
          (theta) only. If x>(delta)  , (theta) cannot be determined with
          any accuracy at all. Thus if x is greater than, or of the order
          of, the inverse of the machine precision, it is impossible to
          calculate the phase of Y (x) and the routine must fail.
                                  1

          8. Further Comments

          For details of the time taken by the routine see the Users' Note
          for your implementation.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs17aef}{nags.ht}
{ Returns the value of the Bessel Function $J_0(x)$}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs17aef}{NAG Documentation: s17aef}
\beginscroll
\begin{verbatim}



     S17AEF(3NAG)      Foundation Library (12/10/92)      S17AEF(3NAG)



          S17 -- Approximations of Special Functions                 S17AEF
                  S17AEF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S17AEF returns the value of the Bessel Function J (x), via the
                                                           0
          routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S17AEF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          This routine evaluates an approximation to the Bessel Function of
          the first kind J (x).
                          0

          Note: J (-x)=J (x), so the approximation need only consider x>=0.
                 0      0

          The routine is based on three Chebyshev expansions:

          For 0<x<=8,                           2
                       --'                  ( x)
                J (x)= >   a T (t), with t=2( -) -1.
                 0     --   r r             ( 8)
                       r=0

          For x>8,
                          

                         /   2  {        (   (pi))         (   (pi))}
                J (x)=  /  -----{P (x)cos(x- ----)-Q (x)sin(x- ----)}
                 0    \/   (pi)x{ 0      (    4  )  0      (    4  )}

                               --'
                where P (x) =  >   b T (t),
                       0       --   r r
                               r=0
                                                        2
                             8 --'                  ( 8)
                and Q (x) =  - >   c T (t), with t=2( -) -1.
                     0       x --   r r             ( x)
                               r=0

          For x near zero, J (x)~=1. This approximation is used when x is
                            0
          sufficiently small for the result to be correct to machine
          precision.

          For very large x, it becomes impossible to provide results with
          any reasonable accuracy (see Section 7), hence the routine fails.
          Such arguments contain insufficient information to determine the
                                                                 

                                                                /    2
          phase of oscillation of J (x); only the amplitude,   /  -------,
                                   0                         \/   (pi)|x|
          can be determined and this is returned on soft failure. The range
          for which this occurs is roughly related to the machine
          precision; the routine will fail if |x|>~1/machine precision (see
          the Users' Note for your implementation).

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          [2]   Clenshaw C W (1962) Mathematical Tables. Chebyshev Series
                for Mathematical Functions. HMSO.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               X is too large. On soft failure the routine returns the
                                                     

                                                    /    2
               amplitude of the J  oscillation,    /  -------.
                                 0               \/   (pi)|x|

          7. Accuracy

          Let (delta) be the relative error in the argument and E be the
          absolute error in the result. (Since J (x) oscillates about zero,
                                                0
          absolute error and not relative error is significant.)

          If (delta) is somewhat larger than the machine precision (e.g. if
          (delta) is due to data errors etc), then E and (delta) are
          approximately related by:

                                 E~=|xJ (x)|(delta)
                                       1

          (provided E is also within machine bounds). Figure 1 displays the
          behaviour of the amplification factor |xJ (x)|.
                                                   1


                                     Figure 1
                   Please see figure in printed Reference Manual

          However, if (delta) is of the same order as machine precision,
          then rounding errors could make E slightly larger than the above
          relation predicts.

          For very large x, the above relation ceases to apply. In this
                             

                            /    2      (   (pi))
          region, J (x)~=  /  -------cos(x- ----). The amplitude
                   0     \/   (pi)|x|   (    4  )
              

             /    2
            /  ------- can be calculated with reasonable accuracy for all x
          \/   (pi)|x|
                 (   (pi))               (pi)
          but cos(x- ----) cannot. If x- ---- is written as
                 (    4  )                4
          2N(pi)+(theta) where N is an integer and 0 <= (theta) < 2(pi),
                  (   (pi))                                             -1
          then cos(x- ----) is determined by (theta) only. If x>~(delta)  ,
                  (    4  )
          (theta) cannot be determined with any accuracy at all. Thus if x
          is greater than, or of the order of, the inverse of the machine
          precision, it is impossible to calculate the phase of J (x) and
                                                                 0
          the routine must fail.

          8. Further Comments

          For details of the time taken by the routine see the Users' Note
          for your implementation.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs17aff}{nags.ht}
{ Returns the value of the Bessel Function $J_1(x)$}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs17aff}{NAG Documentation: s17aff}
\beginscroll
\begin{verbatim}



     S17AFF(3NAG)      Foundation Library (12/10/92)      S17AFF(3NAG)



          S17 -- Approximations of Special Functions                 S17AFF
                  S17AFF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S17AFF returns the value of the Bessel Function J (x), via the
                                                           1
          routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S17AFF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          This routine evaluates an approximation to the Bessel Function of
          the first kind J (x).
                          1

          Note: J (-x)=-J (x), so the approximation need only consider x>=0
                 1       1

          The routine is based on three Chebyshev expansions:

          For 0<x<=8,                              2
                       x --'                   ( x)
                J (x)= - >   a T (t) , with t=2( -) -1.
                 1     8 --   r r              ( 8)
                         r=0

          For x>8,
                          

                         /  2   {        (   3(pi))         (   3(pi))}
                J (x)=  /  ----x{P (x)cos(x- -----)-Q (x)sin(x- -----)}
                 1    \/   (pi) { 1      (     4  )  1      (     4  )}

                            --'
                whereP (x)= >   b T (t),
                      1     --   r r
                            r=0
                                                      2
                           8 --'                  ( 8)
                and Q (x)= - >   c T (t), with t=2( -) -1.
                     1     x --   r r             ( x)
                             r=0
                                   x
          For x near zero, J (x)~= -. This approximation is used when x is
                            1      2
          sufficiently small for the result to be correct to machine
          precision.

          For very large x, it becomes impossible to provide results with
          any reasonable accuracy (see Section 7), hence the routine fails.
          Such arguments contain insufficient information to determine the
                                                                 

                                                                /    2
          phase of oscillation of J (x); only the amplitude,   /  -------,
                                   1                         \/   (pi)|x|
          can be determined and this is returned on soft failure. The range
          for which this occurs is roughly related to the machine
          precision; the routine will fail if |x|>~1/machine precision (see
          the Users' Note for your implementation for details).

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          [2]   Clenshaw C W (1962) Mathematical Tables. Chebyshev Series
                for Mathematical Functions. HMSO.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               X is too large. On soft failure the routine returns the
                                                     

                                                    /    2
               amplitude of the J  oscillation,    /  -------.
                                 1               \/   (pi)|x|

          7. Accuracy


          Let (delta) be the relative error in the argument and E be the
          absolute error in the result. (Since J (x) oscillates about zero,
                                                1
          absolute error and not relative error is significant.)

          If (delta) is somewhat larger than machine precision (e.g. if
          (delta) is due to data errors etc), then E and (delta) are
          approximately related by:

                              E~=|xJ (x)-J (x)|(delta)
                                    0     1

          (provided E is also within machine bounds). Figure 1 displays the
          behaviour of the amplification factor |xJ (x)-J (x)|.
                                                   0     1


                                     Figure 1
                   Please see figure in printed Reference Manual

          However, if (delta) is of the same order as machine precision,
          then rounding errors could make E slightly larger than the above
          relation predicts.

          For very large x, the above relation ceases to apply. In this
                             

                            /    2      (   3(pi))
          region, J (x)~=  /  -------cos(x- -----). The amplitude
                   1     \/   (pi)|x|   (     4  )
              

             /    2
            /  ------- can be calculated with reasonable accuracy for all x
          \/   (pi)|x|
                 (   3(pi))               3(pi)
          but cos(x- -----) cannot. If x- ----- is written as
                 (     4  )                 4
          2N(pi)+(theta) where N is an integer and 0<=(theta)<2(pi), then
             (   3(pi))                                             -1
          cos(x- -----) is determined by (theta) only. If x>~(delta)  ,
             (     4  )
          (theta) cannot be determined with any accuracy at all. Thus if x
          is greater than, or of the order of, machine precision, it is
          impossible to calculate the phase of J (x) and the routine must
                                                1
          fail.

          8. Further Comments

          For details of the time taken by the routine see the Users' Note
          for your implementation.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs17agf}{nags.ht}
{ Returns a value for the Airy function, $Ai(x)$}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs17agf}{NAG Documentation: s17agf}
\beginscroll
\begin{verbatim}



     S17AGF(3NAG)      Foundation Library (12/10/92)      S17AGF(3NAG)



          S17 -- Approximations of Special Functions                 S17AGF
                  S17AGF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S17AGF returns a value for the Airy function, Ai(x), via the
          routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S17AGF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          This routine evaluates an approximation to the Airy function,
          Ai(x). It is based on a number of Chebyshev expansions:

          For x<-5,

                                     a(t)sinz-b(t)cosz
                              Ai(x)= -----------------
                                              1/4
                                          (-x)

                             

                   (pi)  2  /  3
          where z= ----+ -\/ -x , and a(t) and b(t) are expansions in the
                    4    3
                           3
                       ( 5)
          variable t=-2( -) -1.
                       ( x)

          For -5<=x<=0,

                                  Ai(x)=f(t)-xg(t),
                                                  3
                                              ( x)
          where f and g are expansions in t=-2( -) -1.
                                              ( 5)

          For 0<x<4.5,

                                         -3x/2
                                  Ai(x)=e     y(t),

          where y is an expansion in t=4x/9-1.

          For 4.5<=x<9,

                                         -5x/2
                                  Ai(x)=e     u(t),

          where u is an expansion in t=4x/9-3.

          For x>=9,

                                           -z
                                          e  v(t)
                                   Ai(x)= -------,
                                            1/4
                                           x

                       

                   2  / 3                             ( 18)
          where z= -\/ x  and v is an expansion in t=2( --)-1.
                   3                                  ( z )

          For |x|< the machine precision, the result is set directly to
          Ai(0). This both saves time and guards against underflow in
          intermediate calculations.

          For large negative arguments, it becomes impossible to calculate
          the phase of the oscillatory function with any precision and so
                                                                2/3
                                                   (     3     )
          the routine must fail. This occurs if x<-( ----------)   , where
                                                   ( 2(epsilon))
          (epsilon) is the machine precision.

          For large positive arguments, where Ai decays in an essentially
          exponential manner, there is a danger of underflow so the routine
          must fail.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.
               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               X is too large and positive. On soft failure, the routine
               returns zero.

          IFAIL= 2
               X is too large and negative. On soft failure, the routine
               returns zero.

          7. Accuracy

          For negative arguments the function is oscillatory and hence
          absolute error is the appropriate measure. In the positive region
          the function is essentially exponential-like and here relative
          error is appropriate. The absolute error, E, and the relative
          error, (epsilon), are related in principle to the relative error
          in the argument, (delta), by

                                                 | xAi'(x)|
                 E~=|xAi'(x)|(delta), (epsilon)~=| -------|(delta).
                                                 |  Ai(x) |

          In practice, approximate equality is the best that can be
          expected. When (delta), (epsilon) or E is of the order of the
          machine precision, the errors in the result will be somewhat
          larger.

          For small x, errors are strongly damped by the function and hence
          will be bounded by the machine precision.

          For moderate negative x, the error behaviour is oscillatory but
          the amplitude of the error grows like

                                                     5/4
                                      (    E   )  |x|
                            amplitude ( -------)~ ------.
                                      ( (delta))    
                                                  \/(pi)

                                                                    

                                                                2  /   3
          However the phase error will be growing roughly like  -\/ |x|
                                                                3
          and hence all accuracy will be lost for large negative arguments
          due to the impossibility of calculating sin and cos to any
                           

                       2  /   3     1
          accuracy if  -\/ |x| > -------.
                       3         (delta)

          For large positive arguments, the relative error amplification is
          considerable:

                                                

                                   (epsilon)   / 3
                                   ---------~\/ x .
                                    (delta)

          This means a loss of roughly two decimal places accuracy for
          arguments in the region of 20. However very large arguments are
          not possible due to the danger of setting underflow and so the
          errors are limited in practice.

          8. Further Comments

          None.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs17ahf}{nags.ht}
{ Returns a value of the Airy function, $Bi(x)$}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs17ahf}{NAG Documentation: s17ahf}
\beginscroll
\begin{verbatim}



     S17AHF(3NAG)      Foundation Library (12/10/92)      S17AHF(3NAG)



          S17 -- Approximations of Special Functions                 S17AHF
                  S17AHF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S17AHF returns a value of the Airy function, Bi(x), via the
          routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S17AHF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          This routine evaluates an approximation to the Airy function
          Bi(x). It is based on a number of Chebyshev expansions.

          For x<-5,

                                     a(t)cosz+b(t)sinz
                              Bi(x)= -----------------,
                                              1/4
                                          (-x)

                             

                   (pi)  2  /  3
          where z= ----+ -\/ -x  and a(t) and b(t) are expansions in the
                    4    3
                           3
                       ( 5)
          variable t=-2( -) -1.
                       ( x)

          For -5<=x<=0,

                                       

                               Bi(x)=\/3(f(t)+xg(t)),
                                                  3
                                              ( x)
          where f and g are expansions in t=-2( -) -1.
                                              ( 5)

          For 0<x<4.5,

                                         11x/8
                                  Bi(x)=e     y(t),

          where y is an expansion in t=4x/9-1.

          For 4.5<=x<=9,

                                         5x/2
                                  Bi(x)=e    v(t),

          where v is an expansion in t=4x/9-3.

          For x>=9,

                                           z
                                          e u(t)
                                   Bi(x)= ------,
                                            1/4
                                           x

                       

                   2  / 3                             ( 18)
          where z= -\/ x  and u is an expansion in t=2( --)-1.
                   3                                  ( z )

          For |x|< the machine precision, the result is set directly to
          Bi(0). This both saves time and avoids possible intermediate
          underflows.

          For large negative arguments, it becomes impossible to calculate
          the phase of the oscillating function with any accuracy so the
                                                            2/3
                                               (     3     )
          routine must fail. This occurs if x<-( ----------)   , where
                                               ( 2(epsilon))
          (epsilon) is the machine precision.

          For large positive arguments, there is a danger of causing
          overflow since Bi grows in an essentially exponential manner, so
          the routine must fail.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               X is too large and positive. On soft failure, the routine
               returns zero.

          IFAIL= 2
               X is too large and negative. On soft failure, the routine
               returns zero.

          7. Accuracy

          For negative arguments the function is oscillatory and hence
          absolute error is the appropriate measure. In the positive region
          the function is essentially exponential-like and here relative
          error is appropriate. The absolute error, E, and the relative
          error, (epsilon), are related in principle to the relative error
          in the argument, (delta), by

                                                 | xBi'(x)|
                 E~=|xBi'(x)|(delta), (epsilon)~=| -------|(delta).
                                                 |  Bi(x) |

          In practice, approximate equality is the best that can be
          expected. When (delta), (epsilon) or E is of the order of the
          machine precision, the errors in the result will be somewhat
          larger.

          For small x, errors are strongly damped and hence will be bounded
          essentially by the machine precision.

          For moderate to large negative x, the error behaviour is clearly
          oscillatory but the amplitude of the error grows like amplitude
                         5/4
          (    E   )  |x|
          ( -------)~ ------.
          ( (delta))    
                      \/(pi)

                                                                  

                                                              2  /   3
          However the phase error will be growing roughly as  -\/ |x|  and
                                                              3
          hence all accuracy will be lost for large negative arguments.

          This is due to the impossibility of calculating sin and cos to
                               

                           2  /   3     1
          any accuracy if  -\/ |x| > -------.
                           3         (delta)

          For large positive arguments, the relative error amplification is
          considerable:

                                                

                                   (epsilon)   / 3
                                   ---------~\/ x .
                                    (delta)

          This means a loss of roughly two decimal places accuracy for
          arguments in the region of 20. However very large arguments are
          not possible due to the danger of causing overflow and errors are
          therefore limited in practice.

          8. Further Comments

          For details of the time taken by the routine see the Users' Note
          for your implementation.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs17ajf}{nags.ht}
{ Value of the derivative of the Airy function $Ai(x)$}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs17ajf}{NAG Documentation: s17ajf}
\beginscroll
\begin{verbatim}



     S17AJF(3NAG)      Foundation Library (12/10/92)      S17AJF(3NAG)



          S17 -- Approximations of Special Functions                 S17AJF
                  S17AJF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S17AJF returns a value of the derivative of the Airy function
          Ai(x), via the routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S17AJF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          This routine evaluates an approximation to the derivative of the
          Airy function Ai(x). It is based on a number of Chebyshev
          expansions.

          For x<-5,

                                4   [           b(t)     ]
                         Ai'(x)=\/-x[a(t)cosz+ ------sinz],
                                    [          (zeta)    ]

                                            

                   (pi)                 2  /  3
          where z= ----+(zeta), (zeta)= -\/ -x  and a(t) and b(t) are
                    4                   3
                                         3
                                     ( 5)
          expansions in variable t=-2( -) -1.
                                     ( x)

          For -5<=x<=0,

                                         2
                                 Ai'(x)=x f(t)-g(t),
                                                  3
                                              ( x)
          where f and g are expansions in t=-2( -) -1.
                                              ( 5)

          For 0<x<4.5,

                                         -11x/8
                                 Ai'(x)=e      y(t),

                                           ( x)
          where y(t) is an expansion in t=4( -)-1.
                                           ( 9)

          For 4.5<=x<9,

                                         -5x/2
                                 Ai'(x)=e     v(t),

                                           ( x)
          where v(t) is an expansion in t=4( -)-3.
                                           ( 9)

          For x>=9,

                                        4    -z
                                 Ai'(x)=\/-xe  u(t),


                   2  / 3                                ( 18)
          where z= -\/ x  and u(t) is an expansion in t=2( --)-1.
                   3                                     ( z )

          For |x|< the square of the machine precision, the result is set
          directly to Ai'(0). This both saves time and avoids possible
          intermediate underflows.

          For large negative arguments, it becomes impossible to calculate
          a result for the oscillating function with any accuracy and so
                                                                4/7
                                                    (          )
                                                    (  \/(pi)  )
          the routine must fail. This occurs for x<-( ---------)   , where
                                                    ( (epsilon))
          (epsilon) is the machine precision.

          For large positive arguments, where Ai' decays in an essentially
          exponential manner, there is a danger of underflow so the routine
          must fail.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               X is too large and positive. On soft failure, the routine
               returns zero.

          IFAIL= 2
               X is too large and negative. On soft failure, the routine
               returns zero.

          7. Accuracy

          For negative arguments the function is oscillatory and hence
          absolute error is the appropriate measure. In the positive region
          the function is essentially exponential in character and here
          relative error is needed. The absolute error, E, and the relative
          error, (epsilon), are related in principle to the relative error
          in the argument, (delta), by

                                                  |  2     |
                     2                            | x Ai(x)|
                E~=|x Ai(x)|(delta)    (epsilon)~=| -------|(delta).
                                                  | Ai'(x) |

          In practice, approximate equality is the best that can be
          expected. When (delta), (epsilon) or E is of the order of the
          machine precision, the errors in the result will be somewhat
          larger.

          For small x, positive or negative, errors are strongly attenuated
          by the function and hence will be roughly bounded by the machine
          precision.

          For moderate to large negative x, the error, like the function,
          is oscillatory; however the amplitude of the error grows like

                                          7/4
                                       |x|
                                       ------.

                                       \/(pi)


          Therefore it becomes impossible to calculate the function with
                                    

                             7/4  \/(pi)
          any accuracy if |x|   > -------.
                                  (delta)

          For large positive x, the relative error amplification is
          considerable:

                                                

                                  (epsilon)    / 3
                                  ---------~=\/ x .
                                   (delta)

          However, very large arguments are not possible due to the danger
          of underflow. Thus in practice error amplification is limited.

          8. Further Comments

          None.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs17akf}{nags.ht}
{ Value for the derivative of the Airy function $Bi(x)$}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs17akf}{NAG Documentation: s17akf}
\beginscroll
\begin{verbatim}



     S17AKF(3NAG)      Foundation Library (12/10/92)      S17AKF(3NAG)



          S17 -- Approximations of Special Functions                 S17AKF
                  S17AKF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S17AKF returns a value for the derivative of the Airy function
          Bi(x), via the routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S17AKF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          This routine calculates an approximate value for the derivative
          of the Airy function Bi(x). It is based on a number of Chebyshev
          expansions.

          For x<-5,

                                4   [            b(t)     ]
                         Bi'(x)=\/-x[-a(t)sinz+ ------cosz],
                                    [           (zeta)    ]

                                           

                   (pi)                2  /  3
          where z= ----+(zeta),(zeta)= -\/ -x  and a(t) and b(t) are
                    4                  3
                                             3
                                         ( 5)
          expansions in the variable t=-2( -) -1.
                                         ( x)

          For -5<=x<=0,

                                          2
                              Bi'(x)=\/3(x f(t)+g(t)),
                                                  3
                                              ( x)
          where f and g are expansions in t=-2( -) -1.
                                              ( 5)

          For 0<x<4.5,

                                          3x/2
                                  Bi'(x)=e    y(t),

          where y(t) is an expansion in t=4x/9-1.

          For 4.5<=x<9,

                                         21x/8
                                 Bi'(x)=e     u(t),

          where u(t) is an expansion in t=4x/9-3.

          For x>=9,

                                         4   z
                                  Bi'(x)=\/xe v(t),

                       

                   2  / 3                                ( 18)
          where z= -\/ x  and v(t) is an expansion in t=2( --)-1.
                   3                                     ( z )

          For |x|< the square of the machine precision, the result is set
          directly to Bi'(0). This saves time and avoids possible
          underflows in calculation.

          For large negative arguments, it becomes impossible to calculate
          a result for the oscillating function with any accuracy so the
                                                            4/7
                                                (          )
                                                (  \/(pi)  )
          routine must fail. This occurs for x<-( ---------)   , where
                                                ( (epsilon))
          (epsilon) is the machine precision.

          For large positive arguments, where Bi' grows in an essentially
          exponential manner, there is a danger of overflow so the routine
          must fail.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.
               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               X is too large and positive. On soft failure the routine
               returns zero.

          IFAIL= 2
               X is too large and negative. On soft failure the routine
               returns zero.

          7. Accuracy

          For negative arguments the function is oscillatory and hence
          absolute error is appropriate. In the positive region the
          function has essentially exponential behaviour and hence relative
          error is needed. The absolute error, E, and the relative error
          (epsilon), are related in principle to the relative error in the
          argument (delta), by

                                                  |  2     |
                     2                            | x Bi(x)|
                E~=|x Bi(x)|(delta)    (epsilon)~=| -------|(delta).
                                                  | Bi'(x) |

          In practice, approximate equality is the best that can be
          expected. When (delta), (epsilon) or E is of the order of the
          machine precision, the errors in the result will be somewhat
          larger.

          For small x, positive or negative, errors are strongly attenuated
          by the function and hence will effectively be bounded by the
          machine precision.

          For moderate to large negative x, the error is, like the
          function, oscillatory. However, the amplitude of the absolute
                               7/4
                            |x|
          error grows like  ------. Therefore it becomes impossible to
                              

                            \/(pi)
                                                                

                                                         7/4  \/(pi)
          calculate the function with any accuracy if |x|   > -------.
                                                              (delta)

          For large positive x, the relative error amplification is
                                      

                         (epsilon)   / 3
          considerable:  ---------~\/ x . However, very large arguments are
                          (delta)
          not possible due to the danger of overflow. Thus in practice the
          actual amplification that occurs is limited.

          8. Further Comments

          None.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs17dcf}{nags.ht}
{ Values for the Bessel functions $Y_{\nu+n}(z)$}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs17dcf}{NAG Documentation: s17dcf}
\beginscroll
\begin{verbatim}



     S17DCF(3NAG)      Foundation Library (12/10/92)      S17DCF(3NAG)



          S17 -- Approximations of Special Functions                 S17DCF
                  S17DCF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S17DCF returns a sequence of values for the Bessel functions
          Y      (z) for complex z, non-negative (nu) and n=0,1,...,N-1,
           (nu)+n
          with an option for exponential scaling.

          2. Specification

                 SUBROUTINE S17DCF (FNU, Z, N, SCALE, CY, NZ, CWRK, IFAIL)
                 INTEGER              N, NZ, IFAIL
                 DOUBLE PRECISION     FNU
                 COMPLEX(KIND(1.0D0)) Z, CY(N), CWRK(N)
                 CHARACTER*1          SCALE

          3. Description

          This subroutine evaluates a sequence of values for the Bessel
          function Y    (z), where z is complex, -(pi) < arg z <= (pi), and
                    (nu)
          (nu) is the real, non-negative order. The N-member sequence is
          generated for orders (nu), (nu)+1,...,(nu)+N-1. Optionally, the
                                            -|Im z|
          sequence is scaled by the factor e       .

          Note: although the routine may not be called with (nu) less than
          zero, for negative orders the formula
          Y     (z)=Y    (z)cos((pi)(nu))+J    (z)sin((pi)(nu)) may be used
           -(nu)     (nu)                  (nu)
          (for the Bessel function J    (z), see S17DEF).
                                    (nu)

          The routine is derived from the routine CBESY in Amos [2]. It is
                                           (1)      (2)
                                          H    (z)-H    (z)
                                           (nu)     (nu)            (1)
          based on the relation Y    (z)= -----------------, where H    (z)
                                 (nu)            2i                 (nu)
               (2)
          and H    (z) are the Hankel functions of the first and second
               (nu)
          kinds respectively (see S17DLF).

          When N is greater than 1, extra values of Y    (z) are computed
                                                     (nu)
          using recurrence relations.

          For very large |z| or ((nu)+N-1), argument reduction will cause
          total loss of accuracy, and so no computation is performed. For
          slightly smaller |z| or ((nu)+N-1), the computation is performed
          but results are accurate to less than half of machine precision.
          If |z| is very small, near the machine underflow threshold, or
          ((nu)+N-1) is too large, there is a risk of overflow and so no
          computation is performed. In all the above cases, a warning is
          given by the routine.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          [2]   Amos D E (1986) Algorithm 644: A Portable Package for Bessel
                Functions of a Complex Argument and Nonnegative Order. ACM
                Trans. Math. Softw. 12 265--273.

          5. Parameters

           1:  FNU -- DOUBLE PRECISION                                Input
               On entry: the order, (nu), of the first member of the
               sequence of functions. Constraint: FNU >= 0.0.

           2:  Z -- COMPLEX(KIND(1.0D0))                              Input
               On entry: the argument, z, of the functions. Constraint: Z
               /= (0.0, 0.0).

           3:  N -- INTEGER                                           Input
               On entry: the number, N, of members required in the sequence
               Y    (z), Y      (z),...,Y        (z). Constraint: N >= 1.
                (nu)      (nu)+1         (nu)+N-1

           4:  SCALE -- CHARACTER*1                                   Input
               On entry: the scaling option.

               If SCALE = 'U', the results are returned unscaled.

               If SCALE = 'S', the results are returned scaled by the
                       -|Imz|
               factor e      . Constraint: SCALE = 'U' or 'S'.

           5:  CY(N) -- COMPLEX(KIND(1.0D)) array                    Output
               On exit: the N required function values: CY(i) contains
               Y        (z), for i=1,2,...,N.
                (nu)+i-1

           6:  NZ -- INTEGER                                         Output
               On exit: the number of components of CY that are set to zero
               due to underflow. The positions of such components in the
               array CY are arbitrary.

           7:  CWRK(N) -- COMPLEX(KIND(1.0D)) array               Workspace

           8:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry FNU < 0.0,

               or       Z = (0.0, 0.0),

               or       N < 1,

               or       SCALE /= 'U' or 'S'.

          IFAIL= 2
               No computation has been performed due to the likelihood of
               overflow, because ABS(Z) is less than a machine-dependent
               threshold value (given in the Users' Note for your
               implementation).

          IFAIL= 3
               No computation has been performed due to the likelihood of
               overflow, because FNU + N - 1 is too large - how large
               depends on Z as well as the overflow threshold of the
               machine.

          IFAIL= 4
               The computation has been performed, but the errors due to
               argument reduction in elementary functions make it likely
               that the results returned by S17DCF are accurate to less
               than half of machine precision. This error exit may occur if
               either ABS(Z) or FNU + N - 1 is greater than a machine-
               dependent threshold value (given in the Users' Note for
               your implementation).

          IFAIL= 5
               No computation has been performed because the errors due to
               argument reduction in elementary functions mean that all
               precision in results returned by S17DCF would be lost. This
               error exit may occur if either ABS(Z) or FNU + N - 1 is
               greater than a machine-dependent threshold value (given in
               the Users' Note for your implementation).

          IFAIL= 6
               No results are returned because the algorithm termination
               condition has not been met. This may occur because the
               parameters supplied to S17DCF would have caused overflow or
               underflow.

          7. Accuracy

          All constants in subroutine S17DCF are given to approximately 18
          digits of precision. Calling the number of digits of precision in
          the floating-point arithmetic being used t, then clearly the
          maximum number of correct digits in the results obtained is
          limited by p=min(t,18). Because of errors in argument reduction
          when computing elementary functions inside S17DCF, the actual
          number of correct digits is limited, in general, by p-s, where
          s~max(1,|log  |z||,|log  (nu)|) represents the number of digits
                      10         10
          lost due to the argument reduction. Thus the larger the values of
          |z| and (nu), the less the precision in the result. If S17DCF is
          called with N>1, then computation of function values via
          recurrence may lead to some further small loss of accuracy.

          If function values which should nominally be identical are
          computed by calls to S17DCF with different base values of (nu)
          and different N, the computed values may not agree exactly.
          Empirical tests with modest values of (nu) and z have shown that
          the discrepancy is limited to the least significant 3-4 digits of
          precision.

          8. Further Comments

          The time taken by the routine for a call of S17DCF is
          approximately proportional to the value of N, plus a constant. In
          general it is much cheaper to call S17DCF with N greater than 1,
          rather than to make N separate calls to S17DCF.

          Paradoxically, for some values of z and (nu), it is cheaper to
          call S17DCF with a larger value of N than is required, and then
          discard the extra function values returned. However, it is not
          possible to state the precise circumstances in which this is
          likely to occur. It is due to the fact that the base value used
          to start recurrence may be calculated in different regions for
          different N, and the costs in each region may differ greatly.

          Note that if the function required is Y (x) or Y (x), i.e., (nu)
                                                 0        1
          = 0.0 or 1.0, where x is real and positive, and only a single
          unscaled function value is required, then it may be much cheaper
          to call S17ACF or S17ADF respectively.

          9. Example

          The example program prints a caption and then proceeds to read
          sets of data from the input data stream. The first datum is a
          value for the order FNU, the second is a complex value for the
          argument, Z, and the third is a value for the parameter SCALE.
          The program calls the routine with N = 2 to evaluate the function
          for orders FNU and FNU + 1, and it prints the results. The
          process is repeated until the end of the input data stream is
          encountered.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs17def}{nags.ht}
{ Values for the Bessel functions $J_{\nu+n}(z)$}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs17def}{NAG Documentation: s17def}
\beginscroll
\begin{verbatim}



     S17DEF(3NAG)      Foundation Library (12/10/92)      S17DEF(3NAG)



          S17 -- Approximations of Special Functions                 S17DEF
                  S17DEF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S17DEF returns a sequence of values for the Bessel functions
          J      (z) for complex z, non-negative (nu) and n=0,1,...,N-1,
           (nu)+n
          with an option for exponential scaling.

          2. Specification

                 SUBROUTINE S17DEF (FNU, Z, N, SCALE, CY, NZ, IFAIL)
                 INTEGER              N, NZ, IFAIL
                 DOUBLE PRECISION     FNU
                 COMPLEX(KIND(1.0D0)) Z, CY(N)
                 CHARACTER*1          SCALE

          3. Description

          This subroutine evaluates a sequence of values for the Bessel
          function J    (z), where z is complex, -(pi) < arg z <= (pi), and
                    (nu)
          (nu) is the real, non-negative order. The N-member sequence is
          generated for orders (nu), (nu)+1,...,(nu)+N-1. Optionally, the
                                            -|Im z|
          sequence is scaled by the factor e       .

          Note: although the routine may not be called with (nu) less than
          zero, for negative orders the formula
          J     (z)=J    (z)cos((pi)(nu))-Y    (z)sin((pi)(nu)) may be used
           -(nu)     (nu)                  (nu)
          (for the Bessel function Y    (z), see S17DCF).
                                    (nu)

          The routine is derived from the routine CBESJ in Amos [2]. It is
                                           (nu)(pi)i/2
          based on the relations J    (z)=e           I    (-iz), Im z>=0.0
                                  (nu)                 (nu)
                        -(nu)(pi)i/2
          and J    (z)=e            I    (iz), Im z<0.0.
               (nu)                  (nu)

          The Bessel function I    (z) is computed using a variety of
                               (nu)
          techniques depending on the region under consideration.

          When N is greater than 1, extra values of J    (z) are computed
                                                     (nu)
          using recurrence relations.

          For very large |z| or ((nu)+N-1), argument reduction will cause
          total loss of accuracy, and so no computation is performed. For
          slightly smaller |z| or ((nu)+N-1), the computation is performed
          but results are accurate to less than half of machine precision.
          If Im z is large, there is a risk of overflow and so no
          computation is performed. In all the above cases, a warning is
          given by the routine.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          [2]   Amos D E (1986) Algorithm 644: A Portable Package for Bessel
                Functions of a Complex Argument and Nonnegative Order. ACM
                Trans. Math. Softw. 12 265--273.

          5. Parameters

           1:  FNU -- DOUBLE PRECISION                                Input
               On entry: the order, (nu), of the first member of the
               sequence of functions. Constraint: FNU >= 0.0.

           2:  Z -- COMPLEX(KIND(1.0D0))                              Input
               On entry: the argument z of the functions.

           3:  N -- INTEGER                                           Input
               On entry: the number, N, of members required in the sequence
               J    (z),J      (z),...,J        (z). Constraint: N >= 1.
                (nu)     (nu)+1         (nu)+N-1

           4:  SCALE -- CHARACTER*1                                   Input
               On entry: the scaling option.
                    If SCALE = 'U', the results are returned unscaled.

                    If SCALE = 'S', the results are returned scaled by the
                            -|Imz|
                    factor e      .
               Constraint: SCALE = 'U' or 'S'.

           5:  CY(N) -- COMPLEX(KIND(1.0D)) array                    Output
               On exit: the N required function values: CY(i) contains
               J        (z), for i=1,2,...,N.
                (nu)+i-1

           6:  NZ -- INTEGER                                         Output
               On exit: the number of components of CY that are set to zero
               due to underflow. If NZ > 0, then elements CY(N-NZ+1), CY(N-
               NZ+2),...,CY(N) are set to zero.

           7:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry FNU < 0.0,

               or       N < 1,

               or       SCALE /= 'U' or 'S'.

          IFAIL= 2
               No computation has been performed due to the likelihood of
               overflow, because Im Z is larger than a machine-dependent
               threshold value (given in the Users' Note for your
               implementation). This error exit can only occur when SCALE =
               'U'.

          IFAIL= 3
               The computation has been performed, but the errors due to
               argument reduction in elementary functions make it likely
               that the results returned by S17DEF are accurate to less
               than half of machine precision. This error exit may occur if
               either ABS(Z) or FNU + N - 1 is greater than a machine-
               dependent threshold value (given in the Users' Note for
               your implementation).

          IFAIL= 4
               No computation has been performed because the errors due to
               argument reduction in elementary functions mean that all
               precision in results returned by S17DEF would be lost. This
               error exit may occur when either ABS(Z) or FNU + N - 1 is
               greater than a machine-dependent threshold value (given in
               the Users' Note for your implementation).

          IFAIL= 5
               No results are returned because the algorithm termination
               condition has not been met. This may occur because the
               parameters supplied to S17DEF would have caused overflow or
               underflow.

          7. Accuracy

          All constants in subroutine S17DEF are given to approximately 18
          digits of precision. Calling the number of digits of precision in
          the floating-point arithmetic being used t, then clearly the
          maximum number of correct digits in the results obtained is
          limited by p=min(t,18). Because of errors in argument reduction
          when computing elementary functions inside S17DEF, the actual
          number of correct digits is limited, in general, by p-s, where
          s~max(1,|log  |(|z|),|log  (nu)|) represents the number of digits
                      10           10
          lost due to the argument reduction. Thus the larger the values of
          |z| and (nu), the less the precision in the result. If S17DEF is
          called with N>1, then computation of function values via
          recurrence may lead to some further small loss of accuracy.

          If function values which should nominally be identical are
          computed by calls to S17DEF with different base values of (nu)
          and different N, the computed values may not agree exactly.
          Empirical tests with modest values of (nu) and z have shown that
          the discrepancy is limited to the least significant 3-4 digits of
          precision.

          8. Further Comments

          The time taken by the routine for a call of S17DEF is
          approximately proportional to the value of N, plus a constant. In
          general it is much cheaper to call S17DEF with N greater than 1,
          rather than to make N separate calls to S17DEF.

          Paradoxically, for some values of z and (nu), it is cheaper to
          call S17DEF with a larger value of N than is required, and then
          discard the extra function values returned. However, it is not
          possible to state the precise circumstances in which this is
          likely to occur. It is due to the fact that the base value used
          to start recurrence may be calculated in different regions for
          different N, and the costs in each region may differ greatly.

          Note that if the function required is J (x) or J (x), i.e., (nu)
                                                 0        1
          = 0.0 or 1.0, where x is real and positive, and only a single
          unscaled function value is required, then it may be much cheaper
          to call S17AEF or S17AFF respectively.

          9. Example

          The example program prints a caption and then proceeds to read
          sets of data from the input data stream. The first datum is a
          value for the order FNU, the second is a complex value for the
          argument, Z, and the third is a value for the parameter SCALE.

          The program calls the routine with N = 2 to evaluate the function
          for orders FNU and FNU + 1, and it prints the results. The
          process is repeated until the end of the input data stream is
          encountered.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs17dgf}{nags.ht}
{ Value of the Airy function $Ai(z)$ or derivative $Ai'(z)$}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs17dgf}{NAG Documentation: s17dgf}
\beginscroll
\begin{verbatim}



     S17DGF(3NAG)      Foundation Library (12/10/92)      S17DGF(3NAG)



          S17 -- Approximations of Special Functions                 S17DGF
                  S17DGF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S17DGF returns the value of the Airy function Ai(z) or its
          derivative Ai'(z) for complex z, with an option for exponential
          scaling.

          2. Specification

                 SUBROUTINE S17DGF (DERIV, Z, SCALE, AI, NZ, IFAIL)
                 INTEGER              NZ, IFAIL
                 COMPLEX(KIND(1.0D0)) Z, AI
                 CHARACTER*1          DERIV, SCALE

          3. Description

          This subroutine returns a value for the Airy function Ai(z) or
          its derivative Ai'(z), where z is complex, -(pi) < arg z <= (pi).
                                                             

                                                         2z\/z/3
          Optionally, the value is scaled by the factor e       .

          The routine is derived from the routine CAIRY in Amos [2]. It is
                                          

                                        \/zK   (w)              -zK   (w)
                                            1/3                    2/3
          based on the relations Ai(z)= ----------, and Ai'(z)= ---------,
                                                                       

                                         (pi)\/3                 (pi)/3
                                                                

          where K     is the modified Bessel function and w=2z\/z/3.
                 (nu)

          For very large |z|, argument reduction will cause total loss of
          accuracy, and so no computation is performed. For slightly
          smaller |z|, the computation is performed but results are
          accurate to less than half of machine precision. If Re w is too
          large, and the unscaled function is required, there is a risk of
          overflow and so no computation is performed. In all the above
          cases, a warning is given by the routine.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          [2]   Amos D E (1986) Algorithm 644: A Portable Package for Bessel
                Functions of a Complex Argument and Nonnegative Order. ACM
                Trans. Math. Softw. 12 265--273.

          5. Parameters

           1:  DERIV -- CHARACTER*1                                   Input
               On entry: specifies whether the function or its derivative
               is required.
                    If DERIV = 'F', Ai(z) is returned.

                    If DERIV = 'D', Ai'(z) is returned.
               Constraint: DERIV = 'F' or 'D'.

           2:  Z -- COMPLEX(KIND(1.0D0))                              Input
               On entry: the argument z of the function.

           3:  SCALE -- CHARACTER*1                                   Input
               On entry: the scaling option.

               If SCALE = 'U', the result is returned unscaled.

               If SCALE = 'S', the result is returned scaled by the factor
                    

                2z\/z/3
               e       . Constraint: SCALE = 'U' or 'S'.

           4:  AI -- COMPLEX(KIND(1.0D0))                            Output
               On exit: the required function or derivative value.

           5:  NZ -- INTEGER                                         Output
               On exit: NZ indicates whether or not AI is set to zero due
               to underflow. This can only occur when SCALE = 'U'.

               If NZ = 0, AI is not set to zero.

               If NZ = 1, AI is set to zero.

           6:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry DERIV /= 'F' or 'D'.

               or       SCALE /= 'U' or 'S'.

          IFAIL= 2
               No computation has been performed due to the likelihood of
                                                                

               overflow, because Re w is too large, where w=2Z\/Z/3 -- how
               large depends on Z and the overflow threshold of the
               machine. This error exit can only occur when SCALE = 'U'.

          IFAIL= 3
               The computation has been performed, but the errors due to
               argument reduction in elementary functions make it likely
               that the result returned by S17DGF is accurate to less than
               half of machine precision. This error exit may occur if ABS
               (Z) is greater than a machine-dependent threshold value
               (given in the Users' Note for your implementation).

          IFAIL= 4
               No computation has been performed because the errors due to
               argument reduction in elementary functions mean that all
               precision in the result returned by S17DGF would be lost.
               This error exit may occur if ABS(Z) is greater than a
               machine-dependent threshold value (given in the Users' Note
               for your implementation).

          IFAIL= 5
               No result is returned because the algorithm termination
               condition has not been met. This may occur because the
               parameters supplied to S17DGF would have caused overflow or
               underflow.

          7. Accuracy

          All constants in subroutine S17DGF are given to approximately 18
          digits of precision. Calling the number of digits of precision in
          the floating-point arithmetic being used t, then clearly the
          maximum number of correct digits in the results obtained is
          limited by p=min(t,18). Because of errors in argument reduction
          when computing elementary functions inside S17DGF, the actual
          number of correct digits is limited, in general, by p-s, where
          s~max(1,|log  |z||) represents the number of digits lost due to
                      10
          the argument reduction. Thus the larger the value of |z|, the
          less the precision in the result.

          Empirical tests with modest values of z, checking relations
          between Airy functions Ai(z), Ai'(z), Bi(z) and Bi'(z), have
          shown errors limited to the least significant 3-4 digits of
          precision.

          8. Further Comments

          Note that if the function is required to operate on a real
          argument only, then it may be much cheaper to call S17AGF or
          S17AJF.

          9. Example

          The example program prints a caption and then proceeds to read
          sets of data from the input data stream. The first datum is a
          value for the parameter DERIV, the second is a complex value for
          the argument, Z, and the third is a value for the parameter
          SCALE. The program calls the routine and prints the results. The
          process is repeated until the end of the input data stream is
          encountered.


          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs17dhf}{nags.ht}
{ Value of the Airy function $Bi(z)$ or derivative $Bi'(z)$}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs17dhf}{NAG Documentation: s17dhf}
\beginscroll
\begin{verbatim}



     S17DHF(3NAG)      Foundation Library (12/10/92)      S17DHF(3NAG)



          S17 -- Approximations of Special Functions                 S17DHF
                  S17DHF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S17DHF returns the value of the Airy function Bi(z) or its
          derivative Bi'(z) for complex z, with an option for exponential
          scaling.

          2. Specification

                 SUBROUTINE S17DHF (DERIV, Z, SCALE, BI, IFAIL)
                 INTEGER              IFAIL
                 COMPLEX(KIND(1.0D0)) Z, BI
                 CHARACTER*1          DERIV, SCALE

          3. Description

          This subroutine returns a value for the Airy function Bi(z) or
          its derivative Bi'(z), where z is complex, -(pi) < argz <= (pi).
                                                                  

                                                         |Re (2z\/z/3)|
          Optionally, the value is scaled by the factor e              .

          The routine is derived from the routine CBIRY in Amos [2]. It is
                                          

                                        \/z
          based on the relations Bi(z)= ---(I    (w)+I   (w)), and
                                             -1/3     1/3
                                        \/3
                   z
          Bi'(z)= ---(I    (w)+I   (w)), where I     is the modified Bessel
                       -2/3     2/3             (nu)
                  \/3
                             

          function and w=2z\/z/3.

          For very large |z|, argument reduction will cause total loss of
          accuracy, and so no computation is performed. For slightly
          smaller |z|, the computation is performed but results are
          accurate to less than half of machine precision. If Re  z is too
          large, and the unscaled function is required, there is a risk of
          overflow and so no computation is performed. In all the above
          cases, a warning is given by the routine.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          [2]   Hammersley J M and Handscomb D C (1967) Monte-Carlo Methods.
                Methuen.

          5. Parameters

           1:  DERIV -- CHARACTER*1                                   Input
               On entry: specifies whether the function or its derivative
               is required.
                    If DERIV = 'F', Bi(z) is returned.

                    If DERIV = 'D', Bi'(z) is returned.
               Constraint: DERIV = 'F' or 'D'.

           2:  Z -- COMPLEX(KIND(1.0D0))                              Input
               On entry: the argument z of the function.

           3:  SCALE -- CHARACTER*1                                   Input
               On entry: the scaling option.
                    If SCALE = 'U', the result is returned unscaled.

                    If SCALE = 'S', the result is returned scaled by the
                                    

                            |Re(2z\/z/3)|
                    factor e             .
               Constraint: SCALE = 'U' or 'S'.

           4:  BI -- COMPLEX(KIND(1.0D0))                            Output
               On exit: the required function or derivative value.

           5:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry DERIV /= 'F' or 'D'.

               or       SCALE /= 'U' or 'S'.

          IFAIL= 2
               No computation has been performed due to the likelihood of
               overflow, because real(Z) is too large - how large depends
               on the overflow threshold of the machine. This error exit
               can only occur when SCALE = 'U'.

          IFAIL= 3
               The computation has been performed, but the errors due to
               argument reduction in elementary functions make it likely
               that the result returned by S17DHF is accurate to less than
               half of machine precision. This error exit may occur if ABS
               (Z) is greater than a machine-dependent threshold value
               (given in the Users' Note for your implementation).

          IFAIL= 4
               No computation has been performed because the errors due to
               argument reduction in elementary functions mean that all
               precision in the result returned by S17DHF would be lost.
               This error exit may occur if ABS(Z) is greater than a
               machine-dependent threshold value (given in the Users' Note
               for your implementation).

          IFAIL= 5
               No result is returned because the algorithm termination
               condition has not been met. This may occur because the
               parameters supplied to S17DHF would have caused overflow or
               underflow.

          7. Accuracy

          All constants in subroutine S17DHF are given to approximately 18
          digits of precision. Calling the number of digits of precision in
          the floating-point arithmetic being used t, then clearly the
          maximum number of correct digits in the results obtained is
          limited by p=min(t,18). Because of errors in argument reduction
          when computing elementary functions inside S17DHF, the actual
          number of correct digits is limited, in general, by p-s, where
          s~max(1,|log  |z||) represents the number of digits lost due to
                      10
          the argument reduction. Thus the larger the value of |z|, the
          less the precision in the result.

          Empirical tests with modest values of z, checking relations
          between Airy functions Ai(z), Ai'(z), Bi(z) and Bi'(z), have
          shown errors limited to the least significant 3-4 digits of
          precision.

          8. Further Comments

          Note that if the function is required to operate on a real
          argument only, then it may be much cheaper to call S17AHF or
          S17AKF.

          9. Example

          The example program prints a caption and then proceeds to read
          sets of data from the input data stream. The first datum is a
          value for the parameter DERIV, the second is a complex value for
          the argument, Z, and the third is a value for the parameter
          SCALE. The program calls the routine and prints the results. The
          process is repeated until the end of the input data stream is
          encountered.


          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs17dlf}{nags.ht}
{ Returns a sequence of values for the Hankel functions}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs17dlf}{NAG Documentation: s17dlf}
\beginscroll
\begin{verbatim}



     S17DLF(3NAG)      Foundation Library (12/10/92)      S17DLF(3NAG)



          S17 -- Approximations of Special Functions                 S17DLF
                  S17DLF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S17DLF returns a sequence of values for the Hankel functions
           (1)           (2)
          H      (z) or H      (z) for complex z, non-negative (nu) and
           (nu)+n        (nu)+n
          n=0,1,...,N-1, with an option for exponential scaling.

          2. Specification

                 SUBROUTINE S17DLF (M, FNU, Z, N, SCALE, CY, NZ, IFAIL)
                 INTEGER              M, N, NZ, IFAIL
                 DOUBLE PRECISION     FNU
                 COMPLEX(KIND(1.0D0)) Z, CY(N)
                 CHARACTER*1          SCALE

          3. Description

          This subroutine evaluates a sequence of values for the Hankel
                    (1)         (2)
          function H    (z) or H    (z), where z is complex, -(pi) < argz
                    (nu)        (nu)
          <= (pi), and (nu) is the real, non-negative order. The N-member
          sequence is generated for orders (nu), (nu)+1,...,(nu)+N-1.
                                                            -iz
          Optionally, the sequence is scaled by the factor e    if the
                       (1)                       iz
          function is H    (z) or by the factor e   if the function is
                       (nu)
           (2)
          H    (z).
           (nu)

          Note: although the routine may not be called with (nu) less than
          zero, for negative orders the formulae
           (1)       (nu)(pi)i (1)           (2)       -(nu)(pi)i (2)
          H     (z)=e         H    (z), and H     (z)=e          H    (z)
           -(nu)               (nu)          -(nu)                (nu)
          may be used.

          The routine is derived from the routine CBESH in Amos [2]. It is
          based on the relation

                            (m)      1 -p(nu)        -p
                           H    (z)= -e      K    (ze  ),
                            (nu)     p        (nu)

                    (pi)                 (pi)
          where p=i ---- if m=1 and p=-i ---- if m=2, and the Bessel
                     2                    2
          function K    (z) is computed in the right half-plane only.
                    (nu)
          Continuation of K    (z) to the left half-plane is computed in
                           (nu)
          terms of the Bessel function I    (z). These functions are
                                        (nu)
          evaluated using a variety of different techniques, depending on
          the region under consideration.

                                                     (m)
          When N is greater than 1, extra values of H    (z) are computed
                                                     (nu)
          using recurrence relations.

          For very large |z| or ((nu)+N-1), argument reduction will cause
          total loss of accuracy, and so no computation is performed. For
          slightly smaller |z| or ((nu)+N-1), the computation is performed
          but results are accurate to less than half of machine precision.
          If |z| is very small, near the machine underflow threshold, or
          ((nu)+N-1) is too large, there is a risk of overflow and so no
          computation is performed. In all the above cases, a warning is
          given by the routine.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          [2]   Amos D E (1986) Algorithm 644: A Portable Package for Bessel
                Functions of a Complex Argument and Nonnegative Order. ACM
                Trans. Math. Softw. 12 265--273.

          5. Parameters

           1:  M -- INTEGER                                           Input
               On entry: the kind of functions required.
                                                 (1)
                    If M = 1, the functions are H    (z).
                                                 (nu)

                                                 (2)
                    If M = 2, the functions are H    (z).
                                                 (nu)
               Constraint: M = 1 or 2.

           2:  FNU -- DOUBLE PRECISION                                Input
               On entry: the order, (nu), of the first member of the
               sequence of functions. Constraint: FNU >= 0.0.

           3:  Z -- COMPLEX(KIND(1.0D0))                              Input
               On entry: the argument z of the functions. Constraint: Z /=
               (0.0, 0.0).

           4:  N -- INTEGER                                           Input
               On entry: the number, N, of members required in the sequence
                (M)    (M)          (M)
               H    , H      ,..., H        . Constraint: N >= 1.
                (nu)   (nu)+1       (nu)+N-1

           5:  SCALE -- CHARACTER*1                                   Input
               On entry: the scaling option.
                    If SCALE = 'U', the results are returned unscaled.

                    If SCALE = 'S', the results are returned scaled by the
                            -iz                               iz
                    factor e    when M = 1, or by the factor e   when M =
                    2.
               Constraint: SCALE = 'U' or 'S'.

           6:  CY(N) -- COMPLEX(KIND(1.0D)) array                    Output
               On exit: the N required function values: CY(i) contains
                (M)
               H        , for i=1,2,...,N.
                (nu)+i-1

           7:  NZ -- INTEGER                                         Output
               On exit: the number of components of CY that are set to zero
               due to underflow. If NZ > 0, then if Imz>0.0 and M = 1, or
               Imz<0.0 and M = 2, elements CY(1), CY(2),...,CY(NZ) are set
               to zero. In the complementary half-planes, NZ simply states
               the number of underflows, and not which elements they are.

           8:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry M /= 1 and M /= 2,

               or       FNU < 0.0,

               or       Z = (0.0, 0.0),

               or       N < 1,

               or       SCALE /= 'U' or 'S'.

          IFAIL= 2
               No computation has been performed due to the likelihood of
               overflow, because ABS(Z) is less than a machine-dependent
               threshold value (given in the Users' Note for your
               implementation).

          IFAIL= 3
               No computation has been performed due to the likelihood of
               overflow, because FNU + N - 1 is too large - how large
               depends on Z and the overflow threshold of the machine.

          IFAIL= 4
               The computation has been performed, but the errors due to
               argument reduction in elementary functions make it likely
               that the results returned by S17DLF are accurate to less
               than half of machine precision. This error exit may occur if
               either ABS(Z) or FNU + N - 1 is greater than a machine-
               dependent threshold value (given in the Users' Note for
               your implementation).

          IFAIL= 5
               No computation has been performed because the errors due to
               argument reduction in elementary functions mean that all
               precision in results returned by S17DLF would be lost. This
               error exit may occur when either of ABS(Z) or FNU + N - 1 is
               greater than a machine-dependent threshold value (given in
               the Users' Note for your implementation).

          IFAIL= 6
               No results are returned because the algorithm termination
               condition has not been met. This may occur because the
               parameters supplied to S17DLF would have caused overflow or
               underflow.

          7. Accuracy

          All constants in subroutine S17DLF are given to approximately 18
          digits of precision. Calling the number of digits of precision in
          the floating-point arithmetic being used t, then clearly the
          maximum number of correct digits in the results obtained is
          limited by p=min(t,18). Because of errors in argument reduction
          when computing elementary functions inside S17DLF, the actual
          number of correct digits is limited, in general, by p-s, where
          s~max(1,|log  |z||,|log  (nu)|) represents the number of digits
                      10         10
          lost due to the argument reduction. Thus the larger the values of
          |z| and (nu), the less the precision in the result. If S17DLF is
          called with N>1, then computation of function values via
          recurrence may lead to some further small loss of accuracy.

          If function values which should nominally be identical are
          computed by calls to S17DLF with different base values of (nu)
          and different N, the computed values may not agree exactly.
          Empirical tests with modest values of (nu) and z have shown that
          the discrepancy is limited to the least significant 3-4 digits of
          precision.

          8. Further Comments

          The time taken by the routine for a call of S17DLF is
          approximately proportional to the value of N, plus a constant. In
          general it is much cheaper to call S17DLF with N greater than 1,
          rather than to make N separate calls to S17DLF.

          Paradoxically, for some values of z and (nu), it is cheaper to
          call S17DLF with a larger value of N than is required, and then
          discard the extra function values returned. However, it is not
          possible to state the precise circumstances in which this is
          likely to occur. It is due to the fact that the base value used
          to start recurrence may be calculated in different regions for
          different N, and the costs in each region may differ greatly.

          9. Example

          The example program prints a caption and then proceeds to read
          sets of data from the input data stream. The first datum is a
          value for the kind of function, M, the second is a value for the
          order FNU, the third is a complex value for the argument, Z, and
          the fourth is a value for the parameter SCALE. The program calls
          the routine with N = 2 to evaluate the function for orders FNU
          and FNU + 1, and it prints the results. The process is repeated
          until the end of the input data stream is encountered.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs18acf}{nags.ht}
{ Returns the value of the modified Bessel Function $K_0(x)$}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs18acf}{NAG Documentation: s18acf}
\beginscroll
\begin{verbatim}



     S18ACF(3NAG)      Foundation Library (12/10/92)      S18ACF(3NAG)



          S18 -- Approximations of Special Functions                 S18ACF
                  S18ACF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S18ACF returns the value of the modified Bessel Function K (x),
                                                                    0
          via the routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S18ACF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          This routine evaluates an approximation to the modified Bessel
          Function of the second kind K (x).
                                       0

          Note: K (x) is undefined for x<=0 and the routine will fail for
                 0
          such arguments.

          The routine is based on five Chebyshev expansions:

          For 0<x<=1,

                           --'          --'                     2
                K (x)=-lnx >   a T (t)+ >   b T (t) , where t=2x -1;
                 0         --   r r     --   r r
                           r=0          r=0

          For 1<x<=2,

                               -x --'
                        K (x)=e   >   c T (t) , where t=2x-3;
                         0        --   r r
                                  r=0

          For 2<x<=4,

                               -x --'
                        K (x)=e   >   d T (t) , where t=x-3;
                         0        --   r r
                                  r=0
          For x>4,

                               -x
                              e   --'                    9-x
                       K (x)= --- >   e T (t) , where t= ---.
                        0         --   r r               1+x
                              \/x r=0

                                             ( x)
          For x near zero, K (x)~=-(gamma)-ln( -), where (gamma) denotes
                            0                ( 2)
          Euler's constant. This approximation is used when x is
          sufficiently small for the result to be correct to machine
          precision.

          For large x, where there is a danger of underflow due to the
          smallness of K , the result is set exactly to zero.
                        0

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function. Constraint: X > 0.
               0.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               X <= 0.0, K  is undefined. On soft failure the routine
                          0
               returns zero.

          7. Accuracy

          Let (delta) and (epsilon) be the relative errors in the argument
          and result respectively.

          If (delta) is somewhat larger than the machine precision (i.e.,
          if (delta) is due to data errors etc), then (epsilon) and (delta)
          are approximately related by:

                                       | xK (x)|
                                       |   1   |
                            (epsilon)~=| ------|(delta).
                                       | K (x) |
                                       |  0    |

          Figure 1 shows the behaviour of the error amplification factor

                                     | xK (x)|
                                     |   1   |
                                     | ------|.
                                     | K (x) |
                                     |  0    |

                                     Figure 1
                   Please see figure in printed Reference Manual

          However, if (delta) is of the same order as machine precision,
          then rounding errors could make (epsilon) slightly larger than
          the above relation predicts.

                                                                 |  1 |
          For small x, the amplification factor is approximately | ---|,
                                                                 | lnx|
          which implies strong attenuation of the error, but in general
          (epsilon) can never be less than the machine precision.

          For large x, (epsilon)~=x(delta) and we have strong amplification
          of the relative error. Eventually K , which is asymptotically
                                             0
                     -x
                    e
          given by  ---, becomes so small that it cannot be calculated
                      

                    \/x
          without underflow and hence the routine will return zero. Note
          that for large x the errors will be dominated by those of the
          Fortran intrinsic function EXP.

          8. Further Comments

          For details of the time taken by the routine see the appropriate
          the Users' Note for your implementation.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs18adf}{nags.ht}
{ Returns the value of the modified Bessel Function $K_1(x)$}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs18adf}{NAG Documentation: s18adf}
\beginscroll
\begin{verbatim}



     S18ADF(3NAG)      Foundation Library (12/10/92)      S18ADF(3NAG)



          S18 -- Approximations of Special Functions                 S18ADF
                  S18ADF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S18ADF returns the value of the modified Bessel Function K (x),
                                                                    1
          via the routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S18ADF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          This routine evaluates an approximation to the modified Bessel
          Function of the second kind K (x).
                                       1

          Note: K (x) is undefined for x<=0 and the routine will fail for
                 1
          such arguments.

          The routine is based on five Chebyshev expansions:

          For 0<x<=1,

                     1      --'           --'                     2
              K (x)= -+xlnx >   a T (t)-x >   b T (t) , where t=2x -1;
               1     x      --   r r      --   r r
                            r=0           r=0

          For 1<x<=2,

                               -x --'
                        K (x)=e   >   c T (t) , where t=2x-3;
                         1        --   r r
                                  r=0

          For 2<x<=4,

                               -x --'
                        K (x)=e   >   d T (t) , where t=x-3;
                         1        --   r r
                                  r=0

          For x>4,

                               -x
                              e   --'                    9-x
                       K (x)= --- >   e T (t) , where t= ---.
                        1         --   r r               1+x
                              \/x r=0

                                   1
          For x near zero, K (x)~= -. This approximation is used when x is
                            1      x
          sufficiently small for the result to be correct to machine
          precision. For very small x on some machines, it is impossible to
                     1
          calculate  - without overflow and the routine must fail.
                     x

          For large x, where there is a danger of underflow due to the
          smallness of K , the result is set exactly to zero.
                        1

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function. Constraint: X > 0.
               0.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               X <= 0.0, K  is undefined. On soft failure the routine
                          1
               returns zero.

          IFAIL= 2
               X is too small, there is a danger of overflow. On soft
               failure the routine returns approximately the largest
               representable value.

          7. Accuracy

          Let (delta) and (epsilon) be the relative errors in the argument
          and result respectively.

          If (delta) is somewhat larger than the machine precision (i.e.,
          if (delta) is due to data errors etc), then (epsilon) and (delta)
          are approximately related by:

                                    | xK (x)-K (x)|
                                    |   0     1   |
                         (epsilon)~=| ------------|(delta).
                                    |    K (x)    |
                                    |     1       |

          Figure 1 shows the behaviour of the error amplification factor

                                  | xK (x)-K (x)|
                                  |   0     1   |
                                  | ------------|.
                                  |    K (x)    |
                                  |     1       |

                                     Figure 1
                   Please see figure in printed Reference Manual

          However if (delta) is of the same order as the machine precision,
          then rounding errors could make (epsilon) slightly larger than
          the above relation predicts.

          For small x, (epsilon)~=(delta) and there is no amplification of
          errors.

          For large x, (epsilon)~=x(delta) and we have strong amplification
          of the relative error. Eventually K , which is asymptotically
                                             1
                     -x
                    e
          given by  ---, becomes so small that it cannot be calculated
                      

                    \/x
          without underflow and hence the routine will return zero. Note
          that for large x the errors will be dominated by those of the
          Fortran intrinsic function EXP.

          8. Further Comments

          For details of the time taken by the routine see the Users' Note
          for your implementation.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs18aef}{nags.ht}
{ Returns the value of the modified Bessel Function $I_0(x)$}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs18aef}{NAG Documentation: s18aef}
\beginscroll
\begin{verbatim}



     S18AEF(3NAG)      Foundation Library (12/10/92)      S18AEF(3NAG)



          S18 -- Approximations of Special Functions                 S18AEF
                  S18AEF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S18AEF returns the value of the modified Bessel Function I (x),
                                                                    0
          via the routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S18AEF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          This routine evaluates an approximation to the modified Bessel
          Function of the first kind I (x).
                                      0

          Note: I (-x)=I (x), so the approximation need only consider x>=0.
                 0      0

          The routine is based on three Chebyshev expansions:

          For 0<x<=4,

                              x --'                    ( x)
                       I (x)=e  >   a T (t) , where t=2( -)-1;
                        0       --   r r               ( 4)
                                r=0

          For 4<x<=12,

                               x --'                    x-8
                        I (x)=e  >   b T (t) , where t= ---;
                         0       --   r r                4
                                 r=0

          For x>12,

                             x
                            e   --'                    ( 12)
                     I (x)= --- >   c T (t) , where t=2( --)-1.
                      0         --   r r               ( x )
                            \/x r=0

          For small x, I (x)~=1. This approximation is used when x is
                        0
          sufficiently small for the result to be correct to machine
          precision.

          For large x, the routine must fail because of the danger of
                                   x
          overflow in calculating e .

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               X is too large. On soft failure the routine returns the
               approximate value of I (x) at the nearest valid argument.
                                     0

          7. Accuracy

          Let (delta) and (epsilon) be the relative errors in the argument
          and result respectively.

          If (delta) is somewhat larger than the machine precision (i.e.,
          if (delta) is due to data errors etc), then (epsilon) and (delta)
          are approximately related by:

                                       | xI (x)|
                                       |   1   |
                            (epsilon)~=| ------|(delta).
                                       | I (x) |
                                       |  0    |

          Figure 1 shows the behaviour of the error amplification factor

                                     | xI (x)|
                                     |   1   |
                                     | ------|.
                                     | I (x) |
                                     |  0    |

                                     Figure 1
                   Please see figure in printed Reference Manual

          However if (delta) is of the same order as machine precision,
          then rounding errors could make (epsilon) slightly larger than
          the above relation predicts.

                                                                  2
                                                                 x
          For small x the amplification factor is approximately  --, which
                                                                 2
          implies strong attenuation of the error, but in general (epsilon)
          can never be less than the machine precision.

          For large x, (epsilon)~=x(delta) and we have strong amplification
          of errors. However the routine must fail for quite moderate
          values of x, because I (x) would overflow; hence in practice the
                                0
          loss of accuracy for large x is not excessive. Note that for
          large x the errors will be dominated by those of the Fortran
          intrinsic function EXP.

          8. Further Comments

          For details of the time taken by the routine see the Users' Note
          for your implementation.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs18aff}{nags.ht}
{ Returns a value for the modified Bessel Function $I_1(x)$}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs18aff}{NAG Documentation: s18aff}
\beginscroll
\begin{verbatim}



     S18AFF(3NAG)      Foundation Library (12/10/92)      S18AFF(3NAG)



          S18 -- Approximations of Special Functions                 S18AFF
                  S18AFF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S18AFF returns a value for the modified Bessel Function I (x),
                                                                   1
          via the routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S18AFF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          This routine evaluates an approximation to the modified Bessel
          Function of the first kind I (x).
                                      1

          Note: I (-x)=-I (x), so the approximation need only consider x>=0
                 1       1

          The routine is based on three Chebyshev expansions:

          For 0<x<=4,

                               --'                    ( x)2
                       I (x)=x >   a T (t) , where t=2( -) -1;
                        1      --   r r               ( 4)
                               r=0

          For 4<x<=12,

                               x --'                    x-8
                        I (x)=e  >   b T (t) , where t= ---;
                         1       --   r r                4
                                 r=0

          For x>12,

                             x
                            e   --'                    ( 12)
                     I (x)= --- >   c T (t) , where t=2( --)-1.
                      1         --   r r               ( x )
                            \/x r=0

          For small x, I (x)~=x. This approximation is used when x is
                        1
          sufficiently small for the result to be correct to machine
          precision.

          For large x, the routine must fail because I (x) cannot be
                                                      1
          represented without overflow.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               X is too large. On soft failure the routine returns the
               approximate value of I (x) at the nearest valid argument.
                                     1

          7. Accuracy

          Let (delta) and (epsilon) be the relative errors in the argument
          and result respectively.

          If (delta) is somewhat larger than the machine precision (i.e.,
          if (delta) is due to data errors etc), then (epsilon) and (delta)
          are approximately related by:

                                    | xI (x)-I (x)|
                                    |   0     1   |
                         (epsilon)~=| ------------|(delta).
                                    |    I (x)    |
                                    |     1       |

          Figure 1 shows the behaviour of the error amplification factor

                                  | xI (x)-I (x)|
                                  |   0     1   |
                                  | ------------|,
                                  |    I (x)    |
                                  |     1       |

                                     Figure 1
                   Please see figure in printed Reference Manual

          However if (delta) is of the same order as machine precision,
          then rounding errors could make (epsilon) slightly larger than
          the above relation predicts.

          For small x, (epsilon)~=(delta) and there is no amplification of
          errors.

          For large x, (epsilon)~=x(delta) and we have strong amplification
          of errors. However the routine must fail for quite moderate
          values of x because I (x) would overflow; hence in practice the
                               1
          loss of accuracy for large x is not excessive. Note that for
          large x, the errors will be dominated by those of the Fortran
          intrinsic function EXP.

          8. Further Comments

          For details of the time taken by the routine see the Users' Note
          for your implementation.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs18dcf}{nags.ht}
{ Sequence of values for the modified Bessel $K_{\nu_n}(z)$}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs18dcf}{NAG Documentation: s18dcf}
\beginscroll
\begin{verbatim}



     S18DCF(3NAG)      Foundation Library (12/10/92)      S18DCF(3NAG)



          S18 -- Approximations of Special Functions                 S18DCF
                  S18DCF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S18DCF returns a sequence of values for the modified Bessel
          functions K      (z) for complex z, non-negative (nu) and
                     (nu)+n
          n=0,1,...,N-1, with an option for exponential scaling.

          2. Specification

                 SUBROUTINE S18DCF (FNU, Z, N, SCALE, CY, NZ, IFAIL)
                 INTEGER              N, NZ, IFAIL
                 DOUBLE PRECISION     FNU
                 COMPLEX(KIND(1.0D0)) Z, CY(N)
                 CHARACTER*1          SCALE

          3. Description

          This subroutine evaluates a sequence of values for the modified
          Bessel function K    (z), where z is complex, -(pi) < arg z <=
                           (nu)
          (pi), and (nu) is the real, non-negative order. The N-member
          sequence is generated for orders (nu), (nu)+1,...,(nu)+N-1.
                                                            z
          Optionally, the sequence is scaled by the factor e .

          The routine is derived from the routine CBESK in Amos [2].

          Note: although the routine may not be called with (nu) less than
          zero, for negative orders the formula K     (z)=K    (z) may be
                                                 -(nu)     (nu)
          used.

          When N is greater than 1, extra values of K    (z) are computed
                                                     (nu)
          using recurrence relations.

          For very large |z| or ((nu)+N-1), argument reduction will cause
          total loss of accuracy, and so no computation is performed. For
          slightly smaller |z| or ((nu)+N-1), the computation is performed
          but results are accurate to less than half of machine precision.
          If |z| is very small, near the machine underflow threshold, or
          ((nu)+N-1) is too large, there is a risk of overflow and so no
          computation is performed. In all the above cases, a warning is
          given by the routine.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          [2]   Amos D E (1986) Algorithm 644: A Portable Package for Bessel
                Functions of a Complex Argument and Nonnegative Order. ACM
                Trans. Math. Softw. 12 265--273.

          5. Parameters

           1:  FNU -- DOUBLE PRECISION                                Input
               On entry: the order, (nu), of the first member of the
               sequence of functions. Constraint: FNU >= 0.0.

           2:  Z -- COMPLEX(KIND(1.0D0))                              Input
               On entry: the argument z of the functions. Constraint: Z /=
               (0.0, 0.0).

           3:  N -- INTEGER                                           Input
               On entry: the number, N, of members required in the sequence
               K    (z), K      (z),..., K        (z). Constraint: N >= 1.
                (nu)      (nu)+1          (nu)+N-1

           4:  SCALE -- CHARACTER*1                                   Input
               On entry: the scaling option.

               If SCALE = 'U', the results are returned unscaled.

               If SCALE = 'S', the results are returned scaled by the
                       z
               factor e . Constraint: SCALE = 'U' or 'S'.

           5:  CY(N) -- COMPLEX(KIND(1.0D)) array                    Output
               On exit: the N required function values: CY(i) contains
               K        (z), for i=1,2,...,N.
                (nu)+i-1

           6:  NZ -- INTEGER                                         Output
               On exit: the number of components of CY that are set to zero
               due to underflow. If NZ > 0 and Rez>=0.0, elements CY(1),CY
               (2),...,CY(NZ) are set to zero. If Rez<0.0, NZ simply states
               the number of underflows, and not which elements they are.

           7:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).


          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry FNU < 0.0,

               or       Z = (0.0, 0.0),

               or       N < 1,

               or       SCALE /= 'U' or 'S'.

          IFAIL= 2
               No computation has been performed due to the likelihood of
               overflow, because ABS(Z) is less than a machine-dependent
               threshold value (given in the Users' Note for your
               implementation).

          IFAIL= 3
               No computation has been performed due to the likelihood of
               overflow, because FNU + N - 1 is too large - how large
               depends on Z and the overflow threshold of the machine.

          IFAIL= 4
               The computation has been performed, but the errors due to
               argument reduction in elementary functions make it likely
               that the results returned by S18DCF are accurate to less
               than half of machine precision. This error exit may occur if
               either ABS(Z) or FNU + N - 1 is greater than a machine-
               dependent threshold value (given in the Users' Note for
               your implementation).

          IFAIL= 5
               No computation has been performed because the errors due to
               argument reduction in elementary functions mean that all
               precision in results returned by S18DCF would be lost. This
               error exit may occur when either ABS(Z) or FNU + N - 1 is
               greater than a machine-dependent threshold value (given in
               the Users' Note for your implementation).

          IFAIL= 6
               No results are returned because the algorithm termination
               condition has not been met. This may occur because the
               parameters supplied to S18DCF would have caused overflow or
               underflow.

          7. Accuracy


          All constants in subroutine S18DCF are given to approximately 18
          digits of precision. Calling the number of digits of precision in
          the floating-point arithmetic being used t, then clearly the
          maximum number of correct digits in the results obtained is
          limited by p=min(t,18). Because of errors in argument reduction
          when computing elementary functions inside S18DCF, the actual
          number of correct digits is limited, in general, by p-s, where
          s~max(1,|log  |z||,|log  (nu)|) represents the number of digits
                      10         10
          lost due to the argument reduction. Thus the larger the values of
          |z| and (nu), the less the precision in the result. If S18DCF is
          called with N>1, then computation of function values via
          recurrence may lead to some further small loss of accuracy.

          If function values which should nominally be identical are
          computed by calls to S18DCF with different base values of (nu)
          and different N, the computed values may not agree exactly.
          Empirical tests with modest values of (nu) and z have shown that
          the discrepancy is limited to the least significant 3-4 digits of
          precision.

          8. Further Comments

          The time taken by the routine for a call of S18DCF is
          approximately proportional to the value of N, plus a constant. In
          general it is much cheaper to call S18DCF with N greater than 1,
          rather than to make N separate calls to S18DCF.

          Paradoxically, for some values of z and (nu), it is cheaper to
          call S18DCF with a larger value of N than is required, and then
          discard the extra function values returned. However, it is not
          possible to state the precise circumstances in which this is
          likely to occur. It is due to the fact that the base value used
          to start recurrence may be calculated in different regions for
          different N, and the costs in each region may differ greatly.

          Note that if the function required is K (x) or K (x), i.e.,
                                                 0        1
          (nu)=0.0 or 1.0, where x is real and positive, and only a single
          function value is required, then it may be much cheaper to call
          S18ACF, S18ADF, S18CCF(*) or S18CDF(*), depending on whether a
          scaled result is required or not.

          9. Example

          The example program prints a caption and then proceeds to read
          sets of data from the input data stream. The first datum is a
          value for the order FNU, the second is a complex value for the
          argument, Z, and the third is a value for the parameter SCALE.
          The program calls the routine with N = 2 to evaluate the function
          for orders FNU and FNU + 1, and it prints the results. The
          process is repeated until the end of the input data stream is
          encountered.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs18def}{nags.ht}
{ Sequence of values for the modified Bessel $I_{\nu+n}$}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs18def}{NAG Documentation: s18def}
\beginscroll
\begin{verbatim}



     S18DEF(3NAG)      Foundation Library (12/10/92)      S18DEF(3NAG)



          S18 -- Approximations of Special Functions                 S18DEF
                  S18DEF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S18DEF returns a sequence of values for the modified Bessel
          functions I      (z) for complex z, non-negative (nu) and
                     (nu)+n
          n=0,1,...,N-1, with an option for exponential scaling.

          2. Specification

                 SUBROUTINE S18DEF (FNU, Z, N, SCALE, CY, NZ, IFAIL)
                 INTEGER              N, NZ, IFAIL
                 DOUBLE PRECISION     FNU
                 COMPLEX(KIND(1.0D0)) Z, CY(N)
                 CHARACTER*1          SCALE

          3. Description

          This subroutine evaluates a sequence of values for the modified
          Bessel function I    (z), where z is complex, -(pi) < argz <=
                           (nu)
          (pi), and (nu) is the real, non-negative order. The N-member
          sequence is generated for orders (nu), (nu)+1,...,(nu)+N-1.
                                                            -|Rez|
          Optionally, the sequence is scaled by the factor e      .

          The routine is derived from the routine CBESI in Amos [2].

          Note: although the routine may not be called with (nu) less than
          zero, for negative orders the formula
                               2
          I     (z)=I    (z)+ ----sin((pi)(nu))K    (z) may be used (for
           -(nu)     (nu)     (pi)              (nu)
          the Bessel function K    (z), see S18DCF).
                               (nu)

          When N is greater than 1, extra values of I    (z) are computed
                                                     (nu)
          using recurrence relations.

          For very large |z| or ((nu)+N-1), argument reduction will cause
          total loss of accuracy, and so no computation is performed. For
          slightly smaller |z| or ((nu)+N-1), the computation is performed
          but results are accurate to less than half of machine precision.
          If Re(z) is too large and the unscaled function is required,
          there is a risk of overflow and so no computation is performed.
          In all the above cases, a warning is given by the routine.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          [2]   Amos D E (1986) Algorithm 644: A Portable Package for Bessel
                Functions of a Complex Argument and Nonnegative Order. ACM
                Trans. Math. Softw. 12 265--273.

          5. Parameters

           1:  FNU -- DOUBLE PRECISION                                Input
               On entry: the order, (nu), of the first member of the
               sequence of functions. Constraint: FNU >= 0.0.

           2:  Z -- COMPLEX(KIND(1.0D0))                              Input
               On entry: the argument z of the functions.

           3:  N -- INTEGER                                           Input
               On entry: the number, N, of members required in the sequence
               I    (z),I      (z),...,I        (z). Constraint: N >= 1.
                (nu)     (nu)+1         (nu)+N-1

           4:  SCALE -- CHARACTER*1                                   Input
               On entry: the scaling option.
                    If SCALE = 'U', the results are returned unscaled.

                    If SCALE = 'S', the results are returned scaled by the
                            -|Rez|
                    factor e      .
               Constraint: SCALE = 'U' or 'S'.

           5:  CY(N) -- COMPLEX(KIND(1.0D)) array                    Output
               On exit: the N required function values: CY(i) contains
               I        (z), for i=1,2,...,N.
                (nu)+i-1

           6:  NZ -- INTEGER                                         Output
               On exit: the number of components of CY that are set to zero
               due to underflow.

               If NZ > 0, then elements CY(N-NZ+1),CY(N-NZ+2),...,CY(N) are
               set to zero.

           7:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry FNU < 0.0,

               or       N < 1,

               or       SCALE /= 'U' or 'S'.

          IFAIL= 2
               No computation has been performed due to the likelihood of
               overflow, because real(Z) is greater than a machine-
               dependent threshold value (given in the Users' Note for
               your implementation). This error exit can only occur when
               SCALE = 'U'.

          IFAIL= 3
               The computation has been performed, but the errors due to
               argument reduction in elementary functions make it likely
               that the results returned by S18DEF are accurate to less
               than half of machine precision. This error exit may occur
               when either ABS(Z) or FNU + N - 1 is greater than a machine-
               dependent threshold value (given in the Users' Note for
               your implementation).

          IFAIL= 4
               No computation has been performed because the errors due to
               argument reduction in elementary functions mean that all
               precision in results returned by S18DEF would be lost. This
               error exit may occur when either ABS(Z) or FNU + N - 1 is
               greater than a machine-dependent threshold value (given in
               the Users' Note for your implementation).

          IFAIL= 5
               No results are returned because the algorithm termination
               condition has not been met. This may occur because the
               parameters supplied to S18DEF would have caused overflow or
               underflow.

          7. Accuracy

          All constants in subroutine S18DEF are given to approximately 18
          digits of precision. Calling the number of digits of precision in
          the floating-point arithmetic being used t, then clearly the
          maximum number of correct digits in the results obtained is
          limited by p=min(t,18). Because of errors in argument reduction
          when computing elementary functions inside S18DEF, the actual
          number of correct digits is limited, in general, by p-s, where
          s~max(1,|log  |z||,|log  (nu)|) represents the number of digits
                      10         10
          lost due to the argument reduction. Thus the larger the values of
          |z| and (nu), the less the precision in the result. If S18DEF is
          called with N>1, then computation of function values via
          recurrence may lead to some further small loss of accuracy.

          If function values which should nominally be identical are
          computed by calls to S18DEF with different base values of (nu)
          and different N, the computed values may not agree exactly.
          Empirical tests with modest values of (nu) and z have shown that
          the discrepancy is limited to the least significant 3-4 digits of
          precision.

          8. Further Comments

          The time taken by the routine for a call of S18DEF is
          approximately proportional to the value of N, plus a constant. In
          general it is much cheaper to call S18DEF with N greater than 1,
          rather than to make N separate calls to S18DEF.

          Paradoxically, for some values of z and (nu), it is cheaper to
          call S18DEF with a larger value of N than is required, and then
          discard the extra function values returned. However, it is not
          possible to state the precise circumstances in which this is
          likely to occur. It is due to the fact that the base value used
          to start recurrence may be calculated in different regions for
          different N, and the costs in each region may differ greatly.

          Note that if the function required is I (x) or I (x), i.e.,
                                                 0        1
          (nu)=0.0 or 1.0, where x is real and positive, and only a single
          function value is required, then it may be much cheaper to call
          S18AEF, S18AFF, S18CEF(*) or S18CFF(*), depending on whether a
          scaled result is required or not.

          9. Example

          The example program prints a caption and then proceeds to read
          sets of data from the input data stream. The first datum is a
          value for the order FNU, the second is a complex value for the
          argument, Z, and the third is a value for the parameter SCALE.
          The program calls the routine with N = 2 to evaluate the function
          for orders FNU and FNU + 1, and it prints the results. The
          process is repeated until the end of the input data stream is
          encountered.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs19aaf}{nags.ht}
{ Returns a value for the Kelvin function ber x}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs19aaf}{NAG Documentation: s19aaf}
\beginscroll
\begin{verbatim}



     S19AAF(3NAG)      Foundation Library (12/10/92)      S19AAF(3NAG)



          S19 -- Approximations of Special Functions                 S19AAF
                  S19AAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S19AAF returns a value for the Kelvin function ber x via the
          routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S19AAF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          This routine evaluates an approximation to the Kelvin function
          berx.

          Note: ber(-x)=berx, so the approximation need only consider
          x>=0.0.

          The routine is based on several Chebyshev expansions:

          For 0<=x<=5,

                               --'                 ( x)4
                         berx= >   a T (t) with t=2( -) -1;
                               --   r r            ( 5)
                               r=0

          For x>5,

                            

                        x/\/2
                       e      [(   1    )            1              ]
                berx= --------[(1+ -a(t))cos(alpha)+ -b(t)sin(alpha)]
                              [(   x    )            x              ]
                      \/2(pi)x

                            

                       -x/\/2
                      e      [(   1    )           1             ]
                   + --------[(1+ -c(t))sin(beta)+ -d(t)cos(beta)]
                             [(   x    )           x             ]
                     \/2(pi)x

                          x   (pi)           x   (pi)
          where (alpha)= ---- ----, (beta)= ---+ ----,
                               8                  8
                         \/2                /2

          and a(t), b(t), c(t), and d(t) are expansions in the variable
             10
          t= ---1.
             x

          When x is sufficiently close to zero, the result is set directly
          to ber 0=1.0.

          For large x, there is a danger of the result being totally
          inaccurate, as the error amplification factor grows in an
          essentially exponential manner; therefore the routine must fail.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               On entry ABS(X) is too large for an accurate result to be
               returned. On soft failure, the routine returns zero.

          7. Accuracy

          Since the function is oscillatory, the absolute error rather than
          the relative error is important. Let E be the absolute error in
          the result and (delta) be the relative error in the argument. If
          (delta) is somewhat larger than the machine precision, then we
          have:

                               |  x              |
                            E~=| ---(ber x+bei x)|(delta)
                               |        1     1  |
                               | \/2             |

          (provided E is within machine bounds).

          For small x the error amplification is insignificant and thus the
          absolute error is effectively bounded by the machine precision.

          For medium and large x, the error behaviour is oscillatory and
                                                  

                                      /   x   x/\/2
          its amplitude grows like   /  -----e    . Therefore it is not
                                   \/   2(pi)

          possible to calculate the function with any accuracy when
                       

              x/\/2  /2(pi)
          \/xe     > -------. Note that this value of x is much smaller than
                     (delta)

          the minimum value of x for which the function overflows.

          8. Further Comments

          For details of the time taken by the routine see the Users' Note
          for your implementation.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs19abf}{nags.ht}
{ Returns a value for the Kelvin function bei x}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs19abf}{NAG Documentation: s19abf}
\beginscroll
\begin{verbatim}



     S19ABF(3NAG)      Foundation Library (12/10/92)      S19ABF(3NAG)



          S19 -- Approximations of Special Functions                 S19ABF
                  S19ABF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S19ABF returns a value for the Kelvin function bei x via the
          routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S19ABF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          This routine evaluates an approximation to the Kelvin function
          beix.

          Note: bei(-x)=beix, so the approximation need only consider
          x>=0.0.

          The routine is based on several Chebyshev expansions:

          For 0<=x<=5,

                              2
                             x  --'                    ( x)4
                      bei x= -- >   a T (t),  with  t=2( -) -1;
                             4  --   r r               ( 5)
                                r=0

          For x>5,

                            

                        x/\/2
                       e      [(   1    )            1              ]
               bei x= --------[(1+ -a(t))sin(alpha)- -b(t)cos(alpha)]
                              [(   x    )            x              ]
                      \/2(pi)x

                            

                        x/\/2
                       e     [(   1    )           1             ]
                   + --------[(1+ -c(t))cos(beta)- -d(t)sin(beta)]
                             [(   x    )           x             ]
                     \/2(pi)x

                         x   (pi)          x   (pi)
          where(alpha)= ---- ----,(beta)= ---+ ----,
                              8                 8
                        \/2               /2

          and a(t), b(t), c(t), and d(t) are expansions in the variable
             10
          t= ---1.
             x

          When x is sufficiently close to zero, the result is computed as
                  2
                 x
          bei x= --. If this result would underflow, the result returned is
                 4
          beix=0.0.

          For large x, there is a danger of the result being totally
          inaccurate, as the error amplification factor grows in an
          essentially exponential manner; therefore the routine must fail.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               On entry ABS(X) is too large for an accurate result to be
               returned. On soft failure, the routine returns zero.

          7. Accuracy

          Since the function is oscillatory, the absolute error rather than
          the relative error is important. Let E be the absolute error in
          the function, and (delta) be the relative error in the argument.
          If (delta) is somewhat larger than the machine precision, then we
          have:

                              |  x               |
                           E~=| ---(-ber x+bei x)|(delta)
                              |         1     1  |
                              | \/2              |

          (provided E is within machine bounds).

          For small x the error amplification is insignificant and thus the
          absolute error is effectively bounded by the machine precision.

          For medium and large x, the error behaviour is oscillatory and
                                                 

                                      /   x   x\/2
          its amplitude grows like   /  -----e    . Therefore it is
                                   \/   2(pi)

          impossible to calculate the functions with any accuracy when
                  

              x/\/2 /2(pi)
          \/xe     > -------. Note that this value of x is much smaller than
                     (delta)

          the minimum value of x for which the function overflows.

          8. Further Comments

          For details of the time taken by the routine see the Users' Note
          for your implementation.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs19acf}{nags.ht}
{ Returns a value for the Kelvin function ker x}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs19acf}{NAG Documentation: s19acf}
\beginscroll
\begin{verbatim}



     S19ACF(3NAG)      Foundation Library (12/10/92)      S19ACF(3NAG)



          S19 -- Approximations of Special Functions                 S19ACF
                  S19ACF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S19ACF returns a value for the Kelvin function ker x, via the
          routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S19ACF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          This routine evaluates an approximation to the Kelvin function
          ker x.

          Note: for x<0 the function is undefined and at x=0 it is infinite
          so we need only consider x>0.

          The routine is based on several Chebyshev expansions:

          For 0<x<=1,

                                           (pi) 2
                          ker x=-f(t)logx+ ----x g(t)+y(t)
                                            16

                                                                       4
          where f(t), g(t) and y(t) are expansions in the variable t=2x -1;

          For 1<x<=3,

                                         (  11 )
                                ker x=exp(- --x)q(t)
                                         (  16 )

          where q(t) is an expansion in the variable t=x-2;

          For x>3,

                                  

                             -x/\/2
                      / (pi)       [(   1    )           1             ]
             ker x=  /  ----e      [(1+ -c(t))cos(beta)- -d(t)sin(beta)]
                   \/    2x        [(   x    )           x             ]


                         x   (pi)
          where (beta)= ---+ ----, and c(t) and d(t) are expansions in the
                              8
                        \/2
                      6
          variable t= --1.
                      x

          When x is sufficiently close to zero, the result is computed as

                                                            2
                                          ( x) (      3 2) x
                        ker x=-(gamma)-log( -)+((pi)- -x ) --
                                          ( 2) (      8  ) 16

          and when x is even closer to zero, simply as
                            ( x)
          ker x=-(gamma)-log( -).
                            ( 2)

                                                                       

                                                           / (pi) -x/\/2
          For large x, ker x is asymptotically given by   /  ----e      and
                                                        \/    2x

          this becomes so small that it cannot be computed without
          underflow and the routine fails.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function. Constraint: X > 0.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               On entry X is too large, the result underflows. On soft
               failure, the routine returns zero.

          IFAIL= 2
               On entry X <= 0, the function is undefined. On soft failure
               the routine returns zero.

          7. Accuracy

          Let E be the absolute error in the result, (epsilon) be the
          relative error in the result and (delta) be the relative error in
          the argument. If (delta) is somewhat larger than the machine
          precision, then we have:

                              |  x               |
                           E~=| ---(ker  x+kei x)|(delta),
                              |         1     1  |
                              | \/2              |

                                  |     ker  x+kei x|
                                  |  x      1     1 |
                       (epsilon)~=| --- ------------|(delta).
                                  |        ker x    |
                                  | \/2             |

          For very small x, the relative error amplification factor is
                                    1
          approximately given by  ------, which implies a strong
                                  |logx|
          attenuation of relative error. However, (epsilon) in general
          cannot be less than the machine precision.

          For small x, errors are damped by the function and hence are
          limited by the machine precision.

          For medium and large x, the error behaviour, like the function
          itself, is oscillatory, and hence only the absolute accuracy for
          the function can be maintained. For this range of x, the
                                                                      

                                                         / (pi)x -x/\/2
          amplitude of the absolute error decays like   /  -----e
                                                      \/     2

          which implies a strong attenuation of error. Eventually, ker x,
                                                           

                                               / (pi) -x/\/2
          which asymptotically behaves like   /  ----e     , becomes so
                                            \/    2x

          small that it cannot be calculated without causing underflow, and
          the routine returns zero. Note that for large x the errors are
          dominated by those of the Fortran intrinsic function EXP.

          8. Further Comments

          Underflow may occur for a few values of x close to the zeros of
          ker x, below the limit which causes a failure with IFAIL = 1.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs19adf}{nags.ht}
{ Returns a value for the Kelvin function keix}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs19adf}{NAG Documentation: s19adf}
\beginscroll
\begin{verbatim}



     S19ADF(3NAG)      Foundation Library (12/10/92)      S19ADF(3NAG)



          S19 -- Approximations of Special Functions                 S19ADF
                  S19ADF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S19ADF returns a value for the Kelvin function keix via the
          routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S19ADF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          This routine evaluates an approximation to the Kelvin function
          keix.

          Note: for x<0 the function is undefined, so we need only consider
          x>=0.

          The routine is based on several Chebyshev expansions:

          For 0<=x<=1,

                                           2
                                (pi)      x
                         keix=- ----f(t)+ --[-g(t)logx+v(t)]
                                 4        4

                                                                       4
          where f(t), g(t) and v(t) are expansions in the variable t=2x -1;

          For 1<x<=3,

                                         (  9 )
                                 keix=exp(- -x)u(t)
                                         (  8 )

          where u(t) is an expansion in the variable t=x-2;

          For x>3,

                                  

                      / (pi) -x/\/2[(   1)               1             ]
              keix=  /  ----e      [(1+ -)c(t)sin(beta)+ -d(t)cos(beta)]
                   \/    2x        [(   x)               x             ]


                         x   (pi)
          where (beta)= ---+ ----, and c(t) and d(t) are expansions in the
                              8
                        \/2
                      6
          variable t= --1.
                      x

          For x<0, the function is undefined, and hence the routine fails
          and returns zero.

          When x is sufficiently close to zero, the result is computed as

                                                          2
                                (pi) (             ( x)) x
                         keix=- ----+(1-(gamma)-log( -)) --
                                 4   (             ( 2)) 4

          and when x is even closer to zero simply as

                                           (pi)
                                    keix=- ----.
                                            4

                                                                      

                                                          / (pi) -x/\/2
          For large x, keix is asymptotically given by   /  ----e       and
                                                       \/    2x

          this becomes so small that it cannot be computed without
          underflow and the routine fails.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function. Constraint: X >=
               0.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          IFAIL= 1
               On entry X is too large, the result underflows. On soft
               failure, the routine returns zero.

          IFAIL= 2
               On entry X < 0, the function is undefined. On soft failure
               the routine returns zero.

          7. Accuracy

          Let E be the absolute error in the result, and (delta) be the
          relative error in the argument. If (delta) is somewhat larger
          than the machine representation error, then we have:

                             |  x                |
                          E~=| ---(-ker  x+kei x)|(delta).
                             |          1     1  |
                             | \/2               |

          For small x, errors are attenuated by the function and hence are
          limited by the machine precision.

          For medium and large x, the error behaviour, like the function
          itself, is oscillatory and hence only absolute accuracy of the
          function can be maintained. For this range of x, the amplitude of
                                                         

                                            / (pi)x -x/\/2
          the absolute error decays like   /  -----e      , which implies a
                                         \/     2

          strong attenuation of error. Eventually, keix, which is
                                                 

                                     / (pi) -x/\/2
          asymptotically given by   /  ----e      , becomes so small that it
                                  \/    2x

          cannot be calculated without causing underflow and therefore the
          routine returns zero. Note that for large x, the errors are
          dominated by those of the Fortran intrinsic function EXP.

          8. Further Comments

          Underflow may occur for a few values of x close to the zeros of
          keix, below the limit which causes a failure with IFAIL = 1.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs20acf}{nags.ht}
{ Returns a value for the Fresnel Integral $S(x)$}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs20acf}{NAG Documentation: s20acf}
\beginscroll
\begin{verbatim}



     S20ACF(3NAG)      Foundation Library (12/10/92)      S20ACF(3NAG)



          S20 -- Approximations of Special Functions                 S20ACF
                  S20ACF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S20ACF returns a value for the Fresnel Integral S(x), via the
          routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S20ACF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          This routine evaluates an approximation to the Fresnel Integral

                                     x
                                     /   ( (pi) 2)
                               S(x)= |sin( ----t )dt.
                                     /   (  2    )
                                     0

          Note: S(x)=-S(-x), so the approximation need only consider x>=0.0

          The routine is based on three Chebyshev expansions:

          For 0<x<=3,

                             3 --'                   ( x)4
                       S(x)=x  >   a T (t) , with t=2( -) -1;
                               --   r r              ( 3)
                               r=0

          For x>3,

                          1  f(x)   ( (pi) 2)  g(x)   ( (pi) 2)
                    S(x)= -- ----cos( ----x )- ----sin( ----x ),
                          2   x     (  2    )    3    (  2    )
                                                x

                        --'
          where f(x) =  >   b T (t),
                        --   r r
                        r=0

                      --'                  ( 3)4
          and g(x) =  >   c T (t), with t=2( -) -1.
                      --   r r             ( x)
                      r=0

                              (pi) 3
          For small x, S(x)~= ----x . This approximation is used when x is
                               6
          sufficiently small for the result to be correct to machine
          precision. For very small x, this approximation would underflow;
          the result is then set exactly to zero.

                               1                1
          For large x, f(x)~= ---- and g(x)~= -----. Therefore for
                              (pi)                2
                                              (pi)
                                       1                                 1
          moderately large x, when  ------- is negligible compared with  -,
                                        2 3                              2
                                    (pi) x
          the second term in the approximation for x>3 may be dropped. For
                                1                              1
          very large x, when  ----- becomes negligible, S(x)~= -. However
                              (pi)x                            2
          there will be considerable difficulties in calculating
             ( (pi) 2)
          cos( ----x ) accurately before this final limiting value can be
             (  2    )
                         ( (pi) 2)
          used. Since cos( ----x ) is periodic, its value is essentially
                         (  2    )
                                                2      2
          determined by the fractional part of x . If x =N+(theta) where N
                                                  ( (pi) 2)
          is an integer and 0<=(theta)<1, then cos( ----x ) depends on
                                                  (  2    )
          (theta) and on N modulo 4. By exploiting this fact, it is
          possible to retain significance in the calculation of
             ( (pi) 2)
          cos( ----x ) either all the way to the very large x limit, or at
             (  2    )
                                           x
          least until the integer part of  - is equal to the maximum
                                           2
          integer allowed on the machine.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          There are no failure exits from this routine. The parameter IFAIL
          has been included for consistency with other routines in this
          chapter.

          7. Accuracy

          Let (delta) and (epsilon) be the relative errors in the argument
          and result respectively.

          If (delta) is somewhat larger than the machine precision (i.e.,
          if (delta) is due to data errors etc), then (epsilon) and (delta)
          are approximately related by:

                                    |     ( (pi) 2)|
                                    | xsin( ----x )|
                                    |     (  2    )|
                         (epsilon)~=| -------------|(delta).
                                    |     S(x)     |

          Figure 1 shows the behaviour of the error amplification factor

          |     ( (pi) 2)|
          | xsin( ----x )|
          |     (  2    )|
          | -------------|.
          |     S(x)     |


                                     Figure 1
                   Please see figure in printed Reference Manual

          However if (delta) is of the same order as the machine precision,
          then rounding errors could make (epsilon) slightly larger than
          the above relation predicts.

          For small x, (epsilon)~=3(delta) and hence there is only moderate
          amplification of relative error. Of course for very small x where
          the correct result would underflow and exact zero is returned,
          relative error-control is lost.

          For moderately large values of x,

                                    |     ( (pi) 2)|
                       |(epsilon)|~=|2xsin( ----x )||(delta)|
                                    |     (  2    )|

          and the result will be subject to increasingly large
          amplification of errors. However the above relation breaks down
                                             1
          for large values of x (i.e., when  -- is of the order of the
                                              2
                                             x
          machine precision in this region the relative error in the result
                                       2
          is essentially bounded by  -----).
                                     (pi)x

          Hence the effects of error amplification are limited and at worst
          the relative error loss should not exceed half the possible
          number of significant figures.

          8. Further Comments

          None.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs20adf}{nags.ht}
{ Returns a value for the Fresnel Integral $C(x)$}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs20adf}{NAG Documentation: s20adf}
\beginscroll
\begin{verbatim}



     S20ADF(3NAG)      Foundation Library (12/10/92)      S20ADF(3NAG)



          S20 -- Approximations of Special Functions                 S20ADF
                  S20ADF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S20ADF returns a value for the Fresnel Integral C(x), via the
          routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S20ADF (X, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X

          3. Description

          This routine evaluates an approximation to the Fresnel Integral

                                     x
                                     /   ( (pi) 2)
                               C(x)= |cos( ----t )dt.
                                     /   (  2    )
                                     0

          Note: C(x)=-C(-x), so the approximation need only consider x>=0.0

          The routine is based on three Chebyshev expansions:

          For 0<x<=3,

                               --'                   ( x)4
                        C(x)=x >   a T (t) , with t=2( -) -1;
                               --   r r              ( 3)
                               r=0

          For x>3,

                          1  f(x)   ( (pi) 2)  g(x)   ( (pi) 2)
                    C(x)= -+ ----sin( ----x )- ----cos( ----x ),
                          2   x     (  2    )    3    (  2    )
                                                x

                        --'
          where f(x) =  >   b T (t),
                        --   r r
                        r=0

                      --'                  ( 3)4
          and g(x) =  >   c T (t), with t=2( -) -1.
                      --   r r             ( x)
                      r=0

          For small x, C(x)~=x. This approximation is used when x is
          sufficiently small for the result to be correct to machine
          precision.

                               1                1
          For large x, f(x)~= ---- and g(x)~= -----. Therefore for
                              (pi)                2
                                              (pi)
                                       1                                 1
          moderately large x, when  ------- is negligible compared with  -,
                                        2 3                              2
                                    (pi) x
          the second term in the approximation for x>3 may be dropped. For
                                1                              1
          very large x, when  ----- becomes negligible, C(x)~= -. However
                              (pi)x                            2
          there will be considerable difficulties in calculating
             ( (pi) 2)
          sin( ----x ) accurately before this final limiting value can be
             (  2    )
                         ( (pi) 2)
          used. Since sin( ----x ) is periodic, its value is essentially
                         (  2    )
                                                2      2
          determined by the fractional part of x . If x =N+(theta), where N
                                                  ( (pi) 2)
          is an integer and 0<=(theta)<1, then sin( ----x ) depends on
                                                  (  2    )
          (theta) and on N modulo 4. By exploiting this fact, it is
          possible to retain some significance in the calculation of
             ( (pi) 2)
          sin( ----x ) either all the way to the very large x limit, or at
             (  2    )
                                           x
          least until the integer part of  - is equal to the maximum
                                           2
          integer allowed on the machine.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input
               On entry: the argument x of the function.

           2:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          There are no failure exits from this routine. The parameter IFAIL
          has been included for consistency with other routines in this
          chapter.

          7. Accuracy

          Let (delta) and (epsilon) be the relative errors in the argument
          and result respectively.

          If (delta) is somewhat larger than the machine precision (i.e if
          (delta) is due to data errors etc), then (epsilon) and (delta)
          are approximately related by:

                                    |     ( (pi) 2)|
                                    | xcos( ----x )|
                                    |     (  2    )|
                         (epsilon)~=| -------------|(delta).
                                    |     C(x)     |

          Figure 1 shows the behaviour of the error amplification factor

          |     ( (pi) 2)|
          | xcos( ----x )|
          |     (  2    )|
          | -------------|.
          |     C(x)     |


                                     Figure 1
                   Please see figure in printed Reference Manual

          However if (delta) is of the same order as the machine precision,
          then rounding errors could make (epsilon) slightly larger than
          the above relation predicts.

          For small x, (epsilon)~=(delta) and there is no amplification of
          relative error.

          For moderately large values of x,

                                    |     ( (pi) 2)|
                       |(epsilon)|~=|2xcos( ----x )||(delta)|
                                    |     (  2    )|

          and the result will be subject to increasingly large
          amplification of errors. However the above relation breaks down
                                             1
          for large values of x (i.e., when  -- is of the order of the
                                              2
                                             x
          machine precision); in this region the relative error in the
                                              2
          result is essentially bounded by  -----).
                                            (pi)x

          Hence the effects of error amplification are limited and at worst
          the relative error loss should not exceed half the possible
          number of significant figures.

          8. Further Comments

          None.

          9. Example

          The example program reads values of the argument x from a file,
          evaluates the function at each value of x and prints the results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs21baf}{nags.ht}
{ Returns a value of an elementary integral}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs21baf}{NAG Documentation: s21baf}
\beginscroll
\begin{verbatim}



     S21BAF(3NAG)      Foundation Library (12/10/92)      S21BAF(3NAG)



          S21 -- Approximations of Special Functions                 S21BAF
                  S21BAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S21BAF returns a value of an elementary integral, which occurs as
          a degenerate case of an elliptic integral of the first kind, via
          the routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S21BAF (X, Y, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X, Y

          3. Description

          This routine calculates an approximate value for the integral

                                        infty
                                      1 /         dt
                             R (x,y)= - |     ----------
                              C       2 /       
                                        0     \/t+x(t+y)

          where x>=0 and y/=0.

          This function, which is related to the logarithm or inverse
          hyperbolic functions for y<x and to inverse circular functions if
          x<y, arises as a degenerate form of the elliptic integral of the
          first kind. If y<0, the result computed is the Cauchy principal
          value of the integral.

          The basic algorithm, which is due to Carlson [2] and [3], is to
          reduce the arguments recursively towards their mean by the
          system:

              x =x,
               0

              y =y
               0

              (mu) =(x +2y )/3,
                  n   n   n

              S =(y -x )/3(mu)
               n   n  n       n

                               

              (lambda) =y +2  /x y
                      n  n  \/  n n

              x   =(x +(lambda) )/4,
               n+1   n         n

              y   =(y +(lambda) )/4.
               n+1   n         n

          The quantity |S | for n=0,1,2,3,... decreases with increasing n,
                         n
                             n
          eventually |S |~1/4 . For small enough S  the required function
                       n                          n
          value can be approximated by the first few terms of the Taylor
          series about the mean. That is

                              (     2   3    4    5)
                              (   3S   S   3S   9S )
                              (     n   n    n    n)    
                      R (x,y)=(1+ ---+ --+ ---+ ---)/  /(mu) .
                       C      (   10   7    8   22 ) \/     n

          The truncation error involved in using this approximation is
                           6
          bounded by 16|S | /(1-2|S |) and the recursive process is stopped
                         n         n
          when S  is small enough for this truncation error to be
                n
          negligible compared to the machine precision.

          Within the domain of definition, the function value is itself
          representable for all representable values of its arguments.
          However, for values of the arguments near the extremes the above
          algorithm must be modified so as to avoid causing underflows or
          overflows in intermediate steps. In extreme regions arguments are
          pre-scaled away from the extremes and compensating scaling of the
          result is done before returning to the calling program.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          [2]   Carlson B C (1978) Computing Elliptic Integrals by
                Duplication. (Preprint) Department of Physics, Iowa State
                University.

          [3]   Carlson B C (1988) A Table of Elliptic Integrals of the
                Third Kind. Math. Comput. 51 267--280.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input

           2:  Y -- DOUBLE PRECISION                                  Input
               On entry: the arguments x and y of the function,
               respectively. Constraint: X >= 0.0 and Y /= 0.0.

           3:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry X < 0.0; the function is undefined.

          IFAIL= 2
               On entryY = 0.0; the function is undefined.

               On soft failure the routine returns zero.

          7. Accuracy

          In principle the routine is capable of producing full machine
          precision. However round-off errors in internal arithmetic will
          result in slight loss of accuracy. This loss should never be
          excessive as the algorithm does not involve any significant
          amplification of round-off error. It is reasonable to assume that
          the result is accurate to within a small multiple of the machine
          precision.

          8. Further Comments

          Users should consult the Chapter Introduction which shows the
          relationship of this function to the classical definitions of the
          elliptic integrals.

          9. Example

          This example program simply generates a small set of non-extreme
          arguments which are used with the routine to produce the table of
          low accuracy results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs21bbf}{nags.ht}
{ Value of the symmetrised elliptic integral of first kind}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs21bbf}{NAG Documentation: s21bbf}
\beginscroll
\begin{verbatim}



     S21BBF(3NAG)      Foundation Library (12/10/92)      S21BBF(3NAG)



          S21 -- Approximations of Special Functions                 S21BBF
                  S21BBF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S21BBF returns a value of the symmetrised elliptic integral of
          the first kind, via the routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S21BBF (X, Y, Z, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X, Y, Z

          3. Description

          This routine calculates an approximation to the integral

                                     infty
                                   1 /            dt
                        R (x,y,z)= - |     -----------------
                         F         2 /       
                                     0     \/(t+x)(t+y)(t+z)

          where x, y, z>=0 and at most one is zero.

          The basic algorithm, which is due to Carlson [2] and [3], is to
          reduce the arguments recursively towards their mean by the rule:

               x =min(x,y,z),z =max(x,y,z),
                0             0

               y = remaining third intermediate value argument.
                0

          (This ordering, which is possible because of the symmetry of the
          function, is done for technical reasons related to the avoidance
          of overflow and underflow.)

              (mu) =   (x +y +3z )/3
                  n      n  n   n

              X    =   (1-x )/(mu)
               n           n      n

              Y    =   (1-y )/(mu)
               n           n      n

              Z    =   (1-z )/(mu)
               n           n      n

                                           

              (lambda) =  /x y +  /y z +  /z x
                      n \/  n n /  n n /  n n

              x    =   (x +(lambda) )/4
               n+1       n         n

              y    =   (y +(lambda) )/4
               n+1       n         n

              z    =   (z +(lambda) )/4
               n+1       n         n

          (epsilon) =max(|X |,|Y |,|Z |) and the function may be
                   n       n    n    n
          approximated adequately by a 5th order power series:

                                         (        2           )
                                         (   E   E   3E E   E )
                                    1    (    2   2    2 3   3)
                      R (x,y,z)= --------(1- --+ --- -----+ --)
                       F                 (   10  24   44    14)
                                   /(mu)
                                 \/     n

          where E =X Y +Y Z +Z X ,E =X Y Z .
                 2  n n  n n  n n  3  n n n

          The truncation error involved in using this approximation is
                              6
          bounded by (epsilon) /4(1-(epsilon) ) and the recursive process
                              n              n
          is stopped when this truncation error is negligible compared with
          the machine precision.

          Within the domain of definition, the function value is itself
          representable for all representable values of its arguments.
          However, for values of the arguments near the extremes the above
          algorithm must be modified so as to avoid causing underflows or
          overflows in intermediate steps. In extreme regions arguments are
          pre-scaled away from the extremes and compensating scaling of the
          result is done before returning to the calling program.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          [2]   Carlson B C (1978) Computing Elliptic Integrals by
                Duplication. (Preprint) Department of Physics, Iowa State
                University.

          [3]   Carlson B C (1988) A Table of Elliptic Integrals of the
                Third Kind. Math. Comput. 51 267--280.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input

           2:  Y -- DOUBLE PRECISION                                  Input

           3:  Z -- DOUBLE PRECISION                                  Input
               On entry: the arguments x, y and z of the function.
               Constraint: X, Y, Z >= 0.0 and only one of X, Y and Z may be
               zero.

           4:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry one or more of X, Y and Z is negative; the function
               is undefined.

          IFAIL= 2
               On entry two or more of X, Y and Z are zero; the function is
               undefined.

               On soft failure, the routine returns zero.

          7. Accuracy

          In principle the routine is capable of producing full machine
          precision. However round-off errors in internal arithmetic will
          result in slight loss of accuracy. This loss should never be
          excessive as the algorithm does not involve any significant
          amplification of round-off error. It is reasonable to assume that
          the result is accurate to within a small multiple of the machine
          precision.

          8. Further Comments

          Users should consult the Chapter Introduction which shows the
          relationship of this function to the classical definitions of the
          elliptic integrals.

          If two arguments are equal, the function reduces to the
          elementary integral R , computed by S21BAF.
                               C

          9. Example

          This example program simply generates a small set of non-extreme
          arguments which are used with the routine to produce the table of
          low accuracy results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs21bcf}{nags.ht}
{ Value of the symmetrised elliptic integral of second kind}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs21bcf}{NAG Documentation: s21bcf}
\beginscroll
\begin{verbatim}



     S21BCF(3NAG)      Foundation Library (12/10/92)      S21BCF(3NAG)



          S21 -- Approximations of Special Functions                 S21BCF
                  S21BCF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S21BCF returns a value of the symmetrised elliptic integral of
          the second kind, via the routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S21BCF (X, Y, Z, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X, Y, Z

          3. Description

          This routine calculates an approximate value for the integral

                                    infty
                                  3 /             dt
                       R (x,y,z)= - |     -------------------
                        D         2 /        
                                    0       /               3
                                          \/ (t+x)(t+y)(t+z)

          where x, y>=0, at most one of x and y is zero, and z>0.

          The basic algorithm, which is due to Carlson [2] and [3], is to
          reduce the arguments recursively towards their mean by the rule:

              x    =   x
               0

              y    =   y
               0

              z    =   z
               0

              (mu) =   (x +y +3z )/5
                  n      n  n   n

              X    =   (1-x )/(mu)
               n           n      n

              Y    =   (1-y )/(mu)
               n           n      n

              Z    =   (1-z )/(mu)
               n           n      n

                                           

              (lambda) =  /x y +  /y z +  /z x
                       n\/  n n /  n n /  n n

              x    =   (x +(lambda) )/4
               n+1       n         n

              y    =   (y +(lambda) )/4
               n+1       n         n

              z    =   (z +(lambda) )/4
               n+1       n         n

          For n sufficiently large,

                                                       ( 1)n
                        (epsilon) =max(|X |,|Y |,|Z |)~( -)
                                 n       n    n    n   ( 4)

          and the function may be approximated adequately by a 5th order
                                   n-1          -m
                                   --          4
          power series R (x,y,z)=3 >   -------------------+
                        D          --                   
                                   m=0 (z +(lambda) )  /z
                                         m         n \/  m


               -n
              4     [   3 (2)  1 (3)  3   (2) 2  3  (4)  3  (2) (3)  3  (5)]
           ---------[1+ -S   + -S   + --(S   ) + --S   + --S   S   + --S   ]
                    [   7 n    3 n    22  n      11 n    13 n   n    13 n  ]
              /    3
             / (mu)
           \/      n

          where

                                 (m) ( m  m   m)
                                S   =(X +Y +3Z )/2m.
                                 n   ( n  n   n)

          The truncation error in this expansion is bounded by
                         6
               3(epsilon)
                         n
           ------------------- and the recursive process is terminated when
               

              /              3
             / (1-(epsilon) )
           \/              n
          this quantity is negligible compared with the machine precision.

          The routine may fail either because it has been called with
          arguments outside the domain of definition, or with arguments so
          extreme that there is an unavoidable danger of setting underflow
          or overflow.

                           -3/2
          Note: R (x,x,x)=x    , so there exists a region of extreme
                 D
          arguments for which the function value is not representable.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          [2]   Carlson B C (1978) Computing Elliptic Integrals by
                Duplication. (Preprint) Department of Physics, Iowa State
                University.

          [3]   Carlson B C (1988) A Table of Elliptic Integrals of the
                Third Kind. Math. Comput. 51 267--280.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input

           2:  Y -- DOUBLE PRECISION                                  Input

           3:  Z -- DOUBLE PRECISION                                  Input
               On entry: the arguments x, y and z of the function.
               Constraint: X, Y >= 0.0, Z > 0.0 and only one of X and Y may
               be zero.

           4:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry either X or Y is negative, or both X and Y are
               zero; the function is undefined.

          IFAIL= 2
               On entry Z <= 0.0; the function is undefined.

          IFAIL= 3
               On entry either Z is too close to zero or both X and Y are
               too close to zero: there is a danger of setting overflow.

          IFAIL= 4
               On entry at least one of X, Y and Z is too large: there is a
               danger of setting underflow.

               On soft failure the routine returns zero.

          7. Accuracy

          In principle the routine is capable of producing full machine
          precision. However round-off errors in internal arithmetic will
          result in slight loss of accuracy. This loss should never be
          excessive as the algorithm does not involve any significant
          amplification of round-off error. It is reasonable to assume that
          the result is accurate to within a small multiple of the machine
          precision.

          8. Further Comments

          Users should consult the Chapter Introduction which shows the
          relationship of this function to the classical definitions of the
          elliptic integrals.

          9. Example

          This example program simply generates a small set of non-extreme
          arguments which are used with the routine to produce the table of
          low accuracy results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXs21bdf}{nags.ht}
{ Value of the symmetrised elliptic integral of third kind}
\begin{chunk}{nags.ht}
\begin{page}{manpageXXs21bdf}{NAG Documentation: s21bdf}
\beginscroll
\begin{verbatim}



     S21BDF(3NAG)      Foundation Library (12/10/92)      S21BDF(3NAG)



          S21 -- Approximations of Special Functions                 S21BDF
                  S21BDF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          S21BDF returns a value of the symmetrised elliptic integral of
          the third kind, via the routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION S21BDF (X, Y, Z, R, IFAIL)
                 INTEGER          IFAIL
                 DOUBLE PRECISION X, Y, Z, R

          3. Description

          This routine calculates an approximation to the integral

                                    infty
                                  3 /                 dt
                 R (x,y,z,(rho))= - |     --------------------------
                  J               2 /                
                                    0     (t+(rho))\/(t+x)(t+y)(t+z)

          where x, y, z>=0, (rho)/=0 and at most one of x, y and z is zero.

          If p<0, the result computed is the Cauchy principal value of the
          integral.

          The basic algorithm, which is due to Carlson [2] and [3], is to
          reduce the arguments recursively towards their mean by the rule:

              x    =   x
               0

              y    =   y
               0

              z    =   z
               0

              (rho) =  (rho)
                   0

              (mu) =   (x +y +z +2(rho) )/5
                  n      n  n  n       n

              X    =   (1-x )/(mu)
               n           n      n

              Y    =   (1-y )/(mu)
               n           n      n

              Z    =   (1-z )/(mu)
               n           n      n

              P    =   (1-(rho) )/(mu)
               n               n      n

                                            

              (lambda) =   /x y +  /y z +  /z x
                        n\/  n n /  n n /  n n

              x    =   (x +(lambda) )/4
               n+1       n         n

              y    =   (y +(lambda) )/4
               n+1       n         n

              z    =   (z +(lambda) )/4
               n+1       n         n

              (rho) =  ((rho) +(lambda) )/4
                   n+1       n         n
                                                            2
                       [                                   ]
              (alpha) =[(rho) (  /x +  /y +  /z )+  /x y z ]
                     n [     n \/  n /  n /  n  /  n n n]

                                               2
              (beta) = (rho) ((rho) +(lambda) )
                    n       n      n         n

          For n sufficiently large,

                                                            1
                       (epsilon) =max(|X |,|Y |,|Z |,|P |)~ --
                                n       n    n    n    n     n
                                                            4

          and the function may be approximated by a 5th order power series
                            n-1
                            --  -m
          R (x,y,z,(rho))=3 >  4  R ((alpha) ,(beta) )
           J                --     C        m       m
                            m=0


                -n
               4     [   3 (2)  1 (3)  3   (2) 2  3  (4)  3  (2) (3)  3  (5)]
          + ---------[1+ -S   + -S   + --(S   ) + --S   + --S   S   + --S   ]
                     [   7 n    3 n    22  n      11 n    13 n   n    13 n  ]
               /    3
              / (mu)
            \/      n

                 (m)     m  m  m   m
          where S    = (X +Y +Z +2P )/2m.
                 n       n  n  n   n

          The truncation error in this expansion is bounded by
                          

                    6    /              3
          3(epsilon) /  / (1-(epsilon) )  and the recursion process is
                    n \/              n
          terminated when this quantity is negligible compared with the
          machine precision. The routine may fail either because it has
          been called with arguments outside the domain of definition or
          with arguments so extreme that there is an unavoidable danger of
          setting underflow or overflow.

                               3
                             - -
                               2

          Note: R (x,x,x,x)=x   , so there exists a region of extreme
                 J
          arguments for which the function value is not representable.

          4. References

          [1]   Abramowitz M and Stegun I A (1968) Handbook of Mathematical
                Functions. Dover Publications.

          [2]   Carlson B C (1978) Computing Elliptic Integrals by
                Duplication. (Preprint) Department of Physics, Iowa State
                University.

          [3]   Carlson B C (1988) A Table of Elliptic Integrals of the
                Third Kind. Math. Comput. 51 267--280.

          5. Parameters

           1:  X -- DOUBLE PRECISION                                  Input

           2:  Y -- DOUBLE PRECISION                                  Input

           3:  Z -- DOUBLE PRECISION                                  Input

           4:  R -- DOUBLE PRECISION                                  Input
               On entry: the arguments x, y, z and (rho) of the function.
               Constraint: X, Y, Z >= 0.0, R /= 0.0 and at most one of X, Y
               and Z may be zero.

           5:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry at least one of X, Y and Z is negative, or at least
               two of them are zero; the function is undefined.

          IFAIL= 2
               On entry R = 0.0; the function is undefined.

          IFAIL= 3
               On entry either R is too close to zero, or any two of X, Y
               and Z are too close to zero; there is a danger of setting
               overflow.

          IFAIL= 4
               On entry at least one of X, Y, Z and R is too large; there
               is a danger of setting underflow.

          IFAIL= 5
               An error has occurred in a call to S21BAF. Any such
               occurrence should be reported to NAG.

               On soft failure, the routine returns zero.

          7. Accuracy

          In principle the routine is capable of producing full machine
          precision. However round-off errors in internal arithmetic will
          result in slight loss of accuracy. This loss should never be
          excessive as the algorithm does not involve any significant
          amplification of round-off error. It is reasonable to assume that
          the result is accurate to within a small multiple of the machine
          precision.

          8. Further Comments

          Users should consult the Chapter Introduction which shows the
          relationship of this function to the classical definitions of the
          elliptic integrals.

          If the argument R is equal to any of the other arguments, the
          function reduces to the integral R , computed by S21BCF.
                                            D

          9. Example

          This example program simply generates a small set of non-extreme
          arguments which are used with the routine to produce the table of
          low accuracy results.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\section{nagx.ht}
\pagetitle{manpageXXx01}{nagx.ht}{ Mathematical Constants}
\begin{chunk}{nagx.ht}
\begin{page}{manpageXXx01}{NAG Documentation: x01}
\beginscroll
\begin{verbatim}



     X01(3NAG)         Foundation Library (12/10/92)         X01(3NAG)



          X01 -- Mathematical Constants                 Introduction -- X01
                                    Chapter X01
                              Mathematical Constants

          1. Scope of the Chapter

          This chapter is concerned with the provision of mathematical
          constants required by other routines within the Library.

          It should be noted that because of the trivial nature of the
          routines individual routine documents are not provided.

          2. Background to the Problems

          Some Library routines require mathematical constants to maximum
          machine precision. These routines call Chapter X01 and thus
          lessen the number of changes that have to be made between
          different implementations of the Library.

          3. Recommendations on Choice and Use of Routines

          Although these routines are primarily intended for use by other
          routines they may be accessed directly by the user:

          Constant           Fortran Specification

          (pi)               DOUBLE PRECISION FUNCTION X01AAF(X)
                             DOUBLE PRECISION X

          (gamma)            DOUBLE PRECISION FUNCTION X01ABF(X)
          (Euler constant)   DOUBLE PRECISION X

          The argument X of these routines is a dummy argument.


          X01 -- Mathematical Constants                     Contents -- X01
          Chapter X01

          Mathematical Constants

          X01AAF  (pi)

          X01ABF  Euler's constant, (gamma)

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXx02}{nagx.ht}{ Machine Constants}
\begin{chunk}{nagx.ht}
\begin{page}{manpageXXx02}{NAG Documentation: x02}
\beginscroll
\begin{verbatim}



     X02(3NAG)         Foundation Library (12/10/92)         X02(3NAG)



          X02 -- Machine Constants                      Introduction -- X02
                                    Chapter X02
                                 Machine Constants

          1. Scope of the Chapter

          This chapter is concerned with parameters which characterise
          certain aspects of the computing environment in which the NAG
          Foundation Library is implemented. They relate primarily to
          floating-point arithmetic, but also to integer arithmetic and the
          elementary functions. The values of the parameters vary from one
          implementation of the Library to another, but within the context
          of a single implementation they are constants.

          The parameters are intended for use primarily by other routines
          in the Library, but users of the Library may sometimes need to
          refer to them directly.

          Each parameter-value is returned by a separate Fortran function.
          Because of the trivial nature of the functions, individual
          routine documents are not provided; the necessary details are
          given in Section 3 of this Introduction.

          2. Background to the Problems

          2.1. Floating-Point Arithmetic

          2.1.1.  A model of floating-point arithmetic

          In order to characterise the important properties of floating-
          point arithmetic by means of a small number of parameters, NAG
          uses a simplified model of floating-point arithmetic. The
          parameters of the model can be chosen to provide a sufficiently
          close description of the behaviour of actual implementations of
          floating-point arithmetic, but not, in general, an exact
          description; actual implementations vary too much in the details
          of how numbers are represented or arithmetic operations are
          performed.

          The model is based on that developed by Brown [1], but differs in
          some respects. The essential features are summarised here.

          The model is characterised by four integer parameters and one
          logical parameter. The four integer parameters are:

                b  :  the base

                p  :  the precision (i.e. the number of significant base-B
                      digits)

              e    :  the minimum exponent
               min

              e    :  the maximum exponent
               max

          These parameters define a set of numerical values of the form:

                                           e
                                        f*b

          where the exponent e must lie in the range [e   ,e   ], and the
                                                       min  max
          fraction f (also called the mantissa or significand) lies in the
          range [1/b,1), and may be written:

                                    f=0.f f ...f
                                         1 2    p

          Thus f is a p-digit fraction to the base b; the f  are the base-b
                                                           i
          digits of the fraction: they are integers in the range 0 to b-1,
          and the leading digit f  must not be zero.
                                 1

          The set of values so defined (together with zero) are called
          model numbers. For example, if b=10, p=5, e   =-99 and e   =+99,
                                                     min          max
                                                   67
          then a typical model number is 0.12345*10  .

          The model numbers must obey certain rules for the computed
          results of the following basic arithmetic operations: addition,
          subtraction, multiplication, negation, absolute value, and
          comparisons. The rules depend on the value of the logical
          parameter ROUNDS.

          If ROUNDS is true, then the computed result must be the nearest
          model number to the exact result (assuming that overflow or
          underflow does not occur); if the exact result is midway between
          two model numbers, then it may be rounded either way.

          If ROUNDS is false, then: if the exact result is a model number,
          the computed result must be equal to the exact result; otherwise,
          the computed result may be either of the adjacent model numbers
          on either side of the exact result.

          For division and square root, this latter rule is further relaxed
          (regardless of the value of ROUNDS): the computed result may also
          be one of the next adjacent model numbers on either side of the
          permitted values just stated.

          On some machines, the full set of representable floating-point
          numbers conforms to the rules of the model with appropriate
          values of b, p, e   , e    and ROUNDS. For example, for machines
                           min   max
          with IEEE arithmetic, in double precision:

              b    =  2

              p    =  53

              e    =-1021
               min

              e    =1024 and ROUNDS is true.
               max

          For other machines, values of the model parameters must be chosen
          which define a large subset of the representable numbers;
          typically it may be necessary to decrease p by 1 (in which case
          ROUNDS is always set to false), or to increase e    or decrease
                                                          min
          e    by a little bit. There are additional rules to ensure that
           max
          arithmetic operations on those representable numbers which are
          not model numbers, are consistent with arithmetic on model
          numbers.

          (Note: the model used here differs from that described in Brown
          [1] in the following respects: square-root is treated, like
          division, as a weakly supported operator; and the logical
          parameter ROUNDS has been introduced to take account of machines
          with good rounding.)

          2.1.2.  Derived parameters of floating-point arithmetic

          Most numerical algorithms require access, not to the basic
          parameters of the model, but to certain derived values, of which
          the most important are:

                                   (1)  1-p
          the machine precision =  (-)*b    if ROUNDS is true,
          (epsilon):               (2)

                                    1-p
                                =  b    otherwise (but see Note below).

                                    e   -1
                                     min
          the smallest positive =  b
          model number:

                                            e
                                       -p    max
          the largest positive  =  (1-b  )*b
          model number:

          Note: this value is increased very slightly in some
          implementations to ensure that the computed result of 1+(epsilon)
          or 1-(epsilon) differs from 1. For example in IEEE binary single
                                                    -24  -47
          precision arithmetic the value is set to 2   +2   .

          Two additional derived values are used in the NAG Foundation
          Library. Their definitions depend not only on the properties of
          the basic arithmetic operations just considered, but also on
          properties of some of the elementary functions. We define the
          safe range parameter to be the smallest positive model number z
          such that for any x in the range [z,1/z] the following can be
          computed without undue loss of accuracy, overflow, underflow or
          other error:

              -x

              1/x

              -1/x

              SQRT(x)

              LOG(x)

              EXP(LOG(x))

              y**(LOG(x)/LOG(y)) for any y

          In a similar fashion we define the safe range parameter for
          complex arithmetic as the smallest positive model number z such
          that for any x in the range [z,1/z] the following can be computed
          without any undue loss of accuracy, overflow, underflow or other
          error:

              -w

              1/w

              -1/w

              SQRT(w)

              LOG(w)

              EXP(LOG(w))

              y**(LOG(w)/LOG(y)) for any y

              ABS(w)

          where w is any of x, ix, x+ix, 1/x, i/x, 1/x+i/x, and i is the
          square root of -1.

          This parameter was introduced to take account of the quality of
          complex arithmetic on the machine. On machines with well
          implemented complex arithmetic, its value will differ from that
          of the real safe range parameter by a small multiplying factor
          less than 10. For poorly implemented complex arithmetic this
          factor may be larger by many orders of magnitude.

          2.2. Other Aspects of the Computing Environment

          No attempt has been made to characterise comprehensively any
          other aspects of the computing environment. The other functions
          in this chapter provide specific information that is occasionally
          required by routines in the Library.

          2.3. References

          [1]   Brown W S (1981) A Simple but Realistic Model of Floating-
                point Computation. ACM Trans. Math. Softw. 7 445--480.

          3. Recommendations on Choice and Use of Routines

          3.1. Parameters of Floating-point Arithmetic

          DOUBLE PRECISION FUNCTION returns the machine precision i.e.
          X02AJF()                  (1)  1-p                       1-p
                                    (-)*b    if ROUNDS is true or b
                                    (2)
                                    otherwise (or a value very slightly
                                    larger than this, see Section 2.1.2)

          DOUBLE PRECISION FUNCTION returns the smallest positive model
          X02AKF()                               e   -1
                                                  min
                                    number i.e. b

          DOUBLE PRECISION FUNCTION returns the largest positive model
          X02ALF()                                       e
                                                    -p    max
                                    number i.e. (1-b  )*b


          DOUBLE PRECISION FUNCTION returns the safe range parameter as
          X02AMF()                  defined in Section 2.1.2

          DOUBLE PRECISION FUNCTION returns the safe range parameter for
          X02ANF()                  complex arithmetic as defined in
                                    Section 2.1.2

          INTEGER FUNCTION X02BHF() returns the model parameter b

          INTEGER FUNCTION X02BJF() returns the model parameter p

          INTEGER FUNCTION X02BKF() returns the model parameter e
                                                                 min

          INTEGER FUNCTION X02BLF() returns the model parameter e
                                                                 max

          LOGICAL FUNCTION X02DJF() returns the model parameter ROUNDS

          3.2. Parameters of Other Aspects of the Computing Environment

          DOUBLE PRECISION FUNCTION returns the largest positive real
          X02AHF(X)                 argument for which the SIN and COS
          DOUBLE PRECISION X        routines return a result with some
                                    meaningful accuracy

          INTEGER FUNCTION X02BBF   returns the largest positive integer
          (X)                       value
          DOUBLE PRECISION X

          INTEGER FUNCTION X02BEF   returns the maximum number of decimal
          (X)                       digits which can be accurately
          DOUBLE PRECISION X        represented over the whole range of
                                    floating-point numbers

          The argument X of these routines is a dummy argument.

          4. Example Program Text

          The example program simply prints the values of all the functions
          in Chapter X02. Obviously the results will vary from one
          implementation of the Library to another.


          X02 -- Machine Constants                          Contents -- X02
          Chapter X02

          Machine Constants

          X02AHF  Largest permissible argument for SIN and COS

          X02AJF  Machine precision

          X02AKF  Smallest positive model number

          X02ALF  Largest positive model number

          X02AMF  Safe range of floating-point arithmetic

          X02ANF  Safe range of complex floating-point arithmetic

          X02BBF  Largest representable integer

          X02BEF  Maximum number of decimal digits that can be represented

          X02BHF  Parameter of floating-point arithmetic model, b

          X02BJF  Parameter of floating-point arithmetic model, p

          X02BKF  Parameter of floating-point arithmetic model, e
                                                                 min

          X02BLF  Parameter of floating-point arithmetic model, e
                                                                 max

          X02DJF  Parameter of floating-point arithmetic model, ROUNDS

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXx04}{nagx.ht}{ Input/Output Utilities}
\begin{chunk}{nagx.ht}
\begin{page}{manpageXXx04}{NAG Documentation: x04}
\beginscroll
\begin{verbatim}



     X04(3NAG)         Foundation Library (12/10/92)         X04(3NAG)



          X04 -- Input/Output Utilities                 Introduction -- X04
                                    Chapter X04
                              Input/Output Utilities

          1. Scope of the Chapter

          This chapter contains utility routines concerned with input and
          output to or from an external file.

          2. Background to the Problems

          2.1. Output from NAG Foundation Library Routines

          Output from NAG Foundation Library routines to an external file
          falls into two categories:

          (a)   Error messages which are always associated with an error
                exit from a routine, that is, with a non-zero value of
                IFAIL as specified in Section 6 of the routine document.

          (b)   Advisory messages which include output of final results,
                output of intermediate results to monitor the course of a
                computation, and various warning or informative messages.

          Each category of output is written to its own Fortran output unit
          - the  error message unit  or the  advisory message unit. In
          practice these may be the same unit number. Default unit numbers
          are provided for each implementation of the Library (see the
          Users' Note); they may be changed by users. Output of error
          messages may be controlled by the setting of IFAIL (see the
          Essential Introduction). Output of advisory messages may usually
          be controlled by the setting of some other parameter (e.g.
          MSGLVL) (or in some routines also by IFAIL). An alternative
          mechanism for completely suppressing output is to set the
          relevant unit number < 0.

          For further information about error and advisory messages, see
          Chapter P01.

          2.2. Matrix Printing Routines

          Routines are provided to allow formatted output of general
          rectangular or triangular matrices stored in a two-dimensional
          array (real and complex data types).

          All output is directed to the unit number for output of advisory
          messages, which may be altered by a call to X04ABF.

          3. Recommendations on Choice and Use of Routines

          Apart from the obvious utility of the matrix printing routines,
          users of the Library may need to call routines in Chapter X04 for
          the following purposes:

               if the default unit number for error messages (given in the
               Users' Note for your implementation) is not satisfactory,
               it may be changed to a new value NERR by the statement

                     CALL X04AAF(1,NERR)

               Similarly the unit number for advisory messages may be
               changed to a new value NADV by the statement

                     CALL X04ABF(1,NADV)

          4. Index

          Accessing unit number:
               of advisory message unit                              X04ABF
               of error message unit                                 X04AAF
          Printing matrices:
               general complex matrix                                X04DAF
               general real matrix                                   X04CAF



          X04 -- Input/Output Utilities                     Contents -- X04
          Chapter X04

          Input/Output Utilities

          X04AAF  Return or set unit number for error messages

          X04ABF  Return or set unit number for advisory messages

          X04CAF  Print a real general matrix

          X04DAF  Print a complex general matrix

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXx04aaf}{nagx.ht}
{ Value of the current error message unit number}
\begin{chunk}{nagx.ht}
\begin{page}{manpageXXx04aaf}{NAG Documentation: x04aaf}
\beginscroll
\begin{verbatim}



     X04AAF(3NAG)      Foundation Library (12/10/92)      X04AAF(3NAG)



          X04 -- Input/Output Utilities                              X04AAF
                  X04AAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          X04AAF returns the value of the current error message unit
          number, or sets the current error message unit number to a new
          value.

          2. Specification

                 SUBROUTINE X04AAF (IFLAG, NERR)
                 INTEGER          IFLAG, NERR

          3. Description

          This routine enables those library routines which output error
          messages, to determine the number of the output unit to which the
          error messages are to be sent; in this case X04AAF is called with
          IFLAG = 0. X04AAF may also be called with IFLAG = 1 to set the
          unit number to a specified value. Otherwise a default value
          (stated in the Users' Note for your implementation) is returned.

          Records written to this output unit by other library routines are
          at most 80 characters long (including a line-printer carriage
          control character).

          Note that if the unit number is set < 0, no messages will be
          output.

          4. References

          None.

          5. Parameters

           1:  IFLAG -- INTEGER                                       Input
               On entry: the action to be taken (see NERR). Constraint:
               IFLAG = 0 or 1.

           2:  NERR -- INTEGER                                 Input/Output
               On entry:
                    if IFLAG = 0, NERR need not be set;

                    if IFLAG = 1, NERR must specify the new error message
                    unit number.
               On exit:
                    if IFLAG = 0, NERR is set to the current error message
                    unit number,

                    if IFLAG = 1, NERR is unchanged.
               Note that Fortran unit numbers must be positive or zero. If
               NERR is set < 0, output of error messages is totally
               suppressed.

          6. Error Indicators and Warnings

          None.

          7. Accuracy

          Not applicable.

          8. Further Comments

          The time taken by the routine is negligible.

          9. Example

          In this example X04AAF is called by the user's main program to
          make the error message from the routine DUMMY appear on the same
          unit as the rest of the output (unit 6). Normally a NAG
          Foundation Library routine with an IFAIL parameter (see Essential
          Introduction) would take the place of DUMMY.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXx04abf}{nagx.ht}
{ Value of the current advisory message unit number}
\begin{chunk}{nagx.ht}
\begin{page}{manpageXXx04abf}{NAG Documentation: x04abf}
\beginscroll
\begin{verbatim}



     X04ABF(3NAG)      Foundation Library (12/10/92)      X04ABF(3NAG)



          X04 -- Input/Output Utilities                              X04ABF
                  X04ABF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          X04ABF returns the value of the current advisory message unit
          number, or sets the current advisory message unit number to a new
          value.

          2. Specification

                 SUBROUTINE X04ABF (IFLAG, NADV)
                 INTEGER          IFLAG, NADV

          3. Description

          This routine enables those library routines which output advisory
          messages, to determine the number of the output unit to which the
          advisory messages are to be sent; in this case X04ABF is called
          with IFLAG = 0. X04ABF may also be called with IFLAG = 1 to set
          the unit number to a specified value. Otherwise a default value
          (stated in the User's Note for your implementation) is returned.

          Records written to this output unit by other library routines are
          at most 120 characters long (including a line-printer carriage
          control character), unless those library routines allow users to
          specify longer records.

          Note that if the unit number is set < 0, no messages will be
          output.

          4. References

          None.

          5. Parameters

           1:  IFLAG -- INTEGER                                       Input
               On entry: the action to be taken (see NADV). Constraint:
               IFLAG = 0 or 1.

           2:  NADV -- INTEGER                                 Input/Output
               On entry:
                    if IFLAG = 0, NADV need not be set;

                    if IFLAG = 1, NADV must specify the new advisory
                    message unit number.
               On exit:
                    if IFLAG = 0, NADV is set to the current advisory
                    message unit number;

                    if IFLAG = 1, NADV is unchanged.
               Note that Fortran unit numbers must be positive or zero. If
               NADV is set < 0, output of advisory messages is totally
               suppressed.

          6. Error Indicators and Warnings

          None.

          7. Accuracy

          Not applicable.

          8. Further Comments

          The time taken by this routine is negligible.

          9. Example

          In this example X04ABF is called by the user's main program to
          make the advisory message from the routine DUMMY appear on the
          same unit as the rest of the output (unit 6). Normally a NAG
          Foundation Library routine with an IFAIL parameter (see Essential
          Introduction) would take the place of DUMMY.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXx04caf}{nagx.ht}
{ Print a real matrix stored in a two-dimensional array}
\begin{chunk}{nagx.ht}
\begin{page}{manpageXXx04caf}{NAG Documentation: x04caf}
\beginscroll
\begin{verbatim}



     X04CAF(3NAG)      Foundation Library (12/10/92)      X04CAF(3NAG)



          X04 -- Input/Output Utilities                              X04CAF
                  X04CAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          X04CAF is an easy-to-use routine to print a real matrix stored in
          a two-dimensional array.

          2. Specification

                 SUBROUTINE X04CAF (MATRIX, DIAG, M, N, A, LDA, TITLE,
                1                   IFAIL)
                 INTEGER          M, N, LDA, IFAIL
                 DOUBLE PRECISION A(LDA,*)
                 CHARACTER*1      MATRIX, DIAG
                 CHARACTER*(*)    TITLE

          3. Description

          X04CAF prints a real matrix. It is an easy-to-use driver for
          X04CBF(*). The routine uses default values for the format in
          which numbers are printed, for labelling the rows and columns,
          and for output record length.

          X04CAF will choose a format code such that numbers will be
          printed with either an F8.4, F11.4 or a 1PE13.4 format. The F8.4
          code is chosen if the sizes of all the matrix elements to be
          printed lie between 0.001 and 1.0. The F11.4 code is chosen if
          the sizes of all the matrix elements to be printed lie between 0.
          001 and 9999.9999. Otherwise the 1PE13.4 code is chosen.

          The matrix is printed with integer row and column labels, and
          with a maximum record length of 80.

          The matrix is output to the unit defined by X04ABF.

          4. References

          None.

          5. Parameters

           1:  MATRIX -- CHARACTER*1                                  Input
               On entry: indicates the part of the matrix to be printed, as
               follows:

               MATRIX = 'G' (General), the whole of the rectangular matrix.

               MATRIX = 'L' (Lower), the lower triangle of the matrix, or
               the lower trapezium if the matrix has more rows than
               columns.

               MATRIX = 'U' (Upper), the upper triangle of the matrix, or
               the upper trapezium if the matrix has more columns than
               rows. Constraint: MATRIX must be one of 'G', 'L' or 'U'.

           2:  DIAG -- CHARACTER*1                                    Input
               On entry: unless MATRIX = 'G', DIAG must specify whether the
               diagonal elements of the matrix are to be printed, as
               follows:

               DIAG = 'B' (Blank), the diagonal elements of the matrix are
               not referenced and not printed.

               DIAG = 'U' (Unit diagonal), the diagonal elements of the
               matrix are not referenced, but are assumed all to be unity,
               and are printed as such.

               DIAG = 'N' (Non-unit diagonal), the diagonal elements of the
               matrix are referenced and printed.

               If MATRIX = 'G', then DIAG need not be set. Constraint: If
               MATRIX /= 'G', then DIAG must be one of 'B', 'U' or 'N'.

           3:  M -- INTEGER                                           Input

           4:  N -- INTEGER                                           Input
               On entry: the number of rows and columns of the matrix,
               respectively, to be printed.

               If either of M or N is less than 1, X04CAF will exit
               immediately after printing TITLE; no row or column labels
               are printed.

           5:  A(LDA,*) -- DOUBLE PRECISION array                     Input
               Note: the second dimension of the array A must be at least
               max(1,N).
               On entry: the matrix to be printed. Only the elements that
               will be referred to, as specified by parameters MATRIX and
               DIAG, need be set.

           6:  LDA -- INTEGER                                         Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which X04CAF is called.
               Constraint: LDA >= M.

           7:  TITLE -- CHARACTER*(*)                                 Input
               On entry: a title to be printed above the matrix. If TITLE =
               ' ', no title (and no blank line) will be printed.

               If TITLE contains more than 80 characters, the contents of
               TITLE will be wrapped onto more than one line, with the
               break after 80 characters.

               Any trailing blank characters in TITLE are ignored.

           8:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry MATRIX /= 'G', 'L' or 'U'.

          IFAIL= 2
               On entry MATRIX = 'L' or 'U', but DIAG /= 'N', 'U' or 'B'.

          IFAIL= 3
               On entry LDA < M.

          7. Accuracy

          Not applicable.

          8. Further Comments

          A call to X04CAF is equivalent to a call to X04CBF(*) with the
          following argument values:


                NCOLS = 80
                INDENT = 0
                LABROW = 'I'
                LABCOL = 'I'
                FORMAT = ' '


          9. Example

          This example program calls X04CAF twice, first to print a 3 by 5
          rectangular matrix, and then to print a 5 by 5 lower triangular
          matrix.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXx04daf}{nagx.ht}
{ Print a complex matrix stored in a 2D array}
\begin{chunk}{nagx.ht}
\begin{page}{manpageXXx04daf}{NAG Documentation: x04daf}
\beginscroll
\begin{verbatim}



     X04DAF(3NAG)      Foundation Library (12/10/92)      X04DAF(3NAG)



          X04 -- Input/Output Utilities                              X04DAF
                  X04DAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          X04DAF is an easy-to-use routine to print a complex matrix stored
          in a two-dimensional array.

          2. Specification

                 SUBROUTINE X04DAF (MATRIX, DIAG, M, N, A, LDA, TITLE,
                1                   IFAIL)
                 INTEGER              M, N, LDA, IFAIL
                 COMPLEX(KIND(1.0D0)) A(LDA,*)
                 CHARACTER*1          MATRIX, DIAG
                 CHARACTER*(*)        TITLE

          3. Description

          X04DAF prints a complex matrix. It is an easy-to-use driver for
          X04DBF(*). The routine uses default values for the format in
          which numbers are printed, for labelling the rows and columns,
          and for output record length.

          X04DAF will choose a format code such that numbers will be
          printed with either an F8.4, F11.4 or a 1PE13.4 format. The F8.4
          code is chosen if the sizes of all the matrix elements to be
          printed lie between 0.001 and 1.0. The F11.4 code is chosen if
          the sizes of all the matrix elements to be printed lie between 0.
          001 and 9999.9999. Otherwise the 1PE13.4 code is chosen. The
          chosen code is used to print each complex element of the matrix
          with the real part above the imaginary part.

          The matrix is printed with integer row and column labels, and
          with a maximum record length of 80.

          The matrix is output to the unit defined by X04ABF.

          4. References

          None.

          5. Parameters

           1:  MATRIX -- CHARACTER*1                                  Input
               On entry: indicates the part of the matrix to be printed, as
               follows:

               MATRIX = 'G' (General), the whole of the rectangular matrix.

               MATRIX = 'L' (Lower), the lower triangle of the matrix, or
               the lower trapezium if the matrix has more rows than
               columns.

               MATRIX = 'U' (Upper), the upper triangle of the matrix, or
               the upper trapezium if the matrix has more columns than
               rows. Constraint: MATRIX must be one of 'G', 'L' or 'U'.

           2:  DIAG -- CHARACTER*1                                    Input
               On entry: unless MATRIX = 'G', DIAG must specify whether the
               diagonal elements of the matrix are to be printed, as
               follows:

               DIAG = 'B' (Blank), the diagonal elements of the matrix are
               not referenced and not printed.

               DIAG = 'U' (Unit diagonal), the diagonal elements of the
               matrix are not referenced, but are assumed all to be unity,
               and are printed as such.

               DIAG = 'N' (Non-unit diagonal), the diagonal elements of the
               matrix are referenced and printed.

               If MATRIX = 'G', then DIAG need not be set. Constraint: If
               MATRIX /= 'G', then DIAG must be one of 'B', 'U' or 'N'.

           3:  M -- INTEGER                                           Input

           4:  N -- INTEGER                                           Input
               On entry: the number of rows and columns of the matrix,
               respectively, to be printed.

               If either of M or N is less than 1, X04DAF will exit
               immediately after printing TITLE; no row or column labels
               are printed.

           5:  A(LDA,*) -- COMPLEX(KIND(1.0D)) array                  Input
               Note: the second dimension of the array A must be at least
               max(1,N).
               On entry: the matrix to be printed. Only the elements that
               will be referred to, as specified by parameters MATRIX and
               DIAG, need be set.

           6:  LDA -- INTEGER                                         Input
               On entry:
               the first dimension of the array A as declared in the
               (sub)program from which X04DAF is called.
               Constraint: LDA >= M.

           7:  TITLE -- CHARACTER*(*)                                 Input

               On entry: a title to be printed above the matrix. If TITLE =
               ' ', no title (and no blank line) will be printed.

               If TITLE contains more than 80 characters, the contents of
               TITLE will be wrapped onto more than one line, with the
               break after 80 characters.

               Any trailing blank characters in TITLE are ignored.

           8:  IFAIL -- INTEGER                                Input/Output
               On entry: IFAIL must be set to 0, -1 or 1. For users not
               familiar with this parameter (described in the Essential
               Introduction) the recommended value is 0.

               On exit: IFAIL = 0 unless the routine detects an error (see
               Section 6).

          6. Error Indicators and Warnings

          Errors detected by the routine:

          If on entry IFAIL = 0 or -1, explanatory error messages are
          output on the current error message unit (as defined by X04AAF).

          IFAIL= 1
               On entry MATRIX /= 'G', 'L' or 'U'.

          IFAIL= 2
               On entry MATRIX = 'L' or 'U', but DIAG /= 'N', 'U' or 'B'.

          IFAIL= 3
               On entry LDA < M.

          7. Accuracy

          Not applicable.

          8. Further Comments

          A call to X04DAF is equivalent to a call to X04DBF(*) with the
          following argument values:


                NCOLS = 80
                INDENT = 0
                LABROW = 'I'
                LABCOL = 'I'
                FORMAT = ' '
                USEFRM = 'A'


          9. Example

          This example program calls X04DAF twice, first to print a 4 by 3
          rectangular matrix, and then to print a 4 by 4 lower triangular
          matrix.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.


\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXx05}{nagx.ht}{ Date and Time Utilities}
\begin{chunk}{nagx.ht}
\begin{page}{manpageXXx05}{NAG Documentation: x05}
\beginscroll
\begin{verbatim}



     X05(3NAG)         Foundation Library (12/10/92)         X05(3NAG)



          X05 -- Date and Time Utilities                Introduction -- X05
                                    Chapter X05
                              Date and Time Utilities

          1. Scope of the Chapter

          This chapter provides routines to obtain the current real time,
          and the amount of processor time used.

          2. Background to the Problems

          2.1. Real Time

          Routines are provided to obtain the current time in two different
          formats, and to compare two such times.

          2.2. Processor Time

          A routine is provided to return the current amount of processor
          time used. This allows the timing of a particular routine or
          section of code.

          3. Recommendations on Choice and Use of Routines

          X05AAF     returns the current date/time in integer format.

          X05ABF     converts from integer to character string date/time.

          X05ACF     compares two date/time character strings.

          X05BAF     returns the amount of processor time used.


          X05 -- Date and Time Utilities                    Contents -- X05
          Chapter X05

          Date and Time Utilities

          X05AAF  Return date and time as an array of integers

          X05ABF  Convert array of integers representing date and time to
                  character string

          X05ACF  Compare two character strings representing date and time

          X05BAF  Return the CPU time

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXx05aaf}{nagx.ht}{ Returns the current date and time}
\begin{chunk}{nagx.ht}
\begin{page}{manpageXXx05aaf}{NAG Documentation: x05aaf}
\beginscroll
\begin{verbatim}



     X05AAF(3NAG)      Foundation Library (12/10/92)      X05AAF(3NAG)



          X05 -- Date and Time Utilities                             X05AAF
                  X05AAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          X05AAF returns the current date and time.

          2. Specification

                 SUBROUTINE X05AAF (ITIME)
                 INTEGER          ITIME(7)

          3. Description

          X05AAF returns the current date and time as a set of seven
          integers.

          4. References

          None.

          5. Parameters

           1:  ITIME(7) -- INTEGER array                             Output
               On exit: the current date and time, as follows:

               ITIME(1) contains the current year.

               ITIME(2) contains the current month, in the range 1--12.

               ITIME(3) contains the current day, in the range 1--31.

               ITIME(4) contains the current hour, in the range 0--23.

               ITIME(5) contains the current minute, in the range 0--59.

               ITIME(6) contains the current second, in the range 0--59.

               ITIME(7) contains the current millisecond, in the range 0--
               999.

          6. Error Indicators and Warnings

          None.

          7. Accuracy

          The accuracy of this routine depends on the accuracy of the host
          machine. In particular, on some machines it may not be possible
          to return a value for the current millisecond, for example. In
          this case, the value returned will be zero.

          8. Further Comments

          None.

          9. Example

          This program prints out the vector ITIME after a call to X05AAF.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXx05abf}{nagx.ht}
{ From seven-integer format time and date to character string}
\begin{chunk}{nagx.ht}
\begin{page}{manpageXXx05abf}{NAG Documentation: x05abf}
\beginscroll
\begin{verbatim}



     X05ABF(3NAG)      Foundation Library (12/10/92)      X05ABF(3NAG)



          X05 -- Date and Time Utilities                             X05ABF
                  X05ABF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          X05ABF converts from a seven-integer format time and date, as
          returned by X05AAF, into a character string, returned via the
          routine name.

          2. Specification

                 CHARACTER*30 FUNCTION X05ABF (ITIME)
                 INTEGER          ITIME(7)

          3. Description

          X05ABF returns a character string of length 30 which contains the
          date and time as supplied in argument ITIME. On exit, the
          character string has the following format:


                `DAY XXTH MTH YEAR HR:MN:SC.MIL',


            where  DAY   is one of 'Sun', 'Mon', 'Tue', 'Wed', 'Thu',
                         'Fri', 'Sat',

                   XX    is an integer denoting the day of the month,

                   TH    is one of 'st', 'nd', 'rd', 'th',

                   MTH   is one of 'Jan', 'Feb', 'Mar', 'Apr', 'May',
                         'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',

                   YEAR  is the year as a four digit integer,

                   HR    is the hour,

                   MN    is the minute,

                   SC    is the second,

                   MIL   is the millisecond.

          If on entry the date in ITIME is invalid, the string returned is

          4. References

          None.

          5. Parameters

           1:  ITIME(7) -- INTEGER array                              Input
               On entry: a date and time in the format returned by X05AAF,
               as follows:
                   ITIME   must contain the year as a positive integer.
                   (1)

                   ITIME   must contain the month, in the range 1-12.
                   (2)

                   ITIME   must contain the day, in the range 1 to p, where
                   (3)     p = 28, 29, 30 or 31, depending on the month and
                           year.

                   ITIME   must contain the hour, in the range 0-23.
                   (4)

                   ITIME   must contain the minute, in the range 0-59.
                   (5)

                   ITIME   must contain the second, in the range 0-59.
                   (6)

                   ITIME   must contain the millisecond, in the range 0-
                   (7)     999.

          6. Error Indicators and Warnings

          None.

          7. Accuracy

          The day name included as part of the character string returned by
          this routine is calculated assuming that the date is part of the
          Gregorian calendar. This calendar has been in operation in Europe
          since October the 15th 1582, and in Great Britain since September
          the 14th 1752. Entry to this routine with a date earlier than
          these will therefore not return a day name that is historically
          accurate.

          8. Further Comments

          Two dates stored in character string format, as returned by this
          routine, may be compared by X05ACF.

          9. Example

          This program initialises a time in ITIME, and converts it to
          character format by a call to X05ABF.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXx05acf}{nagx.ht}{ Compares two date/time character strings}
\begin{chunk}{nagx.ht}
\begin{page}{manpageXXx05acf}{NAG Documentation: x05acf}
\beginscroll
\begin{verbatim}



     X05ACF(3NAG)      Foundation Library (12/10/92)      X05ACF(3NAG)



          X05 -- Date and Time Utilities                             X05ACF
                  X05ACF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          X05ACF compares two date/time character strings, each stored in
          the format returned by X05ABF.

          2. Specification

                 INTEGER FUNCTION X05ACF (CTIME1, CTIME2)
                 CHARACTER*(*)    CTIME1, CTIME2

          3. Description

          X05ACF compares two date/time character strings, and returns an
          integer that specifies which one is the earliest. The result is
          an integer returned through the routine name, with meaning as
          follows:

               X05ACF = -1: the first date/time string is earlier than the
               second.

               X05ACF = 0: the two date/time strings are equivalent.

               X05ACF = 1: the first date/time string is later than the
               second.

          4. References

          None.

          5. Parameters

           1:  CTIME1 -- CHARACTER*(*)                                Input

           2:  CTIME2 -- CHARACTER*(*)                                Input
               On entry: the date/time strings to be compared. These are
               expected be in the format returned by X05ABF, although
               X05ACF will still attempt to interpret the strings if they
               vary slightly from this format. See Section 8 for further
               details.

          6. Error Indicators and Warnings

          None.

          7. Accuracy

          Not applicable.

          8. Further Comments

          For flexibility, X05ACF will accept various formats for the two
          date/time strings CTIME1 and CTIME2.

          The strings do not have to be the same length. It is permissible,
          for example, to enter with one or both of the strings truncated
          to a smaller length, in which case missing fields are treated as
          zero.

          Each character string may be of any length, but everything after
          character 80 is ignored.

          Each string may or may not include an alphabetic day name, such
          as 'Wednesday', at its start. These day names are ignored, and no
          check is made that the day name corresponds correctly to the rest
          of the date.

          The month name may contain any number of characters provided it
          uniquely identifies the month, however all characters that are
          supplied are significant.

          Each field in the character string must be separated by one or
          more spaces.

          The case of all alphabetic characters is insignificant.

          Any field in a date time string that is indecipherable according
          to the above rules will be converted to a zero value internally.
          Thus two strings that are completely indecipherable will compare
          equal.

          According to these rules, all the following date/time strings are
          equivalent:

              'Thursday 10th July 1958 12:43:17.320'

              'THU 10th JULY 1958 12:43:17.320'

              '10th Jul 1958 12:43:17.320'

          9. Example

          This program initialises two date/time strings, and compares them
          by a call to X05ACF.


          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.

\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\pagetitle{manpageXXx05baf}{nagx.ht}{ Amount of processor time used}
\begin{chunk}{nagx.ht}
\begin{page}{manpageXXx05baf}{NAG Documentation: x05baf}
\beginscroll
\begin{verbatim}



     X05BAF(3NAG)      Foundation Library (12/10/92)      X05BAF(3NAG)



          X05 -- Date and Time Utilities                             X05BAF
                  X05BAF -- NAG Foundation Library Routine Document

          Note: Before using this routine, please read the Users' Note for
          your implementation to check implementation-dependent details.
          The symbol (*) after a NAG routine name denotes a routine that is
          not included in the Foundation Library.

          1. Purpose

          X05BAF returns the amount of processor time used since an
          unspecified previous time, via the routine name.

          2. Specification

                 DOUBLE PRECISION FUNCTION X05BAF ()

          3. Description

          X05BAF returns the number of seconds of processor time used since
          some previous time. The previous time is system dependent, but
          may be, for example, the time the current job or the current
          program started running.

          If the system clock of the host machine is inaccessible for any
          reason, X05BAF returns the value zero.

          4. References

          None.

          5. Parameters

          None.

          6. Error Indicators and Warnings

          None.

          7. Accuracy

          The accuracy of the value returned depends on the accuracy of the
          system clock on the host machine.

          8. Further Comments

          Since the value returned by X05BAF is the amount of processor
          time since some unspecified earlier time, no significance should
          be placed on the value other than as a marker to be compared with
          some later figure returned by X05BAF. The amount of processor
          time that has elapsed between two calls of X05BAF can be simply
          calculated as the earlier value subtracted from the later value.

          9. Example

          This program makes a call to X05BAF, performs some computations,
          makes another call to X05BAF, and gives the time used by the
          computations as the difference between the two returned values.

          The example program is not reproduced here. The source code for
          all example programs is distributed with the NAG Foundation
          Library software and should be available on-line.
\end{verbatim}
\endscroll
\end{page}

\end{chunk}
\chapter{NAG ASP Example Code}
\section{aspex.ht}
\pagetitle{Asp1ExampleCode}{aspex.ht}{Asp1 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp1ExampleCode}{Asp1 Example Code}
\begin{verbatim}
      DOUBLE PRECISION FUNCTION F(X)
      DOUBLE PRECISION X
      F=DSIN(X)
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp10ExampleCode}{aspex.ht}{Asp10 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp10ExampleCode}{Asp10 Example Code}
\begin{verbatim}
      SUBROUTINE COEFFN(P,Q,DQDL,X,ELAM,JINT)
      DOUBLE PRECISION ELAM,P,Q,X,DQDL
      INTEGER JINT
      P=1.0D0
      Q=((-1.0D0*X**3)+ELAM*X*X-2.0D0)/(X*X)
      DQDL=1.0D0
      RETURN
      END
\end{verbatim}
\end{page}


\end{chunk}
\pagetitle{Asp12ExampleCode}{aspex.ht}{Asp12 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp12ExampleCode}{Asp12 Example Code}
\begin{verbatim}
      SUBROUTINE MONIT (MAXIT,IFLAG,ELAM,FINFO)
      DOUBLE PRECISION ELAM,FINFO(15)
      INTEGER MAXIT,IFLAG
      IF(MAXIT.EQ.-1)THEN
        PRINT*,"Output from Monit"
      ENDIF
      PRINT*,MAXIT,IFLAG,ELAM,(FINFO(I),I=1,4)
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp19ExampleCode}{aspex.ht}{Asp19 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp19ExampleCode}{Asp19 Example Code}
\begin{verbatim}
      SUBROUTINE LSFUN2(M,N,XC,FVECC,FJACC,LJC)
      DOUBLE PRECISION FVECC(M),FJACC(LJC,N),XC(N)
      INTEGER M,N,LJC
      INTEGER I,J
      DO 25003 I=1,LJC
        DO 25004 J=1,N
          FJACC(I,J)=0.0D0
25004   CONTINUE
25003 CONTINUE
      FVECC(1)=((XC(1)-0.14D0)*XC(3)+(15.0D0*XC(1)-2.1D0)*XC(2)+1.0D0)/(
     &XC(3)+15.0D0*XC(2))
      FVECC(2)=((XC(1)-0.18D0)*XC(3)+(7.0D0*XC(1)-1.26D0)*XC(2)+1.0D0)/(
     &XC(3)+7.0D0*XC(2))
      FVECC(3)=((XC(1)-0.22D0)*XC(3)+(4.333333333333333D0*XC(1)-0.953333
     &3333333333D0)*XC(2)+1.0D0)/(XC(3)+4.333333333333333D0*XC(2))
      FVECC(4)=((XC(1)-0.25D0)*XC(3)+(3.0D0*XC(1)-0.75D0)*XC(2)+1.0D0)/(
     &XC(3)+3.0D0*XC(2))
      FVECC(5)=((XC(1)-0.29D0)*XC(3)+(2.2D0*XC(1)-0.6379999999999999D0)*
     &XC(2)+1.0D0)/(XC(3)+2.2D0*XC(2))
      FVECC(6)=((XC(1)-0.32D0)*XC(3)+(1.666666666666667D0*XC(1)-0.533333
     &3333333333D0)*XC(2)+1.0D0)/(XC(3)+1.666666666666667D0*XC(2))
      FVECC(7)=((XC(1)-0.35D0)*XC(3)+(1.285714285714286D0*XC(1)-0.45D0)*
     &XC(2)+1.0D0)/(XC(3)+1.285714285714286D0*XC(2))
      FVECC(8)=((XC(1)-0.39D0)*XC(3)+(XC(1)-0.39D0)*XC(2)+1.0D0)/(XC(3)+
     &XC(2))
      FVECC(9)=((XC(1)-0.37D0)*XC(3)+(XC(1)-0.37D0)*XC(2)+1.285714285714
     &286D0)/(XC(3)+XC(2))
      FVECC(10)=((XC(1)-0.58D0)*XC(3)+(XC(1)-0.58D0)*XC(2)+1.66666666666
     &6667D0)/(XC(3)+XC(2))
      FVECC(11)=((XC(1)-0.73D0)*XC(3)+(XC(1)-0.73D0)*XC(2)+2.2D0)/(XC(3)
     &+XC(2))
      FVECC(12)=((XC(1)-0.96D0)*XC(3)+(XC(1)-0.96D0)*XC(2)+3.0D0)/(XC(3)
     &+XC(2))
      FVECC(13)=((XC(1)-1.34D0)*XC(3)+(XC(1)-1.34D0)*XC(2)+4.33333333333
     &3333D0)/(XC(3)+XC(2))
      FVECC(14)=((XC(1)-2.1D0)*XC(3)+(XC(1)-2.1D0)*XC(2)+7.0D0)/(XC(3)+X
     &C(2))
      FVECC(15)=((XC(1)-4.39D0)*XC(3)+(XC(1)-4.39D0)*XC(2)+15.0D0)/(XC(3
     &)+XC(2))
      FJACC(1,1)=1.0D0
      FJACC(1,2)=-15.0D0/(XC(3)**2+30.0D0*XC(2)*XC(3)+225.0D0*XC(2)**2)
      FJACC(1,3)=-1.0D0/(XC(3)**2+30.0D0*XC(2)*XC(3)+225.0D0*XC(2)**2)
      FJACC(2,1)=1.0D0
      FJACC(2,2)=-7.0D0/(XC(3)**2+14.0D0*XC(2)*XC(3)+49.0D0*XC(2)**2)
      FJACC(2,3)=-1.0D0/(XC(3)**2+14.0D0*XC(2)*XC(3)+49.0D0*XC(2)**2)
      FJACC(3,1)=1.0D0
      FJACC(3,2)=((-0.1110223024625157D-15*XC(3))-4.333333333333333D0)/(
     &XC(3)**2+8.666666666666666D0*XC(2)*XC(3)+18.77777777777778D0*XC(2)
     &**2)
      FJACC(3,3)=(0.1110223024625157D-15*XC(2)-1.0D0)/(XC(3)**2+8.666666
     &666666666D0*XC(2)*XC(3)+18.77777777777778D0*XC(2)**2)
      FJACC(4,1)=1.0D0
      FJACC(4,2)=-3.0D0/(XC(3)**2+6.0D0*XC(2)*XC(3)+9.0D0*XC(2)**2)
      FJACC(4,3)=-1.0D0/(XC(3)**2+6.0D0*XC(2)*XC(3)+9.0D0*XC(2)**2)
      FJACC(5,1)=1.0D0
      FJACC(5,2)=((-0.1110223024625157D-15*XC(3))-2.2D0)/(XC(3)**2+4.399
     &999999999999D0*XC(2)*XC(3)+4.839999999999998D0*XC(2)**2)
      FJACC(5,3)=(0.1110223024625157D-15*XC(2)-1.0D0)/(XC(3)**2+4.399999
     &999999999D0*XC(2)*XC(3)+4.839999999999998D0*XC(2)**2)
      FJACC(6,1)=1.0D0
      FJACC(6,2)=((-0.2220446049250313D-15*XC(3))-1.666666666666667D0)/(
     &XC(3)**2+3.333333333333333D0*XC(2)*XC(3)+2.777777777777777D0*XC(2)
     &**2)
      FJACC(6,3)=(0.2220446049250313D-15*XC(2)-1.0D0)/(XC(3)**2+3.333333
     &333333333D0*XC(2)*XC(3)+2.777777777777777D0*XC(2)**2)
      FJACC(7,1)=1.0D0
      FJACC(7,2)=((-0.5551115123125783D-16*XC(3))-1.285714285714286D0)/(
     &XC(3)**2+2.571428571428571D0*XC(2)*XC(3)+1.653061224489796D0*XC(2)
     &**2)
      FJACC(7,3)=(0.5551115123125783D-16*XC(2)-1.0D0)/(XC(3)**2+2.571428
     &571428571D0*XC(2)*XC(3)+1.653061224489796D0*XC(2)**2)
      FJACC(8,1)=1.0D0
      FJACC(8,2)=-1.0D0/(XC(3)**2+2.0D0*XC(2)*XC(3)+XC(2)**2)
      FJACC(8,3)=-1.0D0/(XC(3)**2+2.0D0*XC(2)*XC(3)+XC(2)**2)
      FJACC(9,1)=1.0D0
      FJACC(9,2)=-1.285714285714286D0/(XC(3)**2+2.0D0*XC(2)*XC(3)+XC(2)*
     &*2)
      FJACC(9,3)=-1.285714285714286D0/(XC(3)**2+2.0D0*XC(2)*XC(3)+XC(2)*
     &*2)
      FJACC(10,1)=1.0D0
      FJACC(10,2)=-1.666666666666667D0/(XC(3)**2+2.0D0*XC(2)*XC(3)+XC(2)
     &**2)
      FJACC(10,3)=-1.666666666666667D0/(XC(3)**2+2.0D0*XC(2)*XC(3)+XC(2)
     &**2)
      FJACC(11,1)=1.0D0
      FJACC(11,2)=-2.2D0/(XC(3)**2+2.0D0*XC(2)*XC(3)+XC(2)**2)
      FJACC(11,3)=-2.2D0/(XC(3)**2+2.0D0*XC(2)*XC(3)+XC(2)**2)
      FJACC(12,1)=1.0D0
      FJACC(12,2)=-3.0D0/(XC(3)**2+2.0D0*XC(2)*XC(3)+XC(2)**2)
      FJACC(12,3)=-3.0D0/(XC(3)**2+2.0D0*XC(2)*XC(3)+XC(2)**2)
      FJACC(13,1)=1.0D0
      FJACC(13,2)=-4.333333333333333D0/(XC(3)**2+2.0D0*XC(2)*XC(3)+XC(2)
     &**2)
      FJACC(13,3)=-4.333333333333333D0/(XC(3)**2+2.0D0*XC(2)*XC(3)+XC(2)
     &**2)
      FJACC(14,1)=1.0D0
      FJACC(14,2)=-7.0D0/(XC(3)**2+2.0D0*XC(2)*XC(3)+XC(2)**2)
      FJACC(14,3)=-7.0D0/(XC(3)**2+2.0D0*XC(2)*XC(3)+XC(2)**2)
      FJACC(15,1)=1.0D0
      FJACC(15,2)=-15.0D0/(XC(3)**2+2.0D0*XC(2)*XC(3)+XC(2)**2)
      FJACC(15,3)=-15.0D0/(XC(3)**2+2.0D0*XC(2)*XC(3)+XC(2)**2)
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp20ExampleCode}{aspex.ht}{Asp20 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp20ExampleCode}{Asp20 Example Code}
\begin{verbatim}
      SUBROUTINE QPHESS(N,NROWH,NCOLH,JTHCOL,HESS,X,HX)
      DOUBLE PRECISION HX(N),X(N),HESS(NROWH,NCOLH)
      INTEGER JTHCOL,N,NROWH,NCOLH
      HX(1)=2.0D0*X(1)
      HX(2)=2.0D0*X(2)
      HX(3)=2.0D0*X(4)+2.0D0*X(3)
      HX(4)=2.0D0*X(4)+2.0D0*X(3)
      HX(5)=2.0D0*X(5)
      HX(6)=(-2.0D0*X(7))+(-2.0D0*X(6))
      HX(7)=(-2.0D0*X(7))+(-2.0D0*X(6))
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp24ExampleCode}{aspex.ht}{Asp24 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp24ExampleCode}{Asp24 Example Code}
\begin{verbatim}
      SUBROUTINE FUNCT1(N,XC,FC)
      DOUBLE PRECISION FC,XC(N)
      INTEGER N
      FC=10.0D0*XC(4)**4+(-40.0D0*XC(1)*XC(4)**3)+(60.0D0*XC(1)**2+5
     &.0D0)*XC(4)**2+((-10.0D0*XC(3))+(-40.0D0*XC(1)**3))*XC(4)+16.0D0*X
     &C(3)**4+(-32.0D0*XC(2)*XC(3)**3)+(24.0D0*XC(2)**2+5.0D0)*XC(3)**2+
     &(-8.0D0*XC(2)**3*XC(3))+XC(2)**4+100.0D0*XC(2)**2+20.0D0*XC(1)*XC(
     &2)+10.0D0*XC(1)**4+XC(1)**2
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp27ExampleCode}{aspex.ht}{Asp27 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp27ExampleCode}{Asp27 Example Code}
\begin{verbatim}
      FUNCTION DOT(IFLAG,N,Z,W,RWORK,LRWORK,IWORK,LIWORK)
      DOUBLE PRECISION W(N),Z(N),RWORK(LRWORK)
      INTEGER N,LIWORK,IFLAG,LRWORK,IWORK(LIWORK)
      DOT=(W(16)+(-0.5D0*W(15)))*Z(16)+((-0.5D0*W(16))+W(15)+(-0.5D0*W(1
     &4)))*Z(15)+((-0.5D0*W(15))+W(14)+(-0.5D0*W(13)))*Z(14)+((-0.5D0*W(
     &14))+W(13)+(-0.5D0*W(12)))*Z(13)+((-0.5D0*W(13))+W(12)+(-0.5D0*W(1
     &1)))*Z(12)+((-0.5D0*W(12))+W(11)+(-0.5D0*W(10)))*Z(11)+((-0.5D0*W(
     &11))+W(10)+(-0.5D0*W(9)))*Z(10)+((-0.5D0*W(10))+W(9)+(-0.5D0*W(8))
     &)*Z(9)+((-0.5D0*W(9))+W(8)+(-0.5D0*W(7)))*Z(8)+((-0.5D0*W(8))+W(7)
     &+(-0.5D0*W(6)))*Z(7)+((-0.5D0*W(7))+W(6)+(-0.5D0*W(5)))*Z(6)+((-0.
     &5D0*W(6))+W(5)+(-0.5D0*W(4)))*Z(5)+((-0.5D0*W(5))+W(4)+(-0.5D0*W(3
     &)))*Z(4)+((-0.5D0*W(4))+W(3)+(-0.5D0*W(2)))*Z(3)+((-0.5D0*W(3))+W(
     &2)+(-0.5D0*W(1)))*Z(2)+((-0.5D0*W(2))+W(1))*Z(1)
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp28ExampleCode}{aspex.ht}{Asp28 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp28ExampleCode}{Asp28 Example Code}
\begin{verbatim}
      SUBROUTINE IMAGE(IFLAG,N,Z,W,RWORK,LRWORK,IWORK,LIWORK)
      DOUBLE PRECISION Z(N),W(N),IWORK(LRWORK),RWORK(LRWORK)
      INTEGER N,LIWORK,IFLAG,LRWORK
      W(1)=0.01707454969713436D0*Z(16)+0.001747395874954051D0*Z(15)+0.00
     &2106973900813502D0*Z(14)+0.002957434991769087D0*Z(13)+(-0.00700554
     &0882865317D0*Z(12))+(-0.01219194009813166D0*Z(11))+0.0037230647365
     &3087D0*Z(10)+0.04932374658377151D0*Z(9)+(-0.03586220812223305D0*Z(
     &8))+(-0.04723268012114625D0*Z(7))+(-0.02434652144032987D0*Z(6))+0.
     &2264766947290192D0*Z(5)+(-0.1385343580686922D0*Z(4))+(-0.116530050
     &8238904D0*Z(3))+(-0.2803531651057233D0*Z(2))+1.019463911841327D0*Z
     &(1)
      W(2)=0.0227345011107737D0*Z(16)+0.008812321197398072D0*Z(15)+0.010
     &94012210519586D0*Z(14)+(-0.01764072463999744D0*Z(13))+(-0.01357136
     &72105995D0*Z(12))+0.00157466157362272D0*Z(11)+0.05258889186338282D
     &0*Z(10)+(-0.01981532388243379D0*Z(9))+(-0.06095390688679697D0*Z(8)
     &)+(-0.04153119955569051D0*Z(7))+0.2176561076571465D0*Z(6)+(-0.0532
     &5555586632358D0*Z(5))+(-0.1688977368984641D0*Z(4))+(-0.32440166056
     &67343D0*Z(3))+0.9128222941872173D0*Z(2)+(-0.2419652703415429D0*Z(1
     &))
      W(3)=0.03371198197190302D0*Z(16)+0.02021603150122265D0*Z(15)+(-0.0
     &06607305534689702D0*Z(14))+(-0.03032392238968179D0*Z(13))+0.002033
     &305231024948D0*Z(12)+0.05375944956767728D0*Z(11)+(-0.0163213312502
     &9967D0*Z(10))+(-0.05483186562035512D0*Z(9))+(-0.04901428822579872D
     &0*Z(8))+0.2091097927887612D0*Z(7)+(-0.05760560341383113D0*Z(6))+(-
     &0.1236679206156403D0*Z(5))+(-0.3523683853026259D0*Z(4))+0.88929961
     &32269974D0*Z(3)+(-0.2995429545781457D0*Z(2))+(-0.02986582812574917
     &D0*Z(1))
      W(4)=0.05141563713660119D0*Z(16)+0.005239165960779299D0*Z(15)+(-0.
     &01623427735779699D0*Z(14))+(-0.01965809746040371D0*Z(13))+0.054688
     &97337339577D0*Z(12)+(-0.014224695935687D0*Z(11))+(-0.0505181779315
     &6355D0*Z(10))+(-0.04353074206076491D0*Z(9))+0.2012230497530726D0*Z
     &(8)+(-0.06630874514535952D0*Z(7))+(-0.1280829963720053D0*Z(6))+(-0
     &.305169742604165D0*Z(5))+0.8600427128450191D0*Z(4)+(-0.32415033802
     &68184D0*Z(3))+(-0.09033531980693314D0*Z(2))+0.09089205517109111D0*
     &Z(1)
      W(5)=0.04556369767776375D0*Z(16)+(-0.001822737697581869D0*Z(15))+(
     &-0.002512226501941856D0*Z(14))+0.02947046460707379D0*Z(13)+(-0.014
     &45079632086177D0*Z(12))+(-0.05034242196614937D0*Z(11))+(-0.0376966
     &3291725935D0*Z(10))+0.2171103102175198D0*Z(9)+(-0.0824949256021352
     &4D0*Z(8))+(-0.1473995209288945D0*Z(7))+(-0.315042193418466D0*Z(6))
     &+0.9591623347824002D0*Z(5)+(-0.3852396953763045D0*Z(4))+(-0.141718
     &5427288274D0*Z(3))+(-0.03423495461011043D0*Z(2))+0.319820917706851
     &6D0*Z(1)
      W(6)=0.04015147277405744D0*Z(16)+0.01328585741341559D0*Z(15)+0.048
     &26082005465965D0*Z(14)+(-0.04319641116207706D0*Z(13))+(-0.04931323
     &319055762D0*Z(12))+(-0.03526886317505474D0*Z(11))+0.22295383396730
     &01D0*Z(10)+(-0.07375317649315155D0*Z(9))+(-0.1589391311991561D0*Z(
     &8))+(-0.328001910890377D0*Z(7))+0.952576555482747D0*Z(6)+(-0.31583
     &09975786731D0*Z(5))+(-0.1846882042225383D0*Z(4))+(-0.0703762046700
     &4427D0*Z(3))+0.2311852964327382D0*Z(2)+0.04254083491825025D0*Z(1)
      W(7)=0.06069778964023718D0*Z(16)+0.06681263884671322D0*Z(15)+(-0.0
     &2113506688615768D0*Z(14))+(-0.083996867458326D0*Z(13))+(-0.0329843
     &8523869648D0*Z(12))+0.2276878326327734D0*Z(11)+(-0.067356038933017
     &95D0*Z(10))+(-0.1559813965382218D0*Z(9))+(-0.3363262957694705D0*Z(
     &8))+0.9442791158560948D0*Z(7)+(-0.3199955249404657D0*Z(6))+(-0.136
     &2463839920727D0*Z(5))+(-0.1006185171570586D0*Z(4))+0.2057504515015
     &423D0*Z(3)+(-0.02065879269286707D0*Z(2))+0.03160990266745513D0*Z(1
     &)
      W(8)=0.126386868896738D0*Z(16)+0.002563370039476418D0*Z(15)+(-0.05
     &581757739455641D0*Z(14))+(-0.07777893205900685D0*Z(13))+0.23117338
     &45834199D0*Z(12)+(-0.06031581134427592D0*Z(11))+(-0.14805474755869
     &52D0*Z(10))+(-0.3364014128402243D0*Z(9))+0.9364014128402244D0*Z(8)
     &+(-0.3269452524413048D0*Z(7))+(-0.1396841886557241D0*Z(6))+(-0.056
     &1733845834199D0*Z(5))+0.1777789320590069D0*Z(4)+(-0.04418242260544
     &359D0*Z(3))+(-0.02756337003947642D0*Z(2))+0.07361313110326199D0*Z(
     &1)
      W(9)=0.07361313110326199D0*Z(16)+(-0.02756337003947642D0*Z(15))+(-
     &0.04418242260544359D0*Z(14))+0.1777789320590069D0*Z(13)+(-0.056173
     &3845834199D0*Z(12))+(-0.1396841886557241D0*Z(11))+(-0.326945252441
     &3048D0*Z(10))+0.9364014128402244D0*Z(9)+(-0.3364014128402243D0*Z(8
     &))+(-0.1480547475586952D0*Z(7))+(-0.06031581134427592D0*Z(6))+0.23
     &11733845834199D0*Z(5)+(-0.07777893205900685D0*Z(4))+(-0.0558175773
     &9455641D0*Z(3))+0.002563370039476418D0*Z(2)+0.126386868896738D0*Z(
     &1)
      W(10)=0.03160990266745513D0*Z(16)+(-0.02065879269286707D0*Z(15))+0
     &.2057504515015423D0*Z(14)+(-0.1006185171570586D0*Z(13))+(-0.136246
     &3839920727D0*Z(12))+(-0.3199955249404657D0*Z(11))+0.94427911585609
     &48D0*Z(10)+(-0.3363262957694705D0*Z(9))+(-0.1559813965382218D0*Z(8
     &))+(-0.06735603893301795D0*Z(7))+0.2276878326327734D0*Z(6)+(-0.032
     &98438523869648D0*Z(5))+(-0.083996867458326D0*Z(4))+(-0.02113506688
     &615768D0*Z(3))+0.06681263884671322D0*Z(2)+0.06069778964023718D0*Z(
     &1)
      W(11)=0.04254083491825025D0*Z(16)+0.2311852964327382D0*Z(15)+(-0.0
     &7037620467004427D0*Z(14))+(-0.1846882042225383D0*Z(13))+(-0.315830
     &9975786731D0*Z(12))+0.952576555482747D0*Z(11)+(-0.328001910890377D
     &0*Z(10))+(-0.1589391311991561D0*Z(9))+(-0.07375317649315155D0*Z(8)
     &)+0.2229538339673001D0*Z(7)+(-0.03526886317505474D0*Z(6))+(-0.0493
     &1323319055762D0*Z(5))+(-0.04319641116207706D0*Z(4))+0.048260820054
     &65965D0*Z(3)+0.01328585741341559D0*Z(2)+0.04015147277405744D0*Z(1)
      W(12)=0.3198209177068516D0*Z(16)+(-0.03423495461011043D0*Z(15))+(-
     &0.1417185427288274D0*Z(14))+(-0.3852396953763045D0*Z(13))+0.959162
     &3347824002D0*Z(12)+(-0.315042193418466D0*Z(11))+(-0.14739952092889
     &45D0*Z(10))+(-0.08249492560213524D0*Z(9))+0.2171103102175198D0*Z(8
     &)+(-0.03769663291725935D0*Z(7))+(-0.05034242196614937D0*Z(6))+(-0.
     &01445079632086177D0*Z(5))+0.02947046460707379D0*Z(4)+(-0.002512226
     &501941856D0*Z(3))+(-0.001822737697581869D0*Z(2))+0.045563697677763
     &75D0*Z(1)
      W(13)=0.09089205517109111D0*Z(16)+(-0.09033531980693314D0*Z(15))+(
     &-0.3241503380268184D0*Z(14))+0.8600427128450191D0*Z(13)+(-0.305169
     &742604165D0*Z(12))+(-0.1280829963720053D0*Z(11))+(-0.0663087451453
     &5952D0*Z(10))+0.2012230497530726D0*Z(9)+(-0.04353074206076491D0*Z(
     &8))+(-0.05051817793156355D0*Z(7))+(-0.014224695935687D0*Z(6))+0.05
     &468897337339577D0*Z(5)+(-0.01965809746040371D0*Z(4))+(-0.016234277
     &35779699D0*Z(3))+0.005239165960779299D0*Z(2)+0.05141563713660119D0
     &*Z(1)
      W(14)=(-0.02986582812574917D0*Z(16))+(-0.2995429545781457D0*Z(15))
     &+0.8892996132269974D0*Z(14)+(-0.3523683853026259D0*Z(13))+(-0.1236
     &679206156403D0*Z(12))+(-0.05760560341383113D0*Z(11))+0.20910979278
     &87612D0*Z(10)+(-0.04901428822579872D0*Z(9))+(-0.05483186562035512D
     &0*Z(8))+(-0.01632133125029967D0*Z(7))+0.05375944956767728D0*Z(6)+0
     &.002033305231024948D0*Z(5)+(-0.03032392238968179D0*Z(4))+(-0.00660
     &7305534689702D0*Z(3))+0.02021603150122265D0*Z(2)+0.033711981971903
     &02D0*Z(1)
      W(15)=(-0.2419652703415429D0*Z(16))+0.9128222941872173D0*Z(15)+(-0
     &.3244016605667343D0*Z(14))+(-0.1688977368984641D0*Z(13))+(-0.05325
     &555586632358D0*Z(12))+0.2176561076571465D0*Z(11)+(-0.0415311995556
     &9051D0*Z(10))+(-0.06095390688679697D0*Z(9))+(-0.01981532388243379D
     &0*Z(8))+0.05258889186338282D0*Z(7)+0.00157466157362272D0*Z(6)+(-0.
     &0135713672105995D0*Z(5))+(-0.01764072463999744D0*Z(4))+0.010940122
     &10519586D0*Z(3)+0.008812321197398072D0*Z(2)+0.0227345011107737D0*Z
     &(1)
      W(16)=1.019463911841327D0*Z(16)+(-0.2803531651057233D0*Z(15))+(-0.
     &1165300508238904D0*Z(14))+(-0.1385343580686922D0*Z(13))+0.22647669
     &47290192D0*Z(12)+(-0.02434652144032987D0*Z(11))+(-0.04723268012114
     &625D0*Z(10))+(-0.03586220812223305D0*Z(9))+0.04932374658377151D0*Z
     &(8)+0.00372306473653087D0*Z(7)+(-0.01219194009813166D0*Z(6))+(-0.0
     &07005540882865317D0*Z(5))+0.002957434991769087D0*Z(4)+0.0021069739
     &00813502D0*Z(3)+0.001747395874954051D0*Z(2)+0.01707454969713436D0*
     &Z(1)
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp29ExampleCode}{aspex.ht}{Asp29 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp29ExampleCode}{Asp29 Example Code}
\begin{verbatim}
      SUBROUTINE MONIT(ISTATE,NEXTIT,NEVALS,NEVECS,K,F,D)
      DOUBLE PRECISION D(K),F(K)
      INTEGER K,NEXTIT,NEVALS,NVECS,ISTATE
      CALL F02FJZ(ISTATE,NEXTIT,NEVALS,NEVECS,K,F,D)
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp30ExampleCode}{aspex.ht}{Asp30 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp30ExampleCode}{Asp30 Example Code}
\begin{verbatim}
      SUBROUTINE APROD(MODE,M,N,X,Y,RWORK,LRWORK,IWORK,LIWORK)
      DOUBLE PRECISION X(N),Y(M),RWORK(LRWORK)
      INTEGER M,N,LIWORK,IFAIL,LRWORK,IWORK(LIWORK),MODE
      DOUBLE PRECISION A(5,5)
      EXTERNAL F06PAF
      A(1,1)=1.0D0
      A(1,2)=0.0D0
      A(1,3)=0.0D0
      A(1,4)=-1.0D0
      A(1,5)=0.0D0
      A(2,1)=0.0D0
      A(2,2)=1.0D0
      A(2,3)=0.0D0
      A(2,4)=0.0D0
      A(2,5)=-1.0D0
      A(3,1)=0.0D0
      A(3,2)=0.0D0
      A(3,3)=1.0D0
      A(3,4)=-1.0D0
      A(3,5)=0.0D0
      A(4,1)=-1.0D0
      A(4,2)=0.0D0
      A(4,3)=-1.0D0
      A(4,4)=4.0D0
      A(4,5)=-1.0D0
      A(5,1)=0.0D0
      A(5,2)=-1.0D0
      A(5,3)=0.0D0
      A(5,4)=-1.0D0
      A(5,5)=4.0D0
      IF(MODE.EQ.1)THEN
        CALL F06PAF('N',M,N,1.0D0,A,M,X,1,1.0D0,Y,1)
      ELSEIF(MODE.EQ.2)THEN
        CALL F06PAF('T',M,N,1.0D0,A,M,Y,1,1.0D0,X,1)
      ENDIF
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp31ExampleCode}{aspex.ht}{Asp31 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp31ExampleCode}{Asp31 Example Code}
\begin{verbatim}
      SUBROUTINE PEDERV(X,Y,PW)
      DOUBLE PRECISION X,Y(*)
      DOUBLE PRECISION PW(3,3)
      PW(1,1)=-0.03999999999999999D0
      PW(1,2)=10000.0D0*Y(3)
      PW(1,3)=10000.0D0*Y(2)
      PW(2,1)=0.03999999999999999D0
      PW(2,2)=(-10000.0D0*Y(3))+(-60000000.0D0*Y(2))
      PW(2,3)=-10000.0D0*Y(2)
      PW(3,1)=0.0D0
      PW(3,2)=60000000.0D0*Y(2)
      PW(3,3)=0.0D0
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp33ExampleCode}{aspex.ht}{Asp33 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp33ExampleCode}{Asp33 Example Code}
\begin{verbatim}
      SUBROUTINE REPORT(X,V,JINT)
      DOUBLE PRECISION V(3),X
      INTEGER JINT
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp34ExampleCode}{aspex.ht}{Asp34 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp34ExampleCode}{Asp34 Example Code}
\begin{verbatim}
      SUBROUTINE MSOLVE(IFLAG,N,X,Y,RWORK,LRWORK,IWORK,LIWORK)
      DOUBLE PRECISION RWORK(LRWORK),X(N),Y(N)
      INTEGER I,J,N,LIWORK,IFLAG,LRWORK,IWORK(LIWORK)
      DOUBLE PRECISION W1(3),W2(3),MS(3,3)
      IFLAG=-1
      MS(1,1)=2.0D0
      MS(1,2)=1.0D0
      MS(1,3)=0.0D0
      MS(2,1)=1.0D0
      MS(2,2)=2.0D0
      MS(2,3)=1.0D0
      MS(3,1)=0.0D0
      MS(3,2)=1.0D0
      MS(3,3)=2.0D0
      CALL F04ASF(MS,N,X,N,Y,W1,W2,IFLAG)
      IFLAG=-IFLAG
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp35ExampleCode}{aspex.ht}{Asp35 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp35ExampleCode}{Asp35 Example Code}
\begin{verbatim}
      SUBROUTINE FCN(N,X,FVEC,FJAC,LDFJAC,IFLAG)
      DOUBLE PRECISION X(N),FVEC(N),FJAC(LDFJAC,N)
      INTEGER LDFJAC,N,IFLAG
      IF(IFLAG.EQ.1)THEN
        FVEC(1)=(-1.0D0*X(2))+X(1)
        FVEC(2)=(-1.0D0*X(3))+2.0D0*X(2)
        FVEC(3)=3.0D0*X(3)
      ELSEIF(IFLAG.EQ.2)THEN
        FJAC(1,1)=1.0D0
        FJAC(1,2)=-1.0D0
        FJAC(1,3)=0.0D0
        FJAC(2,1)=0.0D0
        FJAC(2,2)=2.0D0
        FJAC(2,3)=-1.0D0
        FJAC(3,1)=0.0D0
        FJAC(3,2)=0.0D0
        FJAC(3,3)=3.0D0
      ENDIF
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp4ExampleCode}{aspex.ht}{Asp4 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp4ExampleCode}{Asp4 Example Code}
\begin{verbatim}
      DOUBLE PRECISION FUNCTION FUNCTN(NDIM,X)
      DOUBLE PRECISION X(NDIM)
      INTEGER NDIM
      FUNCTN=(4.0D0*X(1)*X(3)**2*DEXP(2.0D0*X(1)*X(3)))/(X(4)**2+(2.0D0*
     &X(2)+2.0D0)*X(4)+X(2)**2+2.0D0*X(2)+1.0D0)
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp41ExampleCode}{aspex.ht}{Asp41 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp41ExampleCode}{Asp41 Example Code}
\begin{verbatim}
      SUBROUTINE FCN(X,EPS,Y,F,N)
      DOUBLE PRECISION EPS,F(N),X,Y(N)
      INTEGER N
      F(1)=Y(2)
      F(2)=Y(3)
      F(3)=(-1.0D0*Y(1)*Y(3))+2.0D0*EPS*Y(2)**2+(-2.0D0*EPS)
      RETURN
      END
      SUBROUTINE JACOBF(X,EPS,Y,F,N)
      DOUBLE PRECISION EPS,F(N,N),X,Y(N)
      INTEGER N
      F(1,1)=0.0D0
      F(1,2)=1.0D0
      F(1,3)=0.0D0
      F(2,1)=0.0D0
      F(2,2)=0.0D0
      F(2,3)=1.0D0
      F(3,1)=-1.0D0*Y(3)
      F(3,2)=4.0D0*EPS*Y(2)
      F(3,3)=-1.0D0*Y(1)
      RETURN
      END
      SUBROUTINE JACEPS(X,EPS,Y,F,N)
      DOUBLE PRECISION EPS,F(N),X,Y(N)
      INTEGER N
      F(1)=0.0D0
      F(2)=0.0D0
      F(3)=2.0D0*Y(2)**2-2.0D0
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp42ExampleCode}{aspex.ht}{Asp42 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp42ExampleCode}{Asp42 Example Code}
\begin{verbatim}
      SUBROUTINE G(EPS,YA,YB,BC,N)
      DOUBLE PRECISION EPS,YA(N),YB(N),BC(N)
      INTEGER N
      BC(1)=YA(1)
      BC(2)=YA(2)
      BC(3)=YB(2)-1.0D0
      RETURN
      END
      SUBROUTINE JACOBG(EPS,YA,YB,AJ,BJ,N)
      DOUBLE PRECISION EPS,YA(N),AJ(N,N),BJ(N,N),YB(N)
      INTEGER N
      AJ(1,1)=1.0D0
      AJ(1,2)=0.0D0
      AJ(1,3)=0.0D0
      AJ(2,1)=0.0D0
      AJ(2,2)=1.0D0
      AJ(2,3)=0.0D0
      AJ(3,1)=0.0D0
      AJ(3,2)=0.0D0
      AJ(3,3)=0.0D0
      BJ(1,1)=0.0D0
      BJ(1,2)=0.0D0
      BJ(1,3)=0.0D0
      BJ(2,1)=0.0D0
      BJ(2,2)=0.0D0
      BJ(2,3)=0.0D0
      BJ(3,1)=0.0D0
      BJ(3,2)=1.0D0
      BJ(3,3)=0.0D0
      RETURN
      END
      SUBROUTINE JACGEP(EPS,YA,YB,BCEP,N)
      DOUBLE PRECISION EPS,YA(N),YB(N),BCEP(N)
      INTEGER N
      BCEP(1)=0.0D0
      BCEP(2)=0.0D0
      BCEP(3)=0.0D0
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp49ExampleCode}{aspex.ht}{Asp49 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp49ExampleCode}{Asp49 Example Code}
\begin{verbatim}
      SUBROUTINE OBJFUN(MODE,N,X,OBJF,OBJGRD,NSTATE,IUSER,USER)
      DOUBLE PRECISION X(N),OBJF,OBJGRD(N),USER(*)
      INTEGER N,IUSER(*),MODE,NSTATE
      OBJF=X(4)*X(9)+((-1.0D0*X(5))+X(3))*X(8)+((-1.0D0*X(3))+X(1))*X(7)
     &+(-1.0D0*X(2)*X(6))
      OBJGRD(1)=X(7)
      OBJGRD(2)=-1.0D0*X(6)
      OBJGRD(3)=X(8)+(-1.0D0*X(7))
      OBJGRD(4)=X(9)
      OBJGRD(5)=-1.0D0*X(8)
      OBJGRD(6)=-1.0D0*X(2)
      OBJGRD(7)=(-1.0D0*X(3))+X(1)
      OBJGRD(8)=(-1.0D0*X(5))+X(3)
      OBJGRD(9)=X(4)
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp50ExampleCode}{aspex.ht}{Asp50 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp50ExampleCode}{Asp50 Example Code}
\begin{verbatim}
      SUBROUTINE LSFUN1(M,N,XC,FVECC)
      DOUBLE PRECISION FVECC(M),XC(N)
      INTEGER I,M,N
      FVECC(1)=((XC(1)-2.4D0)*XC(3)+(15.0D0*XC(1)-36.0D0)*XC(2)+1.0D0)/(
     &XC(3)+15.0D0*XC(2))
      FVECC(2)=((XC(1)-2.8D0)*XC(3)+(7.0D0*XC(1)-19.6D0)*XC(2)+1.0D0)/(X
     &C(3)+7.0D0*XC(2))
      FVECC(3)=((XC(1)-3.2D0)*XC(3)+(4.333333333333333D0*XC(1)-13.866666
     &66666667D0)*XC(2)+1.0D0)/(XC(3)+4.333333333333333D0*XC(2))
      FVECC(4)=((XC(1)-3.5D0)*XC(3)+(3.0D0*XC(1)-10.5D0)*XC(2)+1.0D0)/(X
     &C(3)+3.0D0*XC(2))
      FVECC(5)=((XC(1)-3.9D0)*XC(3)+(2.2D0*XC(1)-8.579999999999998D0)*XC
     &(2)+1.0D0)/(XC(3)+2.2D0*XC(2))
      FVECC(6)=((XC(1)-4.199999999999999D0)*XC(3)+(1.666666666666667D0*X
     &C(1)-7.0D0)*XC(2)+1.0D0)/(XC(3)+1.666666666666667D0*XC(2))
      FVECC(7)=((XC(1)-4.5D0)*XC(3)+(1.285714285714286D0*XC(1)-5.7857142
     &85714286D0)*XC(2)+1.0D0)/(XC(3)+1.285714285714286D0*XC(2))
      FVECC(8)=((XC(1)-4.899999999999999D0)*XC(3)+(XC(1)-4.8999999999999
     &99D0)*XC(2)+1.0D0)/(XC(3)+XC(2))
      FVECC(9)=((XC(1)-4.699999999999999D0)*XC(3)+(XC(1)-4.6999999999999
     &99D0)*XC(2)+1.285714285714286D0)/(XC(3)+XC(2))
      FVECC(10)=((XC(1)-6.8D0)*XC(3)+(XC(1)-6.8D0)*XC(2)+1.6666666666666
     &67D0)/(XC(3)+XC(2))
      FVECC(11)=((XC(1)-8.299999999999999D0)*XC(3)+(XC(1)-8.299999999999
     &999D0)*XC(2)+2.2D0)/(XC(3)+XC(2))
      FVECC(12)=((XC(1)-10.6D0)*XC(3)+(XC(1)-10.6D0)*XC(2)+3.0D0)/(XC(3)
     &+XC(2))
      FVECC(13)=((XC(1)-1.34D0)*XC(3)+(XC(1)-1.34D0)*XC(2)+4.33333333333
     &3333D0)/(XC(3)+XC(2))
      FVECC(14)=((XC(1)-2.1D0)*XC(3)+(XC(1)-2.1D0)*XC(2)+7.0D0)/(XC(3)+X
     &C(2))
      FVECC(15)=((XC(1)-4.39D0)*XC(3)+(XC(1)-4.39D0)*XC(2)+15.0D0)/(XC(3
     &)+XC(2))
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp55ExampleCode}{aspex.ht}{Asp55 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp55ExampleCode}{Asp55 Example Code}
\begin{verbatim}
      SUBROUTINE CONFUN(MODE,NCNLN,N,NROWJ,NEEDC,X,C,CJAC,NSTATE,IUSER
     &,USER)
      DOUBLE PRECISION C(NCNLN),X(N),CJAC(NROWJ,N),USER(*)
      INTEGER N,IUSER(*),NEEDC(NCNLN),NROWJ,MODE,NCNLN,NSTATE
      IF(NEEDC(1).GT.0)THEN
        C(1)=X(6)**2+X(1)**2
        CJAC(1,1)=2.0D0*X(1)
        CJAC(1,2)=0.0D0
        CJAC(1,3)=0.0D0
        CJAC(1,4)=0.0D0
        CJAC(1,5)=0.0D0
        CJAC(1,6)=2.0D0*X(6)
      ENDIF
      IF(NEEDC(2).GT.0)THEN
        C(2)=X(2)**2+(-2.0D0*X(1)*X(2))+X(1)**2
        CJAC(2,1)=(-2.0D0*X(2))+2.0D0*X(1)
        CJAC(2,2)=2.0D0*X(2)+(-2.0D0*X(1))
        CJAC(2,3)=0.0D0
        CJAC(2,4)=0.0D0
        CJAC(2,5)=0.0D0
        CJAC(2,6)=0.0D0
      ENDIF
      IF(NEEDC(3).GT.0)THEN
        C(3)=X(3)**2+(-2.0D0*X(1)*X(3))+X(2)**2+X(1)**2
        CJAC(3,1)=(-2.0D0*X(3))+2.0D0*X(1)
        CJAC(3,2)=2.0D0*X(2)
        CJAC(3,3)=2.0D0*X(3)+(-2.0D0*X(1))
        CJAC(3,4)=0.0D0
        CJAC(3,5)=0.0D0
        CJAC(3,6)=0.0D0
      ENDIF
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp6ExampleCode}{aspex.ht}{Asp6 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp6ExampleCode}{Asp6 Example Code}
\begin{verbatim}
      SUBROUTINE FCN(N,X,FVEC,IFLAG)
      DOUBLE PRECISION X(N),FVEC(N)
      INTEGER N,IFLAG
      FVEC(1)=(-2.0D0*X(2))+(-2.0D0*X(1)**2)+3.0D0*X(1)+1.0D0
      FVEC(2)=(-2.0D0*X(3))+(-2.0D0*X(2)**2)+3.0D0*X(2)+(-1.0D0*X(1))+1.
     &0D0
      FVEC(3)=(-2.0D0*X(4))+(-2.0D0*X(3)**2)+3.0D0*X(3)+(-1.0D0*X(2))+1.
     &0D0
      FVEC(4)=(-2.0D0*X(5))+(-2.0D0*X(4)**2)+3.0D0*X(4)+(-1.0D0*X(3))+1.
     &0D0
      FVEC(5)=(-2.0D0*X(6))+(-2.0D0*X(5)**2)+3.0D0*X(5)+(-1.0D0*X(4))+1.
     &0D0
      FVEC(6)=(-2.0D0*X(7))+(-2.0D0*X(6)**2)+3.0D0*X(6)+(-1.0D0*X(5))+1.
     &0D0
      FVEC(7)=(-2.0D0*X(8))+(-2.0D0*X(7)**2)+3.0D0*X(7)+(-1.0D0*X(6))+1.
     &0D0
      FVEC(8)=(-2.0D0*X(9))+(-2.0D0*X(8)**2)+3.0D0*X(8)+(-1.0D0*X(7))+1.
     &0D0
      FVEC(9)=(-2.0D0*X(9)**2)+3.0D0*X(9)+(-1.0D0*X(8))+1.0D0
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp7ExampleCode}{aspex.ht}{Asp7 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp7ExampleCode}{Asp7 Example Code}
\begin{verbatim}
      SUBROUTINE FCN(X,Z,F)
      DOUBLE PRECISION F(*),X,Z(*)
      F(1)=DTAN(Z(3))
      F(2)=((-0.03199999999999999D0*DCOS(Z(3))*DTAN(Z(3)))+(-0.02D0*Z(2)
     &**2))/(Z(2)*DCOS(Z(3)))
      F(3)=-0.03199999999999999D0/(X*Z(2)**2)
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp73ExampleCode}{aspex.ht}{Asp73 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp73ExampleCode}{Asp73 Example Code}
\begin{verbatim}
      SUBROUTINE PDEF(X,Y,ALPHA,BETA,GAMMA,DELTA,EPSOLN,PHI,PSI)
      DOUBLE PRECISION ALPHA,EPSOLN,PHI,X,Y,BETA,DELTA,GAMMA,PSI
      ALPHA=DSIN(X)
      BETA=Y
      GAMMA=X*Y
      DELTA=DCOS(X)*DSIN(Y)
      EPSOLN=Y+X
      PHI=X
      PSI=Y
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp74ExampleCode}{aspex.ht}{Asp74 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp74ExampleCode}{Asp74 Example Code}
\begin{verbatim}
      SUBROUTINE BNDY(X,Y,A,B,C,IBND)
      DOUBLE PRECISION A,B,C,X,Y
      INTEGER IBND
      IF(IBND.EQ.0)THEN
        A=0.0D0
        B=1.0D0
        C=-1.0D0*DSIN(X)
      ELSEIF(IBND.EQ.1)THEN
        A=1.0D0
        B=0.0D0
        C=DSIN(X)*DSIN(Y)
      ELSEIF(IBND.EQ.2)THEN
        A=1.0D0
        B=0.0D0
        C=DSIN(X)*DSIN(Y)
      ELSEIF(IBND.EQ.3)THEN
        A=0.0D0
        B=1.0D0
        C=-1.0D0*DSIN(Y)
      ENDIF
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp77ExampleCode}{aspex.ht}{Asp77 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp77ExampleCode}{Asp77 Example Code}
\begin{verbatim}
      SUBROUTINE FCNF(X,F)
      DOUBLE PRECISION X
      DOUBLE PRECISION F(2,2)
      F(1,1)=0.0D0
      F(1,2)=1.0D0
      F(2,1)=0.0D0
      F(2,2)=-10.0D0
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp78ExampleCode}{aspex.ht}{Asp78 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp78ExampleCode}{Asp78 Example Code}
\begin{verbatim}
      SUBROUTINE FCNG(X,G)
      DOUBLE PRECISION G(*),X
      G(1)=0.0D0
      G(2)=0.0D0
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp8ExampleCode}{aspex.ht}{Asp8 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp8ExampleCode}{Asp8 Example Code}
\begin{verbatim}
      SUBROUTINE OUTPUT(XSOL,Y,COUNT,M,N,RESULT,FORWRD)
      DOUBLE PRECISION Y(N),RESULT(M,N),XSOL
      INTEGER M,N,COUNT
      LOGICAL FORWRD
      DOUBLE PRECISION X02ALF,POINTS(8)
      EXTERNAL X02ALF
      INTEGER I
      POINTS(1)=1.0D0
      POINTS(2)=2.0D0
      POINTS(3)=3.0D0
      POINTS(4)=4.0D0
      POINTS(5)=5.0D0
      POINTS(6)=6.0D0
      POINTS(7)=7.0D0
      POINTS(8)=8.0D0
      COUNT=COUNT+1
      DO 25001 I=1,N
        RESULT(COUNT,I)=Y(I)
25001 CONTINUE
      IF(COUNT.EQ.M)THEN
        IF(FORWRD)THEN
          XSOL=X02ALF()
        ELSE
          XSOL=-X02ALF()
        ENDIF
      ELSE
        XSOL=POINTS(COUNT)
      ENDIF
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp80ExampleCode}{aspex.ht}{Asp80 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp80ExampleCode}{Asp80 Example Code}
\begin{verbatim}
      SUBROUTINE BDYVAL(XL,XR,ELAM,YL,YR)
      DOUBLE PRECISION ELAM,XL,YL(3),XR,YR(3)
      YL(1)=XL
      YL(2)=2.0D0
      YR(1)=1.0D0
      YR(2)=-1.0D0*DSQRT(XR+(-1.0D0*ELAM))
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\pagetitle{Asp9ExampleCode}{aspex.ht}{Asp9 Example Code}
\begin{chunk}{aspex.ht}
\begin{page}{Asp9ExampleCode}{Asp9 Example Code}
\begin{verbatim}
      DOUBLE PRECISION FUNCTION G(X,Y)
      DOUBLE PRECISION X,Y(*)
      G=X+Y(1)
      RETURN
      END
\end{verbatim}
\end{page}

\end{chunk}
\chapter{NAG ANNA Expert System}
\section{annaex.ht}
\pagetitle{UXANNA}{annaex.ht}{Axiom/NAG Expert System}
\begin{chunk}{annaex.ht}
\begin{page}{UXANNA}{Axiom/NAG Expert System}
\centerline{\tt{\inputbitmap{\htbmdir{}/anna_logo.xbm}}\rm}
\newline
\centerline{This expert system chooses, and uses, NAG numerical routines.}
\begin{scroll}
\blankline
\indent{2}
\beginmenu
\menumemolink{Integration}{UXANNAInt}
\blankline
\menumemolink{Ordinary Differential Equations}{UXANNAOde}
\blankline
\menumemolink{Partial Differential Equations}{UXANNAPde}
\blankline
\menumemolink{Optimization}{UXANNAOpt}
\vspace{10}
\menumemolink{About the Axiom/NAG Expert System}{UXANNATxt}
%\unixcommand{(Postscript)}{ghostview \ \htbmdir{}/anna.ps}
%\blankline
%\menumemolink{How to use the NAGLINK}{nagLinkIntroPage}
%\blankline
%\menumemolink{Tutorial}{tutorialIntroPage}
%\blankline
%\item \menulispdownlink{Interpolation}{(|interp1|}
\endmenu
\indent{0}
\end{scroll}
\autobutt{HelpContents}
\end{page}

\end{chunk}
\pagetitle{UXANNAInt}{annex.ht}{Integration}
\begin{chunk}{annaex.ht}
\begin{page}{UXANNAInt}{Integration}
\pageto{Integration}{LispFunctions}
\pageto{Multiple Integration}{LispFunctions}
Welcome to the Integration section of {\tt
\inputbitmap{\htbmdir{}/anna.xbm.tiny}}, the {\em Axiom/NAG Expert
System}.  This system chooses, and uses, NAG numerical routines.
\begin{scroll}
\blankline
\indent{2}
\beginmenu
\item \menulispdownlink{Integration}{(|annaInt|)}\space{}\newline
\indent{5} Integrating a function over a finite or infinite range.
\blankline
\item \menulispdownlink{Multiple Integration}{(|annaMInt|)}\space{}
\newline
\indent{5} Integrating a multivariate function over a finite space.  
The dimensions of the space need to be 2 <= n <= 15.
\blankline
\menudownlink{Examples}{UXANNAIntEx}\space{}\newline
\indent{5} Examples of integration.  These examples cover all of the major 
methods.  Parameters can be changed to investigate the effect 
on the choice of method.
\endmenu
\indent{0}
\end{scroll}
\autobutt{MainHelp}
\end{page}

\end{chunk}
\pagetitle{UXANNAOde}{annaex.ht}{Ordinary Differential Equations}
\pageto{Ordinary Differential Equations}{LispFunctions}
\begin{chunk}{annaex.ht}
\begin{page}{UXANNAOde}{Ordinary Differential Equations}
Welcome to the Ordinary Differential Equations section of {\tt
\inputbitmap{\htbmdir{}/anna.xbm.tiny}}, the 
{\em Axiom/NAG Expert System}.  
This system chooses, and uses, NAG numerical routines.
\begin{scroll}
\blankline
\blankline
\indent{2}
\beginmenu
\item \menulispdownlink{Ordinary Differential Equations}{(|annaOde|)}
\space{}\newline
\indent{5} Finding a solution to an Initial Value Problem of a set 
of Ordinary Differential Equations.
\blankline
\menudownlink{Examples}{UXANNAOdeEx}\newline
\indent{5} Examples of ODE problems with various features using both
stiff and non-stiff methods.  Parameters can be changed to investigate
the effect on the choice of method.
\autobutt{MainHelp}
\endmenu
\indent{0}
\end{scroll}
\end{page}

\end{chunk}
\pagetitle{UXANNAOpt}{annaex.ht}{Optimization}
\pageto{Optimization of a set of observations of a data set}
{LispFunctions}
\begin{chunk}{annaex.ht}
\begin{page}{UXANNAOpt}{Optimization}
Welcome to the Optimization section of {\tt
\inputbitmap{\htbmdir{}/anna.xbm.tiny}}, the {\em Axiom/NAG Expert System}.  
This system chooses, and uses, NAG numerical routines.
\begin{scroll}
\blankline
\indent{2}
\beginmenu
\item \menulispdownlink{Optimization of a Single Multivariate Function}
{(|annaOpt|)}\space{}\newline
\indent{6} Finding the minimum of a function in n variables. 
\newline
\indent{6} Linear Programming and Quadratic Programming problems.
\blankline
\indent{4} 
\beginmenu
\menudownlink{Examples}{UXANNAOptEx}\newline
\indent{8} 
Examples of optimization problems with various constraint features.
\endmenu
\blankline
\item \menulispdownlink
{Optimization of a set of observations of a data set}
{(|annaOpt2|)}\space{}\newline
\indent{6} Least-squares problems.
\newline
\indent{6} Checking the goodness of fit of a least-squares model.
\blankline
\indent{4} 
\beginmenu
\menudownlink{Examples}{UXANNAOpt2Ex}\newline
\indent{8} Examples of least squares problems.
\endmenu
\endmenu
\indent{0}
\end{scroll}
\autobutt{MainHelp}
\end{page}

\end{chunk}
\pagetitle{UXANNAPde}{annaex.ht}{Partial Differential Equations}
\pageto{Second Order Elliptic Partial Differential Equation}
{LispFunctions}
\begin{chunk}{annaex.ht}
\begin{page}{UXANNAPde}{Partial Differential Equations}
Welcome to the Partial Differential Equations section of {\tt
\inputbitmap{\htbmdir{}/anna.xbm.tiny}}, the
{\em Axiom/NAG Expert System}.  
\begin{scroll}
\indent{2}
\beginmenu
\menulispdownlink{Second Order Elliptic Partial Differential Equation}
{(|annaPDESolve|)}
\newline
\indent{4} Discretizing the PDE:
\newline
\centerline{\inputbitmap{\htbmdir{}/d03eef.xbm}}
defined on a rectangular region with boundary conditions of the form 
\centerline{\inputbitmap{\htbmdir{}/d03eef1.bitmap}} 
and solving the resulting
seven-diagonal finite difference equations using a multigrid technique.
\blankline
%\menulispdownlink{Helmholtz Equation in 3-D, Cartesian Coordinates}
%{(|d03fafVars|)}
%\newline
%\indent{4} Descretizing the PDE:
%\newline
%\centerline{\inputbitmap{\htbmdir{}/d03faf.xbm}}
%and solving the resulting
%seven-diagonal finite difference equations using a method based on 
%the Fast Fourier Transform.
\endmenu
\end{scroll}
\autobutt{MainHelp}
\end{page}

\end{chunk}
\pagetitle{UXANNAOptEx}{annaex.ht}
{Examples Using the Axiom/NAG Expert System}
\begin{chunk}{annaex.ht}
\begin{page}{UXANNAOptEx}{Examples Using the Axiom/NAG Expert System}
\pageto{Example 1}{LispFunctions}
\pageto{Example 2}{LispFunctions}
\pageto{Example 3}{LispFunctions}
\pageto{Example 4}{LispFunctions}
\pageto{Example 5}{LispFunctions}
\begin{scroll}
Select any of these examples and you will be presented with a page which
contains active areas for the function and its parameters.
\blankline
These parameters can be altered by selecting the area and replacing the
default parameters by the new values. 
\blankline
\beginmenu
\item \menulispdownlink{Example 1: \newline 
\indent{2} Minimize the function: 
\centerline{\inputbitmap{\htbmdir{}/opt1.xbm}}}
{(|annaOptDefaultSolve1|)}\space{}
\blankline
\item \menulispdownlink{Example 2: \newline 
\indent{2} Minimize the function: 
\centerline{\inputbitmap{\htbmdir{}/opt2.xbm}}}
{(|annaOptDefaultSolve2|)}\space{}
\newline \indent{3} With conditions: 
\centerline{\inputbitmap{\htbmdir{}/opt2c.xbm}}
\blankline
\item \menulispdownlink{Example 3: \newline 
\indent{2} Minimize the function: 
\centerline{\inputbitmap{\htbmdir{}/opt3.xbm}}}
{(|annaOptDefaultSolve3|)}\space{}
\newline \indent{3} With conditions: 
\centerline{\inputbitmap{\htbmdir{}/opt3c1.xbm}}
\centerline{\inputbitmap{\htbmdir{}/opt3c2.xbm}}
\blankline
\item \menulispdownlink{Example 4: \newline 
\indent{2} Minimize the function: 
\centerline{\inputbitmap{\htbmdir{}/opt4.xbm}}
}{(|annaOptDefaultSolve4|)}\space{}
\newline \indent{3} With conditions: 
\centerline{\inputbitmap{\htbmdir{}/opt4c1.xbm}}
\centerline{\inputbitmap{\htbmdir{}/opt4c2.xbm}}
\centerline{\inputbitmap{\htbmdir{}/opt4c3.xbm}}
\blankline
\item \menulispdownlink{Example 5: \newline 
\indent{2} Minimize the function: 
\centerline{\inputbitmap{\htbmdir{}/opt5.xbm}}
}{(|annaOptDefaultSolve5|)}\space{}
\newline \indent{3} With conditions: 
\centerline{\inputbitmap{\htbmdir{}/opt4c1.xbm}}
\centerline{\inputbitmap{\htbmdir{}/opt4c2.xbm}}
\centerline{\inputbitmap{\htbmdir{}/opt4c3.xbm}}
\blankline
\endmenu
\end{scroll}
\autobutt{Mainhelp}
\end{page}

\end{chunk}
\pagetitle{UXANNAOpt2Ex}{annaex.ht}
{Examples Using the Axiom/NAG Expert System}
\pageto{Example 1}{LispFunctions}
\begin{chunk}{annaex.ht}
\begin{page}{UXANNAOpt2Ex}{Examples Using the Axiom/NAG Expert System}
\begin{scroll}
Select this example and you will be presented with a page which
contains active areas for the function and its parameters.
\blankline
These parameters can be altered by selecting the area and replacing the
default parameters by the new values. 
\blankline
\beginmenu
\blankline
\item \menulispdownlink{Example 1: \newline 
\indent{2} Calculate a least-squares 
minimization of the following functions: 
\centerline{\inputbitmap{\htbmdir{}/opt61.xbm}}
\centerline{\inputbitmap{\htbmdir{}/opt62.xbm}}
\centerline{\inputbitmap{\htbmdir{}/opt63.xbm}}}
{(|annaOpt2DefaultSolve|)}\space{}
\endmenu
\end{scroll}
\autobutt{MainHelp}
\end{page}


\end{chunk}
\pagetitle{UXANNAIntEx}{annaex.ht}
{Examples Using the Axiom/NAG Expert System}
\pageto{Example 1}{LispFunctions}
\pageto{Example 2}{LispFunctions}
\pageto{Example 3}{LispFunctions}
\pageto{Example 4}{LispFunctions}
\pageto{Example 5}{LispFunctions}
\pageto{Example 6}{LispFunctions}
\pageto{Example 7}{LispFunctions}
\pageto{Example 8}{LispFunctions}
\pageto{Example 9}{LispFunctions}
\pageto{Example 10}{LispFunctions}
\pageto{Example 11}{LispFunctions}
\pageto{Example 12}{LispFunctions}
\begin{chunk}{annaex.ht}
\begin{page}{UXANNAIntEx}{Examples Using the Axiom/NAG Expert System}
\begin{scroll}
Select any of these examples and you will be presented with a page which
contains active areas for the function and its parameters.
\blankline
These parameters can be altered by selecting the area and replacing the
default parameters by the new values.  In this way you can investigate the
effect of the new parameters on the choice of method.
\blankline
\beginmenu
\item \menulispdownlink{Example 1: \newline 
\centerline{\inputbitmap{\htbmdir{}/int1.xbm}}}{(|annaFoo|)}\space{}
\blankline
\item \menulispdownlink{Example 2: \newline 
\centerline{\inputbitmap{\htbmdir{}/int2.xbm}}}{(|annaBar|)}\space{}
\blankline
\item \menulispdownlink{Example 3: \newline 
\centerline{\inputbitmap{\htbmdir{}/int3.xbm}}}{(|annaJoe|)}\space{}
\blankline
\item \menulispdownlink{Example 4: \newline 
\centerline{\inputbitmap{\htbmdir{}/int4.xbm}}}{(|annaSue|)}\space{}
\blankline
\item \menulispdownlink{Example 5: \newline 
\centerline{\inputbitmap{\htbmdir{}/int5.xbm}}}{(|annaAnn|)}\space{}
\blankline
\item \menulispdownlink{Example 6: \newline 
\centerline{\inputbitmap{\htbmdir{}/int6.xbm}}}{(|annaBab|)}\space{}
\blankline
\item \menulispdownlink{Example 7: \newline 
\centerline{\inputbitmap{\htbmdir{}/int7.xbm}}}{(|annaFnar|)}\space{}
\blankline
\item \menulispdownlink{Example 8: \newline 
\centerline{\inputbitmap{\htbmdir{}/int8.xbm}}}{(|annaDan|)}\space{}
\blankline
\item \menulispdownlink{Example 9: \newline 
\centerline{\inputbitmap{\htbmdir{}/int9.xbm}}}{(|annaBlah|)}\space{}
\blankline
\item \menulispdownlink{Example 10: \newline 
\centerline{\inputbitmap{\htbmdir{}/int10.xbm}}}{(|annaTub|)}\space{}
\blankline
\item \menulispdownlink{Example 11: \newline 
\centerline{\inputbitmap{\htbmdir{}/int13.xbm}}}{(|annaRats|)}\space{}
\blankline
\item \menulispdownlink{Example 12: \newline 
\centerline{\inputbitmap{\htbmdir{}/int11.xbm}}}{(|annaMInt|)}\space{}
\endmenu
\end{scroll}
\autobutt{MainHelp}
\end{page}

\end{chunk}
\pagetitle{UXANNAOdeEx}{annaex.ht}
{Examples Using the Axiom/NAG Expert System}
\pageto{annaOdeDefaultSolve1}{LispFunctions}
\pageto{annaOdeDefaultSolve2}{LispFunctions}
\begin{chunk}{annaex.ht}
\begin{page}{UXANNAOdeEx}{Examples Using the Axiom/NAG Expert System}
\begin{scroll}
Analyses the function for various attributes, chooses and 
then uses a suitable ODE solver to provide a 
solution to the system of n ODEs \center{\htbitmap{d02gaf},}
for i = 1,2,...,n.
\blankline
Select either of these examples and you will be presented with a page
which contains active areas for the function and its parameters.
\blankline
These parameters can be altered by selecting the area and replacing
the default parameters by the new values.  In this way you can
investigate the effect of the new parameters on the choice of method.
\blankline
\beginmenu
\item \menulispdownlink{Example 1: \tab{12}
\inputbitmap{\htbmdir{}/ode1.xbm}}{(|annaOdeDefaultSolve1|)}
\blankline with initial conditions: \newline
\tab{12}\inputbitmap{\htbmdir{}/y1.xbm} \space{1} and \space{1}
\inputbitmap{\htbmdir{}/x1.xbm}
\blankline
\blankline
\blankline
\item \menulispdownlink{Example 2: \tab{12}
\inputbitmap{\htbmdir{}/ode2.xbm}}{(|annaOdeDefaultSolve2|)}
\blankline with initial conditions: \newline
\tab{12}\inputbitmap{\htbmdir{}/y2.xbm} \space{1} and \space{1}
\inputbitmap{\htbmdir{}/x1.xbm}
\blankline
\blankline
\blankline
\endmenu
\end{scroll}
\autobutt{MainHelp}
\end{page}

\end{chunk}
\pagetitle{UXANNATxt}{annaex.ht}{About the Axiom/NAG Expert System}
\pageto{notitle}{UXANNAEx}
\pageto{notitle}{UXANNAIntro}
\pageto{notitle}{UXANNADec}
\pageto{notitle}{UXANNAInfer}
\pageto{notitle}{UXANNAMeas}
\begin{chunk}{annaex.ht}
\begin{page}{UXANNATxt}{About the Axiom/NAG Expert System}
\begin{scroll}
\centerline{\tt\inputbitmap{\htbmdir{}/anna_logo.xbm}\rm} 
\vspace{-30}\horizontalline
In applied mathematics, electronic and chemical engineering, the
modelling process can produce a number of mathematical problems which
require numerical solutions for which symbolic methods are either not
possible or not obvious.  With the plethora of numerical library
routines for the solution of these problems often the numerical
analyst has to answer the question {\em Which routine to choose?}
\blankline
Some analysis needs to be carried out before the appropriate routine
can be identified i.e. {\em How stiff is this ODE?} and {\em Is this
function continuous?}  It may well be the case that more than one
routine is applicable to the problem.  So the question may become {\em
Which is likely to be the best?}  Such a choice may be critical for
both accuracy and efficiency.
\blankline
An expert system is thus required to make this choice based on the
result of its own analysis of the problem, call the routine and act on
the outcome.  This may be to put the answer in a relevant form or
react to an apparent failure of the chosen routine and thus choose and
call an alternative.  It should also have sufficient explanation
mechanisms to inform on the choice of routine and the reasons for that
choice.
\blankline
\end{scroll}
\downlink{ Examples }{UXANNAEx}
\downlink{ Introduction }{UXANNAIntro}
\downlink{ Decision Agents }{UXANNADec}
\downlink{ Inference Mechanisms }{UXANNAInfer}
\downlink{ Measure Functions }{UXANNAMeas}
\end{page}

\end{chunk}
\pagetitle{UXANNAIntro}{annaex.ht}
{Introduction to the Axiom/NAG Expert System}
\pageto{notitle}{UXANNADec}
\pageto{notitle}{UXANNAInfer}
\pageto{notitle}{UXANNAMeth}
\pageto{notitle}{UXANNAMeas}
\begin{chunk}{annaex.ht}
\begin{page}{UXANNAIntro}{Introduction to the Axiom/NAG Expert System}
\begin{scroll}
\centerline{\tt\inputbitmap{\htbmdir{}/anna_logo.xbm}\rm}
\vspace{-30}\horizontalline
Deciding amongst, and then implementing, several possible approaches
to solving a numerical problem can be daunting for a novice user, or
tedious for an expert.  Different attributes of the problem need to be
identified and their possible interactions weighed up before a final
decision about which method to use can be made.
\blankline
The implementation is then largely an automatic, if laborious, process
of writing, compiling and linking usually Fortran code.  The aim is to
build an expert system which will use computer algebra to analyse such
features of a problem, inference mechanisms and a knowledge base to
choose a numerical method appropriate to the solution of a given
problem.
\blankline
Any interactive system is constrained by the need to provide a
reasonable response time for the user.  Given the complexity of some
of the analysis our system will need to do, it is clear that we should
only aim to select a good method, rather than try to identify the best
one available.  The overall goal is to provide a ``black-box''
interface to numerical software which allows non-experts access to its
full potential.  It will also provide explanation mechanisms
commensurate with its role as a teaching aid.
\blankline
Given, say, an integration to perform (which may or may not be able to be
handled symbolically), the system should choose and apply an appropriate
method, thus mirroring as closely as possible the way that an experienced
numerical analyst would think so, for example, given an integration to
perform:\newline
{\it \centerline{\inputbitmap{\htbmdir{}/int1.xbm}}}
\newline
the experienced analyst would see that the integral is semi-infinite and
transform it by splitting the range and transforming the integral over {\it
[1,\inputbitmap{\htbmdir{}/infty.xbm}]} into an integral over 
{\it [0,1] } using the transformation {\it x -> 1/t}.  
A different numerical routine might be used over each
sub-region and the results added to give the final answer. 
\blankline
It then requires
the translation of the problem into Fortran code which may be extensive.
Even with this simple example, the process is quite involved.
\blankline
\end{scroll}
\autobuttons
\downlink{ Decision Agents }{UXANNADec}
\downlink{ Inference Mechanisms }{UXANNAInfer}
\downlink{ Method Domains }{UXANNAMeth}
\downlink{ Measure Functions }{UXANNAMeas}
\end{page}

\end{chunk}
\pagetitle{UXANNAEx}{annaex.ht}{Example using the Axiom/NAG Expert System}
\pageto{notitle}{UXANNAEx2}
\begin{chunk}{annaex.ht}
\begin{page}{UXANNAEx}{Example using the Axiom/NAG Expert System}
\begin{scroll}
\xtc{
{\bf Example 1}: The integral
{\centerline{\inputbitmap{\htbmdir{}/int1.xbm}}}
\newline
is performed as follows:
\blankline
}{}
\xtc{
}{
\spadpaste{ans := 
integrate((exp(-X^3)+exp(-3*X^2))/sqrt(X),0.0..\%plusInfinity)
\bound{ans} }
}
\blankline
\xtc{
It creates a composite structure for which the field containing 
the result can be 
expanded as required.\blankline
}{
\spadpaste{ans . 'result\free{ans}}
}
\blankline
\xtc{
}{
\spadpaste{ans . 'abserr\free{ans}}
}
\blankline
This system has performed the analysis described above, done the
necessary problem transformation, written any necessary Fortran,
called two different numerical routines, and amalgamated their
results.  This whole process was transparent to the user.
\end{scroll}
\autobuttons
\downlink{Example 2}{UXANNAEx2}
%\downlink{Decision Agents}{UXANNADec}
\end{page}

\begin{patch}{UXANNAExPatch1}
\begin{paste}{UXANNAExFull1}{UXANNAExEmpty1}
\pastebutton{UXANNAExFull1}{\hidepaste}
\tab{5}\spadcommand{ans := integrate((exp(-X^3)+exp(-3*X^2))/sqrt(X),0.0..\%plusInfinity)\bound{ans }}
\indentrel{3}\begin{verbatim}
   (1)
   [d01ajfAnnaTypeAnswer: Result, abserr: DoubleFloat,
    method: Result, result: DoubleFloat,
    explanations: List(String), attributes: List(Any),
    d01apfAnnaTypeAnswer: Result]
                                           Type: Result
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UXANNAExEmpty1}
\begin{paste}{UXANNAExEmpty1}{UXANNAExPatch1}
\pastebutton{UXANNAExEmpty1}{\showpaste}
\tab{5}\spadcommand{ans := integrate((exp(-X^3)+exp(-3*X^2))/sqrt(X),0.0..\%plusInfinity)\bound{ans }}
\end{paste}\end{patch}

\begin{patch}{UXANNAExPatch2}
\begin{paste}{UXANNAExFull2}{UXANNAExEmpty2}
\pastebutton{UXANNAExFull2}{\hidepaste}
\tab{5}\spadcommand{ans . 'result\free{ans }}
\indentrel{3}\begin{verbatim}
   (2)  3.23287256251958
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UXANNAExEmpty2}
\begin{paste}{UXANNAExEmpty2}{UXANNAExPatch2}
\pastebutton{UXANNAExEmpty2}{\showpaste}
\tab{5}\spadcommand{ans . 'result\free{ans }}
\end{paste}\end{patch}

\begin{patch}{UXANNAExPatch3}
\begin{paste}{UXANNAExFull3}{UXANNAExEmpty3}
\pastebutton{UXANNAExFull3}{\hidepaste}
\tab{5}\spadcommand{ans . 'abserr\free{ans }}
\indentrel{3}\begin{verbatim}
   (3)  2.69960156338737e-08
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UXANNAExEmpty3}
\begin{paste}{UXANNAExEmpty3}{UXANNAExPatch3}
\pastebutton{UXANNAExEmpty3}{\showpaste}
\tab{5}\spadcommand{ans . 'abserr\free{ans }}
\end{paste}\end{patch}

\begin{patch}{UXANNAEx2Patch1}
\begin{paste}{UXANNAEx2Full1}{UXANNAEx2Empty1}
\pastebutton{UXANNAEx2Full1}{\hidepaste}
\tab{5}\spadcommand{ans2 := solve([Y[2],-1001*Y[2]-1000*Y[1]], 0.0, 10.0, [1.0,-1.0], [2,4,6,8], 1.0e-4)\bound{ans2 }}
\indentrel{3}\begin{verbatim}
   (1)
   [ifail: Integer, intensityFunctions: List(String),
    tol: DoubleFloat, result: Matrix(DoubleFloat),
    y: Matrix(DoubleFloat), method: Result,
    explanations: List(String), x: DoubleFloat]
                                           Type: Result
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UXANNAEx2Empty1}
\begin{paste}{UXANNAEx2Empty1}{UXANNAEx2Patch1}
\pastebutton{UXANNAEx2Empty1}{\showpaste}
\tab{5}\spadcommand{ans2 := solve([Y[2],-1001*Y[2]-1000*Y[1]], 0.0, 10.0, [1.0,-1.0], [2,4,6,8], 1.0e-4)\bound{ans2 }}
\end{paste}\end{patch}

\begin{patch}{UXANNAEx2Patch2}
\begin{paste}{UXANNAEx2Full2}{UXANNAEx2Empty2}
\pastebutton{UXANNAEx2Full2}{\hidepaste}
\tab{5}\spadcommand{ans2 . 'result\free{ans2 }}
\indentrel{3}\begin{verbatim}
        Ú        1.0                   - 1.0         ¿
        ³                                            ³
        ³ 0.135329965475963     - 0.135329965475963  ³
        ³                                            ³
   (2)  ³ 0.018315370486087     - 0.0183153704860871 ³
        ³                                            ³
        ³0.00247869592278824   - 0.00247869592278825 ³
        ³                                            ³
        À0.000335497710871914  - 0.000335497710871913Ù
                               Type: Matrix DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UXANNAEx2Empty2}
\begin{paste}{UXANNAEx2Empty2}{UXANNAEx2Patch2}
\pastebutton{UXANNAEx2Empty2}{\showpaste}
\tab{5}\spadcommand{ans2 . 'result\free{ans2 }}
\end{paste}\end{patch}

\begin{patch}{UXANNAEx2Patch3}
\begin{paste}{UXANNAEx2Full3}{UXANNAEx2Empty3}
\pastebutton{UXANNAEx2Full3}{\hidepaste}
\tab{5}\spadcommand{ans2 . 'y\free{ans2 }}
\indentrel{3}\begin{verbatim}
   (3)  [4.54002176643708e-05  - 4.54002176643708e-05]
                               Type: Matrix DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UXANNAEx2Empty3}
\begin{paste}{UXANNAEx2Empty3}{UXANNAEx2Patch3}
\pastebutton{UXANNAEx2Empty3}{\showpaste}
\tab{5}\spadcommand{ans2 . 'y\free{ans2 }}
\end{paste}\end{patch}

\begin{patch}{UXANNAEx3Patch1}
\begin{paste}{UXANNAEx3Full1}{UXANNAEx3Empty1}
\pastebutton{UXANNAEx3Full1}{\hidepaste}
\tab{5}\spadcommand{ans3 := optimize((X[1]+10*X[2])**2 + 5*(X[3]-X[4])**2 + (X[2]-2*X[3])**4 + 10*(X[1]-X[4])**4, [3,-1,0,1], [1,-2,\%minusInfinity,1], [3,0,\%plusInfinity,3])\bound{ans3 }}
\indentrel{3}\begin{verbatim}
   (1)
   [ifail: Integer, bl: Matrix(DoubleFloat),
    bu: Matrix(DoubleFloat), method: Result,
    attributes: List(String), explanations: List(String),
    x: Matrix(DoubleFloat), objf: DoubleFloat]
                                           Type: Result
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UXANNAEx3Empty1}
\begin{paste}{UXANNAEx3Empty1}{UXANNAEx3Patch1}
\pastebutton{UXANNAEx3Empty1}{\showpaste}
\tab{5}\spadcommand{ans3 := optimize((X[1]+10*X[2])**2 + 5*(X[3]-X[4])**2 + (X[2]-2*X[3])**4 + 10*(X[1]-X[4])**4, [3,-1,0,1], [1,-2,\%minusInfinity,1], [3,0,\%plusInfinity,3])\bound{ans3 }}
\end{paste}\end{patch}

\begin{patch}{UXANNAEx3Patch2}
\begin{paste}{UXANNAEx3Full2}{UXANNAEx3Empty2}
\pastebutton{UXANNAEx3Full2}{\hidepaste}
\tab{5}\spadcommand{ans3 . objf\free{ans3 }}
\indentrel{3}\begin{verbatim}
   (2)  2.43378751212073
                                      Type: DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UXANNAEx3Empty2}
\begin{paste}{UXANNAEx3Empty2}{UXANNAEx3Patch2}
\pastebutton{UXANNAEx3Empty2}{\showpaste}
\tab{5}\spadcommand{ans3 . objf\free{ans3 }}
\end{paste}\end{patch}

\begin{patch}{UXANNAEx3Patch3}
\begin{paste}{UXANNAEx3Full3}{UXANNAEx3Empty3}
\pastebutton{UXANNAEx3Full3}{\hidepaste}
\tab{5}\spadcommand{ans3 . x\free{ans3 }}
\indentrel{3}\begin{verbatim}
   (3)
   [1.0  - 0.0852325900999037  0.409303588204477  1.0]
                               Type: Matrix DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UXANNAEx3Empty3}
\begin{paste}{UXANNAEx3Empty3}{UXANNAEx3Patch3}
\pastebutton{UXANNAEx3Empty3}{\showpaste}
\tab{5}\spadcommand{ans3 . x\free{ans3 }}
\end{paste}\end{patch}

\begin{patch}{UXANNAEx3Patch4}
\begin{paste}{UXANNAEx3Full4}{UXANNAEx3Empty4}
\pastebutton{UXANNAEx3Full4}{\hidepaste}
\tab{5}\spadcommand{ans3 . attributes\free{ans3 }}
\indentrel{3}\begin{verbatim}
   (4)
   ["The object function is non-linear",
    "There are simple bounds on the variables",
    "There are no constraint functions"]
                                      Type: List String
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UXANNAEx3Empty4}
\begin{paste}{UXANNAEx3Empty4}{UXANNAEx3Patch4}
\pastebutton{UXANNAEx3Empty4}{\showpaste}
\tab{5}\spadcommand{ans3 . attributes\free{ans3 }}
\end{paste}\end{patch}

\begin{patch}{UXANNAAgentPatch1}
\begin{paste}{UXANNAAgentFull1}{UXANNAAgentEmpty1}
\pastebutton{UXANNAAgentFull1}{\hidepaste}
\tab{5}\spadcommand{s := singularitiesOf(tan x,[x],0..12*\%pi)$ESCONT\free{lib3 }}
\indentrel{3}\begin{verbatim}
   (1)
   [1.5707963267948966, 4.7123889803846897,
    7.8539816339744828, 10.995574287564276,
    14.137166941154069, 17.27875959474386,
    20.420352248333657, 23.561944901923447,
    26.703537555513243, 29.845130209103033, ...]
                               Type: Stream DoubleFloat
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}

\begin{patch}{UXANNAAgentEmpty1}
\begin{paste}{UXANNAAgentEmpty1}{UXANNAAgentPatch1}
\pastebutton{UXANNAAgentEmpty1}{\showpaste}
\tab{5}\spadcommand{s := singularitiesOf(tan x,[x],0..12*\%pi)$ESCONT\free{lib3 }}
\end{paste}\end{patch}


\end{chunk}
\pagetitle{UXANNAEx2}{annaex.ht}{Example using the Axiom/NAG Expert System}
\pageto{notitle}{UXANNAEx3}
\begin{chunk}{annaex.ht}
\begin{page}{UXANNAEx2}{Example using the Axiom/NAG Expert System}
\begin{scroll}
\xtc{
{\bf Example 2}: The ODE
{\centerline{\inputbitmap{\htbmdir{}/ode3.xbm}\space{1}with
\space{1}
{\inputbitmap{\htbmdir{}/y3.xbm}}}}
\newline
could be solved as follows:
\blankline
}{}
\xtc{
}{
\spadpaste{ans2 := solve([Y[2],-1001*Y[2]-1000*Y[1]], 0.0, 10.0,
[1.0,-1.0], [2,4,6,8], 1.0e-4)\bound{ans2} }
}
\blankline
\xtc{
It creates a composite structure for which the field containing the
result can be expanded as required.
\blankline
}{
\spadpaste{ans2 . 'result\free{ans2}}
}
\blankline
\xtc{
}{
\spadpaste{ans2 . 'y\free{ans2}}
}
\blankline
\end{scroll}
\autobuttons
\downlink{Example 3}{UXANNAEx3}
%\downlink{Decision Agents}{UXANNADec}
\end{page}

\end{chunk}
\pagetitle{UXANNAEx3}{annaex.ht}{Example using the Axiom/NAG Expert System}
\pageto{notitle}{UXANNADec}
\begin{chunk}{annaex.ht}
\begin{page}{UXANNAEx3}{Example using the Axiom/NAG Expert System}
\begin{scroll}
\xtc{
{\bf Example 3}: The function
{\centerline{\inputbitmap{\htbmdir{}/opt2.xbm}}}
with simple bounds
{\centerline{\inputbitmap{\htbmdir{}/opt2c.xbm}}}
\newline
could be minimized as follows:
\blankline
}{}
\xtc{
}{
\spadpaste{ans3 := optimize((X[1]+10*X[2])**2 + 5*(X[3]-X[4])**2 + 
(X[2]-2*X[3])**4 + 10*(X[1]-X[4])**4, [3,-1,0,1], [1,-2,\%minusInfinity,1], 
[3,0,\%plusInfinity,3])\bound{ans3} }
}
\blankline
\xtc{
It creates a composite structure for which the field containing the
minimum can be expanded as required.
\blankline
}{
\spadpaste{ans3 . objf\free{ans3}}
}
\blankline
\xtc{
}{
\spadpaste{ans3 . x\free{ans3}}
}
\blankline
\xtc{
}{
\spadpaste{ans3 . attributes\free{ans3}}
}
\blankline
\end{scroll}
\autobuttons
\downlink{Decision Agents}{UXANNADec}
\end{page}

\end{chunk}
\pagetitle{UXANNADec}{annaex.ht}{Decision Agents}
\pageto{notitle}{UXANNAInfer}
\pageto{notitle}{UXANNAMeth}
\pageto{notitle}{UXANNAMeas}
\pageto{notitle}{UXANNAAgent}
\begin{chunk}{annaex.ht}
\begin{page}{UXANNADec}{Decision Agents}
\begin{scroll}
\blankline
Some features are either present or absent in a problem.  Examples of
such binary decisions include {\em is a matrix symmetric?} and {\em is
a function continuous?}  However in practice many questions are about
the {\em degree} to which a problem exhibits a property: {\em how much
does a function oscillate?}, or {\em how stiff are these differential
equations?}
\blankline
We have therefore created decision agents of two types, reflecting
their property --- {\em Binary Agents} are Boolean functions returning
either true or false and {\em Intensity Functions} are quantitative
and return a range of different values, either numerical or structured
types. The framework we are developing is able to deal with both these
forms of information.
\blankline

In any given problem area (for example solving ordinary differential
equations, optimization etc.) we have a selection of {\em methods}.
These might be to use a particular NAG routine, or they might involve
employing a higher-level strategy such as transforming the problem
into an equivalent, but easier to solve, form.
\blankline
Associated with every method we define a {\em measure function} which
assesses the suitability of that method to a particular problem.  Each
measure function has access to a range of symbolic {\em agents} which
can answer questions about the various properties of the problem in
hand.
\blankline
\end{scroll}
\downlink{ Inference Mechanisms }{UXANNAInfer}
\downlink{ Method Domains }{UXANNAMeth}
\downlink{ Measure Functions }{UXANNAMeas}
\downlink{ Computational Agents }{UXANNAAgent}

\end{page}

\end{chunk}
\pagetitle{UXANNAInfer}{annaex.ht}{Inference Mechanisms}
\pageto{notitle}{UXANNAMeth}
\pageto{notitle}{UXANNAMeas}
\pageto{notitle}{UXANNAAgent}
\pageto{notitle}{UXANNAEx}
\begin{chunk}{annaex.ht}
\begin{page}{UXANNAInfer}{Inference Mechanisms}
\begin{scroll}
\blankline
The inference machine will take the problem description as provided by
the user and perform an initial analysis to verify its validity.  It
will consider, in turn, all of the available methods within its
knowledge base which might solve that problem.  In doing so it
analyses the input problem to find out about any attributes that could
affect the ability of the methods under consideration to perform
effectively.
\blankline
Some of these measures may use lazy evaluation in the sense that, if a
method already assessed is believed to be a good candidate, and if
evaluating the current measure will be relatively expensive, then that
measure will not be evaluated unless later evidence shows that the
selected method is not, in fact, a successful strategy, for example if
it has failed.
\end{scroll}
\downlink{ Method Domains }{UXANNAMeth}
\downlink{ Measure Functions }{UXANNAMeas}
\downlink{ Computational Agents }{UXANNAAgent}
\downlink{ Examples }{UXANNAEx}
\end{page}

\end{chunk}
\pagetitle{UXANNAMeth}{annaex.ht}{Method Domains}
\pageto{notitle}{UXANNAMeas}
\pageto{notitle}{UXANNAAgent}
\pageto{notitle}{UXANNAEx}
\begin{chunk}{annaex.ht}
\begin{page}{UXANNAMeth}{Method Domains}
\begin{scroll}
\blankline
An Axiom {\em domain} has been created for each method or strategy for
solving the problem.  These method domains each implement two
functions with a uniform (method independant) interface.  \blankline
{\bf measure:} A function which calculates an estimate of suitability
of this particular method to the problem if there is a possibility
that the method under consideration is more appropriate than one
already investigated.
\blankline
If it may be possible to improve on the current favourite method, the
function will call computational agents to analyse the problem for
specific features and calculate the measure from the results these
agents return, using a variation on the Lucks/Gladwell intensity and
compatibility model if conflict between attributes, as investigated by
these computational agents, may be present.
\blankline
{\bf implementation:} A function which may be one of two distinct
kinds.  The first kind uses the interface to the NAG Library to call a
particular routine with the required parameters.  Some of the
parameters may need to be calculated from the data provided before the
external function call.
\blankline
The other kind will apply a ``high level'' strategy to try to solve
the problem e.g.~a transformation of an expression from one that is
difficult to solve to one which is easier, or a splitting of the
problem into several more easily solvable parts.  For example, for a
solution of the equation above, since the integral is semi-infinite we
might wish to transform the range by, say, using the mapping 
{\it y -> 1/x} 
on the section {\it 1 < x < \inputbitmap{\htbmdir{}/infty.xbm}})
and adding the result to the unmapped section {\it 0 < x < 1}.
\blankline
\end{scroll}
\downlink{ Measure Functions }{UXANNAMeas}
\downlink{ Computational Agents }{UXANNAAgent}
\downlink{ Examples }{UXANNAEx}
\end{page}

\end{chunk}
\pagetitle{UXANNAMeas}{annaex.ht}{Measure Functions}
\pageto{notitle}{UXANNAAgent}
\pageto{notitle}{UXANNAEx}
\begin{chunk}{annaex.ht}
\begin{page}{UXANNAMeas}{Measure Functions}
\begin{scroll}
\blankline
Each measure function will estimate the ability of a particular method to
solve a problem.  It will consult whichever agents are needed to perform
analysis on the problem in order to calculate the measure.  There is a
parameter which would contain the best compatibility
value found so far.  
\blankline
However, the interpretation we give to the results of some tests is
not always clear-cut.  If a set of tests give conflicting advice as to
the appropriateness of a particular method, it becomes important to
decide not only {\it whether} certain properties are present but also
their {\it degree}.  This gives us a basis for estimating the
compatibility of each property.
\blankline
We have taken for our model the system recommended by Lucks and
Gladwell which uses a system of measurement of compatibility allowing
for interaction and conflict between a number of attributes.  All of
these processes may not be required if the choice is clear-cut e.g. we
have an integral to calculate which has a particular singularity
structure for which one particular method has been specifically
constructed.  However, for more difficult cases a composite picture
should be built up to calculate a true measurement.
\blankline
How the compatibility functions interpret the measurements of various
attributes is up to them and may vary between differing methods.  It
is this area that takes as its basis the {\it judgement} of Numerical
Analysis `experts' whether that be from the documentation (which may
be deficient in certain respects) or from alternative sources.
However, its assessment of the suitability or otherwise of a
particular method is reflected in a single normalised value
facilitating the direct comparison of the suitability of a number of
possible methods.
\blankline
\end{scroll}
\downlink{ Computational Agents }{UXANNAAgent}
\downlink{ Examples }{UXANNAEx}
\end{page}

\end{chunk}
\pagetitle{UXANNAAgent}{annaex.ht}{Computational Agents}
\pageto{notitle}{UXANNAEx}
\begin{chunk}{annaex.ht}
\begin{page}{UXANNAAgent}{Computational Agents}
\begin{scroll}
\blankline
Computational Agents are those program segments which investigate the
attributes of the input function or functions, such as {\bf
stiffnessAndStabilityOfODEIF} (the {\em IF} indicates that it is an
{\em Intensity Function} i.e. one that returns a normalised real
number or a set of normalised real numbers).  They are usually
functions or programs written completely in the Axiom language and
implemented using computer algebra.
\blankline
Some agents will be common to more than one problem domain whereas
others will be specific to a single domain.  They also vary greatly in
their complexity.  It is a fairly simple task to return details about
the range of a function since this information will have been included
in the problem specification.  It is a different order of complexity
to return details of its singularity structure.
\blankline
\xtc{
As an example, here is a call to the computational agent {\bf
singularitiesOf} to obtain the list of singularities of the function 
{\it tan x} which are in the range 
{\it 0..12\inputbitmap{\htbmdir{}/pi.xbm}}:
\blankline
}{
}
\xtc{
}{
\spadpaste{s := singularitiesOf(tan x,[x],0..12*\%pi)$ESCONT \free{lib3} }
}
\blankline
Each of these computational agents which may be called by a number of
method domains retain their output in a dynamic hash-table, so
speeding the process and retaining efficiency.
\end{scroll}
\downlink{ Examples }{UXANNAEx}
\end{page}

\end{chunk}
\chapter{ANNA Algebra Code}
\begin{verbatim}
)co annacat.spad
)co cont.spad
)co d01Package.spad
)co d01agents.spad
)co d01routine.spad
)co d01transform.spad
)co d01weights.spad
)co d02Package.spad
)co d02agents.spad
)co d02routine.spad
)co d03Package.spad
)co d03agents.spad
)co d03routine.spad
)co e04Package.spad
)co e04agents.spad
)co e04routine.spad
)co functions.spad
)co routines.spad
)co tools.spad
\end{verbatim}
\chapter{Page hierarchy layout}
This is the forest of pages in hyperdoc. Any page at the leftmost
margin is a root page. Notice that the roots are disconnnected.
The only reachable pages are those from the "RootPage" page below.
All others exist but cannot be reached.

Indentation implies that a page can be reached by the less indented page.

Pages which have vertical bars or parens around them are lisp calls.
\begin{verbatim}
RootPage
  BasicCommand
    Calculus
      |bcDifferentiate|
      |bcIndefiniteIntegrate|
      |bcDefiniteIntegrate|
      |bcLimit|
      |bcSum|
      |bcProduct|
    |bcMatrix|
    |bcExpand|
    |bcDraw|
    |bcSeries|
    |bcSolve|
  TopReferencePage
    YouTriedIt
    ugWhatsNewTwoTwoPage
      ugTwoTwoPolynomialsPage
      ugTwoTwoHyperdocPage 
      ugTwoTwoNAGLinkPage 
      ugTwoTwoCCLPage 
    FoundationLibraryDocPage
      manpageXXintro
      manpageXXc02
      manpageXXc02aff
      manpageXXc02agf
      manpageXXc05
      manpageXXc05adf
      manpageXXc05nbf
      manpageXXc05pbf
      manpageXXc05zaf
      manpageXXc06
      manpageXXc06aef
      manpageXXc06ebf
      manpageXXc06ecf
      manpageXXc06ekf
      manpageXXc06fpf
      manpageXXc06fqf
      manpageXXc06frf
      manpageXXc06fuf
      manpageXXc06gbf
      manpageXXc06gcf
      manpageXXc06gqf
      manpageXXc06gsf
      manpageXXd01
      manpageXXd01ajf
      manpageXXd01akf
      manpageXXd01alf
      manpageXXd01amf
      manpageXXd01anf
      manpageXXd01apf
      manpageXXd01aqf
      manpageXXd01asf
      manpageXXd01bbf
      manpageXXd01fcf
      manpageXXd01gaf
      manpageXXd01gbf
      manpageXXd02
      manpageXXd02bbf
      manpageXXd02bhf
      manpageXXd02cjf
      manpageXXd02ejf
      manpageXXd02gaf
      manpageXXd02gbf
      manpageXXd02kef
      manpageXXd02raf
      manpageXXd03
      manpageXXd03edf
      manpageXXd03eef
      manpageXXd03faf
      manpageXXe01
      manpageXXe01baf
      manpageXXe01bef
      manpageXXe01bff
      manpageXXe01bgf
      manpageXXe01bhf
      manpageXXe01daf
      manpageXXe01saf
      manpageXXe01sbf
      manpageXXe01sef
      manpageXXe01sff
      manpageXXe02
      manpageXXe02adf
      manpageXXe02aef
      manpageXXe02agf
      manpageXXe02ahf
      manpageXXe02ajf
      manpageXXe02akf
      manpageXXe02baf
      manpageXXe02bbf
      manpageXXe02bcf
      manpageXXe02bdf
      manpageXXe02bef
      manpageXXe02daf
      manpageXXe02dcf
      manpageXXe02ddf
      manpageXXe02def
      manpageXXe02dff
      manpageXXe02gaf
      manpageXXe02zaf
      manpageXXe04
      manpageXXe04dgf
      manpageXXe04djf
      manpageXXe04dkf
      manpageXXe04fdf
      manpageXXe04gcf
      manpageXXe04jaf
      manpageXXe04mbf
      manpageXXe04naf
      manpageXXe04ucf
      manpageXXe04udf
      manpageXXe04uef
      manpageXXe04ycf
      manpageXXf
      manpageXXf01
      manpageXXf01brf
      manpageXXf01bsf
      manpageXXf01maf
      manpageXXf01mcf
      manpageXXf01qcf
      manpageXXf01qdf
      manpageXXf01qef
      manpageXXf01rcf
      manpageXXf01rdf
      manpageXXf01ref
      manpageXXf02
      manpageXXf02aaf
      manpageXXf02abf
      manpageXXf02adf
      manpageXXf02aef
      manpageXXf02aff
      manpageXXf02agf
      manpageXXf02ajf
      manpageXXf02akf
      manpageXXf02awf
      manpageXXf02axf
      manpageXXf02bbf
      manpageXXf02bjf
      manpageXXf02fjf
      manpageXXf02wef
      manpageXXf02xef
      manpageXXf04
      manpageXXf04adf
      manpageXXf04arf
      manpageXXf04asf
      manpageXXf04atf
      manpageXXf04axf
      manpageXXf04faf
      manpageXXf04jgf
      manpageXXf04maf
      manpageXXf04mbf
      manpageXXf04mcf
      manpageXXf04qaf
      manpageXXf07
      manpageXXf07adf
      manpageXXf07aef
      manpageXXf07fdf
      manpageXXf07fef
      manpageXXs
      manpageXXs01eaf
      manpageXXs13aaf
      manpageXXs13acf
      manpageXXs13adf
      manpageXXs14aaf
      manpageXXs14abf
      manpageXXs14baf
      manpageXXs15adf
      manpageXXs15aef
      manpageXXs17acf
      manpageXXs17adf
      manpageXXs17aef
      manpageXXs17aff
      manpageXXs17agf
      manpageXXs17ahf
      manpageXXs17ajf
      manpageXXs17akf
      manpageXXs17dcf
      manpageXXs17def
      manpageXXs17dgf
      manpageXXs17dhf
      manpageXXs17dlf
      manpageXXs18acf
      manpageXXs18adf
      manpageXXs18aef
      manpageXXs18aff
      manpageXXs18dcf
      manpageXXs18def
      manpageXXs19aaf
      manpageXXs19abf
      manpageXXs19acf
      manpageXXs19adf
      manpageXXs20acf
      manpageXXs20adf
      manpageXXs21baf
      manpageXXs21bbf
      manpageXXs21bcf
      manpageXXs21bdf
      manpageXXonline
      manpageXXkwic
      manpageXXsummary
      manpageXXconvert
    TopicPage
      |htTutorialSearch|
      NumberPage
        IntegerPage
          IntegerXmpPage
          ugxIntegerPrimesPage
          IntNumberTheoryFnsXmpPage
          IntegerExamplePage
            IntegerExampleProofPage
          IntegerProblemPage
            IntegerProblemProofPage
            IntegerProblemAnswerPage1
            IntegerProblemAnswerPage2
        FractionPage
          RationalNumberPage
          FractionXmpPage
        DoubleFloatXmpPage
          ugGraphPage
          ugProblemNumericPage
          FloatXmpPage
        FloatXmpPage
          ugGraphPage
          ugProblemNumericPage
          DoubleFloatXmpPage
          ugxFloatIntroPage
          ugxFloatConvertPage
          ugxFloatOutputPage
          ugxFloatHilbertPage
        ComplexXmpPage
          ugProblemNumericPage
          ugTypesConvertPage
        ugProblemFinitePage
        ugProblemNumericPage
        CardinalNumberXmpPage
        SingleIntegerXmpPage
        RomanNumeralXmpPage
        ContinuedFractionXmpPage
        PartialFractionXmpPage
        QuaternionXmpPage
        OctonionXmpPage
        DecimalExpansionXmpPage
          BinaryExpansionXmpPage
          HexExpansionXmpPage
          RadixExpansionXmpPage
        BinaryExpansionXmpPage
          DecimalExpansionXmpPage
          RadixExpansionXmpPage
        HexExpansionXmpPage
        RadixExpansionXmpPage
        PAdicPage
      PolynomialPage
        PolynomialBasicPage
        PolynomialSubstitutionPage
        ugProblemFactorPage
        PolynomialGCDPage
        PolynomialRootPage
        PolynomialTypesPage
      FunctionPage
        RationalFunctionPage
        AlgebraicFunctionPage
        ElementaryFunctionPage
        FunctionSimplificationPage
      EquationPage
        ugxProblemLinSysPage
        ugxProblemOnePolPage
        ugxProblemPolSysPage
        ugProblemDEQPage
      CalculusPage
        ugProblemLimitsPage
        ugIntroCalcDerivPage
        ugIntroIntegratePage
        ugProblemIntegrationPage
        ugProblemLaplacePage
        ugProblemSeriesPage
        ugProblemDEQPage
      LinAlgPage
        ugIntroTwoDimPage
        ugxMatrixCreatePage
        ugxMatrixOpsPage
        ugProblemEigenPage
        ugxFloatHilbertPage
        PermanentXmpPage
        VectorXmpPage
        SqMatrixXmpPage
        OneDimensionalArrayXmpPage
        TwoDimensionalArrayXmpPage
        ugTypesConvertPage
      GraphicsPage
      AlgebraPage
        NumberTheoryPage
        GroupTheoryPage
          InfoGroupTheoryPage
          InfoRepTheoryPage
          RepA6Page
    ugLangPage
    ExamplesExposedPage
    ugSysCmdPage
    GlossaryPage
    HTXTopPage
      HTXIntroTopPage
        HTXIntroPage1
          HTXIntroPage2
          ugHyperPage
        HTXIntroPage2
          HTXIntroPage3
        HTXIntroPage3
          HTXLinkPage6
          HTXTryPage
          HTXFormatTopPage
      HTXFormatTopPage
        HTXFormatPage1
        HTXFormatPage2
        HTXFormatPage3
        HTXFormatPage4
        HTXFormatPage5
        HTXFormatPage6
        HTXFormatPage7
        HTXFormatPage8
      HTXLinkTopPage
        HTXLinkPage1
          HTXLinkTopPage
          TestHelpPage
          HTXLinkPage2
        HTXLinkPage2
          HTXLinkPage6
          SpadNotConnectedPage
          UnknownPage
          ErrorPage
          ProtectedQuitPage
          HTXLinkPage3
        HTXLinkPage3
          HTXLinkPage4
        HTXLinkPage4
          HTXLinkPage5
        HTXLinkPage5
          HTXLinkPage6
        HTXLinkPage6
          HTXLinkTopPage
      HTXAdvTopPage
        HTXAdvPage1
          HTXAdvPage2
        HTXAdvPage2
          HTXAdvPage3
        HTXAdvPage3
          HTXAdvPage4
        HTXAdvPage4
          HTXAdvPage5
        HTXAdvPage5
          HTXAdvPage6
        HTXAdvPage6
          HTXAdvTopPage
      HTXTryPage 
    RefSearchPage
  TopicPage
  Man0Page
    |kSearch|
    |oSearch|
    |aSearch|
    |aokSearch|
    |docSearch|
    |genSearch|
    |detailedSearch|
    htsearch
    ugSysCmdPage
  TopExamplePage
    GraphicsExamplePage
      AssortedGraphicsExamplePage
      ThreeDimensionalGraphicsExamplePage
        TwoVariableGraphicsPage
        SpaceCurveGraphicsPage
        ParametricTubeGraphicsPage
        ParametricSurfaceGraphicsPage
        ugGraphThreeDBuildPage
      OneVariableGraphicsExamplePage
      PolarGraphicsExamplePage
      ParametricCurveGraphicsExamplePage
      ImplicitCurveGraphicsExamplePage
      ListPointsGraphicsExamplePage
      ComplexFunctionGraphicsExamplePage
    ExamplesExposedPage
      AssociationListXmpPage
        TableXmpPage
        ListXmpPage
      BalancedBinaryTreeXmpPage
      BasicOperatorXmpPage
      BinaryExpansionXmpPage
        HexExpansionXmpPage
        DecimalExpansion
        RadixExpansion
      BinarySearchTreeXmpPage
      CardinalNumberXmpPage
      CartesianTensorXmpPage
      CharacterXmpPage
        CharacterClassXmpPage
        StringXmpPage
      CharacterClassXmpPage
      CliffordAlgebraXmpPage
        ugxCliffordComplexPage
        ugxCliffordQuaternPage
        ugxCliffordExteriorPage
        ugxCliffordDiracPage
      ComplexXmpPage
      ContinuedFractionXmpPage
        StreamXmpPage
      CycleIndicatorsXmpPage
      DeRhamComplexXmpPage
      DecimalExpansionXmpPage
        HexExpansionXmpPage
        BinaryExpansion
        RadixExpansion
      DistributedMultivariatePolyXmpPage
        ugIntroVariablesPage
        ugTypesConvertPage
        PolynomialXmpPage
        UnivariatePolyXmpPage
        MultivariatePolyXmpPage
      DoubleFloatXmpPage
      EqTableXmpPage
        TableXmpPage
      EquationXmpPage
      ExitXmpPage
      ExpressionXmpPage
        KernelXmpPage
        ugIntroCalcDerivPage
        ugIntroCalLimitsPage
        ugIntroSeriesPage
        ugProblemDEQPage
        ugProblemIntegrationPage
        ugUserRulesPage
      FactoredXmpPage
        ugxFactoredDecompPage
        ugxFactoredExpandPage
        ugxFactoredArithPage
        ugxFactoredNewPage
          FactoredFnsTwoXmpPage
        ugxFactoredVarPage
      FactoredFnsTwoXmpPage
        FactoredXmpPage
        ugProblemGaloisPage
      FileXmpPage
        TextFileXmpPage
        KeyedAccessFileXmpPage
        LibraryXmpPage
        FileNameXmpPage
      FileNameXmpPage
      FlexibleArrayXmpPage
        OneDimensionalArrayXmpPage
        VectorXmpPage
      FloatXmpPage
      FractionXmpPage
        ContinuedFractionXmpPage
        PartialFractionXmpPage
      FullPartialFracExpansionXmpPage
        PartialFractionXmpPage
      GeneralSparseTableXmpPage
        TableXmpPage
      GroebnerFactorizationPkgXmpPage
      HeapXmpPage
        FlexibleArray
      HexExpansionXmpPage
        DecimalExpansion
        BinaryExpansion
        RadixExpansion
      IntegerXmpPage
        ugIntroNumbersPage
        IntNumberTheoryFnsXmpPage
        DecimalExpansionXmpPage
        BinaryExpansionXmpPage
        HexExpansionXmpPage
        RadixExpansionXmpPage
        ugxIntegerBasicPage
          FractionXmpPage
          ugTypesUnionsPage
          ugTypesRecordsPage
        ugxIntegerPrimesPage
          FactoredXmpPage
          ComplexXmpPage
        ugxIntegerNTPage
          IntNumberTheoryFnsXmpPage
      IntegerLinearDependenceXmpPage
      IntNumberTheoryFnsXmpPage
      KernelXmpPage
        BasicOperatorXmpPage
        ExpressionXmpPage
      KeyedAccessFileXmpPage
        FileXmpPage
        TextFileXmpPage
        LibraryXmpPage
      LexTriangularPkgXmpPage
      LazardSetSolvingPackageXmpPage
      LibraryXmpPage
        FileXmpPage
        TextFileXmpPage
        KeyedAccessFileXmpPage
      LieExponentialsXmpPage
      LiePolynomialXmpPage
      LinearOrdinaryDifferentialOperatorXmpPage
        ugxLinearOrdinaryDifferentialOperatorSeriesPage
      LinearOrdinaryDifferentialOperatorOneXmpPage
        ugxLinearOrdinaryDifferentialOperatorOneRatPage
      LinearODEOperatorTwoXmpPage
        ugxLinearODEOperatorTwoConstPage
        ugxLinearODEOperatorTwoMatrixPage
      ListXmpPage
        ugxListCreatePage
        ugxListAccessPage
        ugxListChangePage
        ugxListOtherPage
        ugxListDotPage
      LyndonWordXmpPage
      MagmaXmpPage
      MakeFunctionXmpPage
        ugUserMakePage
      MappingPackageOneXmpPage
      MatrixXmpPage
        ugxMatrixCreatePage
        ugxMatrixOpsPage
          ugIntroTwoDimPage
          ugProblemEigenPage
          ugxFloatHilbertPage
          PermanentXmpPage
          VectorXmpPage
          OneDimensionalArrayXmpPage
          TwoDimensionalArrayXmpPage
      MultiSetXmpPage
      MultivariatePolyXmpPage
        PolynomialXmpPage
        UnivariatePolyXmpPage
        DistributedMultivariatePolyXmpPage
      NoneXmpPage
      OctonionXmpPage
        QuaternionXmpPage
      OneDimensionalArrayXmpPage
        VectorXmpPage
        FlexibleArrayXmpPage
      OperatorXmpPage
      OrderedVariableListXmpPage
      OrderlyDifferentialPolyXmpPage
      PartialFractionXmpPage
        FullPartialFracExpansionXmpPage
      PermanentXmpPage
      PolynomialXmpPage
        DistributedMultivariatePolyXmpPage
        MultivariatePolyXmpPage
        UnivariatePolyXmpPage
        FactoredXmpPage
        ugProblemFactorPage
      QuaternionXmpPage
      RadixExpansionXmpPage
        HexExpansionXmpPage
        DecimalExpansion
        BinaryExpansion
      RealClosureXmpPage
      RegularTriangularSetXmpPage
      RomanNumeralXmpPage
      SegmentXmpPage
      SegmentBindingXmpPage
        SegmentXmpPage
        UniversalSegmentXmpPage
      SetXmpPage
        ListXmpPage
      SingleIntegerXmpPage
        ugTypesDeclare
        ugTypesPkgCallPage
        ugBrowsePage
      SparseTableXmpPage
        TableXmpPage
        GeneralSparseTableXmpPage
      SqMatrixXmpPage
        MatrxiXmpPage
        ugTypesWritingModesPage
        ugTypesExposePage
      SqFreeRegTriangSetXmpPage
      StreamXmpPage
        ugLangItsPage
        ugProblemSeriesPage
        ContinuedFractionXmpPage
        ListXmpPage
      StringXmpPage
        CharacterXmpPage
        CharacterClassXmpPage
      StringTableXmpPage
        TableXmpPage
      SymbolXmpPage
      TableXmpPage
        AssociationList
        EqTableXmpPage
        StringTableXmpPage
        SparseTableXmpPage
        KeyedAccessFileXmpPage
      TextFileXmpPage
        FileXmpPage
        KeyedAccessFileXmpPage
        LibraryXmpPage
      TwoDimensionalArrayXmpPage
        ugTypesAnyNonePage
        MatrixXmpPage
        OneDimensionalArrayXmpPage
      UnivariatePolyXmpPage
        ugProblemFactorPage
        ugIntroVariablesPage
        ugTypesConvertPage
        PolynomialXmpPage
        MultivariatePolyXmpPage
        DistributedMultivariatePolyXmpPage
      UnivariateSkewPolynomialPage
      UniversalSegmentXmpPage
        SegmentXmpPage
        SegmentBindingXmpPage
        ListXmpPage
        StreamXmpPage
      VectorXmpPage
        OneDimensionalArrayXmpPage
        ListXmpPage
        MatrixXmpPage
        OneDimensionalArrayXmpPage
        SetXmpPage
        TableXmpPage
        TwoDimensionalArrayXmpPage
      VoidXmpPage
      WuWenTsunTriangularSetXmpPage
      XPBWPolynomialXmpPage
      XPolynomialXmpPage
      XPolynomialRingXmpPage
      ZeroDimSolvePkgXmpPage
    ExampleCoverPage
      Menuexdiff
        ExDiffBasic
        ExDiffSeveralVariables
        ExDiffHigherOrder
        ExDiffMultipleI
        ExDiffMultipleII
        ExDiffFormalIntegral
      Menuexint
        ExIntRationalFunction
        ExIntRationalWithRealParameter
        ExIntRationalWithComplexParameter
        ExIntTwoSimilarIntegrands
        ExIntNoSolution
        ExIntTrig
        ExIntAlgebraicRelation
          ExIntAlgebraicRelationExplain
        ExIntRadicalOfTranscendental
        ExIntNonElementary
      Menuexlap
        ExLapSimplePole
        ExLapTrigTrigh
        ExLapDefInt
        ExLapExpExp
        ExLapSpecial1
        ExLapSpecial2
      Menuexlimit
        ExLimitBasic
          ExLimitTwoSided
          ExLimitOneSided
        ExLimitParameter
        ExLimitOneSided
        ExLimitTwoSided
        ExLimitInfinite
        ExLimitRealComplex
        ExLimitComplexInfinite
      Menuexmatrix
        ExMatrixBasicFunction
        ExConstructMatrix
        ExTraceMatrix
        ExDeterminantMatrix
        ExInverseMatrix
        ExRankMatrix
      Menuexplot2d
        ExPlot2DFunctions
        ExPlot2DParametric
        ExPlot2DPolar
        ExPlot2DAlgebraic
      Menuexplot3d
        ExPlot3DFunctions
        ExPlot3DParametricSurface
        ExPlot3DParametricCurve
      Menuexseries
        ExSeriesConvert
        ExSeriesManipulate
        ExSeriesFunctions
        ExSEriesSubstitution
      Menuexsum
        ExSumListEntriesI
        ExSumListEntriesII
        ExSumApproximateE
        ExSumClosedForm
        ExSumCubes
        ExSumPolynomial
        ExSumGeneralFunction
        ExSumInfinite
  TopSettingsPage
    ugSysCmdPage
  RootPageLogo
  releaseNotes
  ugHyperPage


htxl
  nagLinkIntroPage
  htxl1
    c02
      manpageXXc02
      (|kSearch| "NagPolynomialRootsPackage")
      (|c02aff|)
      (|c02agf|)
    c05
      manpageXXc05
      (|kSearch| "NagRootFindingPackage")
      (|c05adf|)
      (|c05nbf|)
      (|c05pbf|)
    c06
      manpageXXc06
      (|kSearch| "NagSeriesSummationPackage")
      (|c06eaf|)
      (|c06ebf|)
      (|c06ecf|)
      (|c06ekf|)
      (|c06fpf|)
      (|c06fqf|)
      (|c06frf|)
      (|c06fuf|)
      (|c06gbf|)
      (|c06gcf|)
      (|c06gqf|)
      (|c06gsf|)
    d01
      manpageXXd01
      (|kSearch| "NagIntegrationPackage")
      (|d01ajf|)
      (|d01akf|)
      (|d01alf|)
      (|d01amf|)
      (|d01anf|)
      (|d01apf|)
      (|d01aqf|)
      (|d01asf|)
      (|d01bbf|)
      (|d01fcf|)
      (|d01gaf|)
      (|d01gbf|)
    d02
      manpageXXd02
      (|kSearch| "NagOrdinaryDifferentialEquationsPackage")
      (|d02bbf|)
      (|d02bhf|)
      (|d02cjf|)
      (|d02ejf|)
      (|d02gaf|)
      (|d02gbf|)
      (|d02kef|)
      (|d02raf|)
    d03
      manpageXXd03
      (|kSearch| "NagPartialDifferentialEquationsPackage")
      (|d03edf|)
      (|d03eef|)
      (|d03faf|)
    e01
      manpageXXe01
      (|kSearch| "NagInterpolationPackage")
      (|e01baf|)
      (|e01bef|)
      (|e01bff|)
      (|e01bgf|)
      (|e01bhf|)
      (|e01daf|)
      (|e01saf|)
      (|e01sef|)
    e02
      manpageXXe02
      (|kSearch| "NagFittingPackage")
      (|e02adf|)
      (|e02aef|)
      (|e02agf|)
      (|e02ahf|)
      (|e02ajf|)
      (|e02akf|)
      (|e02baf|)
      (|e02bbf|)
      (|e02bcf|)
      (|e02bdf|)
      (|e02bef|)
      (|e02daf|)
      (|e02dcf|)
      (|e02ddf|)
      (|e02def|)
      (|e02dff|)
      (|e02gaf|)
      (|e02zaf|)
    e04
      manpageXXe04
      (|kSearch| "NagOptimisationPackage")
      (|e04dgf|)
      (|e04fdf|)
      (|e04gcf|)
      (|e04jaf|)
      (|e04mbf|)
      (|e04naf|)
      (|e04ucf|)
      (|e04ycf|)
    f01
      manpageXXf
      manpageXXf01
      (|kSearch| "NagMatrixOperationsPackage")
      (|f01brf|)
      (|f01bsf|)
      (|f01maf|)
      (|f01mcf|)
      (|f01qcf|)
      (|f01qdf|)
      (|f01qef|)
      (|f01rcf|)
      (|f01rdf|)
      (|f01ref|)
    f02
      manpageXXf
      manpageXXf02
      (|kSearch| "NagEigenPackage")
      (|f02aaf|)
      (|f02abf|)
      (|f02adf|)
      (|f02aef|)
      (|f02aff|)
      (|f02agf|)
      (|f02ajf|)
      (|f02akf|)
      (|f02awf|)
      (|f02axf|)
      (|f02bbf|)
      (|f02bjf|)
      (|f02fjf|)
      (|f02wef|)
      (|f02xef|)
    f04
      manpageXXf
      manpageXXf04
      (|kSearch| "NagLinearEquationSolvingPackage")
      (|f04adf|)
      (|f04arf|)
      (|f04asf|)
      (|f04atf|)
      (|f04axf|)
      (|f04faf|)
      (|f04jgf|)
      (|f04maf|)
      (|f04mbf|)
      (|f04mcf|)
      (|f04qaf|)
    f07
      manpageXXf
      manpageXXf07
      (|kSearch| "NagLapack")
      (|f07adf|)
      (|f07aef|)
      (|f07fdf|)
      (|f07fef|)
    s
      manpageXXs
      (|kSearch| "NagSpecialFunctionsPackage")
      (|s01eaf|)
      (|s13aaf|)
      (|s13acf|)
      (|s13adf|)
      (|s14aaf|)
      (|s14abf|)
      (|s14baf|)
      (|s15adf|)
      (|s15aef|)
      (|s17acf|)
      (|s17adf|)
      (|s17aef|)
      (|s17aff|)
      (|s17agf|)
      (|s17ahf|)
      (|s17ajf|)
      (|s17akf|)
      (|s17dcf|)
      (|s17def|)
      (|s17dgf|)
      (|s17dhf|)
      (|s17dlf|)
      (|s18acf|)
      (|s18adf|)
      (|s18aef|)
      (|s18aff|)
      (|s18dcf|)
      (|s18def|)
      (|s19aaf|)
      (|s19abf|)
      (|s19acf|)
      (|s19adf|)
      (|s20acf|)
      (|s20adf|)
      (|s21baf|)
      (|s21bbf|)
      (|s21bcf|)
      (|s21bdf|)
  (|kSearch| "Nag*")
  FoundationLibraryDocPage
  nagDocumentationPage 
    manpageXXintro 
    manpageXXonline 
    FoundationLibraryDocPage 
    aspSectionPage 
  nagLinkUsagePage 
  aspSectionPage 
  generalFortranPage 
  nagTechnicalPage 

UXANNA
UXANNAInt
UXANNAOde
UXANNAOpt
UXANNAPde
UXANNAOptEx
UXANNAOpt2Ex
UXANNAIntEx
UXANNAOdeEx
UXANNATxt
  UXANNAEx
  UXANNAIntro
    UXANNADec
    UXANNAInfer
    UXANNAMeth
    UXANNAMeas
  UXANNADec
  UXANNAInfer
  UXANNAMeas
UXANNAIntro
  UXANNADec
  UXANNAInfer
  UXANNAMeth
  UXANNAMeas
UXANNAEx
  UXANNAEx2
UXANNAEx2
  UXANNAEx3
UXANNAEx3
  UXANNADec
UXANNADec
  UXANNAInfer
  UXANNAMeth
  UXANNAMeas
  UXANNAAgent
UXANNAInfer
  UXANNAMeth
  UXANNAMeas
  UXANNAAgent
  UXANNAEx
UXANNAMeth
  UXANNAMeas
  UXANNAAgent
  UXANNAEx
UXANNAMeas
  UXANNAAgent
  UXANNAEx
UXANNAAgent
  UXANNAEx

Asp1ExampleCode
Asp10ExampleCode
Asp12ExampleCode
Asp19ExampleCode
Asp20ExampleCode
Asp24ExampleCode
Asp27ExampleCode
Asp28ExampleCode
Asp29ExampleCode
Asp30ExampleCode
Asp31ExampleCode
Asp33ExampleCode
Asp34ExampleCode
Asp35ExampleCode
Asp4ExampleCode
Asp41ExampleCode
Asp42ExampleCode
Asp49ExampleCode
Asp50ExampleCode
Asp55ExampleCode
Asp6ExampleCode
Asp7ExampleCode
Asp73ExampleCode
Asp74ExampleCode
Asp77ExampleCode
Asp78ExampleCode
Asp8ExampleCode
Asp80ExampleCode
Asp9ExampleCode

NoMoreHelpPage

hyperdoc
  ViewportPage
  BitMaps
  CPHelp

PrefixEval
InfixEval

helpExpose
ExposureSystem
ExposureDef
ExposureDetails

DomainMapping
  (|dbSpecialDescription| '|Mapping|)
  (|dbSpecialOperations| '|Mapping|)
MappingDescription

DomainRecord
  (|dbSpecialDescription| '|Record|)
  (|dbSpecialOperations| '|Record|)
RecordDescription

CategoryType

DomainUnion
  (|dbSpecialDescription| '|Union|)
  (|dbSpecialOperations| '|Union|)
UnionDescription
UntaggedUnion
UTUnionDescription

UsersGuideExposedPage
  ugWhatsNewTwoTwoPage
  ugIntroPage
    ugIntroTypoPage 
    ugIntroStartPage 
      ugHyperPage 
      ugSysCmdPage 
      ugAvailCLEFPage 
    ugIntroTypoPage 
    ugIntroExpressionsPage 
      ugIntroArithmeticPage 
      ugIntroPreviousPage 
      ugIntroTypesPage 
        ugTypesPage 
      ugIntroAssignPage 
        ugLangAssignPage 
      ugIntroConversionPage 
        ugTypesConvertPage 
      ugIntroCallFunPage 
      ugIntroMacrosPage 
        ugUserMacrosPage 
      ugIntroLongPage 
        ugInOutInPage 
        ugLangBlocksPage 
      ugIntroCommentsPage 
    ugIntroGraphicsPage 
      ugProblemNumericPage 
      ugAppGraphicsPage 
      ugGraphPage 
    ugIntroNumbersPage 
      FloatXmpPage 
      DoubleFloatXmpPage 
      ComplexXmpPage 
      DecimalExpansionXmpPage 
      ContinuedFractionXmpPage 
      PartialFractionXmpPage 
      RadixExpansionXmpPage 
      ugxProblemFinitePrimePage 
    ugIntroCollectPage 
      ListXmpPage 
      ugLangItsPage 
      StreamXmpPage 
      ugLangItsPage 
      OneDimensionalArrayXmpPage 
      FlexibleArrayXmpPage 
      HeapXmpPage 
      BinarySearchTreeXmpPage 
      BalancedBinaryTreeXmpPage 
      SetXmpPage 
      MultiSetXmpPage 
      AssociationListXmpPage 
      KeyedAccessFileXmpPage 
      LibraryXmpPage 
      SparseTableXmpPage 
      StringTableXmpPage 
      TableXmpPage 
      ugTypesRecordsPage 
      ugTypesUnionsPage 
      ugDomainsPage 
    ugIntroTwoDimPage 
      TwoDimensionalArrayXmpPage 
      MatrixXmpPage 
      PermanentXmpPage 
      SqMatrixXmpPage 
      VectorXmpPage 
      ugProblemEigenPage 
      ugProblemLinPolEqnPage 
      ugLangItsPage 
    ugIntroYouPage 
      ugUserPage 
      ugInOutInPage 
    ugIntroVariablesPage 
    ugIntroCalcLimitsPage 
      ugProblemLimitsPage 
    ugIntroSeriesPage 
      ugProblemSeriesPage 
    ugIntroCalcDerivPage 
    ugIntroIntegratePage 
      ugProblemIntegrationPage 
    ugIntroDiffEqnsPage 
    ugIntroSolutionPage 
    ugIntroSysCmmandsPage 
      ugSysCmdPage 
  ugTypesPage
    ugTypesBasicPage 
      ugTypesBasicDomainConsPage 
        ugCategoriesPage 
        ugTypesConvertPage 
    ugTypesWritingPage 
      ugTypesBasicPage 
      ugTypesDeclarePage 
      ugTypesConvertPage 
      ugTypesPkgCallPage 
      ugTypesWritingZeroPage 
      ugTypesWritingOnePage 
        ugTypesPkgCallPage 
      ugTypesWritingMorePage 
      ugTypesWritingModesPage 
        ugTypesDeclarePage 
        ugTypesConvertPage 
      ugTypesWritingAbbrPage 
        ugSysCmdwhatPage 
    ugTypesDeclarePage 
      ugLangAssignPage 
      ugUserDeclarePage 
      ugTypesConvertPageugIntroAssignPage 
    ugTypesRecordsPage 
    ugTypesUnionsPage 
      ugTypesUnionsWOSelPage 
      ugTypesUnionsWSelPage 
        ugTypesRecordsPage 
        ugTypesUnionsWOSelPage 
    ugTypesAnyNonePage 
    ugTypesConvertPage 
    ugTypesSubdomainsPage 
    ugTypesPkgCallPage 
      ugTypesDeclarePage 
      ugUserUsePage 
    ugTypesResolvePage 
    ugTypesExposePage 
      ugTypesPkgCallPage 
      ugUserTrianglePage 
      ugSysCmdframePage 
    ugAvailSnoopPage 
      ugBrowsePage 
      ComplexXmpPage 
      ugUserDeclarePage 
  ugHyperPage
    YouTriedIt 
    ugHyperHeadingsPage 
    ugHyperKeysPage 
      ugHyperScrollPage 
      ugHyperInputPage 
    ugHyperScrollPage 
      ugHyperInputPage 
    ugHyperInputPage 
    ugHyperButtonsPage 
    ugHyperSearchPage 
      ugLogicalSearchesPage 
    ugHyperExamplePage 
    ugHyperResourcesPage 
    ugInOutPage
      ugInOutInPage 
        ugLangBlocksPage 
      ugInOutSpadprofPage 
      ugInOutOutPage 
      ugInOutAlgebraPage 
      ugInOutTeXPage 
      ugInOutScriptPage 
      ugInOutFortranPage 
  ugLangPage
    ugLangAssignPage 
      ugUserDelayPage 
    ugLangBlocksPage 
      ugLangIfPage 
        ugTypesResolvePage 
        ugTypesPkgCallPage 
    ugLangIfPage 
      ugTypesResolvePage 
      ugTypesPkgCallPage 
    ugLangLoopsPage 
      ugLangLoopsCompIntPage 
        ugUserCompIntPage 
      ugLangLoopsReturnPage 
        ugUserBlocksPage 
      ugLangLoopsBreakPage 
        ugLangLoopsReturnPage 
      ugLangLoopsBreakVsPage 
      ugLangLoopsBreakMorePage 
        ugLangLoopsForInPage 
      ugLangLoopsIteratePage 
      ugLangLoopsWhilePage 
      ugLangLoopsForInPage 
      ugLangLoopsForInNMPage 
        SegmentXmpPage 
      ugLangLoopsForInNMSPage 
      ugLangLoopsForInNPage 
      ugLangLoopsForInXLPage 
      ugLangLoopsForInPredPage 
      ugLangLoopsParPage 
        ugLangLoopsForInPredPage 
    ugLangItsPage 
      ugLangLoopsPage 
      ListXmpPage 
      StreamXmpPage 
    ugLangStreamsPrimesPage 
  ugUserPage
    ugUserFunMacPage 
      ugUserAnonPage 
      ExitXmpPage 
      VoidXmpPage 
    ugUserMacrosPage 
    ugUserIntroPage 
      ugTypesPkgCallPage 
      ugUserAnonPage 
    ugUserDeclarePage 
      ugTypesDeclarePage 
    ugUserOnePage 
    ugUserDecUndecPage 
      ugCategoriesPage 
    ugUserDecOpersPage 
      MappingPackageOneXmpPage 
      ugPackagesAbstractPage 
      ugPackagesPage 
      ugCategoriesPage 
    ugUserDelayPage 
      ugLangAssignPage 
    ugUserUsePage 
      ugTypesPkgCallPage 
      ugTypesResolvePage 
    ugUserCompIntPage 
      ugTypesSubdomainsPage 
    ugUserPiecePage 
      ugUserPieceBasicPage 
      ugUserPiecePickingPage 
        ugUserPieceBasicPage 
      ugUserPiecePredPage 
        ugUserPieceBasicPage 
    ugUserCachePage 
      ugUserFreeLocalPage 
    ugUserRecurPage 
      ugUserFreeLocalPage 
      ugUserCachePage 
    ugUserMakePage 
      MakeFunctionXmpPage 
    ugUserBlocksPage 
      ugLangBlocksPage 
    ugUserFreeLocalPage 
      ugUserCachePage 
      ugUserRecurPage 
    ugUserAnonPage 
      ugUserAnonExampPage 
      ugUserAnonDeclarePage 
    ugUserDatabasePage 
    ugUserTrianglePage 
      ugTypesExposePage 
    ugUserPalPage 
      ugUserTrianglePage 
    ugUserRulesPage 
  ugGraphPage
    ugGraphTwoDPage 
      ugGraphTwoDPlotPage 
        ugGraphTwoDOptionsPage 
      ugGraphTwoDParPage 
        ugGraphThreeDOptionsPage 
      ugGraphTwoDPlanePage 
        ugGraphTwoDOptionsPage 
      ugGraphTwoDOptionsPage 
        ugGraphColorPage 
        ugGraphColorPalettePage 
        ugGraphColorPage 
        ugGraphColorPalettePage 
      ugGraphColorPage 
      ugGraphColorPalettePage 
      ugGraphTwoDControlPage 
      ugGraphTwoDopsPage 
      ugGraphTwoDbuildPage 
      ugGraphTwoDappendPage 
    ugGraphThreeDPage 
      ugGraphThreeDPlotPage 
        ugGraphThreeDOptionsPage 
      ugGraphThreeDParmPage 
        ugGraphThreeDOptionsPage 
      ugGraphThreeDParPage 
        ugGraphThreeDOptionsPage 
        ugGraphCoordPage 
      ugGraphThreeDOptionsPage 
        ugGraphCoordPage 
      ugGraphMakeObjectPage 
      ugGraphThreeDBuildPage 
      ugGraphCoordPage 
      ugGraphClipPage 
      ugGraphThreeDControlPage 
      ugGraphThreeDopsPage 
      ugXdefaultsPage 
  ugProblemPage
    ugProblemNumericPage 
      ugIntroPage 
      FloatXmpPage 
      DoubleFloatXmpPage 
    ugProblemFactorPage 
      ugProblemFactorIntRatPage 
      ugProblemFactorFFPage 
        ugProblemFinitePage 
      ugProblemFactorAlgPage 
      ugProblemFactorRatFunPage 
    ugProblemSymRootPage 
      ugxProblemOnePolPage 
      ugxProblemPolSysPage 
      ugxProblemSymRootOnePage 
      ugxProblemSymRootAllPage 
        ugxProblemOnePolPage 
    ugProblemEigenPage 
    ugProblemLinPolEqnPage 
      ugProblemDEQPage 
      ugxProblemLinSysPage 
      ugxProblemOnePolPage 
      ugxProblemPolSysPage 
        ugxProblemOnePolPage 
    ugProblemLimitsPage 
    ugProblemLaplacePage 
    ugProblemIntegrationPage 
      ugxProblemSymRootAllPage 
    ugProblemSeriesPage 
      ugxProblemDEQSeriesPage 
        ugxProblemSeriesConversionsPage 
        ugTypesDeclarePage 
        ugxProblemSeriesFunctionsPage 
        ugxProblemSeriesFormulaPage 
      ugxProblemSeriesCreatePage 
      ugxProblemSeriesCoefficientsPage 
      ugxProblemSeriesArithmeticPage 
      ugxProblemSeriesFunctionsPage 
      ugxProblemSeriesConversionsPage 
      ugxProblemSeriesFormulaPage 
        ugxProblemSeriesConversionsPage 
        ugUserAnonPage 
        ugxProblemSeriesConversionsPage 
      ugxProblemSeriesSubstitutePage 
      ugxProblemSeriesBernoulliPage 
    ugProblemDEQPage 
      ugProblemLinPolEqnPage 
      ugxProblemLDEQClosedPage 
      ugxProblemNLDEQClosedPage 
      ugxProblemDEQSeriesPage 
    ugProblemFinitePage 
      ugxProblemFinitePrimePage 
      ugxProblemFinitePrimePage 
      ugxProblemFiniteExtensionFinitePage 
      ugxProblemFiniteModulusPage 
        ugxProblemFiniteExtensionFinitePage 
      ugxProblemFiniteCyclicPage 
        ugxProblemFiniteUtilityPage 
      ugxProblemFiniteNormalPage 
        ugxProblemFiniteUtilityPage 
      ugxProblemFiniteConversionPage 
        ugxProblemFiniteExtensionFinitePage 
      ugxProblemFiniteUtilityPage 
    ugProblemIdealPage 
    ugProblemGaloisPage 
      FactoredXmpPage 
      ugAvailCLEFPage 
    ugProblemGeneticPage 
  OctonionXmpPage 
  ExamplesExposedPage
  ugIntProgPage
    ugAppGraphicsPage 
    ugIntProgDrawingPage 
      ugGraphPage 
    ugIntProgRibbonPage 
      ugUserPage 
      ugLangBlocksPage 
    ugIntProgColorPage 
    ugIntProgPLCPage 
    ugIntProgColorArrPage 
    ugIntProgVecFieldsPage 
    ugIntProgCompFunsPage 
      ugGraphPage 
    ugIntProgFunctionsPage 
      ugUserMakePage 
    ugIntProgNewtonPage 
      MappingPackageOneXmpPage 
  ugPackagesPage
    ugIntProgPage 
    ugIntProgPage 
    ugPackagesNamesPage 
      ugIntProgPage 
      ugTypesWritingAbbrPage 
    ugPackagesSyntaxPage 
    ugPackagesAbstractPage 
      ugIntProgCompFunsPage 
    ugPackagesCapsulesPage 
    ugPackagesInputFilesPage 
    ugPackagesPackagesPage 
    ugPackagesParametersPage 
      ugTypesPage 
      ugUserBlocksPage 
      ugCategoriesAttributesPage 
    ugPackagesCondsPage 
      ugUserBlocksPage 
    ugPackagesCompilingPage 
      EqTableXmpPage 
    ugPackagesHowPage 
      ugCategoriesHierPage 
  ugCategoriesPage
    ugTypesBasicDomainConsPage 
    ugCategoriesDefsPage 
      ugTypesPage 
    ugCategoriesExportsPage 
    ugCategoriesDocPage 
    ugCategoriesHierPage 
    ugCategoriesMembershipPage 
    ugCategoriesDefaultsPage 
      ugCategoriesHierPage 
      ugPackagesPage 
    ugCategoriesAxiomsPage 
      ugCategoriesDefaultsPage 
    ugCategoriesCorrectnessPage 
    ugCategoriesAttributesPage 
    ugCategoriesParametersPage 
    ugCategoriesConditionalsPage 
      ugPackagesCondsPage 
    ugCategoriesAndPackagesPage 
      ugPackagesAbstractPage 
  ugDomainsPage
    ugPackagesDomsPage 
      ugPackagesPage 
    ugDomainsDefsPage 
    ugDomainsAssertionsPage 
      ugCategoriesCorrectnessPage 
      ugCategoriesConditionalsPage 
    ugDomainsDemoPage 
    ugDomainsBrowsePage 
    ugDomainsRepPage 
      ugDomainsDemoPage 
    ugDomainsMultipleRepsPage 
      ugTypesUnionsPage 
    ugDomainsAddDomainPage 
      ugDomainsDemoPage 
    ugDomainsDefaultsPage 
      ugPackagesPage 
      ugCategoriesDefaultsPage 
    ugDomainsOriginsPage 
    ugDomainsShortFormsPage 
    ugDomainsCliffordPage 
      CliffordAlgebraXmpPage 
    ugDomsinsDatabasePage 
      ugDomainsQueryLanguagePage 
      ugDomainsDatabaseConstructorPage 
      ugDomainsQueryEquationsPage 
      ugDomainsDataListsPage 
      ugDomainsDatabasePage 
      ugDomainsCreatingPage 
      ugDomainsPuttingPage 
      ugDomainsExamplesPage 
  ugBrowsePage
    ugBrowseStartPage 
      ugBrowseCapitalizationConventionPage 
      ugBrowseDomainPage 
      ugBrowseViewsOfConstructorsPage 
      ugBrowseViewsOfOperationsPage 
    ugBrowseDomainPage 
    ugBrowseMiscellaneousFeaturesPage 
  ugWhatsNewPage
    ugWhatsNewLanguagePage
      ugLangLoopsBreakPage 
      ugLangBlocksPage 
    ugWhatsNewLibraryPage
      FullPartialFracExpansionXmpPage 
    ugWhatsNewHyperDocPage
      ugHyperKeysPage 
    ugWhatsNewDocumentationPage
      ugGraphTwoDbuildPage 
      ugGraphTwoDappendPage 
      ugIntroCallFunPage 
      ugUserRulesPage 
  ugSysCmdPage
    ugSysCmdOverviewPage 
      ugSysCmdsetPage 
      ugSysCmdcompilePage 
    ugSysCmdabbreviationPage 
    ugSysCmdbootPage 
      ugSysCmdfinPage 
      ugSysCmdlispPage 
      ugSysCmdsetPage 
      ugSysCmdsystemPage 
    ugSysCmdcdPage 
      ugSysCmdcompilePage 
      ugSysCmdeditPage 
      ugSysCmdhistoryPage 
      ugSysCmdlibraryPage 
      ugSysCmdreadPage 
      ugSysCmdspoolPage 
    ugSysCmdclosePage 
      ugSysCmdquitPage 
    ugSysCmdclearPage 
      ugSysCmddisplayPage 
      ugSysCmdhistoryPage 
      ugSysCmdundoPage 
    ugSysCmdcompilePage 
      ugSysCmdcdPage 
      ugSysCmdtracePage 
      ugSysCmdabbreviationPage 
      ugSysCmdeditPage 
      ugSysCmdlibraryPage 
    ugSysCmddisplayPage 
      ugSysCmdclearPage 
      ugSysCmdhistoryPage 
      ugSysCmdsetPage 
      ugSysCmdshowPage 
      ugSysCmdwhatPage 
    ugSysCmdeditPage 
      ugSysCmdsystemPage 
      ugSysCmdcompilePage 
      ugSysCmdreadPage 
    ugSysCmdfinPage 
      ugSysCmdpquitPage 
    ugSysCmdframePage 
      ugSysCmdhistoryPage 
      ugSysCmdsetPage 
    ugSysCmdhelpPage 
    ugSysCmdhistoryPage 
      ugSysCmdframePage 
      ugSysCmdcdPage 
      ugSysCmdreadPage 
      ugSysCmdsetPage 
      ugSysCmdundoPage 
    ugSysCmdlibraryPage 
    ugSysCmdlispPage 
      ugSysCmdsystemPage 
      ugSysCmdbootPage 
      ugSysCmdfinPage 
    ugSysCmdloadPage 
    ugSysCmdltracePage 
      ugSysCmdbootPage 
      ugSysCmdlispPage 
      ugSysCmdtracePage 
    ugSysCmdpquitPage 
      ugSysCmdfinPage 
      ugSysCmdhistoryPage 
      ugSysCmdclosePage 
      ugSysCmdquitPage 
      ugSysCmdsystemPage 
    ugSysCmdquitPage 
      ugSysCmdfinPage 
      ugSysCmdhistoryPage 
      ugSysCmdclosePage 
      ugSysCmdpquitPage 
      ugSysCmdsystemPage 
    ugSysCmdreadPage 
      ugInOutInPage 
      ugSysCmdcompilePage 
      ugSysCmdeditPage 
      ugSysCmdhistoryPage 
    ugSysCmdsetPage 
      ugSysCmdquitPage 
    ugSysCmdshowPage 
      ugSysCmddisplayPage 
      ugSysCmdsetPage 
      ugSysCmdwhatPage 
    ugSysCmdspoolPage 
      ugSysCmdcdPage 
    ugSysCmdsynonymPage 
      ugSysCmdsetPage 
      ugSysCmdwhatPage 
    ugSysCmdsystemPage 
      ugSysCmdbootPage 
      ugSysCmdfinPage 
      ugSysCmdlispPage 
      ugSysCmdpquitPage 
      ugSysCmdquitPage 
    ugSysCmdtracePage 
      ugSysCmdcompilePage 
      ugSysCmdbootPage 
      ugSysCmdlispPage 
      ugSysCmdltracePage 
    ugSysCmdundoPage 
      ugSysCmdhistoryPage 
    ugSysCmdwhatPage 
      ugSysCmddisplayPage 
      ugSysCmdsetPage 
      ugSysCmdshowPage 
      ugAppGraphicsPage


ugFimagesOnePage
ugFimagesTwoPage
ugFimagesThreePage
ugFimagesFivePage
ugFimagesSixPage
ugFimagesSevenPage
ugFimagesEightPage
ugFconformalPage
ugFtknotPage
ugFntubePage
  ugFimagesFivePage 
ugFdhtriPage
ugFtetraPage
ugFantoinePage
ugFscherkPage

GraphicsPage
  GraphicsExamplePage
  TwoDimensionalGraphicsPage
    OneVariableGraphicsPage
    ParametricCurveGraphicsPage
    PolarGraphicsPage
    ImplicitCurveGraphicsPage
    ListPointsGraphicsPage
  ThreeDimensionalGraphicsPage
    TwoVariableGraphicsPage
    SpaceCurveGraphicsPage
    ParametricTubeGraphicsPage
    ParametricSurfaceGraphicsPage
    ugGraphThreeDBuildPage
  ViewportPage

3DObjectGraphicsPage

BROWSEhelp
  ugBrowseStartPage
  ugBrowseDomainPage
  ugBrowseMiscellaneousFeaturesPage

nagm.ht
  manpageXXm01
  manpageXXm01caf
  manpageXXm01daf
  manpageXXm01def
  manpageXXm01djf
  manpageXXm01eaf
  manpageXXm01zaf

nagx.ht
  manpageXXx01
  manpageXXx02
  manpageXXx04
  manpageXXx04aaf
  manpageXXx04abf
  manpageXXx04caf
  manpageXXx04daf
  manpageXXx05
  manpageXXx05aaf
  manpageXXx05abf
  manpageXXx05acf
  manpageXXx05baf


\end{verbatim}
\chapter{Makefile}
\begin{chunk}{*}
BOOK=${SPD}/books/bookvol7.1.pamphlet
WORK=${OBJ}/${SYS}/hyper/pages
IN=${SPD}/books

# These files are not reachable from RootPage
IGNORE=annaex

PHT= alist array1 array2 bbtree binary bop bstree card carten \
     cclass char clif complex contfrac coverex cycles decimal derham \
     dfloat dmp eq eqtbl evalex exdiff exint exit exlap exlimit \
     exmatrix explot2d explot3d expr exseries exsum farray file float \
     fname fparfrac fr2 frac fr function gbf graphics grpthry gstbl \
     heap hexadec intheory int kafile kernel lazm3pk lexp lextripk \
     lib list lodo1 lodo2 lodo lpoly lword magma mappkg1 matrix \
     mkfunc mpoly mset none numbers oct odpol op ovar perman pfr poly1 \
     poly quat radix reclos regset roman segbind seg set sint sqmatrix \
     sregset stbl stream string strtbl symbol table textfile ug01 ug02 \
     ug03 ug04 ug06 ug07 ug08 ug10 ug11 ug12 ug13 ug15 uniseg \
     up vector void wutset xpbwpoly xpoly xpr zdsolve zlindep

PAGELIST= ${PHT} algebra aspex basic  bmcat cphelp expose gloss  \
    htxadvpage1 htxadvpage2 htxadvpage3 htxadvpage4 htxadvpage5 \
    htxadvpage6 htxadvtoppage htxformatpage1 htxformatpage2 \
    htxformatpage3 htxformatpage4 htxformatpage5 htxformatpage6 \
    htxformatpage7 htxformatpage8 htxformattoppage htxintropage1 \
    htxintropage2 htxintropage3 htxintrotoppage htxlinkpage1 \
    htxlinkpage2 htxlinkpage3 htxlinkpage3.ht htxlinkpage4 \
    htxlinkpage5 htxlinkpage6 htxlinktoppage htxtoppage htxtrypage \
    hyperdoc link man0 mapping nagaux nagc nagd nage nagf nagm nags \
    nagx newuser record releasenotes rootpage topics type ug00 ug05 \
    ug14 ug16 ug21 ug union util xmpexp 



HYPER=${MNT}/${SYS}/doc
PAGEFILE=${HYPER}/bookvol7.1.pamphlet
SMAN=${MNT}/${SYS}/bin/sman
HTADD=${MNT}/${SYS}/bin/htadd

all: dir ${PAGEFILE} ${HYPER}/ht.db
	@echo 3 finished ${BOOK}

dir:
	@echo 0 making hypertex directories
	@mkdir -p ${WORK}
	@mkdir -p ${HYPER}

\end{chunk}
Due to the awesome programming skills of Scott Morrison
the htadd program will use the original source file in
literate form to build the ht.db
\begin{chunk}{*}
${PAGEFILE}: ${BOOK}
	@echo 1 making ${PAGEFILE} from ${BOOK}
	@cp ${BOOK} ${PAGEFILE}

%:
	@echo 1 making ${HYPER}/$*.ht from ${BOOK}
	@ echo '(tangle "${BOOK}" "$*.ht" "${HYPER}/$*.ht")' | \
	  ${OBJ}/${SYS}/bin/lisp

\end{chunk}
The patch/paste files are now included directly in bookvol7.1
Add new patch/paste files is a manual process when editing the book.
\begin{chunk}{*}

${HYPER}/ht.db: ${BOOK}
	@echo 2 making ${HYPER} from ${BOOK}
	@ (cd ${HYPER} ; \
           rm -f ht.db ; \
	   ${HTADD} ${PAGEFILE} )
	@ cp -pr ${IN}/bitmaps ${HYPER}
	@ cp -pr ${IN}/viewports ${HYPER}
	@ (cd ${HYPER}/viewports ; \
            for i in `find . -name "*.Z"` ; do gunzip $$i ; done )

\end{chunk}
\eject
\printindex
\end{document}
