\documentclass{book} %\usepackage{axiom} \usepackage{graphicx} % struggle with latex figure-floating behavior \renewcommand\floatpagefraction{.9} \renewcommand\topfraction{.9} \renewcommand\bottomfraction{.9} \renewcommand\textfraction{.1} \setcounter{totalnumber}{50} \setcounter{topnumber}{50} \setcounter{bottomnumber}{50} % spadcommands are the actual text that you type at the axiom prompt \newcommand{\spadcommand}[1]% {\begin{flushleft}{\tt #1}\end{flushleft}\vskip .1cm } % spadgraph are the actual text that you type at the axiom prompt for draw \newcommand{\spadgraph}[1]% {\begin{flushleft}{\tt #1}\end{flushleft}\vskip .1cm } % returnType is the type signature returned by the axiom interpreter \newcommand{\returnType}[1]% {\begin{flushright}{\tt #1}\end{flushright}\vskip .1cm} % spadsig gives the standard -> notation for signatures \newcommand{\spadsig}[2]{{\sf #1 $\rightarrow$ #2}} % The book begins with some introductory material that is not really % listed as a chapter. This creates a header similar to \chapter. \newcommand{\pseudoChapter}[1]% {\vskip .5in \noindent {\Large{\bf #1}}\vskip .5in} % The book begins with some introductory material that is not really % listed as a section. This creates a header similar to \section. \newcommand{\pseudoSection}[1]% {\vskip .25in \noindent {\large{\bf #1}}\vskip .25in} % spadofFrom records the operation in the index and the domain in the index \newcommand{\spadopFrom}[2]{\index{library!operations!#1 @\begingroup \string\tt{} #1 \endgroup}\index{#2}``{\tt #1}''} % spadfunFrom records the function name and domain in the index \newcommand{\spadfunFrom}[2]{{\bf #1}\index{#1 @\begingroup \string\bf{} #1 \endgroup}\index{#2}} % special meanings for math characters \newcommand{\N}{\mbox{\bbold N}} \newcommand{\Natural}{\mbox{\bbold N}} \newcommand{\Z}{\mbox{\bbold Z}} \newcommand{\Integer}{\mbox{\bbold Z}} \newcommand{\Rational}{\mbox{\bbold Q}} \newcommand{\Q}{\mbox{\bbold Q}} \newcommand{\Complex}{\mbox{\bbold C}} \newcommand{\C}{{\mathcal C}} \newcommand{\Real}{\mbox{\bbold R}} \newcommand{\F}{{\mathcal F}} \newcommand{\R}{{\mathcal R}} % draw a box around a text block \newcommand\boxed[2]{% \begin{center} \begin{tabular}{|c|} \hline \begin{minipage}{#1} \normalsize {#2} \end{minipage}\\ \hline \end{tabular} \end{center}} \newcommand{\optArg}[1]{{{\tt [}{#1}{\tt ]}}} \newcommand{\argDef}[1]{{\tt ({#1})}} \newcommand{\funSyntax}[2]{{\bf #1}{\tt ({\small\it{#2}})}} \newcommand{\funArgs}[1]{{\tt ({\small\it {#1}})}\newline} \newcommand{\condata}[4]{{\bf #1} {\bf #2} {\bf #3} {\bf #4}} \def\glossaryTerm#1{{\bf #1}\index{#1}} \def\glossaryTermNoIndex#1{{\bf #1}} \def\glossarySyntaxTerm#1{{\tt #1}\index{#1}} \long\def\ourGloss#1#2{\par\pagebreak[3]{#1}\newline{#2}} \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} } } % these bitmaps are used by HyperDoc \newdimen\commentWidth \commentWidth=11pc \newdimen\colGutterWidth \colGutterWidth=1pc \newdimen\baseLeftSkip \baseLeftSkip=\commentWidth \advance\baseLeftSkip by \colGutterWidth \newcommand\ExitBitmap{{\setlength{\unitlength}{0.01in}\begin{picture}(50,16)(0,0)\special{psfile=ps/exit.ps}\end{picture}}} \newcommand\ReturnBitmap{{\setlength{\unitlength}{0.01in}\begin{picture}(50,16)(0,0)\special{psfile=ps/home.ps}\end{picture}}} \newcommand\HelpBitmap{{\setlength{\unitlength}{0.01in}\begin{picture}(50,16)(0,0)\special{psfile=ps/help.ps}\end{picture}}} \newcommand\UpBitmap{{\setlength{\unitlength}{0.01in}\begin{picture}(50,16)(0,0)\special{psfile=ps/up.ps}\end{picture}}} \newcommand{\tpd}[5]{{\setlength{\unitlength}{0.01in}\begin{picture}(#1,#2)(#3,#4)\special{psfile=#5}\end{picture}}} \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 4: DEVELOPERS GUIDE}} \end{titlepage} \pagenumbering{roman} \begin{verbatim} 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} \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{Getting Axiom} \section{The savannah website} \section{The axiom-developer website} \chapter{Building Axiom} \section{Makefiles} \section{Noweb} \section{Directory Structure} \section{Packages in zip} \section{Lisp} \section{Boot Compiler} \section{Interpreter} \section{Share} \section{Algebra} \section{Etc} \section{Clef} \section{Doc} \section{Graph} \section{Sman} \section{Input} \chapter{Modifying Axiom} \chapter{Becoming a Developer} \section{Using Arch} \chapter{THINGS TO BE INTEGRATED} \section{email 2} \begin{verbatim} There is something called the "add-chain formed by domain extensions" which is described in the Glossary of the Axiom book: "add-chain a hierarchy formed by domain extensions. If domain A extends domain B and domain B extends domain C, then A has add-chain B-C." and "domain extension a domain constructor A is said to extend a domain constructor B if A's definition has the form A == Badd.... This intuitively means "functions not defined by A are assumed to come from B." Successive domain extensions form add-chains affecting the search order for functions not implemented directly by the domain during dynamic lookup. "dynamic lookup In Axiom, a domain may or may not explicitly provide function definitions for all its exported operations. These definitions may instead come from domains in the add-chain or from default packages. When a function call is made for an operation in the domain, up to five steps are carried out. 1. If the domain itself implements a function for the operation, that function is returned. 2. Each of the domains in the add-chain are searched; if one of these domains implements the function, that function is returned. 3. Each of the default packages for the domain are searched in order of the lineage. If any of the default packages implements the function, the first one found is returned. 4. Each of the default packages for each of the domains in the add-chain are searched in the order of their lineage. If any of the default packages implements the function, the first one found is returned. 5. If all of the above steps fail, an error message is reported. --------- \end{verbatim} \section{email 2} \begin{verbatim} > > > The list of prerequisites for running axiom is huge, and > > getting worse it seems! > ... > > So in the interest of having something people can download > > that is functional with a minimum of effort, I think axiom > > (and any help system or hyperdoc) should be decoupled from > > zope and zwiki. A download (think windoze users here) which > > included zope, zwiki, latex, ghostscript, python, PIL, gcl, > > gcc, *and* axiom, is too much, methinks. > > Heh - even I agree there. Perhaps it would be best to > acknowledge the reality that if one wants to take advantage > of all the vast possibilities of open source software, that's > going to be at odds with having the full power of the system > available on all platforms, particularly Windows, as a single > package. Surely power users who are willing and able to use > the full web-like setup, instead of just a TeXmacs or Mathematica > like document interface, would be willing to set it up or at > the very least boot a live Linux CD loaded with the full set > of Axiom tools and dependencies. > Personally, although I have tried knoppix and some variants on several occasions I have always been a little disappointed and frustrated. The problem is that I live in linux about 1/2 the time and windows the other 1/2 and when I boot one of these "live" things I feel like I am in neither. It's fun to play for an hour or so but then it goes in the desk draw with all the other things that once fascinated me but I haven't looked at for so long that they are now collecting dust. So I am quite sceptical about the utility of a "live" Axiom/Doyen CD except as a kind of conference "promotional gimmick". Let's put the list in the following order and fill it in a few more: gcc / | \ gcl latex python / | | \ / noweb | zope / / | | / axiom ghostscript PIL zwiki \ \ | / \ LatexWiki \ / MathAction Add your favourite text editor and browser and set it all up in Linux/Unix or Windows. There. Now that doesn't seem so large and complex does it? (: At least not if you compare it to the list of capabilities that this remarkable combination of entirely open source software provides... :) I am quite sure that this would all easily fit on one-side of a Cdrom, including documentation. And of course we can add as many more optional add-on packages as we want, such as Reduce, Aldor, Maxima, ... eventually all integrated with a common web interface. What this gives you a fully web-integrated, collaborative mathematical research and development, hyper-linked publishing environment right on your desktop, or even in your pocket (I run almost all of this on a Zaurus 5600). This is all easily doable right now for free. I would have given my left arm for something like this back when I was a student! \end{verbatim} \section{email 4} \begin{verbatim} > > Next we see the transition to compiling the non-BOOTSTRAP algebra. > > This is done in the interpsys image. It is also done in an image > > that has access to only the BOOTSTRAP algebra code. Thus the > > new compiler might not have all of the algebra-defined replacements > > available at compile time. Notice the autoload files that contain > > the optimizations. > > > > What do you mean by "algebra-defined replacements". Where are > these replacements defined? How are they different than the > "optimizations" contained in the autoload files? The BOOTSTRAP files contain lsp and spad code. The build steps for the initial BOOTSTRAP layer use "depsys" to compile the lisp code. So, in this case, we see VECTOR.lsp being compiled in the depsys image. VECTOR.lsp is the last algebra file that contains BOOTSTRAP code. So in this phase we see: VECTOR.lsp (BOOTSTRAP) -> VECTOR.o Once we leave the phase (shown in the printout) we start using an "interpsys" image to compile spad code. Much later in the console VECTOR.spad will be compiled and replaces the lisp. However the "interpsys" environment in VECTOR.spad differs significantly from the "depsys" environment that compiles VECTOR.lsp BOOSTRAP code. So we see VECTOR.spad + SINT.NRLIB -> VECTOR.lsp -> VECTOR.o (replaced previous version) Suppose VECTOR.spad used something from SINT.spad. When the VECTOR.lsp BOOTSTRAP file is compiled by depsys it contains (+ ... ...) and generates untyped and unoptimized code. Later when VECTOR.spad is compiled and SINT.o is available then the spad compiler will use the optimization information to generate (QSADD1 ... ...) > What do you mean by "expose". Why does this cause interpsys to > be re-built? That is necessary if code is going to be generated > based on new optimizations isn't it? expose == make available Due to my lack of foresight in choosing the VECTOR.lsp BOOTSTRAP code I did not use the most highly optimized version. But in the algebra recompile of VECTOR.spad later in the build this gets corrected because the operations are made available (exposed) by previously compiled .spad code. So: VECTOR.lsp (BOOTSTRAP) uses SINT.o But the VECTOR.lsp has (+ ... ...) instead of (QSADD1 ... ...) because the rewriting of "+" to "QSADD1" is done by the spad compiler, not the GCL compiler and we are not yet in a position to use the spad compiler. Later when VECTOR.spad -> VECTOR.lsp -> VECTOR.o (replaced previous version) the spad compiler was invoked and it gets a chance to change "+" to "QSADD1". Because I grabbed the wrong version of .lsp file for BOOTSTRAP code you are able to see this difference. The work you and steve are doing is to find stable versions of the .lsp files. > > Since these are only optimizations the final results should not > > be affected. > > > > But it could have an impact on overall performance, right? Oh, clearly. (QSADD1 ... ...) is faster than (+ ... ...) Furthermore, there is another optimization step we could take during the build but we do not (yet). When the GCL compiler compiles VECTOR.lsp it generates VECTOR.fn. If you look in these .fn files you'll find exact type information for each function call. VECTOR.lsp -> VECTOR.o + VECTOR.fn (unoptimized, but type generated) If this exact type information was available at compile time then the GCL compiler can lay down faster code. However there is a bootstrap problem here also since the GCL compiler has to compile the code one time in order to generate the .fn file. VECTOR.lsp + VECTOR.fn -> VECTOR.o (type optimized) So the full, proper procedure, which I have yet to do, would actually call the GCL compile once to generate the .fn file with exact type information for function calls, load the .fn file, and the recompile the lisp file. Since the second compile has exact type information the generated code will be (potentially much) shorter. For each lisp file do ( VECTOR.lsp -> VECTOR.o + VECTOR.fn (unoptimized, but type generated) VECTOR.lsp + VECTOR.fn -> VECTOR.o (type optimized) ) > Still after reading the interp and algebra Makefiles again, > I do not see why interpsys is being rebuilt after I delete > all the *.NRLIB's and repeat the 'make'. I am still missing > something somewhere. Is there some "missing link" that still > connects the algebra/Makefile back to the inter/Makefile? I have to think about this (I'm getting ready for work so I'll give it some "drive-time cycles") but I believe that the issue is related to using fresh databases. The databases are used during the algebra compiles to resolve algebra calls. However recompiling the algebra generates NRLIBs and, from these NRLIBs a fresh database is built thus: DATABASES -> NRLIBs -> FRESH DATABASES This is yet a third bootstrap issue. There are more but not with the algebra files. \end{verbatim} \section{email 4} \begin{verbatim} Yet one other opportunity for speed optimization is available at build time.... Remember that every lisp file generates a .fn file: foo.lsp -> foo.o + foo.fn and that a second compile with the .fn file loaded is faster: foo.lsp + foo.fn -> faster foo.o However if we look at the type information in the foo.fn file we find that it only contains type information for functions defined in foo.lsp. But suppose there are two lisp files with functions from one using functions from the other. The sub-optimal sequence is: foo.lsp -> foo.o + foo.fn foo.lsp + foo.fn -> faster foo.o bar.lsp -> bar.o + bar.fn bar.lsp + bar.fn -> faster bar.o The optimal sequence is: foo.lsp -> foo.o + foo.fn bar.lsp -> bar.o + bar.fn foo.lsp + (foo.fn + bar.fn) -> even faster foo.o bar.lsp + (foo.fn + bar.fn) -> even faster bar.o So, really what we should do is cache ALL of the .fn files from all of the compiles, batch them into a big file, and the completely rebuild the system with the batched .fn files loaded. I've started this process but have not yet completed it. See the file src/boot/boot-proclaims.lisp So there is a faster Axiom coming in the future but the build complexity will be even greater. And Camm, I believe, is doing even more with type propagation which will improve things more. \end{verbatim} \section{email 5} \begin{verbatim} How I Built Axiom on Windows I installed a completely new MinGW/MSYS configuration from the 'current' file list at: http://www.mingw.org/download.shtml#hdr2 In the following order: 1 MinGW-3.1.0-1.exe http://prdownloads.sf.net/mingw/MinGW-3.1.0-1.exe?download 2 MSYS-1.0.10.exe http://prdownloads.sf.net/mingw/MSYS-1.0.10.exe?download 3 msysDTK-1.0.1.exe http://prdownloads.sf.net/mingw/msysDTK-1.0.1.exe?download 4 Then untarred the following: cd /mingw; tar xzvf /home/bpage/... gcc-core-3.4.2-20040916-1.tar.gz http://prdownloads.sf.net/mingw/gcc-core-3.4.2-20040916-1.tar.gz?download 5 binutils-2.15.91-20040904-1.tar.gz http://prdownloads.sf.net/mingw/binutils-2.15.91-20040904-1.tar.gz?download 6 w32api-3.1.tar.gz http://prdownloads.sf.net/mingw/w32api-3.1.tar.gz?download 7 mingw-runtime-3.5.tar.gz http://prdownloads.sf.net/mingw/mingw-runtime-3.5.tar.gz?download 8 You will also need tla for windows from http://download.sipsolutions.de/tla-setup.exe 9 and the windows LaTeX packaged called MikTex http://www.miktex.org/setup.html The "Small MiKTeX" package is sufficient if your windows box is connected to the Internet. Or if you want you can install the complete system. 10 download the axiom--windows--1 branch See deteails instructions at ArchUsage 1 tla my-id "First Last " 2 tla register-archive address@bogus.example.com http://axiom-developer.org/archive/axiom 3 tla my-default-archive address@bogus.example.com 4 tla get axiom--windows--1 axiom--windows--1 Or see ArchUsage to use 'sftp://' protocol if you intend to submit changes. 11 configure and make cd axiom--windows--1 ./configure -- Cut-and-paste environmnet variables to avoid typing errors make -- the build takes between 3 to 6 hours on 2.4 GHz Windows XP \end{verbatim} \section{email 6} \begin{verbatim} What is MinGW? MinGW ("Minimalistic GNU for Windows") refers to a set of runtime headers, used in building a compiler system based on the GNU GCC and binutils projects. It compiles and links code to be run on Win32 platforms... providing C, C++ and Fortran compilers plus other related tools. If you see references to "mingw32" instead of "MinGW", they are referring to the same compiler system. The project's name changed from mingw32 to MinGW is to prevent the implication that MinGW will only works on 32 bit systems (as 64 and higher bit machines become more common, MinGW will evolve to work with them). MinGW uses the Microsoft runtime libraries, distributed with the Windows operating system. Unlike other ports of GCC to Windows, the runtime libraries are not distributed using Gnu's General Public License (GPL). You, therefore, do not have to distribute your source code with your programs unless, of course, you use a GPL library in your programs. What is MSYS? MSYS or Minimal SYStem is a POSIX and Bourne shell environment use with MinGW. It provides a hand picked set of tools to allow a typical configuration script with Bourne syntax to execute. This allows most of the GNU packages to create a Makefile just from executing the typical configure script which can then be used to build the package using the native MinGW version of GCC. The POSIX layer used by MSYS is a fork of the 1.3.3 version of Cygwin . Cygwin is a full POSIX layer and UNIX-like environment for Win32 providing both server and client utilites. \end{verbatim} \section{email 7} \begin{verbatim} The build sequence should be: obj/linux/bin/lisp ... contains the socket extensions obj/linux/bin/bootsys ... contains the boot -> lisp compiler used to compile the interp/*.boot files obj/linux/bin/depsys ... contains macros used by axiom used for compiling the intermediate lisp files obj/linux/bin/interpsys ... contains the final image used to compile the algebra obj/linux/bin/AXIOMsys contains the final image a clean copy for the end user I've attached the interesting part of a console log. At this point the Axiom build is making the transition from building the BOOTSTRAP algebra to building the non-BOOTSTRAP algebra. Notice that the BOOTSTRAP algebra is just lisp code. This code is compiled in a DEPSYS image so that macros are properly expanded. However it is clear that the BOOTSTRAP lisp code was not compiled by the "new" compiler. Next we see the transition to compiling the non-BOOTSTRAP algebra. This is done in the interpsys image. It is also done in an image that has access to only the BOOTSTRAP algebra code. Thus the new compiler might not have all of the algebra-defined replacements available at compile time. Notice the autoload files that contain the optimizations. A second or third round of compiles will expose the algebra-based optimizations and these will be compiled into the code. Since these are only optimizations the final results should not be affected. Also note that the BOOTSTRAP algebra is recompiled as the last step of building the algebra from scratch so that it can use the circular definitions. ========================================================================== ==== running DEPSYS image =============================================== ========================================================================== BOOT>0 making /home/arch/axiom--hyperdoc--1--base-0/int/algebra/VECTOR.lsp from /home/arch/axiom--hyperdoc--1--base-0/src/algebra/vector.spad.pamphlet 0 making /home/arch/axiom--hyperdoc--1--base-0/int/algebra/VECTOR.o from /home/arch/axiom--hyperdoc--1--base-0/int/algebra/VECTOR.lsp > Compiling VECTOR.lsp. End of Pass 1. End of Pass 2. OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, Speed=3 Finished compiling VECTOR.o. #p"VECTOR.o" BOOT>0 making /home/arch/axiom--hyperdoc--1--base-0/int/algebra/AHYP.spad from /home/arch/axiom--hyperdoc--1--base-0/src/algebra/trigcat.spad.pamphlet ========================================================================== ==== running AXIOMSYS image ============================================= ========================================================================== 0 making /home/arch/axiom--hyperdoc--1--base-0/int/algebra/AHYP.NRLIB from /home/arch/axiom--hyperdoc--1--base-0/int/algebra/AHYP.spad AXIOM Computer Algebra System Version of Friday November 19, 2004 at 16:36:16 ----------------------------------------------------------------------------- Issue )copyright to view copyright notices. Issue )summary for a summary of useful system commands. Issue )quit to leave AXIOM and return to shell. ----------------------------------------------------------------------------- Using local database /home/arch/axiom--hyperdoc--1--base-0/src/share/algebra/compress.daase.. Using local database /home/arch/axiom--hyperdoc--1--base-0/src/share/algebra/interp.daase.. Using local database /home/arch/axiom--hyperdoc--1--base-0/src/share/algebra/operation.daase.. Using local database /home/arch/axiom--hyperdoc--1--base-0/src/share/algebra/category.daase.. Using local database /home/arch/axiom--hyperdoc--1--base-0/src/share/algebra/browse.daase.. (1) -> Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/apply. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/c-doc. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/c-util. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/profile. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/category. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/compiler. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/define. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/functor. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/info. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/iterator. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/modemap. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/nruncomp. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/package. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/htcheck. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/xruncomp. Compiling AXIOM source code from file /home/arch/axiom--hyperdoc--1--base-0/int/algebra/AHYP.spad using old system compiler. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/parsing. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/bootlex. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/def. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/fnewmeta. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/metalex. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/metameta. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/parse. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/postpar. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/postprop. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/preparse. AHYP abbreviates category ArcHyperbolicFunctionCategory ------------------------------------------------------------------------ initializing NRLIB AHYP for ArcHyperbolicFunctionCategory compiling into NRLIB AHYP ;;; *** |ArcHyperbolicFunctionCategory| REDEFINED Time: 0 SEC. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/bc-matrix. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/bc-misc. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/bc-solve. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/bc-util. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/ht-util. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/htsetvar. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/ht-root. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/br-con. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/br-data. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/showimp. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/br-op1. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/br-op2. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/br-search. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/br-util. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/topics. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/br-prof. Loading /home/arch/axiom--hyperdoc--1--base-0/mnt/linux/autoload/br-saturn. finalizing NRLIB AHYP Processing ArcHyperbolicFunctionCategory for Browser database: --------(acosh ($ $))--------- --------(acoth ($ $))--------- --------(acsch ($ $))--------- --------(asech ($ $))--------- --------(asinh ($ $))--------- --------(atanh ($ $))--------- --------constructor--------- Compiling /home/arch/axiom--hyperdoc--1--base-0/int/algebra/AHYP.NRLIB/code.lsp. \end{verbatim} \section{email 8} \begin{verbatim} MiKTeX is an up-to-date TeX implementation for the Windows operating system. TeX is a typesetting system written by Donald E. Knuth, who says that it is "intended for the creation of beautiful books - and especially for books that contain a lot of mathematics". MiKTeX offers a complete set of utilities, macro packages and fonts, e.g., LaTeX, pdfTeX, ConTeXt, just to name a few. http://www.miktex.org\end{verbatim} \section{email 9} \begin{verbatim} > > Next we see the transition to compiling the non-BOOTSTRAP algebra. > > This is done in the interpsys image. It is also done in an image > > that has access to only the BOOTSTRAP algebra code. Thus the > > new compiler might not have all of the algebra-defined replacements > > available at compile time. Notice the autoload files that contain > > the optimizations. > > > > What do you mean by "algebra-defined replacements". Where are > these replacements defined? How are they different than the > "optimizations" contained in the autoload files? The BOOTSTRAP files contain lsp and spad code. The build steps for the initial BOOTSTRAP layer use "depsys" to compile the lisp code. So, in this case, we see VECTOR.lsp being compiled in the depsys image. VECTOR.lsp is the last algebra file that contains BOOTSTRAP code. So in this phase we see: VECTOR.lsp (BOOTSTRAP) -> VECTOR.o Once we leave the phase (shown in the printout) we start using an "interpsys" image to compile spad code. Much later in the console VECTOR.spad will be compiled and replaces the lisp. However the "interpsys" environment in VECTOR.spad differs significantly from the "depsys" environment that compiles VECTOR.lsp BOOSTRAP code. So we see VECTOR.spad + SINT.NRLIB -> VECTOR.lsp -> VECTOR.o (replaced previous version) Suppose VECTOR.spad used something from SINT.spad. When the VECTOR.lsp BOOTSTRAP file is compiled by depsys it contains (+ ... ...) and generates untyped and unoptimized code. Later when VECTOR.spad is compiled and SINT.o is available then the spad compiler will use the optimization information to generate (QSADD1 ... ...) > What do you mean by "expose". Why does this cause interpsys to > be re-built? That is necessary if code is going to be generated > based on new optimizations isn't it? expose == make available Due to my lack of foresight in choosing the VECTOR.lsp BOOTSTRAP code I did not use the most highly optimized version. But in the algebra recompile of VECTOR.spad later in the build this gets corrected because the operations are made available (exposed) by previously compiled .spad code. So: VECTOR.lsp (BOOTSTRAP) uses SINT.o But the VECTOR.lsp has (+ ... ...) instead of (QSADD1 ... ...) because the rewriting of "+" to "QSADD1" is done by the spad compiler, not the GCL compiler and we are not yet in a position to use the spad compiler. Later when VECTOR.spad -> VECTOR.lsp -> VECTOR.o (replaced previous version) the spad compiler was invoked and it gets a chance to change "+" to "QSADD1". Because I grabbed the wrong version of .lsp file for BOOTSTRAP code you are able to see this difference. The work you and steve are doing is to find stable versions of the .lsp files. > > Since these are only optimizations the final results should not > > be affected. > > > > But it could have an impact on overall performance, right? Oh, clearly. (QSADD1 ... ...) is faster than (+ ... ...) Furthermore, there is another optimization step we could take during the build but we do not (yet). When the GCL compiler compiles VECTOR.lsp it generates VECTOR.fn. If you look in these .fn files you'll find exact type information for each function call. VECTOR.lsp -> VECTOR.o + VECTOR.fn (unoptimized, but type generated) If this exact type information was available at compile time then the GCL compiler can lay down faster code. However there is a bootstrap problem here also since the GCL compiler has to compile the code one time in order to generate the .fn file. VECTOR.lsp + VECTOR.fn -> VECTOR.o (type optimized) So the full, proper procedure, which I have yet to do, would actually call the GCL compile once to generate the .fn file with exact type information for function calls, load the .fn file, and the recompile the lisp file. Since the second compile has exact type information the generated code will be (potentially much) shorter. For each lisp file do ( VECTOR.lsp -> VECTOR.o + VECTOR.fn (unoptimized, but type generated) VECTOR.lsp + VECTOR.fn -> VECTOR.o (type optimized) ) > Still after reading the interp and algebra Makefiles again, > I do not see why interpsys is being rebuilt after I delete > all the *.NRLIB's and repeat the 'make'. I am still missing > something somewhere. Is there some "missing link" that still > connects the algebra/Makefile back to the inter/Makefile? I have to think about this (I'm getting ready for work so I'll give it some "drive-time cycles") but I believe that the issue is related to using fresh databases. The databases are used during the algebra compiles to resolve algebra calls. However recompiling the algebra generates NRLIBs and, from these NRLIBs a fresh database is built thus: DATABASES -> NRLIBs -> FRESH DATABASES This is yet a third bootstrap issue. There are more but not with the algebra files. \end{verbatim} \section{email 9} \begin{verbatim} Yet one other opportunity for speed optimization is available at build time.... Remember that every lisp file generates a .fn file: foo.lsp -> foo.o + foo.fn and that a second compile with the .fn file loaded is faster: foo.lsp + foo.fn -> faster foo.o However if we look at the type information in the foo.fn file we find that it only contains type information for functions defined in foo.lsp. But suppose there are two lisp files with functions from one using functions from the other. The sub-optimal sequence is: foo.lsp -> foo.o + foo.fn foo.lsp + foo.fn -> faster foo.o bar.lsp -> bar.o + bar.fn bar.lsp + bar.fn -> faster bar.o The optimal sequence is: foo.lsp -> foo.o + foo.fn bar.lsp -> bar.o + bar.fn foo.lsp + (foo.fn + bar.fn) -> even faster foo.o bar.lsp + (foo.fn + bar.fn) -> even faster bar.o So, really what we should do is cache ALL of the .fn files from all of the compiles, batch them into a big file, and the completely rebuild the system with the batched .fn files loaded. I've started this process but have not yet completed it. See the file src/boot/boot-proclaims.lisp So there is a faster Axiom coming in the future but the build complexity will be even greater. And Camm, I believe, is doing even more with type propagation which will improve things more. \end{verbatim} \section{email 10} \begin{verbatim} I am no longer baffled. The explanation for the generic arith vs. fixnum arith is in macros.lisp. In the following code from -REPEAT, X is bound to a form such as '((STEP |i| 3 1)): (COND ((AND (EQ (CAAR X) 'STEP) (|member| (CADDAR X) '(2 1 0 (|One|) (|Zero|))) (|member| (CADR (CDDAR X)) '(1 (|One|)))) (SETQ X (CONS (CONS 'ISTEP (CDAR X)) (CDR X))) )) ; A hack to increase the likelihood of small integers So, one `rule' is, if you iterate with a sequence with lower bound 0,1, or 2, with an increment of 1, you get fixnum arith. Otherwise you get generic arithmetic. However, this is not a hard and fast rule, since the compiler can say '(ISTEP |i| 5 23) [say] during code generation and force fixnum arith. This leads to a question. Tim, in interp/wi2.boot we have a redefinition of compIterator (default implementation is in iterator.boot). This new definition makes an attempt at deciding when fixnum stepping code should be generated. Do you have an explanation as to why is this not the default definition? The original version of the code in iterator.boot is what gets called. I'm wondering if it is possible that during the fixedPoint build if some of the new definitions (particularly those in wi2.boot, xruncomp.boot) are being autoloaded during compilation. The changes which I have already noted in the generated lisp seem to support this (fixnum arith vs. generic arith, inlining of trivial coercions, etc). All the changes make sense if they are the result of calling one of the `improved' functions which these files redefine. Sincerely, Steve On Mon, Jan 17, 2005 at 01:39:45PM -0500, Stephen Wilson wrote: > > Tim, > > I compleatly fine with the fixnum declaration. We just need to make > sure it is a rule programmers can rely on. Consider: > > )abbrev package ITER Iter > Iter(): E == I where > E == with > iter: () -> Void > I == add > iter(): Void == > for i in 2.. repeat > print(i::OutputForm) > > > The relavent lisp decalres we are using fixnums: > > (LETT |i| (QSADD1 |i|) |ITER;iter;V;1|) > > > Now compile the above with a lower bound of 3: > > for i in 3.. repeat > print(i::OutputForm) > > > We get generic arithmetic: > > (LETT |i| (+ |i| 1) |ITER;iter;V;1|) > > > Baffled, > Steve > > > On Mon, Jan 17, 2005 at 12:23:36PM -0500, root wrote: > > Steve, > > > > I don't know if there is an actual statement to the effect that > > the upper bound on a loop would be a register-sized number (32 > > or 64 bits) but at 6Mhz it seemed impossible that one could > > run a loop of any consequence for greater than 2^32 or 2^64 > > iterations. If you wanted to do that you'd have to do the > > looping using some other construct. In general it is safe to > > assume that the upper bound of the register size cannot be > > exceeded. There is a practical performance difference to > > be gained by using (declare (fixnum as the compiler can, > > in the best case, assign a register to the loop variable. > > > > t \end{verbatim} \section{email 11} \begin{verbatim} I installed "Aldor version 1.0.2 for LINUX(glibc2.3)" on axiom-developer.org several months ago. The date on the aldor tarball in /home/page is May 19 2004. Aldor should be accessible to you when you log in at axiom-developer. Just add export ALDORROOT=/usr/local/aldor/linux/1.0.2 export PATH=$ALDORROOT/bin:$PATH to your .bashrc, do . .bashrc and your should be able to type aldor ... You should find the libaries in the standard locations. There is apparently a fairly up to date windows binary version as well, but I haven't had much time to play with this yet. At the time I was planning to implement a MathAction- Aldor web interface that would look something like this \begin{aldor} ... aldor code ... \end{aldor} and which could be intermixed with Axiom code on the MathAction website. I got distracted by other things and so have not yet completed the integration with MathAction but there is not a lot more to do. Recent discussions here about getting Axiom and Aldor working together again suggest that it might be time for me to raise the priority to make this possible. Ralf Hemmecke wrote: > > If you mean cvs.aldor.org, then it might be that May 16 2004 > is a bit late. The libraries have changed since then. > > You could however download the latest precompiled version > 1.0.2 from > > http://www.aldor.org/downl.html > > If you really want to compile the libraries yourself, ask > me again. I think the newest cvs-version should compile, > but if they don't ... There has been some work on the > Makefiles since May 16. > > Ralf > > root wrote: > > Martin, Peter, > > > > I tried to build aldor last night. I succeeded in building > > the compiler but not the libraries. I have a CVS checkout > > from May 16. > > > > I've been reading the Makefiles but they all seem to dissolve > > into home-grown tools (makeon, docc, etc) which undermines my > > ability to figure out what is happening. It's been years since > > I built aldor. > > > > Peter, could you provide the required steps to build a working > > compiler? e.g. > > > > edit Makefile.globals to change.... make aldorcompiler > > .... > > \end{verbatim} \section{email 12} \begin{verbatim} Oops, sorry that I have not read the documentation of Any. I had a look at Any now. Well, from that I just got the feeling that a programmer should never use Any if there are better types around (and often there are). Any seems to be connected to the interpreter. Since everything must have a type and the interpreter cannot figure out something reasonable, it falls back to Any. I'd rather be happy if the interpreter is clearly separated from the compiler. The interpreter is for working with Axiom, so it could help the (lazy) user and find/guesss appropriate types for him/her. However there should be NO guessing when it comes to writing new library code. Looking at the code of Any reminds me much of the things I have suggested here address@bogus.example.com">http://page.axiom-developer.org/zope/mathaction/address@bogus.example.com The code is in cvs.aldor.org/aldor/aldorug/samples/object*.as. The problem I still have with any is that it says Rep := Record(dm: SExpression, ob: None) dom x == x.dm which looks very near to some LISP thing. So I can ask for the domain a: Any by calling dom(a). Then I will get an SExpression which makes me feel lost. Unfortunately, I have no runnig Axiom at the moment :-( And I cannot compile axim--main--1 (bfd.h is missing and I have no idea what to install). So I tested on http://page.axiom-developer.org/zope/mathaction/AxiomInterface i: Integer := 1 Type: Integer a: Any := i::Any Type: Integer <----- very interesting!!! dom a Type: SExpression obj a Type: None j: Integer := a :: Integer Type: Integer It seems the interpreter is quite smart. s: String := "I am a string" Type: String b: Any := s::Any Type: String dom b Type: SExpression? obj b Type: None k: Integer := b :: Integer Cannot convert from type Any to Integer for value "I am a string" This Error is OK. And I think for manually working with Axiom, one just needs to type dom(...) and then coerce to the now known type. But how to use Any in a program is totally unclear to me. I have no idea to get the domain back from the SExpression. \end{verbatim} \section{email 13} \begin{verbatim} > ... > I am, however, very much against the Any type. It is like > building a strongly typed language and than trying to forget > about types. > Well that is more or less what I naively thought as well but from the ANY.spad file I read that: )abbrev domain ANY Any ++ Author: Robert S. Sutor ++ Basic Functions: any, domainOf, objectOf, dom, obj, ++ showTypeInOutput ++ Related Constructors: AnyFunctions1 ++ Description: ++ \spadtype{Any} implements a type that packages up objects and ++ their types in objects of \spadtype{Any}. Roughly speaking ++ that means that if \spad{s : S} then when converted to ++ \spadtype{Any}, the new object will include both the original ++ object and its type. This is a way of converting arbitrary ++ objects into a single type **without losing any** of the ++ original information. Any object can be converted to one of ++ \spadtype{Any}. and in the related file ANY1.spad )abbrev package ANY1 AnyFunctions1 ++ Basic Functions: coerce, retractIfCan, retractable?, retract ++ Description: ++ \spadtype{AnyFunctions1} implements several utility functions ++ for working with \spadtype{Any}. These functions are used to ++ go back and forth between objects of \spadtype{Any} and objects ++ of other types. So the situation is not quiet so simple. Apparently Any does not mean Any in the sense of throwing away essential information. \end{verbatim} \section{email 14} \begin{verbatim} Ralf Hemmecke wrote: > > Hi Bill, > > >>Foo: with { g: (n: PositiveInteger, k: PositiveInteger) -> > >>PrimeField(n) } == add { > >>g(n: PositiveInteger, k: PositiveInteger ): PrimeField(n) == > >> k::Integer::PrimeField(n) } > > > Ok, I will work with this example. Yes, it is better. > > Well, I haven't checked whether it should really work, but > shouldn't be > > Foo: with { > g: (n: PositiveInteger, k: PositiveInteger) -> > (P: PrimeFieldCategory, x: P) > } == add { > g(n: PositiveInteger, k: PositiveInteger ): > (P: PrimeFieldCategory, x:P) == { > (PrimeField(n), k::Integer::PrimeField(n) > } > } > > be even better? In fact you just pointed a way to solve the problem! Notice that you are in effect constructing a domain! So first create this domain (call this anything else you like): --%PointedPrimeField )abbrev domain PPF PointedPrimeField PointedPrimeField(n:PositiveInteger):Cat==Dog where Cat == FiniteFieldCategory with foo:PositiveInteger->PrimeField(n) Dog == PrimeField(n) add foo(k)==k::Integer::PrimeField(n) After compiling, define in the interpreter g(n,k)==foo(k)$PPF(n) and it works (in Axiom)! (Do not declare the types for g because n is not defined). But I have trouble with path in windows: Processing PointedPrimeField for Browser database: --->-->PointedPrimeField((foo ((PrimeField n) (PositiveInteger)))): Not document ed!!!! --->-->PointedPrimeField(constructor): Not documented!!!! --->-->PointedPrimeField(): Missing Description h:/dostools/rm.exe: j:/program: No such file or directory h:/dostools/rm.exe: j:/progra~1/axiom/mnt/windows/lib/files/axiom/mnt/windows/li b/ppf.nrlib: No such file or directory >> System error: Cannot rename the file #P"j:/Program Files/axiom/mnt/windows/lib/PPF.erlib" t o #P"j:/Program Files/axiom/mnt/windows/lib/PPF.NRLIB". protected-symbol-warn called with (NIL) But that is just because "Program Files" need be in quotes? \end{verbatim} \section{email 15} \begin{verbatim} Foo: with { g: (n: PositiveInteger, k: PositiveInteger) -> PrimeField(n) } == add { g(n: PositiveInteger, k: PositiveInteger ): PrimeField(n) == k::Integer::PrimeField(n) } Ok, I will work with this example. Yes, it is better. Well, I haven't checked whether it should really work, but shouldn't be Foo: with { g: (n: PositiveInteger, k: PositiveInteger) -> (P: PrimeFieldCategory, x: P) } == add { g(n: PositiveInteger, k: PositiveInteger ): (P: PrimeFieldCategory, x:P) == { (PrimeField(n), k::Integer::PrimeField(n) } } be even better? The above code will not compile in Aldor, since it does not have PositiveInteger. And maybe it will even not compile with appropriate substitutions since the compiler cannot handle such a construction. I am, however, very much against the Any type. It is like building a strongly typed language and than trying to forget about types. For the interpreter it maybe OK, but not for the compiler. Programming in Axiom should mean writing programs for the compiler. I would say that programming in the interpreter is just writing short scripts but not real programs. See also http://www.aldor.org/docs/HTML/chap23.html#10\end{verbatim} \section{email 16} \begin{verbatim} On Wednesday, January 12, 2005 8:30 AM you wrote: > Bill Page wrote: > > > > I don't really understand when the use of parameterized > > return types on functions would be useful. What information > > is being returned as part of the type of the result that is > > not already known because of it's value? > > The above is an example. Perhaps, more convincing: > > Foo: with { g: (n: PositiveInteger, k: PositiveInteger) -> > PrimeField(n) } == add { > g(n: PositiveInteger, k: PositiveInteger ): PrimeField(n) == > k::Integer::PrimeField(n) } > Ok, I will work with this example. Yes, it is better. > Another example is Marcus Better's problem, more examples > are in expr2ups.spad, where Any is used a lot. Ok. > The type tells you in what domain to interpret the value. > But sometimes, the type will have to depend on a parameter > of the function, as above. That is still now clear to me, at least when it is possible to use a Union. > > > As I see it the concept does considerable damage to the > > notion of the 'domain' of a function. How should we > > interpret the expressioin `PrimeField(n)' when n is > > unknown? Does it represent the Union over all values n? > > We can no longer write the signature of a function in > > the simple form: > > > > f: PositiveInteger -> PrimeField > > Yes you can: Aldor does it. The signature is > > f: (n: PositiveInteger) -> PrimeField n > That does not look like a *signature* to me. What is the value of n? If you can't tell me, then how can I interpret `PrimeField n'? A signature should specify the domains of the function, but `PrimeField n' is not a domain until `n' is replaced with some PositiveInteger. The only interpretation of `PrimeField n' as a domain that I can think of would be to claim that it represents some kind of Union over the primes. Union(PrimeField n for n=1.. | prime? n) But of course we can't write it quite this nicely right now in Axiom... This is similar to Axiom's insistence that A:Integer can not be used in the expression A+1 until A is assigned a value. I this case I think it should be ok to say that if A has no assigned value then it represents the domain {+/-n for n=0..} > > Can you explain again why you don't find the usual > > Axiom solution to this situation acceptible? I.e. the > > use of the `Any' domain: > > > > f:PositiveInteger->Any > > f(n) == n::PrimeField(n) > > Because you cannot use it in compiled code and because you > are using all of the type information, which is the main > point of Axiom. But as you said, `Any' is used extensively in expr2ups.spad. > Of course, the example you just gave doesn't > make any sense, the result is always zero, but given the > function > > Bar: with { h: (n: PositiveInteger, k: PositiveInteger) -> Any } > == add { g(n: PositiveInteger, k: PositiveInteger ): Any == > k::Any } > > you cannot use this function in compiled code anymore. The > interpreter can deal with it, not the compiler. I would write it something like this: (2) -> h:(PositiveInteger,PositiveInteger)->Union( _ PrimeField(2),PrimeField(3),PrimeField(5),PrimeField(7)) Type: Void (3) -> h(n,k)==k::PrimeField(n) Type: Void (4) -> x:=h(7,2) (4) 2 Type: Union(PrimeField 7,...) (5) -> trace x (5) 2 Type: PrimeField 7 > > Look at Marcus code for a really convincing example: He wants > to construct recursively an algebraic extension of a ring, > adding elements one at the time. At the end of the process > he wants to return an element of the final ring. It is tricky > to do this in Axiom currently. I will take a closer look at the emails from Marcus. > > Note, for example, if you have a signature > > f: Integer -> Any > > but really, f returns a SimpleAlgebraicExtension of some > ring, you cannot do any calculations with the result in > compiled code anymore, unless you know *exactly* the defining > polynomial of the ring. I agree that Any throws away too much information, except in the interpreter where it tries to do a better job. But I think even there Any is (usually) not a good choice for the domain. > > So one way out -- in this specific case -- would be to > return a record containing the result of type Any and > the defining polynomial. I hope you admit that this is > ugly. I agree that that is ugly. Using an explicit "streaming Union" (iterator) domain would be my (future) choice. Unfortunately for now: (6) -> Union(PrimeField(i) for i in 1..10) Local variable or parameter used in type We will attempt to interpret the code. Category, domain or package constructor COLLECT is not available. (6) -> Union(PrimeField(i) for i in 1..) Loading C:/Program Files/axiom/mnt/windows/algebra/UNISEG.o for domain UniversalSegment Loading C:/Program Files/axiom/mnt/windows/algebra/INCRMAPS.o for package IncrementingMaps Loading C:/Program Files/axiom/mnt/windows/algebra/ITUPLE.o for domain InfiniteTuple Loading C:/Program Files/axiom/mnt/windows/algebra/STREAM.o for domain Stream Local variable or parameter used in type We will attempt to interpret the code. Interpret-Code mode is not supported for stream bodies. (6) -> \end{verbatim} \section{email 17} \begin{verbatim} > > #include "axiom" > > > > Test: with { f: (n: PositiveInteger) -> PrimeField(n) } > > == add { f(n: PositiveInteger): PrimeField(n) == > > 10::Integer::PrimeField(n) } > > > > Note that such a construction -- the resulting domain depending on the > > function parameter -- is currently illegal in Axiom. In Aldor it is fine. > > I don't really understand when the use of parameterized return types on > functions would be useful. What information is being returned as part of the > type of the result that is not already known because of it's value? The above is an example. Perhaps, more convincing: Foo: with { g: (n: PositiveInteger, k: PositiveInteger) -> PrimeField(n) } == add { g(n: PositiveInteger, k: PositiveInteger ): PrimeField(n) == k::Integer::PrimeField(n) } Another example is Marcus Better's problem, more examples are in expr2ups.spad, where Any is used a lot. The type tells you in what domain to interpret the value. But sometimes, the type will have to depend on a parameter of the function, as above. > As I see it the concept does considerable damage to the notion of the > 'domain' of a function. How should we interpret the expressioin > `PrimeField(n)' when n is unknown? Does it represent the Union over all > values n? We can no longer write the signature of a function in the simple > form: > > f: PositiveInteger -> PrimeField Yes you can: Aldor does it. The signature is f: (n: PositiveInteger) -> PrimeField n > Can you explain again why you don't find the usual Axiom solution to this > situation acceptible? I.e. the use of the `Any' domain: > > f:PositiveInteger->Any > f(n) == n::PrimeField(n) Because you cannot use it in compiled code and because you are using all of the type information, which is the main point of Axiom. Of course, the example you just gave doesn't make any sense, the result is always zero, but given the function Bar: with { h: (n: PositiveInteger, k: PositiveInteger) -> Any } == add { g(n: PositiveInteger, k: PositiveInteger ): Any == k::Any } you cannot use this function in compiled code anymore. The interpreter can deal with it, not the compiler. Look at Marcus code for a really convincing example: He wants to construct recursively an algebraic extension of a ring, adding elements one at the time. At the end of the process he wants to return an element of the final ring. It is tricky to do this in Axiom currently. Note, for example, if you have a signature f: Integer -> Any but really, f returns a SimpleAlgebraicExtension of some ring, you cannot do any calculations with the result in compiled code anymore, unless you know *exactly* the defining polynomial of the ring. So one way out -- in this specific case -- would be to return a record containing the result of type Any and the defining polynomial. I hope you admit that this is ugly.\end{verbatim} \section{email 18} \begin{verbatim} I have been thinking about your example code. On Tuesday, January 11, 2005 9:44 AM you wrote: > ... > I just tried another example, which is in fact the reason > why I would love to have Aldor working. I did not expect > it to work, and it does not, but it works *almost*. The > code is as follows: > > #include "axiom" > > Test: with { f: (n: PositiveInteger) -> PrimeField(n) } > == add { f(n: PositiveInteger): PrimeField(n) == > 10::Integer::PrimeField(n) } > > Note that such a construction -- the resulting domain > depending on the function parameter -- is currently > illegal in Axiom. In Aldor it is fine. I don't really understand when the use of parameterized return types on functions would be useful. What information is being returned as part of the type of the result that is not already known because of it's value? As I see it the concept does considerable damage to the notion of the 'domain' of a function. How should we interpret the expressioin `PrimeField(n)' when n is unknown? Does it represent the Union over all values n? We can no longer write the signature of a function in the simple form: f: PositiveInteger -> PrimeField Can you explain again why you don't find the usual Axiom solution to this situation acceptible? I.e. the use of the `Any' domain: f:PositiveInteger->Any f(n) == n::PrimeField(n) Perhaps in some cases the use of a Union might even be better: f:PositiveInteger->Union(PrimeField(2),PrimeField(3), PrimeField(5), ...) f(n) == n::PrimeField(n) The union allows a 'case' construction like this: f(3) case PrimeField(3) In fact this sort of thing works in Axiom: (1) -> f:PositiveInteger->Union(PrimeField(2),PrimeField(3), _ PrimeField(5),PrimeField(7),"Failed") f(n) == ( prime? n and n<=7 => n::PrimeField(n); "Failed") Function declaration f : PositiveInteger -> Union(PrimeField 2, PrimeField 3,PrimeField 5,PrimeField 7,Failed) has been added to workspace. Type: Void (2) -> f(2) Cannot compile conversion for types involving local variables. In particular, could not compile the expression involving :: PrimeField #1 AXIOM will attempt to step through and interpret the code. Compiling function f with type PositiveInteger -> Union(PrimeField 2 ,PrimeField 3,PrimeField 5,PrimeField 7,Failed) (2) 0 Type: Union(PrimeField 2,...) (3) -> f(3) (3) 0 Type: Union(PrimeField 3,...) (4) -> f(4) (4) Failed Type: Union(Failed,...) (5) -> f(5) (5) 0 Type: Union(PrimeField 5,...) (6) -> x:=f(5) (6) 0 Type: Union(PrimeField 5,...) (7) -> x case PrimeField(5) (7) true Type: Boolean (8) -> x case PrimeField(3) (8) false Type: Boolean etc.\end{verbatim} \section{email 19} \begin{verbatim} Peter Broadbery writes: > On Tue, 2005-01-11 at 14:30 +0100, Martin Rubey wrote: > > Dear Peter, > > > > this is just great stuff -- nearly... I had to try it out right away, but I > > experienced two problems. > > > > the minor one is, that )co inside axiom still does not work: > > > > (1) -> > > (1) -> )co test.as > > Compiling AXIOM source code from file > > /home/rubey/martin/Axiom/test.as using AXIOM-XL compiler and > > options > > -O -Fasy -Fao -Flsp -laxiom -Mno-AXL_W_WillObsolete -DAxiom -Y > > $AXIOM/algebra > > Use the system command )set compiler args to change these > > options. > > > > >> System error: > > NIL is not of type STRING. > > > ln -s $ALDORROOT $AXIOM/compiler may help here. fixing i-syscmd.boot to > produce a nice error would be nice, I guess. I tried that, but it won't work. Tim, is there a way to trace what's happening? Note that both $ALDORROOT and $AXIOM were set correctly. In other words, the link above produced a directory "compiler" in "axiom/mnt/linux", containing the following directories of Aldor: bin/ doc/ include/ lib/ src/ tests/ > The .as file isn't in CVS (the file is compiled - don't be fooled by the > readable coding style) Sorry, my mistake. Only lsp files. By the way, there i *lots* of stuff in the directories under /lsp/ccl/src, some look like they could be really useful... Tim: could you rename them to .pamphlet and correct the \usepackage line in each one of them? Thanks! > > (1) -> fact(5)$Test > > > > (1) 120 > > Type: > > PositiveInteger > > (2) -> fact(4)$Test > > > > >> System error: > > # is not of type LIST. > > > > Fixed by the patch I send earlier (I hope)... Yes indeed! (I found that there was only one line you had to comment out?) > The significant bit is removing an unbound variable from as.boot, the > rest is to fix the )co command (obviously not bullet proof), and the .ap > file generation. > > In terms of aldor internal knowledge, you don't need that much, the hard > work is on the axiom side. The trick is to load all the aldor runtime > env interpreted and see what breaks (this includes daase.lisp, as.clisp > & interop.clisp, plus the aldor .lsp files). This stuff used to vaguely > work, so putting it back in shape can't be too bad. In another mail, you wrote: > As long as you don't use the sig. from the interpreter, you will be ok > (which misses the point,, I know). As far as fixing the error, not really, > I don't know the axiom interpreter that well. Finding how & where the type > is substituted would be a good start [There must be someone who does...] Who could this be? It would be just wonderful to get this working! Thanks a million times, \end{verbatim} \section{email 20} \begin{verbatim} On Tue, 2005-01-11 at 14:30 +0100, Martin Rubey wrote: > Dear Peter, > > this is just great stuff -- nearly... I had to try it out right away, but I > experienced two problems. > > the minor one is, that )co inside axiom still does not work: > > (1) -> > (1) -> )co test.as > Compiling AXIOM source code from file > /home/rubey/martin/Axiom/test.as using AXIOM-XL compiler and > options > -O -Fasy -Fao -Flsp -laxiom -Mno-AXL_W_WillObsolete -DAxiom -Y $AXIOM/algebra > Use the system command )set compiler args to change these > options. > > >> System error: > NIL is not of type STRING. ln -s $ALDORROOT $AXIOM/compiler may help here. fixing i-syscmd.boot to produce a nice error would be nice, I guess. > (1) -> > > Never mind. > > Unfortunately, there is a more severe issue. I put the following simple domain > in a file "test.as" and compiled it using > > aldor -O -Fasy -Fao -Flsp -laxiom -Mno-AXL_W_WillObsolete -DAxiom test.as > > without any problem. There is only the warning > > #1 (Warning) Deprecated message prefix: use `ALDOR_' instead of `_AXL' > > but I suspect that this is of no importance. Yep. > > > ------------------------------------------------------------------------------- > #include "axiom.as" > > Test: with { fact: PositiveInteger -> PositiveInteger } > == add { fact(n: PositiveInteger): PositiveInteger == > { n <= 1 => 1; > res: PositiveInteger := 1; > while n > 1 repeat { > res := res * n; > n := n-1; } > res } } > ------------------------------------------------------------------------------- > > After this I start axiom and load runtime and axextend. By the way axextend > *is* in the distribution, it's only a little hidden... There is even more > obscure stuff in theis directory, maybe it's of use to you! > The .as file isn't in CVS (the file is compiled - don't be fooled by the readable coding style) > (1) -> )sh Test > Test is a domain constructor > Abbreviation for Test is TEST > This constructor is exposed in this frame. > Issue )edit test.as to see algebra source code for TEST > > ------------------------------- Operations -------------------------------- > fact : PositiveInteger -> PositiveInteger > > (1) -> fact(5)$Test > > (1) 120 > Type: PositiveInteger > (2) -> fact(4)$Test > > >> System error: > # is not of type LIST. > Fixed by the patch I send earlier (I hope)... > By the way, could you explain what your patches are doing? It's just a mystery > to me! I suspect that one needs some knowledge of Aldor internals? The significant bit is removing an unbound variable from as.boot, the rest is to fix the )co command (obviously not bullet proof), and the .ap file generation. In terms of aldor internal knowledge, you don't need that much, the hard work is on the axiom side. The trick is to load all the aldor runtime env interpreted and see what breaks (this includes daase.lisp, as.clisp & interop.clisp, plus the aldor .lsp files). This stuff used to vaguely work, so putting it back in shape can't be too bad. \end{verbatim} \section{email 21} \begin{verbatim} I just tried another example, which is in fact the reason why I would love to have Aldor working. I did not expect it to work, and it does not, but it works *almost*. The code is as follows: #include "axiom" Test: with { f: (n: PositiveInteger) -> PrimeField(n) } == add { f(n: PositiveInteger): PrimeField(n) == 10::Integer::PrimeField(n) } Note that such a construction -- the resulting domain depending on the function parameter -- is currently illegal in Axiom. In Aldor it is fine. I compiled it with Aldor as usual, and then loaded it into Axiom. As signature I got the slightly unusual (1) -> )di op f There is one unexposed function called f : [1] PositiveInteger -> PrimeField n from Test and trying it out I obtained (1) -> f(5)$Test Loading /home/rubey/axiom/mnt/linux/algebra/PF.o for domain PrimeField Loading /home/rubey/axiom/mnt/linux/algebra/IPF.o for domain InnerPrimeField Loading /home/rubey/axiom/mnt/linux/algebra/TABLE.o for domain Table Loading /home/rubey/axiom/mnt/linux/algebra/HASHTBL.o for domain HashTable Loading /home/rubey/axiom/mnt/linux/algebra/INTABL.o for domain InnerTable Loading /home/rubey/axiom/mnt/linux/algebra/ZMOD.o for domain IntegerMod >> System error: |n| is not of type NUMBER. protected-symbol-warn called with (NIL) which is roughly what I expected. However, to my great surprise, if you turn on the debugger (beforehand. You always have to start a fresh axiom because of the error I told you about in my previous message) with )lisp (setq |$monitorNewWorld| t) and thus trace (1) -> f(1783)$Test the final bit reads protected-symbol-warn called with (NIL)..IntegerMod 1783 wants positiveRemainder : (%,%) -> % from Integer ---->Integer----> searching op table for: positiveRemainder : (%,%) -> % from Integer <----# Integer goget stuffing slot 47 of IntegerMod 1783 <------# Integer PrimeField n activating lazy slot 8: Integer PrimeField n activating lazy slot 9: IntegerPrimesPackage Integer ..PrimeField n wants prime? : Integer -> Boolean from IntegerPrimesPackage Integer ---->IntegerPrimesPackage Integer----> searching op table for: prime? : Integer -> Boolean from IntegerPrimesPackage Integer <----#(IntegerPrimesPackage,Integer) goget stuffing slot 10 of PrimeField n <------#(IntegerPrimesPackage,Integer) which clearly tells you, that the calculation is done alright, only the signature interferes with success. Any ideas?\end{verbatim} \section{email 22} \begin{verbatim} this is just great stuff -- nearly... I had to try it out right away, but I experienced two problems. the minor one is, that )co inside axiom still does not work: AXIOM Computer Algebra System Version: Axiom 3.0 Beta (February 2005) Timestamp: Tuesday January 11, 2005 at 14:02:04 ----------------------------------------------------------------------------- Issue )copyright to view copyright notices. Issue )summary for a summary of useful system commands. Issue )quit to leave AXIOM and return to shell. ----------------------------------------------------------------------------- Re-reading compress.daase Re-reading interp.daase Re-reading operation.daase Re-reading category.daase Re-reading browse.daase (1) -> (1) -> )co test.as Compiling AXIOM source code from file /home/rubey/martin/Axiom/test.as using AXIOM-XL compiler and options -O -Fasy -Fao -Flsp -laxiom -Mno-AXL_W_WillObsolete -DAxiom -Y $AXIOM/algebra Use the system command )set compiler args to change these options. >> System error: NIL is not of type STRING. protected-symbol-warn called with (NIL) (1) -> )co test Compiling AXIOM source code from file /home/rubey/martin/Axiom/test.as using AXIOM-XL compiler and options -O -Fasy -Fao -Flsp -laxiom -Mno-AXL_W_WillObsolete -DAxiom -Y $AXIOM/algebra Use the system command )set compiler args to change these options. >> System error: NIL is not of type STRING. protected-symbol-warn called with (NIL) (1) -> Never mind. Unfortunately, there is a more severe issue. I put the following simple domain in a file "test.as" and compiled it using aldor -O -Fasy -Fao -Flsp -laxiom -Mno-AXL_W_WillObsolete -DAxiom test.as without any problem. There is only the warning #1 (Warning) Deprecated message prefix: use `ALDOR_' instead of `_AXL' but I suspect that this is of no importance. ------------------------------------------------------------------------------- #include "axiom.as" Test: with { fact: PositiveInteger -> PositiveInteger } == add { fact(n: PositiveInteger): PositiveInteger == { n <= 1 => 1; res: PositiveInteger := 1; while n > 1 repeat { res := res * n; n := n-1; } res } } ------------------------------------------------------------------------------- After this I start axiom and load runtime and axextend. By the way axextend *is* in the distribution, it's only a little hidden... There is even more obscure stuff in theis directory, maybe it's of use to you! AXIOM Computer Algebra System Version: Axiom 3.0 Beta (February 2005) Timestamp: Tuesday January 11, 2005 at 14:02:04 ----------------------------------------------------------------------------- Issue )copyright to view copyright notices. Issue )summary for a summary of useful system commands. Issue )quit to leave AXIOM and return to shell. ----------------------------------------------------------------------------- Re-reading compress.daase Re-reading interp.daase Re-reading operation.daase Re-reading category.daase Re-reading browse.daase (1) -> (1) -> )lisp (load "/home/rubey/aldor/linux/1.0.2/lib/runtime.lsp") Value = T (1) -> )lisp (load "/home/rubey/axiom--main--1--patch-24/lsp/ccl/src/axbase/compiler/lib/axextend.lsp") Value = T (1) -> )lib test Reading /home/rubey/martin/Axiom/test.asy Loading /home/rubey/axiom/mnt/linux/autoload/bc-matrix. Loading /home/rubey/axiom/mnt/linux/autoload/bc-misc. Loading /home/rubey/axiom/mnt/linux/autoload/bc-solve. Loading /home/rubey/axiom/mnt/linux/autoload/bc-util. Loading /home/rubey/axiom/mnt/linux/autoload/ht-util. Loading /home/rubey/axiom/mnt/linux/autoload/htsetvar. Loading /home/rubey/axiom/mnt/linux/autoload/ht-root. Loading /home/rubey/axiom/mnt/linux/autoload/br-con. Loading /home/rubey/axiom/mnt/linux/autoload/br-data. Loading /home/rubey/axiom/mnt/linux/autoload/showimp. Loading /home/rubey/axiom/mnt/linux/autoload/br-op1. Loading /home/rubey/axiom/mnt/linux/autoload/br-op2. Loading /home/rubey/axiom/mnt/linux/autoload/br-search. Loading /home/rubey/axiom/mnt/linux/autoload/br-util. Loading /home/rubey/axiom/mnt/linux/autoload/topics. Loading /home/rubey/axiom/mnt/linux/autoload/br-prof. Loading /home/rubey/axiom/mnt/linux/autoload/br-saturn. Test is now explicitly exposed in frame frame0 Test will be automatically loaded when needed from /home/rubey/martin/Axiom/test (1) -> )sh Test Test is a domain constructor Abbreviation for Test is TEST This constructor is exposed in this frame. Issue )edit test.as to see algebra source code for TEST ------------------------------- Operations -------------------------------- fact : PositiveInteger -> PositiveInteger (1) -> fact(5)$Test (1) 120 Type: PositiveInteger (2) -> fact(4)$Test >> System error: # is not of type LIST. protected-symbol-warn called with (NIL) :-( I am already very very happy, but another patch and/or explanation would greatly improve this... By the way, could you explain what your patches are doing? It's just a mystery to me! I suspect that one needs some knowledge of Aldor internals? \end{verbatim} \section{email 23} \begin{verbatim} I've been playing with the aldor/axiom stuff a little, and the following patch may help get things going(I used to work on it, and thought it'd be fun to get it going again). There are further problems: - aldor "extend" does not work - it ought to, I think - The algebra defined in libaxiom.al is not current, and for it to be rebuilt various .as files need to be available to the build process (axextend.as and friends) - any reason why they're left out of the distribution? - exported attributes from aldor domains are explicitly killed off by this patch (it's probably easy to fix, just no time atm). - Only tested the most trivial domains I could find. Peter. \end{verbatim} \section{email 24} \begin{verbatim} ? Makefile ? Makefile.dvi Index: as.boot.pamphlet =================================================================== RCS file: /cvsroot/axiom/axiom/src/interp/as.boot.pamphlet,v retrieving revision 1.3 diff -u -r1.3 as.boot.pamphlet --- as.boot.pamphlet 24 May 2004 22:53:49 -0000 1.3 +++ as.boot.pamphlet 8 Jan 2005 19:01:23 -0000 @@ -389,7 +389,8 @@ HPUT(ht,id,[entry,:HGET(ht,id)]) opalist := [ [op,:REMDUP HGET(ht,op)] for op in HKEYS ht] --HPUT($opHash,con,[ancestorAlist,attributeAlist,:opalist]) - HPUT($opHash,con,[ancestorAlist,attributeAlist,:opalist]) + --HPUT($opHash,con,[ancestorAlist,attributeAlist,:opalist]) + HPUT($opHash,con,[ancestorAlist,nil,:opalist]) hackToRemoveAnd p == ---remove this as soon as .asy files do not contain forms (And pred) forms Index: ax.boot.pamphlet =================================================================== RCS file: /cvsroot/axiom/axiom/src/interp/ax.boot.pamphlet,v retrieving revision 1.3 diff -u -r1.3 ax.boot.pamphlet --- ax.boot.pamphlet 24 May 2004 22:53:49 -0000 1.3 +++ ax.boot.pamphlet 8 Jan 2005 19:01:26 -0000 @@ -80,11 +80,29 @@ axForms := [ ['Foreign, ['Declare, 'dummyDefault, 'Exit], 'Lisp], :axForms] axForms := APPEND(axDoLiterals(), axForms) - axForm := ['Sequence, ['Import, [], 'AxiomLib], :axForms] + axForm := ['Sequence, ['Import, [], 'AxiomLib], ['Import, [], 'Boolean], :axForms] st := MAKE_-OUTSTREAM(filename) PPRINT(axForm,st) CLOSE st +makeAxExportForm(filename, constructors) == + $defaultFlag : local := false + $literals := [] + axForms := + [modemapToAx(modemap) for cname in constructors | + (modemap:=GETDATABASE(cname,'CONSTRUCTORMODEMAP)) and + (not cname in '(Tuple Exit Type)) and + not isDefaultPackageName cname] + if $baseForms then + axForms := [:$baseForms, :axForms] + if $defaultFlag then + axForms := + [ ['Foreign, ['Declare, 'dummyDefault, 'Exit], 'Lisp], :axForms] + axForms := APPEND(axDoLiterals(), axForms) + axForm := ['Sequence, ['Import, [], 'AxiomLib], ['Import, [], 'Boolean], :axForms] + axForm + + stripType type == $stripTypes => categoryForm? type => 'Type Index: i-syscmd.boot.pamphlet =================================================================== RCS file: /cvsroot/axiom/axiom/src/interp/i-syscmd.boot.pamphlet,v retrieving revision 1.4 diff -u -r1.4 i-syscmd.boot.pamphlet --- i-syscmd.boot.pamphlet 28 Dec 2004 07:42:45 -0000 1.4 +++ i-syscmd.boot.pamphlet 8 Jan 2005 19:01:36 -0000 @@ -642,7 +642,7 @@ if ^beQuiet then sayKeyedMsg("S2IZ0038A",[namestring args, asharpArgs]) command := - STRCONC(TRUENAME(STRCONC(GETENV('"AXIOM"),'"/compiler/bin/")),"axiomxl ", asharpArgs, '" ", namestring args) + STRCONC(STRCONC(GETENV('"AXIOM"),'"/compiler/bin/"),"axiomxl ", asharpArgs, '" ", namestring args) rc := OBEY command if (rc = 0) and doCompileLisp then \end{verbatim} \section{email 25} \begin{verbatim} > It is not so clear to me why the build appears to succeed > even though these definitions are missing. In other languages > I would presume that this situation would be easily caught > as a missing file during `linking'. But here we have this > "domain vector" thing. Is there not some why that the > compilation could be made more robust by verifying the > domain vector at compile time? Bill, there is no "linking" step in any sense of the word. This needs to be documented somewhere. If we look at one of the random BOOTSTRAP files, say, CHAR we see: Character: OrderedFinite() with ord: % -> Integer ++ ord(c) provides an integral code corresponding to the ++ character c. It is always true that \spad{char ord c = c}. char: Integer -> % ++ char(i) provides a character corresponding to the integer ++ code i. It is always true that \spad{ord char i = i}. char: String -> % ++ char(s) provides a character from a string s of length one. space: () -> % ++ space() provides the blank character. quote: () -> % ++ quote() provides the string quote character, \spad{"}. escape: () -> % ++ escape() provides the escape character, \spad{_}, which ++ is used to allow quotes and other characters {\em within} ++ strings. upperCase: % -> % ++ upperCase(c) converts a lower case letter to the corresponding ++ upper case letter. If c is not a lower case letter, then ++ it is returned unchanged. lowerCase: % -> % ++ lowerCase(c) converts an upper case letter to the corresponding ++ lower case letter. If c is not an upper case letter, then ++ it is returned unchanged. digit?: % -> Boolean ++ digit?(c) tests if c is a digit character, ++ i.e. one of 0..9. hexDigit?: % -> Boolean ++ hexDigit?(c) tests if c is a hexadecimal numeral, ++ i.e. one of 0..9, a..f or A..F. alphabetic?: % -> Boolean ++ alphabetic?(c) tests if c is a letter, ++ i.e. one of a..z or A..Z. upperCase?: % -> Boolean ++ upperCase?(c) tests if c is an upper case letter, ++ i.e. one of A..Z. lowerCase?: % -> Boolean ++ lowerCase?(c) tests if c is an lower case letter, ++ i.e. one of a..z. alphanumeric?: % -> Boolean ++ alphanumeric?(c) tests if c is either a letter or number, ++ i.e. one of 0..9, a..z or A..Z. == add Rep := SingleInteger -- 0..255 CC ==> CharacterClass() import CC --cl: Record(dig:CC,hex:CC,upp:CC,low:CC,alpha:CC,alnum:CC) := -- [ digit(), hexDigit(), -- upperCase(), lowerCase(), alphabetic(), alphanumeric() ] OutChars:PrimitiveArray(OutputForm) := construct [NUM2CHAR(i)$Lisp for i in 0..255] minChar := minIndex OutChars a = b == a =$Rep b a < b == a <$Rep b size() == 256 index n == char((n - 1)::Integer) lookup c == (1 + ord c)::PositiveInteger char(n:Integer) == n::% ord c == convert(c)$Rep random() == char(random()$Integer rem size()) space == QENUM(" ", 0$Lisp)$Lisp quote == QENUM("_" ", 0$Lisp)$Lisp escape == QENUM("__ ", 0$Lisp)$Lisp coerce(c:%):OutputForm == OutChars(minChar + ord c) digit? c == member?(c pretend Character, digit()) hexDigit? c == member?(c pretend Character, hexDigit()) upperCase? c == member?(c pretend Character, upperCase()) lowerCase? c == member?(c pretend Character, lowerCase()) alphabetic? c == member?(c pretend Character, alphabetic()) alphanumeric? c == member?(c pretend Character, alphanumeric()) latex c == concat("\mbox{`", concat(new(1,c pretend Character)$String, "'}")$String)$String char(s:String) == -- one?(#s) => s(minIndex s) pretend % (#s) = 1 => s(minIndex s) pretend % error "String is not a single character" upperCase c == QENUM(PNAME(UPCASE(NUM2CHAR(ord c)$Lisp)$Lisp)$Lisp, 0$Lisp)$Lisp lowerCase c == QENUM(PNAME(DOWNCASE(NUM2CHAR(ord c)$Lisp)$Lisp)$Lisp, 0$Lisp)$Lisp The BOOTSTRAP code, annotated, looks like: ===================================================================== The VERSIONCHECK variable came about when we were writing the Aldor compiler. We had completely reimplemented the algebra so that it was incompatible with previous versions. This is checked on loading. (|/VERSIONCHECK| 2) ===================================================================== This implements the a = b == a =$Rep b function. Note that the function name |CHAR;=;2$B;1| is constructed from the domain abbreviation; the function name; the number of arguments and their types; and a unique number Also note that the compiler claims that it knows that the '=' function can be replaced with lisp 'EQL' in compiled code so this function is never run. It uses a property list marker '|SPADreplace|' on the function symbol to implement the replacement during compiles. (PUT (QUOTE |CHAR;=;2$B;1|) (QUOTE |SPADreplace|) (QUOTE EQL)) (DEFUN |CHAR;=;2$B;1| (|a| |b| |$|) (EQL |a| |b|)) ===================================================================== This implements the a < b == a <$Rep b function. Again note that the compiler knows that calls to this function can be replaced by the lisp QSLESSP function. The 'QS' prefix is a VMLisp idiom. 'Q' == quick (no type check) 'S'=singleinteger which, at least in VMLisp turns into a single instruction. QSLESSP (uppercased here because spad is case-sensitive and lisp is not) is defined in src/interp/vmlisp.lisp.pamphlet as a macro with embedded type information. (PUT (QUOTE |CHAR;<;2$B;2|) (QUOTE |SPADreplace|) (QUOTE QSLESSP)) (DEFUN |CHAR;<;2$B;2| (|a| |b| |$|) (QSLESSP |a| |b|)) ===================================================================== This implements size() == 256 and just returns a "boxed integer" (XLAM is a marker for boxing). (PUT (QUOTE |CHAR;size;Nni;3|) (QUOTE |SPADreplace|) (QUOTE (XLAM NIL 256))) (DEFUN |CHAR;size;Nni;3| (|$|) 256) ===================================================================== This implements the index n == char((n - 1)::Integer) function. Notice that this does a 'QREFELT'. This is another VMLisp idiom 'Q' is quick, 'REFELT' is a vector lookup function. This is also implmented as a macro in src/interp/vmlisp.lisp.pamphlet where it does a 'svref', simple vector reference into the current domain (that's what '|$|' means) and calls the 18th element from this domain. The domain is represented by a vector (the domain vector) which you'll find at the bottom of this file. The domain vector for a domain is kept on the property list of the domain name symbol, in this case it is "Character". So we see the code: (MAKEPROP (QUOTE |Character|) (QUOTE |infovec|) (LIST (QUOTE #(NIL NIL ... The |infovec|, the information vector, contains a lot of domain specific information which is looked up at runtime. In this case we are doing a (QVREFELT |$| 18). If you count 18 elements into the |infovec| you'll find |CHAR;char;I$;6|. If you examine the symbol name carefully you can decode that it is a function from the domain "CHAR" (this domain) called "char" that takes one argument of type "I" (integer), and is the 6th function in this domain, which happens to be char(n:Integer) == n::% So this function does what it says, it subtracts 1 from its argument, treats it as an integer and returns the integer. The reason this works is that "Characters" have a representation of SingleInteger: Rep := SingleInteger -- 0..255 (DEFUN |CHAR;index;Pi$;4| (|n| |$|) (SPADCALL (|-| |n| 1) (QREFELT |$| 18))) .....[snip].... ===================================================================== This is the function that gets executed when "Character" gets instantiated. This function has the effect, if memory serves, of putting the function "Character;" into the |$ConstructorCache|. The |$ConstructorCache| is a hash table used for fast lookup and function dispatch. The call to |Character| will call |Character;| (see below). (DEFUN |Character| NIL (PROG NIL (RETURN (PROG (#1=#:G90941) (RETURN (COND ((LETT #1# (HGET |$ConstructorCache| (QUOTE |Character|)) |Character|) (|CDRwithIncrement| (CDAR #1#))) ((QUOTE T) (|UNWIND-PROTECT| (PROG1 (CDDAR (HPUT |$ConstructorCache| (QUOTE |Character|) (LIST (CONS NIL (CONS 1 (|Character;|)))))) (LETT #1# T |Character|)) (COND ((NOT #1#) (HREM |$ConstructorCache| (QUOTE |Character|)))))))))))) ===================================================================== This function initializes the |infovec| data structure. Notice the calls to QSETREFV, another VMLisp-ism, which does a "(setf (svref ...", that is, it sets an element of a simple vector (|infovec|). Notice the call to |SingleInteger|. This will cause the domain SingleInteger to be loaded, initialized, and put in the constructor cache. This domain needs the SingleInteger domain for its representation. (DEFUN |Character;| NIL (PROG (|dv$| |$| |pv$| #1=#:G90939 |i|) (RETURN (SEQ (PROGN (LETT |dv$| (QUOTE (|Character|)) . #2=(|Character|)) (LETT |$| (GETREFV 53) . #2#) (QSETREFV |$| 0 |dv$|) (QSETREFV |$| 3 (LETT |pv$| (|buildPredVector| 0 0 NIL) . #2#)) (|haddProp| |$ConstructorCache| (QUOTE |Character|) NIL (CONS 1 |$|)) (|stuffDomainSlots| |$|) (QSETREFV |$| 6 (|SingleInteger|)) (QSETREFV |$| 10 (SPADCALL (PROGN (LETT #1# NIL . #2#) (SEQ (LETT |i| 0 . #2#) G190 (COND ((QSGREATERP |i| 255) (GO G191))) (SEQ (EXIT (LETT #1# (CONS (NUM2CHAR |i|) #1#) . #2#))) (LETT |i| (QSADD1 |i|) . #2#) (GO G190) G191 (EXIT (NREVERSE0 #1#)))) (QREFELT |$| 9))) (QSETREFV |$| 11 0) |$|))))) ===================================================================== This is the actual representation of the Character domain. The main point of the compiler is to construct the |infovec|. I'm not up to explaining the details of this at this moment. (MAKEPROP (QUOTE |Character|) (QUOTE |infovec|) (LIST (QUOTE #(NIL NIL NIL NIL NIL NIL (QUOTE |Rep|) (|List| 28) (|PrimitiveArray| 28) (0 . |construct|) (QUOTE |OutChars|) (QUOTE |minChar|) (|Boolean|) |CHAR;=;2$B;1| |CHAR;<;2$B;2| (|NonNegativeInteger|) |CHAR;size;Nni;3| (|Integer|) |CHAR;char;I$;6| (|PositiveInteger|) |CHAR;index;Pi$;4| |CHAR;ord;$I;7| |CHAR;lookup;$Pi;5| (5 . |coerce|) |CHAR;random;$;8| |CHAR;space;$;9| |CHAR;quote;$;10| |CHAR;escape;$;11| (|OutputForm|) |CHAR;coerce;$Of;12| (|CharacterClass|) (10 . |digit|) (|Character|) (14 . |member?|) |CHAR;digit?;$B;13| (20 . |hexDigit|) |CHAR;hexDigit?;$B;14| (24 . |upperCase|) |CHAR;upperCase?;$B;15| (28 . |lowerCase|) |CHAR;lowerCase?;$B;16| (32 . |alphabetic|) |CHAR;alphabetic?;$B;17| (36 . |alphanumeric|) |CHAR;alphanumeric?;$B;18| (|String|) |CHAR;latex;$S;19| (40 . |minIndex|) (45 . |elt|) |CHAR;char;S$;20| |CHAR;upperCase;2$;21| |CHAR;lowerCase;2$;22| (|SingleInteger|))) (QUOTE #(|~=| 51 |upperCase?| 57 |upperCase| 62 |space| 67 |size| 71 |random| 75 |quote| 79 |ord| 83 |min| 88 |max| 94 |lowerCase?| 100 |lowerCase| 105 |lookup| 110 |latex| 115 |index| 120 |hexDigit?| 125 |hash| 130 |escape| 135 |digit?| 139 |coerce| 144 |char| 149 |alphanumeric?| 159 |alphabetic?| 164 |>=| 169 |>| 175 |=| 181 |<=| 187 |<| 193)) (QUOTE NIL) (CONS (|makeByteWordVec2| 1 (QUOTE (0 0 0 0 0 0))) (CONS (QUOTE #(NIL |OrderedSet&| NIL |SetCategory&| |BasicType&| NIL)) (CONS (QUOTE #((|OrderedFinite|) (|OrderedSet|) (|Finite|) (|SetCategory|) (|BasicType|) (|CoercibleTo| 28))) (|makeByteWordVec2| 52 (QUOTE (1 8 0 7 9 1 6 0 17 23 0 30 0 31 2 30 12 32 0 33 0 30 0 35 0 30 0 37 0 30 0 39 0 30 0 41 0 30 0 43 1 45 17 0 47 2 45 32 0 17 48 2 0 12 0 0 1 1 0 12 0 38 1 0 0 0 50 0 0 0 25 0 0 15 16 0 0 0 24 0 0 0 26 1 0 17 0 21 2 0 0 0 0 1 2 0 0 0 0 1 1 0 12 0 40 1 0 0 0 51 1 0 19 0 22 1 0 45 0 46 1 0 0 19 20 1 0 12 0 36 1 0 52 0 1 0 0 0 27 1 0 12 0 34 1 0 28 0 29 1 0 0 45 49 1 0 0 17 18 1 0 12 0 44 1 0 12 0 42 2 0 12 0 0 1 2 0 12 0 0 1 2 0 12 0 0 13 2 0 12 0 0 1 2 0 12 0 0 14)))))) (QUOTE |lookupComplete|))) (MAKEPROP (QUOTE |Character|) (QUOTE NILADIC) T) \end{verbatim} \section{email 26} \begin{verbatim} ===================================================================== This is the function that gets executed when "Character" gets instantiated. This function has the effect, if memory serves, of PUTTING THE FUNCTION ^^^^^^^^^^^^^^^^^^^^ wrong, wrong, wrong "Character;" into the |$ConstructorCache|. The |$ConstructorCache| is a hash table used for fast lookup and function dispatch. The call to |Character| will call |Character;| (see below). (DEFUN |Character| NIL ===================================================================== is slightly wrong. It does NOT put the function |Character;| in the |$ConstructorCache|, it puts the RESULT of calling (|Character;|) in the cache, which is a fully initialized |infovec| object. You'll also find the function call (|stuffDomainSlots| |$|) in |Character;| interesting. The function is actually defined in src/interp/nrunopt.boot.pamphlet. From that function you can reverse-engineer the contents of the initial slots (which are just #(NIL NIL NIL NIL NIL NIL .... at compile time. Clearly documenting stuffDomainSlots would help as would documenting all of the rest of it. Also, for your amusement, try the following: axiom (1)-> )lisp (setq $DALYMODE t) (1)-> )set message autoload on (1)-> (maphash #'(lambda (key val) (format t "key=~a val=~a~%~%" key val)) |$ConstructorCache|) (1)-> 1 (1)-> (maphash #'(lambda (key val) (format t "key=~a val=~a~%~%" key val)) |$ConstructorCache|) The first maphash returns NIL The second maphash returns the loaded domains. The messages that get printed (from loadlib in src/interp/lisplib.boot.pamphlet) turn out to be the same domains you'll see in the constructor cache. Loading the domain causes it to be "instantiated" which means that the infovec for the domain gets filled in and stuck in the constructorcache. If a domain is already in the constructor cache it will not be loaded. Thus domain loading occurs on demand and only once. \end{verbatim} \section{email 27} \begin{verbatim} On Mon, Jan 10, 2005 at 09:47:36PM -0500, root wrote: > The code was changed. It used to read: > > one?(x) == ONEP(x)$Lisp > > It now reads: > > one?(x) == x = 1 True, but the bootstrap code does not contain any definition. We have: (DEFUN |SINT;zero?;$B;38| (|x| $) (QSZEROP |x|)) (DEFUN |SINT;max;3$;39| (|x| |y| $) (QSMAX |x| |y|)) The last number in the function names gives the order of the function in definition in the domain. The definition of `one?' follows `zero?'. With fresh code we have: (DEFUN |SINT;zero?;$B;38| (|x| $) (QSZEROP |x|)) (DEFUN |SINT;one?;$B;39| (|x| $) (EQL |x| 1)) (DEFUN |SINT;max;3$;40| (|x| |y| $) (QSMAX |x| |y|)) It was precisely this change in sequence that allowed me to spot this missing function by looking at the domain vectors. All domains which relied of functions defined in SINT with `sequence number' > 38 shifted by one in the second pass of the fixed-point build. \end{verbatim} \section{email 28} \begin{verbatim} It is possible to use the Aldor compiler to compile functions which you then can use in Axiom. Unfortunately, I could not get Domains and Packages to work. If anybody knows how to do this, please contribute! Let's do an example! Let's assume you have Aldor installed. You then have to do a little setup: 1. Grab the file 'axextend.lsp' from your axiom source distribution, it should reside in 'lsp/ccl/src/axbase/compiler/lib'. Rename it into 'axextend.lsp.pamphlet' and run 'document axextend.lsp.pamphlet', to obtain the proper lisp code. 2. Save the following into a file 'axiom.as' residing in 'aldor/1.0.2/linux/include/' of your aldor (binary) distribution:: -- Standard include file for using or extending Axiom library via AXIOM-XL #library AxiomLib "axiom" import from AxiomLib; inline from AxiomLib; macro { rep x == x @ % pretend Rep; per r == r @ Rep pretend %; } --import from Integer, PositiveInteger, NonNegativeInteger, SingleInteger; --import from Float, DoubleFloat; import { true: %, false: % } from Boolean; import { string: Literal -> %; } from String; 3. Save the following example into a file fact.as:: #include "axiom.as" fact(n: PositiveInteger): PositiveInteger == { n <= 1 => 1; res: PositiveInteger := 1; while n > 1 repeat { res := res * n; n := n-1; } res } 4. compile the example with:: aldor -O -Fasy -Fao -Flsp -laxiom -Mno-AXL_W_WillObsolete -DAxiom fact.as 5. start Axiom 6. say -- replacing paths as appropriate:: )lisp (load "aldor/linux/1.0.2/lib/runtime.lsp") )lisp (load "axiom--main--1--patch-24/lsp/ccl/src/axbase/compiler/lib/axextend.lsp") )lib fact fact(5)\end{verbatim} \section{email 29} \begin{verbatim} root writes: > I'm sorry but your note suffers from "context depravation", that is, > a fancy way of say "what?". Sorry, I was a bit short. The "proof of concept" I delivered shows that contrary to the axiom-spad compiler, aldor allows dependent types in function signatures. I.e., you can define a package or domain FOO that exports a function whose return type depends on the *function* parameter! In axiom, it may only depend on domain or package parameters. For example: FOO: with {f:(n:Integer)->IntegerMod(n) } == add {f(n:Integer):IntegerMod(n) == coerce(10)$IntegerMod(n) } Marcus Better ran into a situation where this is needed. In the axiom algebra, the file expr2ups.spad makes heavy use of the Any domain, which could be avoided if we could use the Aldor compiler. > re: Aldor. It should work with Axiom. Aldor has options which allow it to > generate Axiom domains which can be loaded. No, it does not work anymore. More precisely: You *can* compile a *function* with the Aldor compiler and use it in Axiom, as shown in http://lists.nongnu.org/archive/html/axiom-mail/2004-09/msg00035.html But the examples in http://www.csd.uwo.ca/~watt/aldor/UserGuide/chap18.html#1 do not work. They should, but they don't. I would be *VERY* grateful, if you could give me pointers.\end{verbatim} \section{email 31} \begin{verbatim} I managed to get gcl-2.6.6 to compile on Mac OS X (10.3.7). Initially it hung up for not finding libintl.h which seems to be part of the GNU gettext package. So I downloaded and and tried to install gettext and libconv which are related (circularly). The gettext package never finished making because of not finding the javac compiler. But enough did so that "make install" provided whatever gcl needed to finish. As I understand it these packages are primarily for "internationalization" which sounds worthy but I don't think should be allowed to abort a gcl make - just do it with fewer facilities. But I may not know what is going on. I then tried axiom again hoping it would use the gcl-2.6.6 that I installed. Previously axiom was hanging at the same place gcl did. But this time it hung quickly as follows: ----snipped end of output ---- 1 making /Users/cfm/dev-nobu-extra/axiom/src/scripts 17 making /Users/cfm/dev-nobu-extra/axiom/src/lib 18 making /Users/cfm/dev-nobu-extra/axiom/obj/linux/lib/fnct_key.o from /Users/cfm/dev-nobu-extra/axiom/int/lib/fnct_key.c /Users/cfm/dev-nobu-extra/axiom/int/lib/fnct_key.c: In function `handle_function_key': /Users/cfm/dev-nobu-extra/axiom/int/lib/fnct_key.c:339: error: `SIGCLD' undeclared (first use in this function) /Users/cfm/dev-nobu-extra/axiom/int/lib/fnct_key.c:339: error: (Each undeclared identifier is reported only once /Users/cfm/dev-nobu-extra/axiom/int/lib/fnct_key.c:339: error: for each function it appears in.) make[3]: *** [/Users/cfm/dev-nobu-extra/axiom/obj/linux/lib/fnct_key.o] Error 1 make[2]: *** [libdir] Error 2 make[1]: *** [srcsetup] Error 2 make: *** [all] Error 2 -------end of snip--- This sounds familiar. (Same thing happens if I do it in /tmp to avoid capitals in PATH as suggested.) As you know earlier versions of gcl don't compile on Mac OS X. I note the current email messages say axiom is yet to compile for 2.6.6 - to be done in March or so. Seems not much point in persisting for the Mac until that happens. Comments appreciated. Cheers, Chuck > see > > http://developer.apple.com/darwin/runningX11.html > > "Configuring and Running X11 Applications on MAC OSX" > > Tim \end{verbatim} \section{email 32} \begin{verbatim} This is going to be painful to follow but: Suppose a is a domain, b is a domain and b depends on a and a depends on b. Suppose a'.lsp is the lisp code for a b'.lsp is the lisp code for b The .spad files contain \section{a} a \section{a.bootstrap} a'.lsp \section{b} b \section{b.bootstrap} b'.lsp Now we compile this algebra a'.lsp -> a.fasl b'.lsp -> b.fasl (load a) (load b) a -> a.fasl b -> b.fasl now we modify a and recompile it a (mods to) A -> A'.lsp -> A.fasl where A is the modified A and A'.lsp is the new lisp. ASSUMING WE HAVE NOT CHANGED THE SIGNATURE OF a then b will still compile and be valid code and we get: \section{A} A \section{A.bootstrap} A'.lsp \section{b} b \section{b.bootstrap} b'.lsp and it all works. Now if we try to change the signature of a so that it breaks b then we need to rewrite b into B and recompile it with A loaded so we start from scratch with a'.lsp -> a.fasl b'.lsp -> b.fasl (load a) (load b) a -> a.fasl b -> b.fasl a -> A A -> A'.lsp -> A.fasl (load A) b -> B B -> B'.lsp -> B.fasl (modfify .spad file bootstraps thus: \section{A} A \section{A.bootstrap} A'.lsp \section{B} B \section{B.bootstrap} B'.lsp and now we rebuild the system from scratch and it all works. Notice you have to co-modify a -> A, b -> B in the same image and update the .spad file and bootstrap code before rebuiding from scratch. Note that modifying a->A so it breaks b and simultaneously modifying b->B so it breaks a is left as an exercise. This kind of programming is what got axiom into the state where it needed a running axiom to build axiom. Once you get past the circular dependency problem you no longer have a need for the lisp bootstrap code. It is possible to modify non-bootstrap code and break the system build but that's just a simple programming problem. It is very tricky to modify the fundamental cycles but it can be done. It has always been true that you need a running axiom to rebuild axiom. My key breakthru was to make it possible to build axiom from scratch. However it is not true that you can randomly modify anything and expect the algebra to build. In general you would like the makefile to know the dependency graph of algebra code. However you'll find that make can't handle such a graph. I tried another idea which was to decorate each stanza from layer n with a ${LAYER(n-1)} but that fails also. However the fact that I failed is no reason not to try because you have a deeper understanding of make so I'm willing to be convinced. My general approach, when domain signatures change, is to do make clean make The algebra hierarchy needs a future rewrite for 2 reasons, Provisos and ACL2 integration. Hopefully we'll be smarter next time. \end{verbatim} \section{email 33} \begin{verbatim} The hypertex is intended to be edited by users. We are looking to build special purpose pages around courses such as linear algebra. Assume HERE=$AXIOM/doc/hypertex/pages The text can be found in $HERE/foo.ht or $HERE/foo.pht The macros are tex-like and live in $HERE/util.ht To change a page you need to: cd $HERE edit the page rm *~ (to delete backup copies) htadd * hypertex the htadd command takes arguments: htadd [-s|-l|-f db-directory] [-d|-n] filenames but, i'm sorry to say, these have not been fully documented. The htadd function will maintain the file called $HERE/ht.db which is a database of absolute byte indexes into files. Forgetting to run htadd will still work, sort-of, until you hit a bad byte index and then it will fail. Hypertex can also be directed elsewhere by using the HTPATH shell variable. \end{verbatim} \section{email 34} \begin{verbatim} > > What is the purpose of the domain HACKPI ?? > HACKPI is a hack provided for the benefit of the axiom interpreter. As a mathematical type, it is the simple transcendental extension Q(\pi) of the rational numbers. This type allows interactive users to use the name '%pi' without a type both where a numerical value is expected [ as in draw(sin x,x=-%pi..%pi) ] or when the exact symbolic value is meant. The interpreter defaults a typeless %pi to HACKPI and then uses the various conversions to cast it further as required by the context. One could argue that it is unfair to single %pi out from other constants, but it occurs frequently enough in school examples (specially for graphs) so it was worth a special hack. In a non-interactive environment (library), HACKPI would not exist. \end{verbatim} \section{email 35} \begin{verbatim} \end{verbatim} \end{document}